pcre2 2.2.2 → 2.2.3
raw patch · 158 files changed
+137603/−98743 lines, 158 files
Files
- ChangeLog.md +19/−0
- README.md +11/−7
- pcre2.cabal +77/−42
- src/c/config.h +50/−39
- src/c/pcre2.h +93/−24
- src/c/pcre2/deps/sljit/docs/tutorial/sources/array_access.c +90/−0
- src/c/pcre2/deps/sljit/docs/tutorial/sources/brainfuck.c +262/−0
- src/c/pcre2/deps/sljit/docs/tutorial/sources/branch.c +77/−0
- src/c/pcre2/deps/sljit/docs/tutorial/sources/first_program.c +59/−0
- src/c/pcre2/deps/sljit/docs/tutorial/sources/func_call.c +80/−0
- src/c/pcre2/deps/sljit/docs/tutorial/sources/loop.c +76/−0
- src/c/pcre2/deps/sljit/docs/tutorial/sources/struct_access.c +88/−0
- src/c/pcre2/deps/sljit/docs/tutorial/sources/temp_var.c +74/−0
- src/c/pcre2/deps/sljit/regex_src/regexJIT.c +2595/−0
- src/c/pcre2/deps/sljit/regex_src/regexJIT.h +106/−0
- src/c/pcre2/deps/sljit/regex_src/regexMain.c +335/−0
- src/c/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorApple.c +137/−0
- src/c/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c +327/−0
- src/c/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorFreeBSD.c +89/−0
- src/c/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorPosix.c +62/−0
- src/c/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorWindows.c +40/−0
- src/c/pcre2/deps/sljit/sljit_src/allocator_src/sljitProtExecAllocatorNetBSD.c +72/−0
- src/c/pcre2/deps/sljit/sljit_src/allocator_src/sljitProtExecAllocatorPosix.c +172/−0
- src/c/pcre2/deps/sljit/sljit_src/allocator_src/sljitWXExecAllocatorPosix.c +141/−0
- src/c/pcre2/deps/sljit/sljit_src/allocator_src/sljitWXExecAllocatorWindows.c +102/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitConfig.h +142/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitConfigCPU.h +188/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitConfigInternal.h +1008/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitLir.c +3925/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitLir.h +2765/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitNativeARM_32.c +4950/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitNativeARM_64.c +3805/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitNativeARM_T2_32.c +4625/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitNativeLOONGARCH_64.c +4123/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_32.c +467/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_64.c +382/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_common.c +4597/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitNativePPC_32.c +485/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitNativePPC_64.c +719/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitNativePPC_common.c +3513/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_32.c +154/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_64.c +291/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_common.c +4855/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitNativeS390X.c +4822/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitNativeX86_32.c +1707/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitNativeX86_64.c +1430/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitNativeX86_common.c +5434/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitSerialize.c +585/−0
- src/c/pcre2/deps/sljit/sljit_src/sljitUtils.c +344/−0
- src/c/pcre2/deps/sljit/test_src/sljitConfigPost.h +33/−0
- src/c/pcre2/deps/sljit/test_src/sljitConfigPre.h +35/−0
- src/c/pcre2/deps/sljit/test_src/sljitMain.c +84/−0
- src/c/pcre2/deps/sljit/test_src/sljitTest.c +10396/−0
- src/c/pcre2/deps/sljit/test_src/sljitTestBuffers.h +627/−0
- src/c/pcre2/deps/sljit/test_src/sljitTestCall.h +2109/−0
- src/c/pcre2/deps/sljit/test_src/sljitTestFloat.h +3059/−0
- src/c/pcre2/deps/sljit/test_src/sljitTestSerialize.h +501/−0
- src/c/pcre2/deps/sljit/test_src/sljitTestSimd.h +2722/−0
- src/c/pcre2/maint/cmake-tests/build-interface/main.c +11/−0
- src/c/pcre2/maint/cmake-tests/install-interface/main.c +11/−0
- src/c/pcre2/maint/ucptest.c +4/−9
- src/c/pcre2/maint/utf8.c +143/−57
- src/c/pcre2/src/pcre2_auto_possess.c +104/−59
- src/c/pcre2/src/pcre2_chkdint.c +6/−8
- src/c/pcre2/src/pcre2_compile.c +11292/−10950
- src/c/pcre2/src/pcre2_compile.h +356/−0
- src/c/pcre2/src/pcre2_compile_cgroup.c +632/−0
- src/c/pcre2/src/pcre2_compile_class.c +2769/−0
- src/c/pcre2/src/pcre2_config.c +15/−17
- src/c/pcre2/src/pcre2_context.c +63/−16
- src/c/pcre2/src/pcre2_convert.c +113/−41
- src/c/pcre2/src/pcre2_dfa_match.c +117/−102
- src/c/pcre2/src/pcre2_dftables.c +47/−18
- src/c/pcre2/src/pcre2_error.c +57/−18
- src/c/pcre2/src/pcre2_extuni.c +3/−6
- src/c/pcre2/src/pcre2_find_bracket.c +9/−11
- src/c/pcre2/src/pcre2_fuzzsupport.c +67/−15
- src/c/pcre2/src/pcre2_internal.h +528/−259
- src/c/pcre2/src/pcre2_intmodedep.h +139/−35
- src/c/pcre2/src/pcre2_jit_char_inc.h +2280/−0
- src/c/pcre2/src/pcre2_jit_compile.c +14271/−14929
- src/c/pcre2/src/pcre2_jit_match.c +0/−200
- src/c/pcre2/src/pcre2_jit_match_inc.h +202/−0
- src/c/pcre2/src/pcre2_jit_misc.c +0/−234
- src/c/pcre2/src/pcre2_jit_misc_inc.h +234/−0
- src/c/pcre2/src/pcre2_jit_neon_inc.h +0/−354
- src/c/pcre2/src/pcre2_jit_simd_inc.h +511/−360
- src/c/pcre2/src/pcre2_jit_test.c +19/−1
- src/c/pcre2/src/pcre2_maketables.c +42/−30
- src/c/pcre2/src/pcre2_match.c +688/−221
- src/c/pcre2/src/pcre2_match_data.c +6/−7
- src/c/pcre2/src/pcre2_match_next.c +171/−0
- src/c/pcre2/src/pcre2_newline.c +0/−4
- src/c/pcre2/src/pcre2_ord2utf.c +6/−8
- src/c/pcre2/src/pcre2_pattern_info.c +9/−11
- src/c/pcre2/src/pcre2_printint.c +0/−886
- src/c/pcre2/src/pcre2_printint_inc.h +1098/−0
- src/c/pcre2/src/pcre2_script_run.c +2/−3
- src/c/pcre2/src/pcre2_serialize.c +20/−22
- src/c/pcre2/src/pcre2_string_utils.c +1/−39
- src/c/pcre2/src/pcre2_study.c +249/−78
- src/c/pcre2/src/pcre2_substitute.c +1737/−985
- src/c/pcre2/src/pcre2_substring.c +12/−9
- src/c/pcre2/src/pcre2_tables.c +94/−18
- src/c/pcre2/src/pcre2_ucd.c +5751/−5406
- src/c/pcre2/src/pcre2_ucp.h +37/−25
- src/c/pcre2/src/pcre2_ucptables.c +0/−1533
- src/c/pcre2/src/pcre2_ucptables_inc.h +1596/−0
- src/c/pcre2/src/pcre2_util.h +179/−0
- src/c/pcre2/src/pcre2_valid_utf.c +2/−3
- src/c/pcre2/src/pcre2_xclass.c +322/−83
- src/c/pcre2/src/pcre2demo.c +69/−120
- src/c/pcre2/src/pcre2grep.c +248/−167
- src/c/pcre2/src/pcre2posix.c +80/−67
- src/c/pcre2/src/pcre2posix.h +22/−25
- src/c/pcre2/src/pcre2posix_test.c +43/−13
- src/c/pcre2/src/pcre2test.c +4158/−9643
- src/c/pcre2/src/pcre2test_inc.h +6349/−0
- src/c/pcre2/src/sljit/allocator_src/sljitExecAllocatorApple.c +0/−137
- src/c/pcre2/src/sljit/allocator_src/sljitExecAllocatorCore.c +0/−327
- src/c/pcre2/src/sljit/allocator_src/sljitExecAllocatorFreeBSD.c +0/−89
- src/c/pcre2/src/sljit/allocator_src/sljitExecAllocatorPosix.c +0/−62
- src/c/pcre2/src/sljit/allocator_src/sljitExecAllocatorWindows.c +0/−40
- src/c/pcre2/src/sljit/allocator_src/sljitProtExecAllocatorNetBSD.c +0/−72
- src/c/pcre2/src/sljit/allocator_src/sljitProtExecAllocatorPosix.c +0/−172
- src/c/pcre2/src/sljit/allocator_src/sljitWXExecAllocatorPosix.c +0/−141
- src/c/pcre2/src/sljit/allocator_src/sljitWXExecAllocatorWindows.c +0/−102
- src/c/pcre2/src/sljit/sljitConfig.h +0/−142
- src/c/pcre2/src/sljit/sljitConfigCPU.h +0/−188
- src/c/pcre2/src/sljit/sljitConfigInternal.h +0/−907
- src/c/pcre2/src/sljit/sljitLir.c +0/−3561
- src/c/pcre2/src/sljit/sljitLir.h +0/−2466
- src/c/pcre2/src/sljit/sljitNativeARM_32.c +0/−4636
- src/c/pcre2/src/sljit/sljitNativeARM_64.c +0/−3491
- src/c/pcre2/src/sljit/sljitNativeARM_T2_32.c +0/−4302
- src/c/pcre2/src/sljit/sljitNativeLOONGARCH_64.c +0/−3765
- src/c/pcre2/src/sljit/sljitNativeMIPS_32.c +0/−472
- src/c/pcre2/src/sljit/sljitNativeMIPS_64.c +0/−387
- src/c/pcre2/src/sljit/sljitNativeMIPS_common.c +0/−4259
- src/c/pcre2/src/sljit/sljitNativePPC_32.c +0/−485
- src/c/pcre2/src/sljit/sljitNativePPC_64.c +0/−719
- src/c/pcre2/src/sljit/sljitNativePPC_common.c +0/−3161
- src/c/pcre2/src/sljit/sljitNativeRISCV_32.c +0/−142
- src/c/pcre2/src/sljit/sljitNativeRISCV_64.c +0/−222
- src/c/pcre2/src/sljit/sljitNativeRISCV_common.c +0/−3121
- src/c/pcre2/src/sljit/sljitNativeS390X.c +0/−4526
- src/c/pcre2/src/sljit/sljitNativeX86_32.c +0/−1685
- src/c/pcre2/src/sljit/sljitNativeX86_64.c +0/−1398
- src/c/pcre2/src/sljit/sljitNativeX86_common.c +0/−5001
- src/c/pcre2/src/sljit/sljitSerialize.c +0/−516
- src/c/pcre2/src/sljit/sljitUtils.c +0/−344
- src/c/pcre2_chartables.c +0/−4
- src/hs/Text/Regex/Pcre2.hs +5/−1
- src/hs/Text/Regex/Pcre2/Foreign.hs +23/−0
- src/hs/Text/Regex/Pcre2/Internal.hs +403/−456
- src/hs/Text/Regex/Pcre2/TH.hs +45/−25
- src/hs/Text/Regex/Pcre2/Unsafe.hs +4/−0
- test/Spec.hs +13/−2
ChangeLog.md view
@@ -1,5 +1,24 @@ # Changelog and Acknowledgements +## 2.2.3+* Exposed `CapturesInfo` kind of type-level regex info.+* Exposed `predictCapturesInfo` for producing value-level of same, implementing+ [#45](https://github.com/sjshuck/hs-pcre2/issues/45).+* Added `Dupnames` option. Thanks sbsynopsys!+* Updated PCRE2 to 10.47.+ * Added `pcre2_next_match`.+ * Added `pcre2_CONFIG_EFFECTIVE_LINKSIZE` and `effectivelinkSize`.+* Added `Text.Regex.Pcre2.Unsafe.getCaptures` to unwrap a `Captures` into a+ `NonEmpty` list.++## 2.2.2+* Fixed [#34](https://github.com/sjshuck/hs-pcre2/issues/34),+ [#35](https://github.com/sjshuck/hs-pcre2/issues/35), and+ [#39](https://github.com/sjshuck/hs-pcre2/issues/39), all related to a+ use-before-`free()` bug.+* Updated PCRE2 to 10.44 (no API changes).+* Minor simplifications in docs and implementation.+ ## 2.2.1 * Fixed [#26](https://github.com/sjshuck/hs-pcre2/issues/26) where wide UTF-8 characters were not handled correctly.
README.md view
@@ -60,15 +60,18 @@ callbacks to run during matching! * Zero-copying of substrings where beneficial. * Few dependencies.-* Bundled, statically-linked build of up-to-date PCRE2 (version 10.44), with a+* Bundled, statically-linked build of up-to-date PCRE2 (version 10.47), with a complete, exposed Haskell binding. ## Performance-Currently we are slower than other libraries. For example:+Currently we are slower than other libraries. The difference is less pronounced+for `Text` where no conversions are necessary to use this library. -| Operation | `pcre2` | `pcre-light` | `regex-pcre-builtin` |-| :-- | --: | --: | --: |-| Compile and match a regex | 3.9 μs | 1.2 μs | 2.9 μs |+| Operation | `pcre2` | `regex-pcre-builtin` | `pcre-light` |+| :-- | --: | --: | --: |+| Matching a `String` | 1.22 μs | 0.34 μs | 0.23 μs |+| Matching a `Text` (shorter) | 1.22 μs | 0.93 μs | 0.29 μs |+| Matching a `Text` (longer) | 1.89 μs | 1.52 μs | 11.12 μs | If it's really regex processing that's causing a bottleneck, [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)@@ -77,8 +80,9 @@ ## Wishlist * 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+ 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).
pcre2.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.37.0.+-- This file has been generated from package.yaml by hpack version 0.38.1. -- -- see: https://github.com/sol/hpack name: pcre2-version: 2.2.2+version: 2.2.3 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@@ -23,22 +23,82 @@ src/c/config.h src/c/getters.h src/c/pcre2.h+ src/c/pcre2/deps/sljit/regex_src/regexJIT.h+ src/c/pcre2/deps/sljit/sljit_src/sljitConfig.h+ src/c/pcre2/deps/sljit/sljit_src/sljitConfigCPU.h+ src/c/pcre2/deps/sljit/sljit_src/sljitConfigInternal.h+ src/c/pcre2/deps/sljit/sljit_src/sljitLir.h+ src/c/pcre2/deps/sljit/test_src/sljitConfigPost.h+ src/c/pcre2/deps/sljit/test_src/sljitConfigPre.h+ src/c/pcre2/deps/sljit/test_src/sljitTestBuffers.h+ src/c/pcre2/deps/sljit/test_src/sljitTestCall.h+ src/c/pcre2/deps/sljit/test_src/sljitTestFloat.h+ src/c/pcre2/deps/sljit/test_src/sljitTestSerialize.h+ src/c/pcre2/deps/sljit/test_src/sljitTestSimd.h+ src/c/pcre2/src/pcre2_compile.h src/c/pcre2/src/pcre2_internal.h src/c/pcre2/src/pcre2_intmodedep.h- src/c/pcre2/src/pcre2_jit_neon_inc.h+ src/c/pcre2/src/pcre2_jit_char_inc.h+ src/c/pcre2/src/pcre2_jit_match_inc.h+ src/c/pcre2/src/pcre2_jit_misc_inc.h src/c/pcre2/src/pcre2_jit_simd_inc.h+ src/c/pcre2/src/pcre2_printint_inc.h src/c/pcre2/src/pcre2_ucp.h+ src/c/pcre2/src/pcre2_ucptables_inc.h+ src/c/pcre2/src/pcre2_util.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/src/pcre2test_inc.h src/c/pcre2/vms/stdint.h+ src/c/pcre2/deps/sljit/docs/tutorial/sources/array_access.c+ src/c/pcre2/deps/sljit/docs/tutorial/sources/brainfuck.c+ src/c/pcre2/deps/sljit/docs/tutorial/sources/branch.c+ src/c/pcre2/deps/sljit/docs/tutorial/sources/first_program.c+ src/c/pcre2/deps/sljit/docs/tutorial/sources/func_call.c+ src/c/pcre2/deps/sljit/docs/tutorial/sources/loop.c+ src/c/pcre2/deps/sljit/docs/tutorial/sources/struct_access.c+ src/c/pcre2/deps/sljit/docs/tutorial/sources/temp_var.c+ src/c/pcre2/deps/sljit/regex_src/regexJIT.c+ src/c/pcre2/deps/sljit/regex_src/regexMain.c+ src/c/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorApple.c+ src/c/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c+ src/c/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorFreeBSD.c+ src/c/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorPosix.c+ src/c/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorWindows.c+ src/c/pcre2/deps/sljit/sljit_src/allocator_src/sljitProtExecAllocatorNetBSD.c+ src/c/pcre2/deps/sljit/sljit_src/allocator_src/sljitProtExecAllocatorPosix.c+ src/c/pcre2/deps/sljit/sljit_src/allocator_src/sljitWXExecAllocatorPosix.c+ src/c/pcre2/deps/sljit/sljit_src/allocator_src/sljitWXExecAllocatorWindows.c+ src/c/pcre2/deps/sljit/sljit_src/sljitLir.c+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeARM_32.c+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeARM_64.c+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeARM_T2_32.c+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeLOONGARCH_64.c+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_32.c+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_64.c+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_common.c+ src/c/pcre2/deps/sljit/sljit_src/sljitNativePPC_32.c+ src/c/pcre2/deps/sljit/sljit_src/sljitNativePPC_64.c+ src/c/pcre2/deps/sljit/sljit_src/sljitNativePPC_common.c+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_32.c+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_64.c+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_common.c+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeS390X.c+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeX86_32.c+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeX86_64.c+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeX86_common.c+ src/c/pcre2/deps/sljit/sljit_src/sljitSerialize.c+ src/c/pcre2/deps/sljit/sljit_src/sljitUtils.c+ src/c/pcre2/deps/sljit/test_src/sljitMain.c+ src/c/pcre2/deps/sljit/test_src/sljitTest.c+ src/c/pcre2/maint/cmake-tests/build-interface/main.c+ src/c/pcre2/maint/cmake-tests/install-interface/main.c 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_compile_cgroup.c+ src/c/pcre2/src/pcre2_compile_class.c src/c/pcre2/src/pcre2_config.c src/c/pcre2/src/pcre2_context.c src/c/pcre2/src/pcre2_convert.c@@ -49,16 +109,14 @@ src/c/pcre2/src/pcre2_find_bracket.c src/c/pcre2/src/pcre2_fuzzsupport.c src/c/pcre2/src/pcre2_jit_compile.c- src/c/pcre2/src/pcre2_jit_match.c- src/c/pcre2/src/pcre2_jit_misc.c src/c/pcre2/src/pcre2_jit_test.c src/c/pcre2/src/pcre2_maketables.c src/c/pcre2/src/pcre2_match.c src/c/pcre2/src/pcre2_match_data.c+ src/c/pcre2/src/pcre2_match_next.c src/c/pcre2/src/pcre2_newline.c src/c/pcre2/src/pcre2_ord2utf.c src/c/pcre2/src/pcre2_pattern_info.c- src/c/pcre2/src/pcre2_printint.c src/c/pcre2/src/pcre2_script_run.c src/c/pcre2/src/pcre2_serialize.c src/c/pcre2/src/pcre2_string_utils.c@@ -67,7 +125,6 @@ src/c/pcre2/src/pcre2_substring.c src/c/pcre2/src/pcre2_tables.c src/c/pcre2/src/pcre2_ucd.c- src/c/pcre2/src/pcre2_ucptables.c src/c/pcre2/src/pcre2_valid_utf.c src/c/pcre2/src/pcre2_xclass.c src/c/pcre2/src/pcre2demo.c@@ -75,35 +132,6 @@ src/c/pcre2/src/pcre2posix.c src/c/pcre2/src/pcre2posix_test.c src/c/pcre2/src/pcre2test.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/sljitNativeX86_32.c- src/c/pcre2/src/sljit/sljitNativeX86_64.c- src/c/pcre2/src/sljit/sljitNativeX86_common.c- src/c/pcre2/src/sljit/sljitSerialize.c- src/c/pcre2/src/sljit/sljitUtils.c src/c/pcre2_chartables.c source-repository head@@ -122,16 +150,18 @@ Paths_pcre2 hs-source-dirs: src/hs- 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+ ghc-options: -W -optc=-DPCRE2_CODE_UNIT_WIDTH=8 -optc=-DPCRE2_STATIC=1 -optc=-DSUPPORT_PCRE2_8 -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_chartables.c src/c/pcre2/src/pcre2_compile.c+ src/c/pcre2/src/pcre2_compile_cgroup.c+ src/c/pcre2/src/pcre2_compile_class.c src/c/pcre2/src/pcre2_config.c src/c/pcre2/src/pcre2_context.c src/c/pcre2/src/pcre2_convert.c@@ -143,6 +173,7 @@ src/c/pcre2/src/pcre2_maketables.c src/c/pcre2/src/pcre2_match.c src/c/pcre2/src/pcre2_match_data.c+ src/c/pcre2/src/pcre2_match_next.c src/c/pcre2/src/pcre2_newline.c src/c/pcre2/src/pcre2_ord2utf.c src/c/pcre2/src/pcre2_pattern_info.c@@ -164,6 +195,10 @@ , template-haskell , text >=2 default-language: Haskell2010+ if os(darwin)+ ghc-options: -optc=-Wno-ignored-qualifiers+ else+ ghc-options: -optc=-Wno-discarded-qualifiers test-suite pcre2-test type: exitcode-stdio-1.0
src/c/config.h view
@@ -22,11 +22,7 @@ defined (conventionally to 1) for TRUE, and not defined at all for FALSE. All such macros are listed as a commented #undef in config.h.generic. Macros such as MATCH_LIMIT, whose actual value is relevant, have defaults defined, but are-surrounded by #ifndef/#endif lines so that the value can be overridden by -D.--PCRE2 uses memmove() if HAVE_MEMMOVE is defined; otherwise it uses bcopy() if-HAVE_BCOPY is defined. If your system has neither bcopy() nor memmove(), make-sure both macros are undefined; an emulation function will then be used. */+surrounded by #ifndef/#endif lines so that the value can be overridden by -D. */ /* By default, the \R escape sequence matches any Unicode line ending character or sequence of characters. If BSR_ANYCRLF is defined (to any@@ -44,23 +40,34 @@ assumes that all input strings are in EBCDIC. If you do not define this macro, PCRE2 will assume input strings are ASCII or UTF-8/16/32 Unicode. It is not possible to build a version of PCRE2 that supports both EBCDIC and- UTF-8/16/32. */+ ASCII or UTF-8/16/32. */ /* #undef EBCDIC */ +/* To force an EBCDIC environment, define this macro to make the core PCRE2+ library functions use EBCDIC codepage 1047, regardless of whether the+ compiler supports it using C character literals. */+/* #undef EBCDIC_IGNORING_COMPILER */+ /* In an EBCDIC environment, define this macro to any value to arrange for the NL character to be 0x25 instead of the default 0x15. NL plays the role that LF does in an ASCII/Unicode environment. */ /* #undef EBCDIC_NL25 */ +/* Define to 1 if you have the <assert.h> header file. */+/* #undef HAVE_ASSERT_H */+ /* Define this if your compiler supports __attribute__((uninitialized)) */ /* #undef HAVE_ATTRIBUTE_UNINITIALIZED */ -/* Define to 1 if you have the 'bcopy' function. */-/* #undef HAVE_BCOPY */+/* Define this if your compiler provides __assume() */+/* #undef HAVE_BUILTIN_ASSUME */ /* Define this if your compiler provides __builtin_mul_overflow() */ /* #undef HAVE_BUILTIN_MUL_OVERFLOW */ +/* Define this if your compiler provides __builtin_unreachable() */+/* #undef HAVE_BUILTIN_UNREACHABLE */+ /* Define to 1 if you have the <bzlib.h> header file. */ /* #undef HAVE_BZLIB_H */ @@ -82,16 +89,13 @@ /* 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. */-/* #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. */@@ -112,7 +116,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. */@@ -124,9 +128,6 @@ /* Define to 1 if you have the <stdlib.h> header file. */ /* #undef HAVE_STDLIB_H */ -/* Define to 1 if you have the 'strerror' function. */-/* #undef HAVE_STRERROR */- /* Define to 1 if you have the <strings.h> header file. */ /* #undef HAVE_STRINGS_H */ @@ -145,7 +146,8 @@ /* Define to 1 if you have the <unistd.h> header file. */ /* #undef HAVE_UNISTD_H */ -/* Define to 1 if the compiler supports simple visibility declarations. */+/* Define to 1 if the compiler supports GCC compatible visibility+ declarations. */ /* #undef HAVE_VISIBILITY */ /* Define to 1 if you have the <wchar.h> header file. */@@ -245,7 +247,7 @@ #define PACKAGE_NAME "PCRE2" /* Define to the full name and version of this package. */-#define PACKAGE_STRING "PCRE2 10.44"+#define PACKAGE_STRING "PCRE2 10.47" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "pcre2"@@ -254,7 +256,7 @@ #define PACKAGE_URL "" /* Define to the version of this package. */-#define PACKAGE_VERSION "10.44"+#define PACKAGE_VERSION "10.47" /* 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@@ -281,10 +283,24 @@ #define PCRE2GREP_MAX_BUFSIZE 1048576 #endif +/* See PCRE2_EXP_DEFN; but this is applied to functions in the libpcre2-posix+ library. */+/* #undef PCRE2POSIX_EXP_DEFN */++/* Define to any value if linking libpcre2-posix dynamically. Ideally, if both+ static and shared libraries are being built, then PCRE2POSIX_SHARED would+ be defined only for the shared build. Indeed, this is a requirement on+ Windows. However, when building with Autoconf and libtool, we compile the+ sources once only to create both the static and shared library, so in this+ case, PCRE2POSIX_SHARED should only be defined if the shared library is+ being built, regardless of whether or not the static library is also being+ built. */+/* #undef PCRE2POSIX_SHARED */+ /* Define to any value to include debugging code. */ /* #undef PCRE2_DEBUG */ -/* to make a symbol visible */+/* Define to the annotation for making a symbol visible. */ #define PCRE2_EXPORT /* If you are compiling for a system other than a Unix-like system or@@ -299,7 +315,12 @@ in the C sense, but which are internal to the library. */ /* #undef PCRE2_EXP_DEFN */ -/* Define to any value if linking statically (TODO: make nice with Libtool) */+/* Define to any value if linking statically. Ideally, if both static and+ shared libraries are being built, then PCRE2_STATIC would be defined only+ for the static build. Indeed, this is a requirement on Windows. With+ Autoconf and libtool however, it is idiomatic to compile the sources once+ to create both the static and shared library, so in this case, PCRE2_STATIC+ should only be defined if no shared library is being built. */ /* #undef PCRE2_STATIC */ /* Define to necessary symbol if this constant uses a non-standard name on@@ -311,7 +332,7 @@ unless SUPPORT_JIT is also defined. */ /* #undef SLJIT_PROT_EXECUTABLE_ALLOCATOR */ -/* Define to 1 if all of the C89 standard headers exist (not just the ones+/* Define to 1 if all of the C90 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 */@@ -366,7 +387,7 @@ /* Define to any value for valgrind support to find invalid memory reads. */ /* #undef SUPPORT_VALGRIND */ -/* Enable extensions on AIX, Interix, z/OS. */+/* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # define _ALL_SOURCE 1 #endif@@ -427,15 +448,11 @@ #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 C23 Annex H and ISO/IEC TS 18661-3:2015. */+/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */ #ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ # define __STDC_WANT_IEC_60559_TYPES_EXT__ 1 #endif@@ -458,26 +475,20 @@ #endif /* Version number of package */-#define VERSION "10.44"+#define VERSION "10.47" /* 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. */+/* Define for large files, on AIX-style hosts. */ /* #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. */+/* 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 as 'unsigned int' if <stddef.h> doesn't define. */+/* Define to `unsigned int' if <sys/types.h> does not define. */ /* #undef size_t */
src/c/pcre2.h view
@@ -42,25 +42,21 @@ /* The current PCRE version information. */ #define PCRE2_MAJOR 10-#define PCRE2_MINOR 44+#define PCRE2_MINOR 47 #define PCRE2_PRERELEASE -#define PCRE2_DATE 2024-06-07+#define PCRE2_DATE 2025-10-21 -/* When an application links to a PCRE DLL in Windows, the symbols that are+/* 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 setting is defined in pcre2_internal.h, which includes this file. So we-don't change existing definitions of PCRE2_EXP_DECL. */--#if defined(_WIN32) && !defined(PCRE2_STATIC)-# ifndef PCRE2_EXP_DECL-# define PCRE2_EXP_DECL extern __declspec(dllimport)-# endif-#endif+export setting is defined in pcre2_internal.h, which includes this file. So, we+don't change existing definitions of PCRE2_EXP_DECL. -/* By default, we use the standard "extern" declarations. */+By default, we use the standard "extern" declarations. */ #ifndef PCRE2_EXP_DECL-# ifdef __cplusplus+# if defined(_WIN32) && !defined(PCRE2_STATIC)+# define PCRE2_EXP_DECL extern __declspec(dllimport)+# elif defined __cplusplus # define PCRE2_EXP_DECL extern "C" # else # define PCRE2_EXP_DECL extern@@ -68,15 +64,16 @@ #endif /* 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+a "calling convention" before exported function names. For example: void __cdecl function(....) -might be needed. In order so 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. */+might be needed. In order to make this easy, all the exported functions have+PCRE2_CALL_CONVENTION just before their names. +PCRE2 normally uses the platform's standard calling convention, so this should+not be set unless you know you need it. */+ #ifndef PCRE2_CALL_CONVENTION #define PCRE2_CALL_CONVENTION #endif@@ -143,6 +140,7 @@ #define PCRE2_EXTENDED_MORE 0x01000000u /* C */ #define PCRE2_LITERAL 0x02000000u /* C */ #define PCRE2_MATCH_INVALID_UTF 0x04000000u /* J M D */+#define PCRE2_ALT_EXTENDED_CLASS 0x08000000u /* C */ /* An additional compile options word is available in the compile context. */ @@ -159,6 +157,10 @@ #define PCRE2_EXTRA_ASCII_BSW 0x00000400u /* C */ #define PCRE2_EXTRA_ASCII_POSIX 0x00000800u /* C */ #define PCRE2_EXTRA_ASCII_DIGIT 0x00001000u /* C */+#define PCRE2_EXTRA_PYTHON_OCTAL 0x00002000u /* C */+#define PCRE2_EXTRA_NO_BS0 0x00004000u /* C */+#define PCRE2_EXTRA_NEVER_CALLOUT 0x00008000u /* C */+#define PCRE2_EXTRA_TURKISH_CASING 0x00010000u /* C */ /* These are for pcre2_jit_compile(). */ @@ -166,6 +168,7 @@ #define PCRE2_JIT_PARTIAL_SOFT 0x00000002u #define PCRE2_JIT_PARTIAL_HARD 0x00000004u #define PCRE2_JIT_INVALID_UTF 0x00000100u+#define PCRE2_JIT_TEST_ALLOC 0x00000200u /* These are for pcre2_match(), pcre2_dfa_match(), pcre2_jit_match(), and pcre2_substitute(). Some are allowed only for one of the functions, and in@@ -318,9 +321,29 @@ #define PCRE2_ERROR_ALPHA_ASSERTION_UNKNOWN 195 #define PCRE2_ERROR_SCRIPT_RUN_NOT_AVAILABLE 196 #define PCRE2_ERROR_TOO_MANY_CAPTURES 197-#define PCRE2_ERROR_CONDITION_ATOMIC_ASSERTION_EXPECTED 198+#define PCRE2_ERROR_MISSING_OCTAL_DIGIT 198 #define PCRE2_ERROR_BACKSLASH_K_IN_LOOKAROUND 199-+#define PCRE2_ERROR_MAX_VAR_LOOKBEHIND_EXCEEDED 200+#define PCRE2_ERROR_PATTERN_COMPILED_SIZE_TOO_BIG 201+#define PCRE2_ERROR_OVERSIZE_PYTHON_OCTAL 202+#define PCRE2_ERROR_CALLOUT_CALLER_DISABLED 203+#define PCRE2_ERROR_EXTRA_CASING_REQUIRES_UNICODE 204+#define PCRE2_ERROR_TURKISH_CASING_REQUIRES_UTF 205+#define PCRE2_ERROR_EXTRA_CASING_INCOMPATIBLE 206+#define PCRE2_ERROR_ECLASS_NEST_TOO_DEEP 207+#define PCRE2_ERROR_ECLASS_INVALID_OPERATOR 208+#define PCRE2_ERROR_ECLASS_UNEXPECTED_OPERATOR 209+#define PCRE2_ERROR_ECLASS_EXPECTED_OPERAND 210+#define PCRE2_ERROR_ECLASS_MIXED_OPERATORS 211+#define PCRE2_ERROR_ECLASS_HINT_SQUARE_BRACKET 212+#define PCRE2_ERROR_PERL_ECLASS_UNEXPECTED_EXPR 213+#define PCRE2_ERROR_PERL_ECLASS_EMPTY_EXPR 214+#define PCRE2_ERROR_PERL_ECLASS_MISSING_CLOSE 215+#define PCRE2_ERROR_PERL_ECLASS_UNEXPECTED_CHAR 216+#define PCRE2_ERROR_EXPECTED_CAPTURE_GROUP 217+#define PCRE2_ERROR_MISSING_OPENING_PARENTHESIS 218+#define PCRE2_ERROR_MISSING_NUMBER_TERMINATOR 219+#define PCRE2_ERROR_NULL_ERROROFFSET 220 /* "Expected" matching error codes: no match and partial match. */ @@ -407,6 +430,14 @@ #define PCRE2_ERROR_INTERNAL_DUPMATCH (-65) #define PCRE2_ERROR_DFA_UINVALID_UTF (-66) #define PCRE2_ERROR_INVALIDOFFSET (-67)+#define PCRE2_ERROR_JIT_UNSUPPORTED (-68)+#define PCRE2_ERROR_REPLACECASE (-69)+#define PCRE2_ERROR_TOOLARGEREPLACE (-70)+#define PCRE2_ERROR_DIFFSUBSPATTERN (-71)+#define PCRE2_ERROR_DIFFSUBSSUBJECT (-72)+#define PCRE2_ERROR_DIFFSUBSOFFSET (-73)+#define PCRE2_ERROR_DIFFSUBSOPTIONS (-74)+#define PCRE2_ERROR_BAD_BACKSLASH_K (-75) /* Request types for pcre2_pattern_info() */@@ -459,8 +490,33 @@ #define PCRE2_CONFIG_NEVER_BACKSLASH_C 13 #define PCRE2_CONFIG_COMPILED_WIDTHS 14 #define PCRE2_CONFIG_TABLES_LENGTH 15+#define PCRE2_CONFIG_EFFECTIVE_LINKSIZE 16 +/* Optimization directives for pcre2_set_optimize().+For binary compatibility, only add to this list; do not renumber. */ +#define PCRE2_OPTIMIZATION_NONE 0+#define PCRE2_OPTIMIZATION_FULL 1++#define PCRE2_AUTO_POSSESS 64+#define PCRE2_AUTO_POSSESS_OFF 65+#define PCRE2_DOTSTAR_ANCHOR 66+#define PCRE2_DOTSTAR_ANCHOR_OFF 67+#define PCRE2_START_OPTIMIZE 68+#define PCRE2_START_OPTIMIZE_OFF 69++/* Types used in pcre2_set_substitute_case_callout().++PCRE2_SUBSTITUTE_CASE_LOWER and PCRE2_SUBSTITUTE_CASE_UPPER are passed to the+callout to indicate that the case of the entire callout input should be+case-transformed. PCRE2_SUBSTITUTE_CASE_TITLE_FIRST is passed to indicate that+only the first character or glyph should be transformed to Unicode titlecase,+and the rest to lowercase. */++#define PCRE2_SUBSTITUTE_CASE_LOWER 1+#define PCRE2_SUBSTITUTE_CASE_UPPER 2+#define PCRE2_SUBSTITUTE_CASE_TITLE_FIRST 3+ /* Types for code units in patterns and subject strings. */ typedef uint8_t PCRE2_UCHAR8;@@ -613,7 +669,9 @@ pcre2_set_parens_nest_limit(pcre2_compile_context *, uint32_t); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_set_compile_recursion_guard(pcre2_compile_context *, \- int (*)(uint32_t, void *), void *);+ int (*)(uint32_t, void *), void *); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_set_optimize(pcre2_compile_context *, uint32_t); #define PCRE2_MATCH_CONTEXT_FUNCTIONS \ PCRE2_EXP_DECL pcre2_match_context *PCRE2_CALL_CONVENTION \@@ -629,6 +687,11 @@ pcre2_set_substitute_callout(pcre2_match_context *, \ int (*)(pcre2_substitute_callout_block *, void *), void *); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_set_substitute_case_callout(pcre2_match_context *, \+ PCRE2_SIZE (*)(PCRE2_SPTR, PCRE2_SIZE, PCRE2_UCHAR *, PCRE2_SIZE, int, \+ void *), \+ void *); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_set_depth_limit(pcre2_match_context *, uint32_t); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_set_heap_limit(pcre2_match_context *, uint32_t); \@@ -687,14 +750,14 @@ PCRE2_EXP_DECL pcre2_match_data *PCRE2_CALL_CONVENTION \ pcre2_match_data_create_from_pattern(const pcre2_code *, \ pcre2_general_context *); \+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \+ pcre2_match_data_free(pcre2_match_data *); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_dfa_match(const pcre2_code *, PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, \ uint32_t, pcre2_match_data *, pcre2_match_context *, int *, PCRE2_SIZE); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_match(const pcre2_code *, PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, \ uint32_t, pcre2_match_data *, pcre2_match_context *); \-PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \- pcre2_match_data_free(pcre2_match_data *); \ PCRE2_EXP_DECL PCRE2_SPTR PCRE2_CALL_CONVENTION \ pcre2_get_mark(pcre2_match_data *); \ PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \@@ -706,7 +769,9 @@ 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 *);+ pcre2_get_startchar(pcre2_match_data *); \+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \+ pcre2_next_match(pcre2_match_data *, PCRE2_SIZE *, uint32_t *); /* Convenience functions for handling matched substrings. */@@ -740,6 +805,7 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_substring_list_get(pcre2_match_data *, PCRE2_UCHAR ***, PCRE2_SIZE **); + /* Functions for serializing / deserializing compiled patterns. */ #define PCRE2_SERIALIZE_FUNCTIONS \@@ -885,6 +951,7 @@ #define pcre2_match_data_create PCRE2_SUFFIX(pcre2_match_data_create_) #define pcre2_match_data_create_from_pattern PCRE2_SUFFIX(pcre2_match_data_create_from_pattern_) #define pcre2_match_data_free PCRE2_SUFFIX(pcre2_match_data_free_)+#define pcre2_next_match PCRE2_SUFFIX(pcre2_next_match_) #define pcre2_pattern_convert PCRE2_SUFFIX(pcre2_pattern_convert_) #define pcre2_pattern_info PCRE2_SUFFIX(pcre2_pattern_info_) #define pcre2_serialize_decode PCRE2_SUFFIX(pcre2_serialize_decode_)@@ -907,7 +974,9 @@ #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_)+#define pcre2_set_optimize PCRE2_SUFFIX(pcre2_set_optimize_) #define pcre2_set_substitute_callout PCRE2_SUFFIX(pcre2_set_substitute_callout_)+#define pcre2_set_substitute_case_callout PCRE2_SUFFIX(pcre2_set_substitute_case_callout_) #define pcre2_substitute PCRE2_SUFFIX(pcre2_substitute_) #define pcre2_substring_copy_byname PCRE2_SUFFIX(pcre2_substring_copy_byname_) #define pcre2_substring_copy_bynumber PCRE2_SUFFIX(pcre2_substring_copy_bynumber_)
+ src/c/pcre2/deps/sljit/docs/tutorial/sources/array_access.c view
@@ -0,0 +1,90 @@+#include "sljitLir.h"++#include <stdio.h>+#include <stdlib.h>++typedef sljit_sw (SLJIT_FUNC *func_arr_t)(sljit_sw *arr, sljit_sw narr);++static void SLJIT_FUNC print_num(sljit_sw a)+{+ printf("num = %ld\n", (long)a);+}++/*+ This example, we generate a function like this:++sljit_sw func(sljit_sw *array, sljit_sw narray)+{+ sljit_sw i;+ for (i = 0; i < narray; ++i)+ print_num(array[i]);+ return narray;+}++*/++static int array_access(sljit_sw *arr, sljit_sw narr)+{+ void *code;+ sljit_uw len;+ func_arr_t func;+ struct sljit_label *loopstart;+ struct sljit_jump *out;++ /* Create a SLJIT compiler */+ struct sljit_compiler *C = sljit_create_compiler(NULL);++ sljit_emit_enter(C, 0, SLJIT_ARGS2(W, P, W), 1, 3, 0);+ /* opt arg R S local_size */++ /* S2 = 0 */+ sljit_emit_op2(C, SLJIT_XOR, SLJIT_S2, 0, SLJIT_S2, 0, SLJIT_S2, 0);++ /* S1 = narr */+ sljit_emit_op1(C, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, narr);++ /* loopstart: */+ loopstart = sljit_emit_label(C);++ /* S2 >= narr --> jumo out */+ out = sljit_emit_cmp(C, SLJIT_GREATER_EQUAL, SLJIT_S2, 0, SLJIT_S1, 0);++ /* R0 = (sljit_sw *)S0[S2]; */+ sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_S2), SLJIT_WORD_SHIFT);++ /* print_num(R0) */+ sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1V(W), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num));++ /* S2 += 1 */+ sljit_emit_op2(C, SLJIT_ADD, SLJIT_S2, 0, SLJIT_S2, 0, SLJIT_IMM, 1);++ /* jump loopstart */+ sljit_set_label(sljit_emit_jump(C, SLJIT_JUMP), loopstart);++ /* out: */+ sljit_set_label(out, sljit_emit_label(C));++ /* return S1 */+ sljit_emit_return(C, SLJIT_MOV, SLJIT_S1, 0);++ /* Generate machine code */+ code = sljit_generate_code(C, 0, NULL);+ len = sljit_get_generated_code_size(C);++ /* Execute code */+ func = (func_arr_t)code;+ printf("func return %ld\n", (long)func(arr, narr));++ /* dump_code(code, len); */++ /* Clean up */+ sljit_free_compiler(C);+ sljit_free_code(code, NULL);+ return 0;+}++int main(void)+{+ sljit_sw arr[8] = { 3, -10, 4, 6, 8, 12, 2000, 0 };+ return array_access(arr, 8);+}
+ src/c/pcre2/deps/sljit/docs/tutorial/sources/brainfuck.c view
@@ -0,0 +1,262 @@+/*+ * Brainfuck interpreter with SLJIT+ *+ * Copyright 2015 Wen Xichang (wenxichang@163.com). 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 "sljitLir.h"++#include <stdio.h>+#include <stdlib.h>++#define BF_CELL_SIZE 3000+#define BF_LOOP_LEVEL 256++static int readvalid(FILE *src)+{+ int chr;++ while ((chr = fgetc(src)) != EOF) {+ switch (chr) {+ case '+':+ case '-':+ case '>':+ case '<':+ case '.':+ case ',':+ case '[':+ case ']':+ return chr;+ }+ }++ return chr;+}++/* reading same instruction, and count, for optimization */+/* ++++ -> '+', 4 */+static int gettoken(FILE *src, int *ntok)+{+ int chr = readvalid(src);+ int chr2;+ int cnt = 1;++ if (chr == EOF)+ return EOF;++ if (chr == '.' || chr == ',' || chr == '[' || chr == ']') {+ *ntok = 1;+ return chr;+ }+ + while ((chr2 = readvalid(src)) == chr)+ cnt++;++ if (chr2 != EOF)+ ungetc(chr2, src);++ *ntok = cnt;+ return chr;+}++/* maintaining loop matched [] */+struct loop_node_st {+ struct sljit_label *loop_start;+ struct sljit_jump *loop_end;+};++/* stack of loops */+static struct loop_node_st loop_stack[BF_LOOP_LEVEL];+static int loop_sp;++static int loop_push(struct sljit_label *loop_start, struct sljit_jump *loop_end)+{+ if (loop_sp >= BF_LOOP_LEVEL)+ return -1;++ loop_stack[loop_sp].loop_start = loop_start;+ loop_stack[loop_sp].loop_end = loop_end;+ loop_sp++;+ return 0;+}++static int loop_pop(struct sljit_label **loop_start, struct sljit_jump **loop_end)+{+ if (loop_sp <= 0)+ return -1;++ loop_sp--;+ *loop_start = loop_stack[loop_sp].loop_start;+ *loop_end = loop_stack[loop_sp].loop_end;+ return 0;+}++static void *SLJIT_FUNC my_alloc(size_t size, size_t n)+{+ return calloc(size, n);+}++static void SLJIT_FUNC my_putchar(sljit_sw c)+{+ putchar((int)c);+}++static sljit_sw SLJIT_FUNC my_getchar(void)+{+ return getchar();+}++static void SLJIT_FUNC my_free(void *mem)+{+ free(mem);+}++#define loop_empty() (loop_sp == 0)++/* compile bf source to a void func() */+static void *compile(FILE *src, sljit_uw *lcode)+{+ void *code = NULL;+ int chr;+ int nchr;++ struct sljit_compiler *C = sljit_create_compiler(NULL);+ struct sljit_jump *end;+ struct sljit_label *loop_start;+ struct sljit_jump *loop_end;++ int SP = SLJIT_S0; /* bf SP */+ int CELLS = SLJIT_S1; /* bf array */++ sljit_emit_enter(C, 0, SLJIT_ARGS2V(W, W), 2, 2, 0);+ /* opt arg R S local_size */++ /* SP = 0 */+ sljit_emit_op2(C, SLJIT_XOR, SP, 0, SP, 0, SP, 0);++ sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, BF_CELL_SIZE);+ sljit_emit_op1(C, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1);+ sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS2(P, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(my_alloc));/* calloc(BF_CELL_SIZE, 1) => R0 */++ end = sljit_emit_cmp(C, SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0); /* R0 == 0 --> jump end */++ sljit_emit_op1(C, SLJIT_MOV, CELLS, 0, SLJIT_R0, 0); /* CELLS = R0 */++ while ((chr = gettoken(src, &nchr)) != EOF) {+ switch (chr) {+ case '+':+ case '-':+ sljit_emit_op1(C, SLJIT_MOV_U8, SLJIT_R0, 0, SLJIT_MEM2(CELLS, SP), 0); /* R0 = CELLS[SP] */+ sljit_emit_op2(C, chr == '+' ? SLJIT_ADD : SLJIT_SUB, + SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, nchr); /* R0 ?= nchr */+ sljit_emit_op1(C, SLJIT_MOV_U8, SLJIT_MEM2(CELLS, SP), 0, SLJIT_R0, 0); /* CELLS[SP] = R0 */+ break;+ case '>':+ case '<':+ sljit_emit_op2(C, chr == '>' ? SLJIT_ADD : SLJIT_SUB, + SP, 0, SP, 0, SLJIT_IMM, nchr); /* SP ?= nchr */+ break;+ case '.':+ sljit_emit_op1(C, SLJIT_MOV_U8, SLJIT_R0, 0, SLJIT_MEM2(CELLS, SP), 0); /* R0 = CELLS[SP] */+ sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(my_putchar)); /* putchar(R0) */+ break;+ case ',':+ sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS0(W), SLJIT_IMM, SLJIT_FUNC_ADDR(my_getchar)); /* R0 = getchar() */+ sljit_emit_op1(C, SLJIT_MOV_U8, SLJIT_MEM2(CELLS, SP), 0, SLJIT_R0, 0); /* CELLS[SP] = R0 */+ break;+ case '[':+ loop_start = sljit_emit_label(C); /* loop_start: */+ sljit_emit_op1(C, SLJIT_MOV_U8, SLJIT_R0, 0, SLJIT_MEM2(CELLS, SP), 0); /* R0 = CELLS[SP] */+ loop_end = sljit_emit_cmp(C, SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0); /* IF R0 == 0 goto loop_end */+ + if (loop_push(loop_start, loop_end)) {+ fprintf(stderr, "Too many loop level\n");+ goto compile_failed;+ }+ break;+ case ']':+ if (loop_pop(&loop_start, &loop_end)) {+ fprintf(stderr, "Unmatch loop ]\n");+ goto compile_failed;+ }+ + sljit_set_label(sljit_emit_jump(C, SLJIT_JUMP), loop_start); /* goto loop_start */+ sljit_set_label(loop_end, sljit_emit_label(C)); /* loop_end: */+ break;+ }+ }++ if (!loop_empty()) {+ fprintf(stderr, "Unmatch loop [\n");+ goto compile_failed;+ }++ sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, CELLS, 0);+ sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(P, P), SLJIT_IMM, SLJIT_FUNC_ADDR(my_free)); /* free(CELLS) */++ sljit_set_label(end, sljit_emit_label(C));+ sljit_emit_return_void(C);++ code = sljit_generate_code(C, 0, NULL);+ if (lcode)+ *lcode = sljit_get_generated_code_size(C);++compile_failed:+ sljit_free_compiler(C);+ return code;+}++/* function prototype of bf compiled code */+typedef void (*bf_entry_t)(void);++int main(int argc, char **argv)+{+ void *code;+ bf_entry_t entry;+ FILE *fp;++ if (argc < 2) {+ fprintf(stderr, "Usage: %s <brainfuck program>\n", argv[0]);+ return -1;+ }++ fp = fopen(argv[1], "rb");+ if (!fp) {+ perror("open");+ return -1;+ }++ code = compile(fp, NULL);+ fclose(fp);++ if (!code) {+ fprintf(stderr, "[Fatal]: Compile failed\n");+ return -1;+ }++ entry = (bf_entry_t)code;+ entry();++ sljit_free_code(code, NULL);+ return 0;+}
+ src/c/pcre2/deps/sljit/docs/tutorial/sources/branch.c view
@@ -0,0 +1,77 @@+#include "sljitLir.h"++#include <stdio.h>+#include <stdlib.h>++typedef sljit_sw (SLJIT_FUNC *func3_t)(sljit_sw a, sljit_sw b, sljit_sw c);++/*+ This example, we generate a function like this:++sljit_sw func(sljit_sw a, sljit_sw b, sljit_sw c)+{+ if ((a & 1) == 0) + return c;+ return b;+}++ */+static int branch(sljit_sw a, sljit_sw b, sljit_sw c)+{+ void *code;+ sljit_uw len;+ func3_t func;++ struct sljit_jump *ret_c;+ struct sljit_jump *out;++ /* Create a SLJIT compiler */+ struct sljit_compiler *C = sljit_create_compiler(NULL);++ /* 3 arg, 1 temp reg, 3 save reg */+ sljit_emit_enter(C, 0, SLJIT_ARGS3(W, W, W, W), 1, 3, 0);++ /* R0 = a & 1, S0 is argument a */+ sljit_emit_op2(C, SLJIT_AND, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 1);++ /* if R0 == 0 then jump to ret_c, where is ret_c? we assign it later */+ ret_c = sljit_emit_cmp(C, SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0);++ /* R0 = b, S1 is argument b */+ sljit_emit_op1(C, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_S1, 0);++ /* jump to out */+ out = sljit_emit_jump(C, SLJIT_JUMP);++ /* here is the 'ret_c' should jump, we emit a label and set it to ret_c */+ sljit_set_label(ret_c, sljit_emit_label(C));++ /* R0 = c, S2 is argument c */+ sljit_emit_op1(C, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_S2, 0);++ /* here is the 'out' should jump */+ sljit_set_label(out, sljit_emit_label(C));++ /* end of function */+ sljit_emit_return(C, SLJIT_MOV, SLJIT_RETURN_REG, 0);++ /* Generate machine code */+ code = sljit_generate_code(C, 0, NULL);+ len = sljit_get_generated_code_size(C);++ /* Execute code */+ func = (func3_t)code;+ printf("func return %ld\n", (long)func(a, b, c));++ /* dump_code(code, len); */++ /* Clean up */+ sljit_free_compiler(C);+ sljit_free_code(code, NULL);+ return 0;+}++int main()+{+ return branch(4, 5, 6);+}
+ src/c/pcre2/deps/sljit/docs/tutorial/sources/first_program.c view
@@ -0,0 +1,59 @@+#include "sljitLir.h"++#include <stdio.h>+#include <stdlib.h>++typedef sljit_sw (SLJIT_FUNC *func3_t)(sljit_sw a, sljit_sw b, sljit_sw c);++static int add3(sljit_sw a, sljit_sw b, sljit_sw c)+{+ void *code;+ sljit_uw len;+ func3_t func;++ /* Create a SLJIT compiler */+ struct sljit_compiler *C = sljit_create_compiler(NULL);++ /* Start a context (function prologue) */+ sljit_emit_enter(C,+ 0, /* Options */+ SLJIT_ARGS3(W, W, W, W), /* 1 return value and 3 parameters of type sljit_sw */+ 1, /* 1 scratch register used */+ 3, /* 3 saved registers used */+ 0); /* 0 bytes allocated for function local variables */++ /* The first argument of a function is stored in register SLJIT_S0, the 2nd in SLJIT_S1, etc. */+ /* R0 = first */+ sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0);++ /* R0 = R0 + second */+ sljit_emit_op2(C, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S1, 0);++ /* R0 = R0 + third */+ sljit_emit_op2(C, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S2, 0);++ /* This statement moves R0 to RETURN REG and returns */+ /* (in fact, R0 is the RETURN REG itself) */+ sljit_emit_return(C, SLJIT_MOV, SLJIT_R0, 0);++ /* Generate machine code */+ code = sljit_generate_code(C, 0, NULL);+ len = sljit_get_generated_code_size(C);++ /* Execute code */+ func = (func3_t)code;+ printf("func return %ld\n", (long)func(a, b, c));++ /* dump_code(code, len); */++ /* Clean up */+ sljit_free_compiler(C);+ sljit_free_code(code, NULL);++ return 0;+}++int main()+{+ return add3(4, 5, 6);+}
+ src/c/pcre2/deps/sljit/docs/tutorial/sources/func_call.c view
@@ -0,0 +1,80 @@+#include "sljitLir.h"++#include <stdio.h>+#include <stdlib.h>++typedef sljit_sw (SLJIT_FUNC *func3_t)(sljit_sw a, sljit_sw b, sljit_sw c);++static sljit_sw SLJIT_FUNC print_num(sljit_sw a)+{+ printf("a = %ld\n", (long)a);+ return a + 1;+}++/*+ This example, we generate a function like this:++sljit_sw func(sljit_sw a, sljit_sw b, sljit_sw c)+{+ if ((a & 1) == 0) + return print_num(c);+ return print_num(b);+}+*/++static int func_call(sljit_sw a, sljit_sw b, sljit_sw c)+{+ void *code;+ sljit_uw len;+ func3_t func;++ struct sljit_jump *out;+ struct sljit_jump *print_c;++ /* Create a SLJIT compiler */+ struct sljit_compiler *C = sljit_create_compiler(NULL);++ sljit_emit_enter(C, 0, SLJIT_ARGS3(W, W, W, W), 3, 3, 0);++ /* a & 1 --> R0 */+ sljit_emit_op2(C, SLJIT_AND, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 1);+ /* R0 == 0 --> jump print_c */+ print_c = sljit_emit_cmp(C, SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0);++ /* R0 = S1; print_num(R0) */+ sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S1, 0);+ sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num));++ /* jump out */+ out = sljit_emit_jump(C, SLJIT_JUMP);+ /* print_c: */+ sljit_set_label(print_c, sljit_emit_label(C));++ /* R0 = c; print_num(R0); */+ sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S2, 0);+ sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num));++ /* out: */+ sljit_set_label(out, sljit_emit_label(C));+ sljit_emit_return(C, SLJIT_MOV, SLJIT_R0, 0);++ /* Generate machine code */+ code = sljit_generate_code(C, 0, NULL);+ len = sljit_get_generated_code_size(C);++ /* Execute code */+ func = (func3_t)code;+ printf("func return %ld\n", (long)func(a, b, c));++ /* dump_code(code, len); */++ /* Clean up */+ sljit_free_compiler(C);+ sljit_free_code(code, NULL);+ return 0;+}++int main()+{+ return func_call(4, 5, 6);+}
+ src/c/pcre2/deps/sljit/docs/tutorial/sources/loop.c view
@@ -0,0 +1,76 @@+#include "sljitLir.h"++#include <stdio.h>+#include <stdlib.h>++typedef sljit_sw (SLJIT_FUNC *func2_t)(sljit_sw a, sljit_sw b);++/*+ This example, we generate a function like this:++sljit_sw func(sljit_sw a, sljit_sw b)+{+ sljit_sw i;+ sljit_sw ret = 0;+ for (i = 0; i < a; ++i) {+ ret += b;+ }+ return ret;+}+*/++static int loop(sljit_sw a, sljit_sw b)+{+ void *code;+ sljit_uw len;+ func2_t func;++ struct sljit_label *loopstart;+ struct sljit_jump *out;++ /* Create a SLJIT compiler */+ struct sljit_compiler *C = sljit_create_compiler(NULL);++ /* 2 arg, 2 temp reg, 2 saved reg */+ sljit_emit_enter(C, 0, SLJIT_ARGS2(W, W, W), 2, 2, 0);++ /* R0 = 0 */+ sljit_emit_op2(C, SLJIT_XOR, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R1, 0);+ /* RET = 0 */+ sljit_emit_op1(C, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);+ /* loopstart: */+ loopstart = sljit_emit_label(C);+ /* R1 >= a --> jump out */+ out = sljit_emit_cmp(C, SLJIT_GREATER_EQUAL, SLJIT_R1, 0, SLJIT_S0, 0);+ /* RET += b */+ sljit_emit_op2(C, SLJIT_ADD, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0, SLJIT_S1, 0);+ /* R1 += 1 */+ sljit_emit_op2(C, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);+ /* jump loopstart */+ sljit_set_label(sljit_emit_jump(C, SLJIT_JUMP), loopstart);+ /* out: */+ sljit_set_label(out, sljit_emit_label(C));++ /* return RET */+ sljit_emit_return(C, SLJIT_MOV, SLJIT_RETURN_REG, 0);++ /* Generate machine code */+ code = sljit_generate_code(C, 0, NULL);+ len = sljit_get_generated_code_size(C);++ /* Execute code */+ func = (func2_t)code;+ printf("func return %ld\n", (long)func(a, b));++ /* dump_code(code, len); */++ /* Clean up */+ sljit_free_compiler(C);+ sljit_free_code(code, NULL);+ return 0;+}++int main()+{+ return loop(4, 5);+}
+ src/c/pcre2/deps/sljit/docs/tutorial/sources/struct_access.c view
@@ -0,0 +1,88 @@+#include "sljitLir.h"++#include <stdio.h>+#include <stdlib.h>++struct point_st {+ sljit_sw x;+ sljit_s32 y;+ sljit_s16 z;+ sljit_s8 d;+};++typedef sljit_sw (SLJIT_FUNC *point_func_t)(struct point_st *point);++static sljit_sw SLJIT_FUNC print_num(sljit_sw a)+{+ printf("a = %ld\n", (long)a);+ return a + 1;+}++/*+ This example, we generate a function like this:++sljit_sw func(struct point_st *point)+{+ print_num(point->x);+ print_num(point->y);+ print_num(point->z);+ print_num(point->d);+ return point->x;+}+*/++static int struct_access()+{+ void *code;+ sljit_uw len;+ point_func_t func;++ struct point_st point = {+ -5, -20, 5, 'a'+ };++ /* Create a SLJIT compiler */+ struct sljit_compiler *C = sljit_create_compiler(NULL);++ sljit_emit_enter(C, 0, SLJIT_ARGS1(W, W), 1, 1, 0);+ /* opt arg R S local_size */++ /* S0->x --> R0; print_num(R0) */+ sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct point_st, x));+ sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, P), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num));++ /* S0->y --> R0; print_num(R0) */+ sljit_emit_op1(C, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct point_st, y));+ sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, P), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num));++ /* S0->z --> R0; print_num(R0) */+ sljit_emit_op1(C, SLJIT_MOV_S16, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct point_st, z));+ sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, P), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num));++ /* S0->d --> R0; print_num(R0) */+ sljit_emit_op1(C, SLJIT_MOV_S8, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct point_st, d));+ sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, P), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num));++ /* return S0->x */+ sljit_emit_return(C, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct point_st, x));++ /* Generate machine code */+ code = sljit_generate_code(C, 0, NULL);+ len = sljit_get_generated_code_size(C);++ /* Execute code */+ func = (point_func_t)code;+ printf("func return %ld\n", (long)func(&point));++ /* dump_code(code, len); */++ /* Clean up */+ sljit_free_compiler(C);+ sljit_free_code(code, NULL);+ return 0;+}++int main()+{+ return struct_access();+}
+ src/c/pcre2/deps/sljit/docs/tutorial/sources/temp_var.c view
@@ -0,0 +1,74 @@+#include "sljitLir.h"++#include <stdio.h>+#include <stdlib.h>++typedef sljit_sw (SLJIT_FUNC *func3_t)(sljit_sw a, sljit_sw b, sljit_sw c);++static sljit_sw SLJIT_FUNC print_arr(sljit_sw *a, sljit_sw n)+{+ sljit_sw i;+ sljit_sw sum = 0;+ for (i = 0; i < n; ++i) {+ sum += a[i];+ printf("arr[%ld] = %ld\n", (long)i, (long)a[i]);+ }+ return sum;+}++/*+ This example, we generate a function like this:++sljit_sw func(sljit_sw a, sljit_sw b, sljit_sw c)+{+ sljit_sw arr[3] = { a, b, c };+ return print_arr(arr, 3);+}+*/++static int temp_var(sljit_sw a, sljit_sw b, sljit_sw c)+{+ void *code;+ sljit_uw len;+ func3_t func;++ /* Create a SLJIT compiler */+ struct sljit_compiler *C = sljit_create_compiler(NULL);++ /* reserved space in stack for sljit_sw arr[3] */+ sljit_emit_enter(C, 0, SLJIT_ARGS3(W, W, W, W), 2, 3, 3 * sizeof(sljit_sw));+ /* opt arg R S local_size */++ /* arr[0] = S0, SLJIT_SP is the init address of local var */+ sljit_emit_op1(C, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_S0, 0);+ /* arr[1] = S1 */+ sljit_emit_op1(C, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 1 * sizeof(sljit_sw), SLJIT_S1, 0);+ /* arr[2] = S2 */+ sljit_emit_op1(C, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_sw), SLJIT_S2, 0);++ /* R0 = arr; in fact SLJIT_SP is the address of arr, but can't do so in SLJIT */+ sljit_get_local_base(C, SLJIT_R0, 0, 0); /* get the address of local variables */+ sljit_emit_op1(C, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 3); /* R1 = 3; */+ sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS2(W, P, W), SLJIT_IMM, SLJIT_FUNC_ADDR(print_arr));+ sljit_emit_return(C, SLJIT_MOV, SLJIT_R0, 0);++ /* Generate machine code */+ code = sljit_generate_code(C, 0, NULL);+ len = sljit_get_generated_code_size(C);++ /* Execute code */+ func = (func3_t)code;+ printf("func return %ld\n", (long)func(a, b, c));++ /* dump_code(code, len); */++ /* Clean up */+ sljit_free_compiler(C);+ sljit_free_code(code, NULL);+ return 0;+}++int main()+{+ return temp_var(7, 8, 9);+}
+ src/c/pcre2/deps/sljit/regex_src/regexJIT.c view
@@ -0,0 +1,2595 @@+/*+ * 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 "sljitLir.h"+#include "regexJIT.h"++#include <stdlib.h>++#ifdef REGEX_MATCH_VERBOSE+#include <stdio.h>+#endif++/* Extra, hidden flags:+ {id!} where id > 0 found in the code. */+#define REGEX_ID_CHECK 0x100+/* When REGEX_NEWLINE && REGEX_MATCH_BEGIN defined, the pattern turn to a normal search,+ which starts with [\r\n] character range. */+#define REGEX_FAKE_MATCH_BEGIN 0x200+/* When REGEX_NEWLINE && REGEX_MATCH_END defined, the pattern turn to a normal search,+ which ends with [\r\n] character range. */+#define REGEX_FAKE_MATCH_END 0x400++/* --------------------------------------------------------------------- */+/* Structures for JIT-ed pattern matching */+/* --------------------------------------------------------------------- */++struct regex_machine+{+ /* flags. */+ int flags;+ /* Number of state descriptors for one term. */+ sljit_sw no_states;+ /* Total size. */+ sljit_sw size;++ union {+ void *init_match;+ sljit_sw (SLJIT_FUNC *call_init)(void *next, void* match);+ } u;+#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)+ struct sljit_function_context context;+#endif++ void *continue_match;++ /* Variable sized array to contain the handler addresses. */+ sljit_uw entry_addrs[1];+};++struct regex_match+{+ /* Current and next state array. */+ sljit_sw *current;+ sljit_sw *next;+ /* Starting. */+ sljit_sw head;+ /* String character index (ever increasing). */+ sljit_sw index;+ /* Best match found so far (members in priority order). */+ sljit_sw best_begin;+ sljit_sw best_end;+ sljit_sw best_id;+ /* Bool flags (encoded as word). */+ sljit_sw fast_quit;+ sljit_sw fast_forward;+ /* Machine. */+ struct regex_machine *machine;++ union {+ void *continue_match;+ void (SLJIT_FUNC *call_continue)(struct regex_match *match, const regex_char_t *input_string, int length);+ } u;++ /* Variable sized array to contain the state arrays. */+ sljit_sw states[1];+};++/* State vector+ ITEM[0] - pointer to the address inside the machine code+ ITEM[1] - next pointer+ ITEM[2] - string started from (optional)+ ITEM[3] - max ID (optional) */++/* Register allocation. */+/* Current state array (loaded & stored: regex_match->current). */+#define R_CURR_STATE SLJIT_S0+/* Next state array (loaded & stored: regex_match->next). */+#define R_NEXT_STATE SLJIT_S1+/* Head (loaded & stored: regex_match->head). */+#define R_NEXT_HEAD SLJIT_S2+/* String fragment pointer. */+#define R_STRING SLJIT_S3+/* String fragment length. */+#define R_LENGTH SLJIT_S4+/* 'struct regex_match*' */+#define R_REGEX_MATCH SLJIT_R0+/* Current character. */+#define R_CURR_CHAR SLJIT_R1+/* Temporary register. */+#define R_TEMP SLJIT_R2+/* Caches the regex_match->best_begin. */+#define R_BEST_BEGIN SLJIT_R3+/* Current character index. */+#define R_CURR_INDEX SLJIT_R4++/* --------------------------------------------------------------------- */+/* Stack management */+/* --------------------------------------------------------------------- */++/* Try to allocate 2^n blocks. */+#define STACK_FRAGMENT_SIZE (((64 * sizeof(struct stack_item)) - (sizeof(struct stack_fragment_data))) / (sizeof(struct stack_item)))++struct stack_item {+ int type;+ int value;+};++struct stack_fragment_data {+ struct stack_fragment *next;+ struct stack_fragment *prev;+};++struct stack_fragment {+ struct stack_fragment_data data;+ struct stack_item items[STACK_FRAGMENT_SIZE];+};++struct stack {+ struct stack_fragment *first;+ struct stack_fragment *last;+ sljit_uw index;+ sljit_uw count;+};++#if (defined SLJIT_DEBUG && SLJIT_DEBUG)++static void stack_check(struct stack *stack)+{+ struct stack_fragment *curr;+ int found;++ if (!stack)+ return;++ SLJIT_ASSERT(stack->index < STACK_FRAGMENT_SIZE);++ if (stack->first == NULL) {+ SLJIT_ASSERT(stack->first == NULL && stack->last == NULL);+ SLJIT_ASSERT(stack->index == STACK_FRAGMENT_SIZE - 1 && stack->count == 0);+ return;+ }++ found = 0;+ if (stack->last == NULL) {+ SLJIT_ASSERT(stack->index == STACK_FRAGMENT_SIZE - 1 && stack->count == 0);+ found = 1;+ }++ SLJIT_ASSERT(stack->first->data.prev == NULL);+ curr = stack->first;+ while (curr) {+ if (curr == stack->last)+ found = 1;+ if (curr->data.next)+ SLJIT_ASSERT(curr->data.next->data.prev == curr);+ curr = curr->data.next;+ }+ SLJIT_ASSERT(found);+}++#endif++static void stack_init(struct stack *stack)+{+ stack->first = NULL;+ stack->last = NULL;+ stack->index = STACK_FRAGMENT_SIZE - 1;+ stack->count = 0;+}++static void stack_destroy(struct stack *stack)+{+ struct stack_fragment *curr = stack->first;+ struct stack_fragment *prev;++#if (defined SLJIT_DEBUG && SLJIT_DEBUG)+ stack_check(stack);+#endif++ while (curr) {+ prev = curr;+ curr = curr->data.next;+ SLJIT_FREE(prev, NULL);+ }+}++static SLJIT_INLINE struct stack_item* stack_top(struct stack *stack)+{+ SLJIT_ASSERT(stack->last);+ return stack->last->items + stack->index;+}++static int stack_push(struct stack *stack, int type, int value)+{+ if (stack->last) {+ stack->index++;+ if (stack->index >= STACK_FRAGMENT_SIZE) {+ stack->index = 0;+ if (!stack->last->data.next) {+ stack->last->data.next = (struct stack_fragment*)SLJIT_MALLOC(sizeof(struct stack_fragment), NULL);+ if (!stack->last->data.next)+ return 1;+ stack->last->data.next->data.next = NULL;+ stack->last->data.next->data.prev = stack->last;+ }+ stack->last = stack->last->data.next;+ }+ }+ else if (!stack->first) {+ stack->last = (struct stack_fragment*)SLJIT_MALLOC(sizeof(struct stack_fragment), NULL);+ if (!stack->last)+ return 1;+ stack->last->data.prev = NULL;+ stack->last->data.next = NULL;+ stack->first = stack->last;+ stack->index = 0;+ }+ else {+ stack->last = stack->first;+ stack->index = 0;+ }+ stack->last->items[stack->index].type = type;+ stack->last->items[stack->index].value = value;+ stack->count++;+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)+ stack_check(stack);+#endif+ return 0;+}++static struct stack_item* stack_pop(struct stack *stack)+{+ struct stack_item *ret = stack_top(stack);++ if (stack->index > 0)+ stack->index--;+ else {+ stack->last = stack->last->data.prev;+ stack->index = STACK_FRAGMENT_SIZE - 1;+ }++ stack->count--;+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)+ stack_check(stack);+#endif+ return ret;+}++static SLJIT_INLINE void stack_clone(struct stack *src, struct stack *dst)+{+ *dst = *src;+}++static int stack_push_copy(struct stack *stack, int items, int length)+{+ struct stack_fragment *frag1;+ struct stack_fragment *frag2;+ sljit_uw ind1, ind2;+ sljit_uw counter;++ SLJIT_ASSERT(stack->count >= (sljit_uw)length && items <= length && items > 0);++ /* Allocate the necessary elements. */+ counter = (sljit_uw)items;+ frag1 = stack->last;+ ind1 = stack->index;+ while (counter > 0) {+ if (stack->index + counter >= STACK_FRAGMENT_SIZE) {+ SLJIT_ASSERT(counter >= STACK_FRAGMENT_SIZE - stack->index - 1 + 1);+ counter -= STACK_FRAGMENT_SIZE - stack->index - 1 + 1;+ stack->index = 0;+ if (!stack->last->data.next) {+ stack->last->data.next = (struct stack_fragment*)SLJIT_MALLOC(sizeof(struct stack_fragment), NULL);+ if (!stack->last->data.next)+ return 1;+ stack->last->data.next->data.next = NULL;+ stack->last->data.next->data.prev = stack->last;+ }+ stack->last = stack->last->data.next;+ }+ else {+ stack->index += counter;+ counter = 0;+ }+ }++ frag2 = stack->last;+ ind2 = stack->index;+ while (length > 0) {+ frag2->items[ind2] = frag1->items[ind1];++ if (ind1 == 0) {+ ind1 = STACK_FRAGMENT_SIZE;+ frag1 = frag1->data.prev;+ }+ if (ind2 == 0) {+ ind2 = STACK_FRAGMENT_SIZE;+ frag2 = frag2->data.prev;+ }++ ind1--;+ ind2--;+ length--;+ }++#if (defined SLJIT_DEBUG && SLJIT_DEBUG)+ stack_check(stack);+#endif+ stack->count += (sljit_uw)items;+ return 0;+}++/* --------------------------------------------------------------------- */+/* Parser */+/* --------------------------------------------------------------------- */++enum {+ /* Common. */+ type_begin,+ type_end,+ type_char,+ type_newline,+ type_id,+ type_rng_start,+ type_rng_end,+ type_rng_char,+ type_rng_left,+ type_rng_right,++ /* generator only. */+ type_branch,+ type_jump,++ /* Parser only. */+ type_open_br,+ type_close_br,+ type_select,+ type_asterisk,+ type_plus_sign,+ type_qestion_mark+};++struct compiler_common {+ /* Temporary stacks. */+ struct stack stack;+ struct stack depth;+ /* REGEX_ flags. */+ int flags;+ /* Encoded size of the dfa representation. */+ sljit_uw dfa_size;+ /* Number of terms. */+ sljit_sw terms_size;+ /* Number of state descriptors for one term (same as machine->no_states). */+ sljit_sw no_states;+ /* Number of type_rng_(char|left)-s in the longest character range. */+ sljit_sw longest_range_size;++ /* DFA linear representation (size: dfa_size). */+ struct stack_item *dfa_transitions;+ /* Term id and search state pairs (size: dfa_size). */+ struct stack_item *search_states;++ /* sljit compiler */+ struct sljit_compiler *compiler;+ /* Machine data, which must be kept for later use. */+ struct regex_machine *machine;+ /* Temporary space for jumps (size: longest_range_size). */+ struct sljit_jump **range_jump_list;+};++static const regex_char_t* decode_number(const regex_char_t *regex_string, int length, int *result)+{+ int value = 0;++ SLJIT_ASSERT(length > 0);+ if (*regex_string < '0' || *regex_string > '9') {+ *result = -1;+ return regex_string;+ }++ while (length > 0 && *regex_string >= '0' && *regex_string <= '9') {+ value = value * 10 + (*regex_string - '0');+ length--;+ regex_string++;+ }++ *result = value;+ return regex_string;+}++static int iterate(struct stack *stack, int min, int max)+{+ struct stack it;+ struct stack_item *item;+ int count = -1;+ int len = 0;+ int depth = 0;++ stack_clone(stack, &it);++ /* Calculate size. */+ while (count < 0) {+ item = stack_pop(&it);+ switch (item->type) {+ case type_id:+ case type_rng_end:+ case type_rng_char:+ case type_rng_left:+ case type_rng_right:+ case type_plus_sign:+ case type_qestion_mark:+ len++;+ break;++ case type_asterisk:+ len += 2;+ break;++ case type_close_br:+ depth++;+ break;++ case type_open_br:+ SLJIT_ASSERT(depth > 0);+ depth--;+ if (depth == 0)+ count = (int)it.count;+ break;++ case type_select:+ SLJIT_ASSERT(depth > 0);+ len += 2;+ break;++ default:+ SLJIT_ASSERT(item->type != type_begin && item->type != type_end);+ if (depth == 0)+ count = (int)it.count;+ len++;+ break;+ }+ }++ if (min == 0 && max == 0) {+ /* {0,0} case, not {0,} case: delete subtree. */+ stack_clone(&it, stack);+ /* and put an empty bracket expression instead of it. */+ if (stack_push(stack, type_open_br, 0))+ return REGEX_MEMORY_ERROR;+ if (stack_push(stack, type_close_br, 0))+ return REGEX_MEMORY_ERROR;+ return len;+ }++ count = (int)stack->count - count;++ /* Put an open bracket before the sequence. */+ if (stack_push_copy(stack, 1, count))+ return -1;++#if (defined SLJIT_DEBUG && SLJIT_DEBUG)+ SLJIT_ASSERT(stack_push(&it, type_open_br, 0) == 0);+#else+ stack_push(&it, type_open_br, 0);+#endif++ /* Copy the data. */+ if (max > 0) {+ len = len * (max - 1);+ max -= min;+ /* Insert ? operators. */+ len += max;++ if (min > 0) {+ min--;+ while (min > 0) {+ if (stack_push_copy(stack, count, count))+ return -1;+ min--;+ }+ if (max > 0) {+ if (stack_push_copy(stack, count, count))+ return -1;+ if (stack_push(stack, type_qestion_mark, 0))+ return REGEX_MEMORY_ERROR;+ count++;+ max--;+ }+ }+ else {+ SLJIT_ASSERT(max > 0);+ max--;+ count++;+ if (stack_push(stack, type_qestion_mark, 0))+ return REGEX_MEMORY_ERROR;+ }++ while (max > 0) {+ if (stack_push_copy(stack, count, count))+ return -1;+ max--;+ }+ }+ else {+ SLJIT_ASSERT(min > 0);+ min--;+ /* Insert + operator. */+ len = len * min + 1;+ while (min > 0) {+ if (stack_push_copy(stack, count, count))+ return -1;+ min--;+ }++ if (stack_push(stack, type_plus_sign, 0))+ return REGEX_MEMORY_ERROR;+ }++ /* Close the opened bracket. */+ if (stack_push(stack, type_close_br, 0))+ return REGEX_MEMORY_ERROR;++ return len;+}++static int parse_iterator(const regex_char_t *regex_string, int length, struct stack *stack, sljit_uw *dfa_size, int begin)+{+ /* We only know that *regex_string == { . */+ int val1, val2;+ const regex_char_t *base_from = regex_string;+ const regex_char_t *from;++ length--;+ regex_string++;++ /* Decode left value. */+ val2 = -1;+ if (length == 0)+ return -2;+ if (*regex_string == ',') {+ val1 = 0;+ length--;+ regex_string++;+ }+ else {+ from = regex_string;+ regex_string = decode_number(regex_string, length, &val1);+ if (val1 < 0)+ return -2;+ length -= (int)(regex_string - from);++ if (length == 0)+ return -2;+ if (*regex_string == '}') {+ val2 = val1;+ if (val1 == 0)+ val1 = -1;+ }+ else if (length >= 2 && *regex_string == '!' && regex_string[1] == '}') {+ /* Non posix extension. */+ if (stack_push(stack, type_id, val1))+ return -1;+ (*dfa_size)++;+ return (int)(regex_string - base_from) + 1;+ }+ else {+ if (*regex_string != ',')+ return -2;+ length--;+ regex_string++;+ }+ }++ if (begin)+ return -2;++ /* Decode right value. */+ if (val2 == -1) {+ if (length == 0)+ return -2;+ if (*regex_string == '}')+ val2 = 0;+ else {+ from = regex_string;+ regex_string = decode_number(regex_string, length, &val2);+ length -= (int)(regex_string - from);+ if (val2 < 0 || length == 0 || *regex_string != '}' || val2 < val1)+ return -2;+ if (val2 == 0) {+ SLJIT_ASSERT(val1 == 0);+ val1 = -1;+ }+ }+ }++ /* Fast cases. */+ if (val1 > 1 || val2 > 1) {+ val1 = iterate(stack, val1, val2);+ if (val1 < 0)+ return -1;+ *dfa_size += (sljit_uw)val1;+ }+ else if (val1 == 0 && val2 == 0) {+ if (stack_push(stack, type_asterisk, 0))+ return -1;+ *dfa_size += 2;+ }+ else if (val1 == 1 && val2 == 0) {+ if (stack_push(stack, type_plus_sign, 0))+ return -1;+ (*dfa_size)++;+ }+ else if (val1 == 0 && val2 == 1) {+ if (stack_push(stack, type_qestion_mark, 0))+ return -1;+ (*dfa_size)++;+ }+ else if (val1 == -1) {+ val1 = iterate(stack, 0, 0);+ if (val1 < 0)+ return -1;+ *dfa_size -= (sljit_uw)val1;+ SLJIT_ASSERT(*dfa_size >= 2);+ }+ else {+ /* Ignore. */+ SLJIT_ASSERT(val1 == 1 && val2 == 1);+ }+ return (int)(regex_string - base_from);+}++static int parse_char_range(const regex_char_t *regex_string, int length, struct compiler_common *compiler_common)+{+ struct stack* stack = &compiler_common->stack;+ const regex_char_t *base_from = regex_string;+ regex_char_t left_char, right_char, tmp_char;++ length--;+ regex_string++;++ if (length == 0)+ return -2;++ if (*regex_string != '^') {+ if (stack_push(stack, type_rng_start, 0))+ return -1;+ }+ else {+ length--;+ regex_string++;++ if (length == 0)+ return -2;++ if (stack_push(stack, type_rng_start, 1))+ return -1;+ }+ /* For both the type_rng_start & type_rng_end. */+ compiler_common->dfa_size += 2;++ /* Range must be at least 1 character. */+ if (*regex_string == ']') {+ length--;+ regex_string++;+ if (stack_push(stack, type_rng_char, ']'))+ return -1;+ compiler_common->dfa_size++;+ }++ while (1) {+ if (length == 0)+ return -2;++ if (*regex_string == ']')+ break;++ if (*regex_string != '\\')+ left_char = *regex_string;+ else {+ regex_string++;+ length--;+ if (length == 0)+ return -2;+ left_char = *regex_string;+ }+ regex_string++;+ length--;++ /* Is a range here? */+ if (length >= 3 && *regex_string == '-' && *(regex_string + 1) != ']') {+ regex_string++;+ length--;++ if (*regex_string != '\\')+ right_char = *regex_string;+ else {+ regex_string++;+ length--;+ if (length == 0)+ return -2;+ right_char = *regex_string;+ }+ regex_string++;+ length--;++ if (left_char > right_char) {+ /* Swap if necessary. */+ tmp_char = left_char;+ left_char = right_char;+ right_char = tmp_char;+ }++ if (stack_push(stack, type_rng_left, left_char))+ return -1;+ if (stack_push(stack, type_rng_right, right_char))+ return -1;+ compiler_common->dfa_size += 2;+ }+ else {+ if (stack_push(stack, type_rng_char, left_char))+ return -1;+ compiler_common->dfa_size++;+ }+ }++ if (stack_push(stack, type_rng_end, 0))+ return -1;+ return (int)(regex_string - base_from);+}++static int parse(const regex_char_t *regex_string, int length, struct compiler_common *compiler_common)+{+ /* Depth of bracketed expressions. */+ int depth = 0;+ /* Have we already found a term? '1' if not yet. */+ int begin = 1;+ /* Cache stack pointer. */+ struct stack* stack = &compiler_common->stack;+ int tmp;++ /* Type_begin and type_end. */+ compiler_common->dfa_size = 2;+ stack_init(stack);+ if (stack_push(stack, type_begin, 0))+ return REGEX_MEMORY_ERROR;++ if (length > 0 && *regex_string == '^') {+ compiler_common->flags |= REGEX_MATCH_BEGIN;+ length--;+ regex_string++;+ }++ if ((compiler_common->flags & (REGEX_MATCH_BEGIN | REGEX_NEWLINE)) == (REGEX_MATCH_BEGIN | REGEX_NEWLINE)) {+ /* Replace REGEX_MATCH_BEGIN flag to REGEX_FAKE_MATCH_BEGIN */+ compiler_common->flags &= ~REGEX_MATCH_BEGIN;+ compiler_common->flags |= REGEX_FAKE_MATCH_BEGIN;+ /* and append a new-line search. */+ if (stack_push(stack, type_newline, 0))+ return REGEX_MEMORY_ERROR;+ compiler_common->dfa_size++;+ /* Begin intentionally kept as 1. */+ }++ while (length > 0) {+ switch (*regex_string) {+ case '\\' :+ length--;+ regex_string++;+ if (length == 0)+ return REGEX_INVALID_REGEX;+ if (stack_push(stack, type_char, *regex_string))+ return REGEX_MEMORY_ERROR;+ begin = 0;+ compiler_common->dfa_size++;+ break;++ case '.' :+ if (stack_push(stack, type_rng_start, 1))+ return REGEX_MEMORY_ERROR;+ if (compiler_common->flags & REGEX_NEWLINE) {+ if (stack_push(stack, type_rng_char, '\n'))+ return REGEX_MEMORY_ERROR;+ if (stack_push(stack, type_rng_char, '\r'))+ return REGEX_MEMORY_ERROR;+ compiler_common->dfa_size += 2;+ }+ if (stack_push(stack, type_rng_end, 1))+ return REGEX_MEMORY_ERROR;+ begin = 0;+ compiler_common->dfa_size += 2;+ break;++ case '(' :+ depth++;+ if (stack_push(stack, type_open_br, 0))+ return REGEX_MEMORY_ERROR;+ begin = 1;+ break;++ case ')' :+ if (depth == 0)+ return REGEX_INVALID_REGEX;+ depth--;+ if (stack_push(stack, type_close_br, 0))+ return REGEX_MEMORY_ERROR;+ begin = 0;+ break;++ case '|' :+ if (stack_push(stack, type_select, 0))+ return REGEX_MEMORY_ERROR;+ begin = 1;+ compiler_common->dfa_size += 2;+ break;++ case '*' :+ if (begin)+ return REGEX_INVALID_REGEX;+ if (stack_push(stack, type_asterisk, 0))+ return REGEX_MEMORY_ERROR;+ compiler_common->dfa_size += 2;+ break;++ case '?' :+ case '+' :+ if (begin)+ return REGEX_INVALID_REGEX;+ if (stack_push(stack, (*regex_string == '+') ? type_plus_sign : type_qestion_mark, 0))+ return REGEX_MEMORY_ERROR;+ compiler_common->dfa_size++;+ break;++ case '{' :+ tmp = parse_iterator(regex_string, length, stack, &compiler_common->dfa_size, begin);++ if (tmp >= 0) {+ length -= tmp;+ regex_string += tmp;+ }+ else if (tmp == -1)+ return REGEX_MEMORY_ERROR;+ else {+ /* Not a valid range expression. */+ SLJIT_ASSERT(tmp == -2);+ if (stack_push(stack, type_char, '{'))+ return REGEX_MEMORY_ERROR;+ compiler_common->dfa_size++;+ }+ break;++ case '[' :+ tmp = parse_char_range(regex_string, length, compiler_common);+ if (tmp >= 0) {+ length -= tmp;+ regex_string += tmp;+ }+ else if (tmp == -1)+ return REGEX_MEMORY_ERROR;+ else {+ SLJIT_ASSERT(tmp == -2);+ return REGEX_INVALID_REGEX;+ }+ begin = 0;+ break;++ default:+ if (length == 1 && *regex_string == '$') {+ compiler_common->flags |= REGEX_MATCH_END;+ break;+ }+ if (stack_push(stack, type_char, *regex_string))+ return REGEX_MEMORY_ERROR;+ begin = 0;+ compiler_common->dfa_size++;+ break;+ }+ length--;+ regex_string++;+ }++ if (depth != 0)+ return REGEX_INVALID_REGEX;++ if ((compiler_common->flags & (REGEX_MATCH_END | REGEX_NEWLINE)) == (REGEX_MATCH_END | REGEX_NEWLINE)) {+ /* Replace REGEX_MATCH_END flag to REGEX_FAKE_MATCH_END */+ compiler_common->flags &= ~REGEX_MATCH_END;+ compiler_common->flags |= REGEX_FAKE_MATCH_END;+ /* and append a new-line search. */+ if (stack_push(stack, type_newline, 1))+ return REGEX_MEMORY_ERROR;+ compiler_common->dfa_size++;+ /* Begin intentionally kept as 1. */+ }++ if (stack_push(stack, type_end, 0))+ return REGEX_MEMORY_ERROR;++ return REGEX_NO_ERROR;+}++/* --------------------------------------------------------------------- */+/* Generating machine state transitions */+/* --------------------------------------------------------------------- */++#define PUT_TRANSITION(typ, val) \+ do { \+ --transitions_ptr; \+ transitions_ptr->type = typ; \+ transitions_ptr->value = val; \+ } while (0)++static struct stack_item* handle_iteratives(struct stack_item *transitions_ptr, struct stack_item *transitions, struct stack *depth)+{+ struct stack_item *item;++ while (1) {+ item = stack_top(depth);++ switch (item->type) {+ case type_asterisk:+ SLJIT_ASSERT(transitions[item->value].type == type_branch);+ transitions[item->value].value = (int)(transitions_ptr - transitions);+ PUT_TRANSITION(type_branch, item->value + 1);+ break;++ case type_plus_sign:+ SLJIT_ASSERT(transitions[item->value].type == type_branch);+ transitions[item->value].value = (int)(transitions_ptr - transitions);+ break;++ case type_qestion_mark:+ PUT_TRANSITION(type_branch, item->value);+ break;++ default:+ return transitions_ptr;+ }+ stack_pop(depth);+ }+}++static int generate_transitions(struct compiler_common *compiler_common)+{+ struct stack *stack = &compiler_common->stack;+ struct stack *depth = &compiler_common->depth;+ struct stack_item *transitions_ptr;+ struct stack_item *item;++ stack_init(depth);+ compiler_common->dfa_transitions = (struct stack_item *)SLJIT_MALLOC(sizeof(struct stack_item) * compiler_common->dfa_size, NULL);+ if (!compiler_common->dfa_transitions)+ return REGEX_MEMORY_ERROR;++ /* Go through the items of the stack and generate the necessary branches and jumps (edges of DFA). */+ transitions_ptr = compiler_common->dfa_transitions + compiler_common->dfa_size;+ while (stack->count > 0) {+ item = stack_pop(stack);+ switch (item->type) {+ case type_begin:+ case type_open_br:+ item = stack_pop(depth);+ if (item->type == type_select)+ PUT_TRANSITION(type_branch, item->value + 1);+ else+ SLJIT_ASSERT(item->type == type_close_br);+ if (stack->count == 0)+ PUT_TRANSITION(type_begin, 0);+ else+ transitions_ptr = handle_iteratives(transitions_ptr, compiler_common->dfa_transitions, depth);+ break;++ case type_end:+ case type_close_br:+ if (item->type == type_end)+ *--transitions_ptr = *item;+ if (stack_push(depth, type_close_br, (int)(transitions_ptr - compiler_common->dfa_transitions)))+ return REGEX_MEMORY_ERROR;+ break;++ case type_select:+ item = stack_top(depth);+ if (item->type == type_select) {+ SLJIT_ASSERT(compiler_common->dfa_transitions[item->value].type == type_jump);+ PUT_TRANSITION(type_branch, item->value + 1);+ PUT_TRANSITION(type_jump, item->value);+ item->value = (int)(transitions_ptr - compiler_common->dfa_transitions);+ }+ else {+ SLJIT_ASSERT(item->type == type_close_br);+ item->type = type_select;+ PUT_TRANSITION(type_jump, item->value);+ item->value = (int)(transitions_ptr - compiler_common->dfa_transitions);+ }+ break;++ case type_asterisk:+ case type_plus_sign:+ case type_qestion_mark:+ if (item->type != type_qestion_mark)+ PUT_TRANSITION(type_branch, 0);+ if (stack_push(depth, item->type, (int)(transitions_ptr - compiler_common->dfa_transitions)))+ return REGEX_MEMORY_ERROR;+ break;++ case type_char:+ case type_newline:+ case type_rng_start:+ /* Requires handle_iteratives. */+ *--transitions_ptr = *item;+ transitions_ptr = handle_iteratives(transitions_ptr, compiler_common->dfa_transitions, depth);+ break;++ default:+ *--transitions_ptr = *item;+ break;+ }+ }++ SLJIT_ASSERT(compiler_common->dfa_transitions == transitions_ptr);+ SLJIT_ASSERT(depth->count == 0);+ return REGEX_NO_ERROR;+}++#undef PUT_TRANSITION++#ifdef REGEX_MATCH_VERBOSE++static void verbose_transitions(struct compiler_common *compiler_common)+{+ struct stack_item *transitions_ptr = compiler_common->dfa_transitions;+ struct stack_item *transitions_end = transitions_ptr + compiler_common->dfa_size;+ struct stack_item *search_states_ptr = compiler_common->search_states;+ int pos;++ printf("-----------------\nTransitions\n-----------------\n");+ pos = 0;+ while (transitions_ptr < transitions_end) {+ printf("[%3d] ", pos++);+ if (search_states_ptr->type >= 0)+ printf("(%3d) ", search_states_ptr->type);+ switch (transitions_ptr->type) {+ case type_begin:+ printf("type_begin\n");+ break;++ case type_end:+ printf("type_end\n");+ break;++ case type_char:+ if (transitions_ptr->value >= ' ')+ printf("type_char '%c'\n", transitions_ptr->value);+ else+ printf("type_char 0x%x\n", transitions_ptr->value);+ break;++ case type_newline:+ printf("type_newline %s\n", transitions_ptr->value ? "(end)" : "(begin)");+ break;++ case type_id:+ printf("type_id %d\n", transitions_ptr->value);+ break;++ case type_rng_start:+ printf("type_rng_start %s\n", transitions_ptr->value ? "(invert)" : "(normal)");+ break;++ case type_rng_end:+ printf("type_rng_end\n");+ break;++ case type_rng_char:+ if (transitions_ptr->value >= ' ')+ printf("type_rng_char '%c'\n", transitions_ptr->value);+ else+ printf("type_rng_char 0x%x\n", transitions_ptr->value);+ break;++ case type_rng_left:+ if (transitions_ptr->value >= ' ')+ printf("type_rng_left '%c'\n", transitions_ptr->value);+ else+ printf("type_rng_left 0x%x\n", transitions_ptr->value);+ break;++ case type_rng_right:+ if (transitions_ptr->value >= ' ')+ printf("type_rng_right '%c'\n", transitions_ptr->value);+ else+ printf("type_rng_right 0x%x\n", transitions_ptr->value);+ break;++ case type_branch:+ printf("type_branch -> %d\n", transitions_ptr->value);+ break;++ case type_jump:+ printf("type_jump -> %d\n", transitions_ptr->value);+ break;++ default:+ printf("UNEXPECTED TYPE\n");+ break;+ }+ transitions_ptr++;+ search_states_ptr++;+ }+ printf("flags: ");+ if (!(compiler_common->flags & (REGEX_MATCH_BEGIN | REGEX_MATCH_END | REGEX_NEWLINE | REGEX_ID_CHECK | REGEX_FAKE_MATCH_BEGIN | REGEX_FAKE_MATCH_END)))+ printf("none ");+ if (compiler_common->flags & REGEX_MATCH_BEGIN)+ printf("REGEX_MATCH_BEGIN ");+ if (compiler_common->flags & REGEX_MATCH_END)+ printf("REGEX_MATCH_END ");+ if (compiler_common->flags & REGEX_NEWLINE)+ printf("REGEX_NEWLINE ");+ if (compiler_common->flags & REGEX_ID_CHECK)+ printf("REGEX_ID_CHECK ");+ if (compiler_common->flags & REGEX_FAKE_MATCH_BEGIN)+ printf("REGEX_FAKE_MATCH_BEGIN ");+ if (compiler_common->flags & REGEX_FAKE_MATCH_END)+ printf("REGEX_FAKE_MATCH_END ");+ if (compiler_common->longest_range_size > 0)+ printf("(longest range: %ld) ", (long)compiler_common->longest_range_size);+ printf("\n");+}++#endif++/* --------------------------------------------------------------------- */+/* Utilities */+/* --------------------------------------------------------------------- */++static int generate_search_states(struct compiler_common *compiler_common)+{+ struct stack_item *transitions_ptr = compiler_common->dfa_transitions;+ struct stack_item *transitions_end = transitions_ptr + compiler_common->dfa_size;+ struct stack_item *search_states_ptr;+ struct stack_item *rng_start = NULL;++ compiler_common->terms_size = !(compiler_common->flags & REGEX_FAKE_MATCH_END) ? 1 : 2;+ compiler_common->longest_range_size = 0;+ compiler_common->search_states = (struct stack_item *)SLJIT_MALLOC(sizeof(struct stack_item) * compiler_common->dfa_size, NULL);+ if (!compiler_common->search_states)+ return REGEX_MEMORY_ERROR;++ search_states_ptr = compiler_common->search_states;+ while (transitions_ptr < transitions_end) {+ switch (transitions_ptr->type) {+ case type_begin:+ case type_end:+ search_states_ptr->type = 0;+ break;++ case type_char:+ search_states_ptr->type = (int)compiler_common->terms_size++;+ break;++ case type_newline:+ if (transitions_ptr->value)+ search_states_ptr->type = 1;+ else+ search_states_ptr->type = (int)compiler_common->terms_size++;+ SLJIT_ASSERT(search_states_ptr->type == 1 || search_states_ptr->type == 2);+ break;++ case type_id:+ if (transitions_ptr->value > 0)+ compiler_common->flags |= REGEX_ID_CHECK;+ search_states_ptr->type = -1;+ break;++ case type_rng_start:+ search_states_ptr->type = (int)compiler_common->terms_size;+ rng_start = search_states_ptr;+ break;++ case type_rng_end:+ search_states_ptr->type = (int)compiler_common->terms_size++;+ /* This is an over estimation. */+ if (compiler_common->longest_range_size < search_states_ptr - rng_start)+ compiler_common->longest_range_size = search_states_ptr - rng_start;+ break;++ default:+ search_states_ptr->type = -1;+ break;+ }+ search_states_ptr->value = -1;+ search_states_ptr++;+ transitions_ptr++;+ }+ return REGEX_NO_ERROR;+}++static int trace_transitions(int from, struct compiler_common *compiler_common)+{+ int id = 0;+ struct stack *stack = &compiler_common->stack;+ struct stack *depth = &compiler_common->depth;+ struct stack_item *dfa_transitions = compiler_common->dfa_transitions;+ struct stack_item *search_states = compiler_common->search_states;++ SLJIT_ASSERT(search_states[from].type >= 0);++ from++;++ /* Be prepared for any paths (loops, etc). */+ while (1) {+ if (dfa_transitions[from].type == type_id)+ if (id < dfa_transitions[from].value)+ id = dfa_transitions[from].value;++ if (search_states[from].value < id) {+ /* Forward step. */+ if (search_states[from].value == -1)+ if (stack_push(stack, 0, from))+ return REGEX_MEMORY_ERROR;+ search_states[from].value = id;++ if (dfa_transitions[from].type == type_branch) {+ if (stack_push(depth, id, from))+ return REGEX_MEMORY_ERROR;+ from++;+ continue;+ }+ else if (dfa_transitions[from].type == type_jump) {+ from = dfa_transitions[from].value;+ continue;+ }+ else if (search_states[from].type < 0) {+ from++;+ continue;+ }+ }++ /* Back tracking. */+ if (depth->count > 0) {+ id = stack_top(depth)->type;+ from = dfa_transitions[stack_pop(depth)->value].value;+ continue;+ }+ return 0;+ }+}++/* --------------------------------------------------------------------- */+/* Code generator */+/* --------------------------------------------------------------------- */++#define TERM_OFFSET_OF(index, offs) (((index) * no_states + (offs)) * (sljit_sw)sizeof(sljit_sw))+#define TERM_REL_OFFSET_OF(base, offs) ((base) + ((offs) * (sljit_sw)sizeof(sljit_sw)))++#define EMIT_OP1(type, arg1, arg2, arg3, arg4) \+ CHECK(sljit_emit_op1(compiler, type, arg1, arg2, arg3, arg4))++#define EMIT_OP2(type, arg1, arg2, arg3, arg4, arg5, arg6) \+ CHECK(sljit_emit_op2(compiler, type, arg1, arg2, arg3, arg4, arg5, arg6))++#define EMIT_OP2U(type, arg1, arg2, arg3, arg4) \+ CHECK(sljit_emit_op2u(compiler, type, arg1, arg2, arg3, arg4))++#define EMIT_LABEL(label) \+ label = sljit_emit_label(compiler); \+ CHECK(!label)++#define EMIT_JUMP(jump, type) \+ jump = sljit_emit_jump(compiler, type); \+ CHECK(!jump)++#define EMIT_CMP(jump, type, arg1, arg2, arg3, arg4) \+ jump = sljit_emit_cmp(compiler, type, arg1, arg2, arg3, arg4); \+ CHECK(!jump)++/* CHECK depends on the use case. */++#define CHECK(exp) \+ if (SLJIT_UNLIKELY(exp)) \+ return REGEX_MEMORY_ERROR++static int compile_uncond_tran(struct compiler_common *compiler_common, int reg)+{+ struct sljit_compiler *compiler = compiler_common->compiler;+ struct stack *stack = &compiler_common->stack;+ struct stack_item *search_states = compiler_common->search_states;+ int flags = compiler_common->flags;+ sljit_sw no_states = compiler_common->no_states;+ sljit_sw head = 0;+ sljit_sw offset, value;++ if (reg != R_CURR_STATE || !(compiler_common->flags & REGEX_FAKE_MATCH_BEGIN)) {+ CHECK(trace_transitions(0, compiler_common));+ }+ else {+ CHECK(trace_transitions(1, compiler_common));+ }++ while (stack->count > 0) {+ value = stack_pop(stack)->value;+ if (search_states[value].type >= 0) {+ offset = TERM_OFFSET_OF(search_states[value].type, 0);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 1), SLJIT_IMM, head);+ if (offset > 0)+ head = offset;++ if (!(flags & REGEX_MATCH_BEGIN)) {+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 2), R_TEMP, 0);+ if (flags & REGEX_ID_CHECK) {+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 3), SLJIT_IMM, search_states[value].value);+ }+ }+ else if (flags & REGEX_ID_CHECK) {+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 2), SLJIT_IMM, search_states[value].value);+ }+ }+ search_states[value].value = -1;+ }+ if (reg == R_NEXT_STATE) {+ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_NEXT_HEAD, 0);+ }+ else if (flags & REGEX_FAKE_MATCH_BEGIN) {+ SLJIT_ASSERT(compiler_common->dfa_transitions[1].type == type_newline && !compiler_common->dfa_transitions[1].value);+ offset = TERM_OFFSET_OF(search_states[1].type, 0);++ SLJIT_ASSERT(!(flags & REGEX_MATCH_BEGIN));++ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 1), SLJIT_IMM, head);+ head = offset;++ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 2), SLJIT_IMM, 1);+ if (flags & REGEX_ID_CHECK) {+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 3), SLJIT_IMM, 0);+ }+ }+ EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, head);+ return REGEX_NO_ERROR;+}++static int compile_cond_tran(struct compiler_common *compiler_common, sljit_sw curr_index)+{+ struct sljit_compiler *compiler = compiler_common->compiler;+ struct stack *stack = &compiler_common->stack;+ struct stack_item *search_states = compiler_common->search_states;+ sljit_sw offset;+ int flags;+ sljit_sw no_states;+ sljit_sw value;+ struct sljit_jump *jump1;+ struct sljit_jump *jump2;+ struct sljit_jump *jump3;+ struct sljit_jump *jump4;+ struct sljit_jump *jump5;+ struct sljit_label *label1;++ flags = compiler_common->flags;+ no_states = compiler_common->no_states;++ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_forward), SLJIT_IMM, 0);+ if (!(flags & (REGEX_ID_CHECK | REGEX_MATCH_BEGIN))) {+ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(curr_index, 2));+ }++ while (stack->count > 0) {+ value = stack_pop(stack)->value;+ if (search_states[value].type >= 0) {+#ifdef REGEX_MATCH_VERBOSE+ if (flags & REGEX_MATCH_VERBOSE)+ printf("-> (%3d:%3d) ", search_states[value].type, search_states[value].value);+#endif+ offset = TERM_OFFSET_OF(search_states[value].type, 0);++ if (!(flags & REGEX_ID_CHECK)) {+ if (!(flags & REGEX_MATCH_BEGIN)) {+ /* Check whether item is inserted. */+ EMIT_CMP(jump1, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + (sljit_sw)sizeof(sljit_sw), SLJIT_IMM, -1);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + (sljit_sw)sizeof(sljit_sw), R_NEXT_HEAD, 0);+ if (offset > 0) {+ EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, offset);+ }+ EMIT_JUMP(jump2, SLJIT_JUMP);++ /* Check whether old index <= index. */+ EMIT_LABEL(label1);+ sljit_set_label(jump1, label1);++ EMIT_CMP(jump1, SLJIT_LESS_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * (sljit_sw)sizeof(sljit_sw), R_TEMP, 0);++ EMIT_LABEL(label1);+ sljit_set_label(jump2, label1);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * (sljit_sw)sizeof(sljit_sw), R_TEMP, 0);++ EMIT_LABEL(label1);+ sljit_set_label(jump1, label1);+ }+ else {+ /* Check whether item is inserted. */+ EMIT_CMP(jump1, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + (sljit_sw)sizeof(sljit_sw), SLJIT_IMM, -1);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + (sljit_sw)sizeof(sljit_sw), R_NEXT_HEAD, 0);+ if (offset > 0) {+ EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, offset);+ }+ EMIT_LABEL(label1);+ sljit_set_label(jump1, label1);+ }+ }+ else {+ if (!(flags & REGEX_MATCH_BEGIN)) {+ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(curr_index, 2));++ /* Check whether item is inserted. */+ EMIT_CMP(jump1, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + (sljit_sw)sizeof(sljit_sw), SLJIT_IMM, -1);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + (sljit_sw)sizeof(sljit_sw), R_NEXT_HEAD, 0);+ if (offset > 0) {+ EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, offset);+ }+ EMIT_JUMP(jump2, SLJIT_JUMP);++ /* Check whether old index != index. */+ EMIT_LABEL(label1);+ sljit_set_label(jump1, label1);++ EMIT_OP2U(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * (sljit_sw)sizeof(sljit_sw), R_TEMP, 0);+ EMIT_JUMP(jump1, SLJIT_LESS);+ EMIT_JUMP(jump3, SLJIT_NOT_EQUAL); /* Greater. */++ /* Old index == index. */+ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(curr_index, 3));+ if (search_states[value].value > 0) {+ EMIT_CMP(jump4, SLJIT_GREATER, R_TEMP, 0, SLJIT_IMM, search_states[value].value);++ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_IMM, search_states[value].value);+ EMIT_LABEL(label1);+ sljit_set_label(jump4, label1);+ }++ EMIT_OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + 3 * (sljit_sw)sizeof(sljit_sw), R_TEMP, 0);+ EMIT_JUMP(jump4, SLJIT_GREATER_EQUAL);+ EMIT_JUMP(jump5, SLJIT_JUMP);++ /* Overwrite index & id. */+ EMIT_LABEL(label1);+ sljit_set_label(jump3, label1);+ sljit_set_label(jump2, label1);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * (sljit_sw)sizeof(sljit_sw), R_TEMP, 0);++ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(curr_index, 3));+ if (search_states[value].value > 0) {+ EMIT_CMP(jump3, SLJIT_GREATER, R_TEMP, 0, SLJIT_IMM, search_states[value].value);++ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_IMM, search_states[value].value);+ EMIT_LABEL(label1);+ sljit_set_label(jump3, label1);+ }++ EMIT_LABEL(label1);+ sljit_set_label(jump5, label1);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + 3 * (sljit_sw)sizeof(sljit_sw), R_TEMP, 0);++ /* Exit. */+ EMIT_LABEL(label1);+ sljit_set_label(jump1, label1);+ sljit_set_label(jump4, label1);+ }+ else {+ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(curr_index, 2));++ if (search_states[value].value > 0) {+ EMIT_CMP(jump1, SLJIT_GREATER, R_TEMP, 0, SLJIT_IMM, search_states[value].value);++ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_IMM, search_states[value].value);+ EMIT_LABEL(label1);+ sljit_set_label(jump1, label1);+ }++ /* Check whether item is inserted. */+ EMIT_CMP(jump1, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + (sljit_sw)sizeof(sljit_sw), SLJIT_IMM, -1);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + (sljit_sw)sizeof(sljit_sw), R_NEXT_HEAD, 0);+ if (offset > 0) {+ EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, offset);+ }+ EMIT_JUMP(jump2, SLJIT_JUMP);++ /* Check whether old id >= id. */+ EMIT_LABEL(label1);+ sljit_set_label(jump1, label1);++ EMIT_CMP(jump1, SLJIT_GREATER_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * (sljit_sw)sizeof(sljit_sw), R_TEMP, 0);++ EMIT_LABEL(label1);+ sljit_set_label(jump2, label1);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * (sljit_sw)sizeof(sljit_sw), R_TEMP, 0);++ EMIT_LABEL(label1);+ sljit_set_label(jump1, label1);+ }+ }+ }+ search_states[value].value = -1;+ }++#ifdef REGEX_MATCH_VERBOSE+ if (flags & REGEX_MATCH_VERBOSE)+ printf("\n");+#endif+ return REGEX_NO_ERROR;+}++static int compile_end_check(struct compiler_common *compiler_common, struct sljit_label *end_check_label)+{+ struct sljit_compiler *compiler = compiler_common->compiler;+ struct sljit_jump *jump;+ struct sljit_jump *clear_states_jump;+ struct sljit_label *label;+ struct sljit_label *leave_label;+ struct sljit_label *begin_loop_label;++ /* Priority order: best_begin > best_end > best_id.+ In other words:+ if (new best_begin > old test_begin) do nothing+ otherwise we know that new_end > old_end, since R_CURR_INDEX ever increasing+ therefore we must overwrite all best_* variables (new_id also contains the highest id for this turn). */++ /* Both R_CURR_CHAR and R_BEST_BEGIN used as temporary registers. */++ if (!(compiler_common->flags & REGEX_MATCH_BEGIN)) {+ EMIT_OP1(SLJIT_MOV, R_CURR_CHAR, 0, SLJIT_MEM1(R_CURR_STATE), TERM_REL_OFFSET_OF(0, 2));+ EMIT_CMP(jump, !(compiler_common->flags & REGEX_MATCH_NON_GREEDY) ? SLJIT_LESS : SLJIT_LESS_EQUAL, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_begin), R_CURR_CHAR, 0);+ sljit_set_label(jump, end_check_label);++ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_begin), R_CURR_CHAR, 0);+ if (!(compiler_common->flags & (REGEX_FAKE_MATCH_BEGIN | REGEX_FAKE_MATCH_END))) {+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_end), R_CURR_INDEX, 0);+ }+ else {+ if ((compiler_common->flags & (REGEX_FAKE_MATCH_BEGIN | REGEX_FAKE_MATCH_END)) == (REGEX_FAKE_MATCH_BEGIN | REGEX_FAKE_MATCH_END)) {+ EMIT_OP2(SLJIT_SUB, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_end), R_CURR_INDEX, 0, SLJIT_IMM, 2);+ }+ else {+ EMIT_OP2(SLJIT_SUB, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_end), R_CURR_INDEX, 0, SLJIT_IMM, 1);+ }+ }+ if (compiler_common->flags & REGEX_ID_CHECK) {+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_id), SLJIT_MEM1(R_CURR_STATE), TERM_REL_OFFSET_OF(0, 3));+ }++ EMIT_CMP(clear_states_jump, SLJIT_LESS, R_CURR_CHAR, 0, R_BEST_BEGIN, 0);++ EMIT_LABEL(leave_label);+ EMIT_OP1(SLJIT_MOV, R_BEST_BEGIN, 0, R_CURR_CHAR, 0);+ EMIT_JUMP(jump, SLJIT_JUMP);+ sljit_set_label(jump, end_check_label);++ /* A loop to clear all states, which are > (or >=) than R_CURR_CHAR. */+ EMIT_LABEL(label);+ sljit_set_label(clear_states_jump, label);++ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_NEXT_HEAD, 0);+ EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, 0);++ /* Begin of the loop. */+ EMIT_LABEL(begin_loop_label);+ EMIT_CMP(jump, SLJIT_EQUAL, R_TEMP, 0, SLJIT_IMM, 0);+ sljit_set_label(jump, leave_label);++ EMIT_OP2(SLJIT_ADD, R_TEMP, 0, R_TEMP, 0, R_CURR_STATE, 0);+ EMIT_OP1(SLJIT_MOV, R_BEST_BEGIN, 0, SLJIT_MEM1(R_TEMP), sizeof(sljit_sw));+ EMIT_CMP(clear_states_jump, !(compiler_common->flags & REGEX_MATCH_NON_GREEDY) ? SLJIT_GREATER : SLJIT_GREATER_EQUAL, SLJIT_MEM1(R_TEMP), 2 * sizeof(sljit_sw), R_CURR_CHAR, 0);++ /* Case 1: keep this case. */+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_TEMP), sizeof(sljit_sw), R_NEXT_HEAD, 0);+ EMIT_OP2(SLJIT_SUB, R_NEXT_HEAD, 0, R_TEMP, 0, R_CURR_STATE, 0);++ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_BEST_BEGIN, 0);+ EMIT_JUMP(jump, SLJIT_JUMP);+ sljit_set_label(jump, begin_loop_label);++ /* Case 2: remove this case. */+ EMIT_LABEL(label);+ sljit_set_label(clear_states_jump, label);++ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_TEMP), sizeof(sljit_sw), SLJIT_IMM, -1);++ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_BEST_BEGIN, 0);+ EMIT_JUMP(jump, SLJIT_JUMP);+ sljit_set_label(jump, begin_loop_label);+ }+ else {+ EMIT_OP1(SLJIT_MOV, R_BEST_BEGIN, 0, SLJIT_IMM, 0);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_begin), SLJIT_IMM, 0);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_end), R_CURR_INDEX, 0);+ if (compiler_common->flags & REGEX_ID_CHECK) {+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_id), SLJIT_MEM1(R_CURR_STATE), TERM_REL_OFFSET_OF(0, 2));+ }+ EMIT_JUMP(jump, SLJIT_JUMP);+ sljit_set_label(jump, end_check_label);+ }+ return REGEX_NO_ERROR;+}++static int compile_leave_fast_forward(struct compiler_common *compiler_common, struct sljit_label *fast_forward_label)+{+ struct sljit_compiler *compiler = compiler_common->compiler;+ struct stack *stack = &compiler_common->stack;+ struct stack_item *dfa_transitions = compiler_common->dfa_transitions;+ struct stack_item *search_states = compiler_common->search_states;+ int ind;+ struct sljit_jump *jump;+ int init_range = 1, prev_value = 0;++ while (stack->count > 0) {+ ind = stack_pop(stack)->value;+ search_states[ind].value = -1;+ if (search_states[ind].type >= 0) {+ if (dfa_transitions[ind].type == type_char) {+ EMIT_CMP(jump, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, dfa_transitions[ind].value);+ sljit_set_label(jump, fast_forward_label);+ }+ else if (dfa_transitions[ind].type == type_rng_start) {+ SLJIT_ASSERT(!dfa_transitions[ind].value);+ ind++;+ while (dfa_transitions[ind].type != type_rng_end) {+ if (dfa_transitions[ind].type == type_rng_char) {+ EMIT_CMP(jump, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, dfa_transitions[ind].value);+ sljit_set_label(jump, fast_forward_label);+ }+ else {+ SLJIT_ASSERT(dfa_transitions[ind].type == type_rng_left);+ if (init_range) {+ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_CURR_CHAR, 0);+ init_range = 0;+ }+ if (dfa_transitions[ind].value != prev_value) {+ /* Best compatibility to all archs. */+ prev_value -= dfa_transitions[ind].value;+ if (prev_value < 0) {+ EMIT_OP2(SLJIT_SUB, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, -prev_value);+ }+ else {+ EMIT_OP2(SLJIT_ADD, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, prev_value);+ }+ prev_value = dfa_transitions[ind].value;+ }+ EMIT_CMP(jump, SLJIT_LESS_EQUAL, R_TEMP, 0, SLJIT_IMM, dfa_transitions[ind + 1].value - dfa_transitions[ind].value);+ sljit_set_label(jump, fast_forward_label);+ ind++;+ }+ ind++;+ }+ }+ else {+ SLJIT_ASSERT(dfa_transitions[ind].type == type_newline);+ EMIT_CMP(jump, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, '\n');+ sljit_set_label(jump, fast_forward_label);+ EMIT_CMP(jump, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, '\r');+ sljit_set_label(jump, fast_forward_label);+ }+ }+ }+ return REGEX_NO_ERROR;+}++static int compile_newline_check(struct compiler_common *compiler_common, sljit_sw ind)+{+ struct sljit_compiler *compiler = compiler_common->compiler;+ struct sljit_jump *jump1;+ struct sljit_jump *jump2;+ struct sljit_label *label;+ sljit_sw no_states;+ sljit_sw offset;++ /* Check whether a new-line character is found. */+ EMIT_CMP(jump1, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, '\n');+ EMIT_CMP(jump2, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, '\r');++ no_states = compiler_common->no_states;+ offset = TERM_OFFSET_OF(compiler_common->search_states[ind].type, 1);+ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), offset);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_CURR_STATE), offset, SLJIT_IMM, -1);+ CHECK(sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM2(R_CURR_STATE, R_TEMP), 0));++ EMIT_LABEL(label);+ sljit_set_label(jump1, label);+ sljit_set_label(jump2, label);+ return REGEX_NO_ERROR;+}++#undef CHECK++#define CHECK(exp) \+ if (SLJIT_UNLIKELY(exp)) \+ return 0++static SLJIT_INLINE void range_set_label(struct sljit_jump **range_jump_list, struct sljit_label *label)+{+ while (*range_jump_list) {+ sljit_set_label(*range_jump_list, label);+ range_jump_list++;+ }+}++static sljit_sw compile_range_check(struct compiler_common *compiler_common, sljit_sw ind)+{+ struct sljit_compiler *compiler = compiler_common->compiler;+ struct stack_item *dfa_transitions = compiler_common->dfa_transitions;+ struct sljit_jump **range_jump_list = compiler_common->range_jump_list;+ int invert = dfa_transitions[ind].value;+ struct sljit_label *label;+ sljit_sw no_states;+ sljit_sw offset;+ int init_range = 1, prev_value = 0;++ ind++;++ while (dfa_transitions[ind].type != type_rng_end) {+ if (dfa_transitions[ind].type == type_rng_char) {+ EMIT_CMP(*range_jump_list, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, dfa_transitions[ind].value);+ range_jump_list++;+ }+ else {+ SLJIT_ASSERT(dfa_transitions[ind].type == type_rng_left);+ if (init_range) {+ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_CURR_CHAR, 0);+ init_range = 0;+ }+ if (dfa_transitions[ind].value != prev_value) {+ /* Best compatibility to all archs. */+ prev_value -= dfa_transitions[ind].value;+ if (prev_value < 0) {+ EMIT_OP2(SLJIT_SUB, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, -prev_value);+ }+ else {+ EMIT_OP2(SLJIT_ADD, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, prev_value);+ }+ prev_value = dfa_transitions[ind].value;+ }+ EMIT_CMP(*range_jump_list, SLJIT_LESS_EQUAL, R_TEMP, 0, SLJIT_IMM, dfa_transitions[ind + 1].value - dfa_transitions[ind].value);+ range_jump_list++;+ ind++;+ }+ ind++;+ }++ *range_jump_list = NULL;++ if (!invert) {+ no_states = compiler_common->no_states;+ offset = TERM_OFFSET_OF(compiler_common->search_states[ind].type, 1);+ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), offset);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_CURR_STATE), offset, SLJIT_IMM, -1);+ CHECK(sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM2(R_CURR_STATE, R_TEMP), 0));++ EMIT_LABEL(label);+ range_set_label(compiler_common->range_jump_list, label);+ /* Clears the jump list. */+ *compiler_common->range_jump_list = NULL;+ }+ return ind;+}++#undef TERM_OFFSET_OF+#undef EMIT_OP1+#undef EMIT_OP2+#undef EMIT_LABEL+#undef EMIT_JUMP+#undef EMIT_CMP+#undef CHECK++/* --------------------------------------------------------------------- */+/* Main compiler */+/* --------------------------------------------------------------------- */++#define TERM_OFFSET_OF(ind, offs) (((ind) * compiler_common.no_states + (offs)) * (sljit_sw)sizeof(sljit_sw))++#define EMIT_OP1(type, arg1, arg2, arg3, arg4) \+ CHECK(sljit_emit_op1(compiler_common.compiler, type, arg1, arg2, arg3, arg4))++#define EMIT_OP2(type, arg1, arg2, arg3, arg4, arg5, arg6) \+ CHECK(sljit_emit_op2(compiler_common.compiler, type, arg1, arg2, arg3, arg4, arg5, arg6))++#define EMIT_LABEL(label) \+ label = sljit_emit_label(compiler_common.compiler); \+ CHECK(!label)++#define EMIT_JUMP(jump, type) \+ jump = sljit_emit_jump(compiler_common.compiler, type); \+ CHECK(!jump)++#define EMIT_CMP(jump, type, arg1, arg2, arg3, arg4) \+ jump = sljit_emit_cmp(compiler_common.compiler, type, arg1, arg2, arg3, arg4); \+ CHECK(!jump)++/* A do {} while(0) expression helps to avoid goto statements. */+#define BEGIN_GUARD \+ do {++#define END_GUARD \+ } while(0);++#define CHECK(exp) \+ if (SLJIT_UNLIKELY(exp)) \+ break;++struct regex_machine* regex_compile(const regex_char_t *regex_string, int length, int re_flags, int *error)+{+ struct compiler_common compiler_common;+ sljit_sw ind;+ int error_code, done, suggest_fast_forward;+ /* ID of an empty match (-1 if not reachable). */+ int empty_match_id;++ struct sljit_jump *jump;+ struct sljit_jump *best_match_found_jump;+ struct sljit_jump *fast_forward_jump = NULL;+ struct sljit_jump *length_is_zero_jump;+ struct sljit_jump *end_check_jump = NULL;+ struct sljit_jump *best_match_check_jump = NULL;+ struct sljit_jump *non_greedy_end_jump = NULL;+ struct sljit_label *label;+ struct sljit_label *end_check_label = NULL;+ struct sljit_label *start_label;+ struct sljit_label *fast_forward_label;+ struct sljit_label *fast_forward_return_label;++ if (error)+ *error = REGEX_NO_ERROR;+#ifdef REGEX_MATCH_VERBOSE+ compiler_common.flags = re_flags & (REGEX_MATCH_BEGIN | REGEX_MATCH_END | REGEX_MATCH_NON_GREEDY | REGEX_NEWLINE | REGEX_MATCH_VERBOSE);+#else+ compiler_common.flags = re_flags & (REGEX_MATCH_BEGIN | REGEX_MATCH_END | REGEX_MATCH_NON_GREEDY | REGEX_NEWLINE);+#endif++ /* Step 1: parsing (Left->Right).+ Syntax check and AST generator. */+ error_code = parse(regex_string, length, &compiler_common);+ if (error_code) {+ stack_destroy(&compiler_common.stack);+ if (error)+ *error = error_code;+ return NULL;+ }++ /* Step 2: generating branches (Right->Left). */+ error_code = generate_transitions(&compiler_common);+ stack_destroy(&compiler_common.stack);+ stack_destroy(&compiler_common.depth);+ if (error_code) {+ if (compiler_common.dfa_transitions)+ SLJIT_FREE(compiler_common.dfa_transitions, NULL);+ if (error)+ *error = error_code;+ return NULL;+ }++ /* Step 3: Generate necessary data for depth-first search (Left->Right). */+ error_code = generate_search_states(&compiler_common);+ if (error_code) {+ SLJIT_FREE(compiler_common.dfa_transitions, NULL);+ if (error)+ *error = error_code;+ return NULL;+ }++#ifdef REGEX_MATCH_VERBOSE+ if (compiler_common.flags & REGEX_MATCH_VERBOSE)+ verbose_transitions(&compiler_common);+#endif++ /* Step 4: Left->Right generate code. */+ stack_init(&compiler_common.stack);+ stack_init(&compiler_common.depth);+ done = 0;+ compiler_common.machine = NULL;+ compiler_common.compiler = NULL;+ compiler_common.range_jump_list = NULL;++ BEGIN_GUARD++ compiler_common.machine = (struct regex_machine*)SLJIT_MALLOC(sizeof(struct regex_machine) + (sljit_uw)(compiler_common.terms_size - 1) * sizeof(sljit_uw), NULL);+ CHECK(!compiler_common.machine);++ compiler_common.compiler = sljit_create_compiler(NULL);+ CHECK(!compiler_common.compiler);++ if (compiler_common.longest_range_size > 0) {+ compiler_common.range_jump_list = (struct sljit_jump**)SLJIT_MALLOC(sizeof(struct sljit_jump*) * (sljit_uw)compiler_common.longest_range_size, NULL);+ CHECK(!compiler_common.range_jump_list);+ }++ if ((compiler_common.flags & REGEX_ID_CHECK) && !(compiler_common.flags & REGEX_MATCH_BEGIN))+ compiler_common.no_states = 4;+ else if (!(compiler_common.flags & REGEX_ID_CHECK) && (compiler_common.flags & REGEX_MATCH_BEGIN))+ compiler_common.no_states = 2;+ else+ compiler_common.no_states = 3;++ compiler_common.machine->flags = compiler_common.flags;+ compiler_common.machine->no_states = compiler_common.no_states;+ compiler_common.machine->size = compiler_common.machine->no_states * compiler_common.terms_size;++ /* Study the regular expression. */+ empty_match_id = -1;+ suggest_fast_forward = 1;+ if (!(compiler_common.flags & REGEX_FAKE_MATCH_BEGIN)) {+ CHECK(trace_transitions(0, &compiler_common));+ while (compiler_common.stack.count > 0) {+ ind = stack_pop(&compiler_common.stack)->value;+ if (compiler_common.search_states[ind].type == 0) {+ SLJIT_ASSERT(compiler_common.dfa_transitions[ind].type == type_end);+ suggest_fast_forward = 0;+ empty_match_id = compiler_common.search_states[ind].value;+ }+ else if (compiler_common.search_states[ind].type > 0) {+ SLJIT_ASSERT(compiler_common.dfa_transitions[ind].type != type_end);+ if (compiler_common.dfa_transitions[ind].type == type_rng_start && compiler_common.dfa_transitions[ind].value)+ suggest_fast_forward = 0;+ }+ compiler_common.search_states[ind].value = -1;+ }+ }+ else {+ SLJIT_ASSERT(compiler_common.dfa_transitions[1].type == type_newline);+ CHECK(trace_transitions(1, &compiler_common));+ while (compiler_common.stack.count > 0) {+ ind = stack_pop(&compiler_common.stack)->value;+ if (compiler_common.search_states[ind].type == 0) {+ SLJIT_ASSERT(compiler_common.dfa_transitions[ind].type == type_end);+ suggest_fast_forward = 0;+ empty_match_id = compiler_common.search_states[ind].value;+ }+ compiler_common.search_states[ind].value = -1;+ }+ }++ /* Step 4.1: Generate entry. */+ CHECK(sljit_emit_enter(compiler_common.compiler, 0, SLJIT_ARGS3V(P, P, 32), 5, 5, 0));++ /* Copy arguments to their place. */+ EMIT_OP1(SLJIT_MOV, R_REGEX_MATCH, 0, SLJIT_S0, 0);+ EMIT_OP1(SLJIT_MOV, R_STRING, 0, SLJIT_S1, 0);+ EMIT_OP2(SLJIT_ADD, R_LENGTH, 0, SLJIT_S2, 0, SLJIT_IMM, 1);++ /* Init global registers. */+ EMIT_OP1(SLJIT_MOV, R_CURR_STATE, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, current));+ EMIT_OP1(SLJIT_MOV, R_NEXT_STATE, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, next));+ EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, head));+ EMIT_OP1(SLJIT_MOV, R_BEST_BEGIN, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_begin));+ EMIT_OP1(SLJIT_MOV, R_CURR_INDEX, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, index));++ /* Check whether the best match has already found in a previous frame. */+ EMIT_CMP(jump, SLJIT_EQUAL, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_quit), SLJIT_IMM, 0);+ EMIT_JUMP(best_match_found_jump, SLJIT_JUMP);++#ifdef REGEX_MATCH_VERBOSE+ if (compiler_common.flags & REGEX_MATCH_VERBOSE)+ printf("\n-----------------\nTrace\n-----------------\n");+#endif++ /* Step 4.2: Generate code for state 0. */+ EMIT_LABEL(label);+ sljit_emit_op0(compiler_common.compiler, SLJIT_ENDBR);+ compiler_common.machine->entry_addrs[0] = (sljit_uw)label;++ /* Swapping current and next. */+ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_CURR_STATE, 0);+ EMIT_OP1(SLJIT_MOV, R_CURR_STATE, 0, R_NEXT_STATE, 0);+ EMIT_OP1(SLJIT_MOV, R_NEXT_STATE, 0, R_TEMP, 0);++ /* Checking whether the best case needs to be updated. */+ if (!(compiler_common.flags & REGEX_MATCH_END)) {+ EMIT_CMP(end_check_jump, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_CURR_STATE), TERM_REL_OFFSET_OF(0, 1), SLJIT_IMM, -1);+ EMIT_LABEL(end_check_label);+ }+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), TERM_REL_OFFSET_OF(0, 1), SLJIT_IMM, -1);+ EMIT_OP2(SLJIT_ADD, R_CURR_INDEX, 0, R_CURR_INDEX, 0, SLJIT_IMM, 1);++ /* Checking whether best case has already found. */+ if (!(compiler_common.flags & REGEX_MATCH_END) || (compiler_common.flags & REGEX_MATCH_BEGIN)) {+ if (!(compiler_common.flags & REGEX_MATCH_BEGIN)) {+ /* We can bail out if no more active states remain and R_BEST_BEGIN != -1. */+ EMIT_CMP(best_match_check_jump, SLJIT_NOT_EQUAL, R_BEST_BEGIN, 0, SLJIT_IMM, -1);+ }+ else {+ /* We can bail out if no more active states remain (regardless of R_BEST_BEGIN). */+ EMIT_CMP(best_match_check_jump, SLJIT_EQUAL, R_NEXT_HEAD, 0, SLJIT_IMM, 0);+ }+ }++ EMIT_LABEL(start_label);+ sljit_set_label(jump, start_label);++ if (!(compiler_common.flags & REGEX_MATCH_BEGIN) && suggest_fast_forward) {+ EMIT_CMP(fast_forward_jump, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_forward), SLJIT_IMM, 0);+ }++ /* Loading the next character. */+ EMIT_OP2(SLJIT_SUB | SLJIT_SET_Z, R_LENGTH, 0, R_LENGTH, 0, SLJIT_IMM, 1);+ EMIT_JUMP(length_is_zero_jump, SLJIT_EQUAL);++ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_STRING, 0);+#ifdef REGEX_USE_8BIT_CHARS+ EMIT_OP1(SLJIT_MOV_U8, R_CURR_CHAR, 0, SLJIT_MEM1(R_TEMP), 0);+ EMIT_OP2(SLJIT_ADD, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, 1);+#else+ EMIT_OP1(SLJIT_MOV_UH, R_CURR_CHAR, 0, SLJIT_MEM1(R_TEMP), 0);+ EMIT_OP2(SLJIT_ADD, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, 2);+#endif+ EMIT_OP1(SLJIT_MOV, R_STRING, 0, R_TEMP, 0);++#ifdef REGEX_MATCH_VERBOSE+ if (compiler_common.flags & REGEX_MATCH_VERBOSE) {+ printf("(%3d): ", 0);+ CHECK(trace_transitions(0, &compiler_common));+ while (compiler_common.stack.count > 0) {+ ind = stack_pop(&compiler_common.stack)->value;+ if (compiler_common.search_states[ind].type >= 0)+ printf("-> (%3d:%3d) ", compiler_common.search_states[ind].type, compiler_common.search_states[ind].value);+ compiler_common.search_states[ind].value = -1;+ }+ printf("\n");+ }+#endif++ EMIT_LABEL(fast_forward_return_label);+ if (!(compiler_common.flags & REGEX_MATCH_BEGIN)) {+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_forward), SLJIT_IMM, 1);+ if (!(compiler_common.flags & REGEX_MATCH_END)) {+ EMIT_CMP(jump, SLJIT_NOT_EQUAL, R_BEST_BEGIN, 0, SLJIT_IMM, -1);+ }++ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_CURR_INDEX, 0);+ CHECK(compile_uncond_tran(&compiler_common, R_NEXT_STATE));+ /* And branching to the first state. */+ CHECK(sljit_emit_ijump(compiler_common.compiler, SLJIT_JUMP, SLJIT_MEM2(R_CURR_STATE, R_TEMP), 0));++ if (!(compiler_common.flags & REGEX_MATCH_END)) {+ EMIT_LABEL(label);+ sljit_set_label(jump, label);+ }+ }+ /* This is the case where we only have to reset the R_NEXT_HEAD. */+ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_NEXT_HEAD, 0);+ EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, 0);+ CHECK(sljit_emit_ijump(compiler_common.compiler, SLJIT_JUMP, SLJIT_MEM2(R_CURR_STATE, R_TEMP), 0));++ /* Fast-forward loop. */+ if (fast_forward_jump) {+ /* Quit from fast-forward loop. */+ EMIT_LABEL(fast_forward_label);+ EMIT_OP2(SLJIT_SUB, R_TEMP, 0, R_NEXT_HEAD, 0, SLJIT_IMM, 1);+ EMIT_OP1(SLJIT_MOV, R_LENGTH, 0, R_NEXT_STATE, 0);+ EMIT_OP1(SLJIT_MOV, R_STRING, 0, R_CURR_STATE, 0);+ EMIT_OP1(SLJIT_MOV, R_CURR_INDEX, 0, R_NEXT_HEAD, 0);+ EMIT_OP1(SLJIT_MOV, R_NEXT_STATE, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, next));+ EMIT_OP1(SLJIT_MOV, R_CURR_STATE, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, current));+ EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, head));++ /* Update the start field of the locations. */+ CHECK(trace_transitions(0, &compiler_common));+ while (compiler_common.stack.count > 0) {+ ind = stack_pop(&compiler_common.stack)->value;+ if (compiler_common.search_states[ind].type >= 0) {+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(compiler_common.search_states[ind].type, 2), R_TEMP, 0);+ }+ compiler_common.search_states[ind].value = -1;+ }+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_forward), SLJIT_IMM, 0);+ EMIT_JUMP(jump, SLJIT_JUMP);+ sljit_set_label(jump, fast_forward_return_label);++ /* Start fast-forward. */+ EMIT_LABEL(label);+ sljit_set_label(fast_forward_jump, label);++ /* Moving everything to registers. */+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, next), R_NEXT_STATE, 0);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, current), R_CURR_STATE, 0);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, head), R_NEXT_HEAD, 0);+ EMIT_OP1(SLJIT_MOV, R_NEXT_STATE, 0, R_LENGTH, 0);+ EMIT_OP1(SLJIT_MOV, R_CURR_STATE, 0, R_STRING, 0);+ EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, R_CURR_INDEX, 0);++ /* Fast forward mainloop. */+ EMIT_LABEL(label);+ EMIT_OP2(SLJIT_SUB | SLJIT_SET_Z, R_NEXT_STATE, 0, R_NEXT_STATE, 0, SLJIT_IMM, 1);+ EMIT_JUMP(fast_forward_jump, SLJIT_EQUAL);++#ifdef REGEX_USE_8BIT_CHARS+ EMIT_OP1(SLJIT_MOV_U8, R_CURR_CHAR, 0, SLJIT_MEM1(R_CURR_STATE), 0);+ EMIT_OP2(SLJIT_ADD, R_CURR_STATE, 0, R_CURR_STATE, 0, SLJIT_IMM, 1);+#else+ EMIT_OP1(SLJIT_MOV_UH, R_CURR_CHAR, 0, SLJIT_MEM1(R_CURR_STATE), 0);+ EMIT_OP2(SLJIT_ADD, R_CURR_STATE, 0, R_CURR_STATE, 0, SLJIT_IMM, 2);+#endif++ CHECK(trace_transitions(0, &compiler_common));+ CHECK(compile_leave_fast_forward(&compiler_common, fast_forward_label));++ EMIT_OP2(SLJIT_ADD, R_NEXT_HEAD, 0, R_NEXT_HEAD, 0, SLJIT_IMM, 1);+ EMIT_JUMP(jump, SLJIT_JUMP);+ sljit_set_label(jump, label);++ /* String is finished. */+ EMIT_LABEL(label);+ sljit_set_label(fast_forward_jump, label);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, index), R_NEXT_HEAD, 0);+ EMIT_JUMP(fast_forward_jump, SLJIT_JUMP);+ }++ /* End check. */+ if (end_check_jump) {+ EMIT_LABEL(label);+ sljit_set_label(end_check_jump, label);++ if (!(compiler_common.flags & REGEX_MATCH_NON_GREEDY) || !(compiler_common.flags & REGEX_MATCH_BEGIN)) {+ CHECK(compile_end_check(&compiler_common, end_check_label));+ }+ else {+ /* Since we leave, we do not need to update the R_BEST_BEGIN. */+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_begin), SLJIT_IMM, 0);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_end), R_CURR_INDEX, 0);+ if (compiler_common.flags & REGEX_ID_CHECK) {+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_id), SLJIT_MEM1(R_CURR_STATE), TERM_REL_OFFSET_OF(0, 2));+ }+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_quit), SLJIT_IMM, 1);+ EMIT_JUMP(non_greedy_end_jump, SLJIT_JUMP);+ }+ }++ /* Finish check. */+ if (best_match_check_jump) {+ EMIT_LABEL(label);+ sljit_set_label(best_match_check_jump, label);++ if (!(compiler_common.flags & REGEX_MATCH_BEGIN)) {+ EMIT_CMP(jump, SLJIT_NOT_EQUAL, R_NEXT_HEAD, 0, SLJIT_IMM, 0);+ sljit_set_label(jump, start_label);+ }+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_quit), SLJIT_IMM, 1);+ }++ /* Leaving matching and storing the necessary values. */+ EMIT_LABEL(label);+ sljit_set_label(length_is_zero_jump, label);+ if (non_greedy_end_jump)+ sljit_set_label(non_greedy_end_jump, label);++ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, index), R_CURR_INDEX, 0);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, head), R_NEXT_HEAD, 0);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, next), R_NEXT_STATE, 0);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, current), R_CURR_STATE, 0);++ /* Exit from JIT. */+ EMIT_LABEL(label);+ sljit_set_label(best_match_found_jump, label);+ if (fast_forward_jump)+ sljit_set_label(fast_forward_jump, label);+ CHECK(sljit_emit_return_void(compiler_common.compiler));++ for (ind = 1; ind < (sljit_sw)compiler_common.dfa_size - 1; ind++) {+ if (compiler_common.search_states[ind].type >= 0) {+ SLJIT_ASSERT(compiler_common.search_states[ind].type < compiler_common.terms_size);+ EMIT_LABEL(label);+ sljit_emit_op0(compiler_common.compiler, SLJIT_ENDBR);+ compiler_common.machine->entry_addrs[compiler_common.search_states[ind].type] = (sljit_uw)label;++ if (compiler_common.dfa_transitions[ind].type == type_char) {+ EMIT_CMP(jump, SLJIT_NOT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, compiler_common.dfa_transitions[ind].value);+ }+ else if (compiler_common.dfa_transitions[ind].type == type_rng_start) {+ ind = compile_range_check(&compiler_common, ind);+ CHECK(!ind);+ }+ else {+ SLJIT_ASSERT(compiler_common.dfa_transitions[ind].type == type_newline);+ CHECK(compile_newline_check(&compiler_common, ind));+ }++ CHECK(trace_transitions((int)ind, &compiler_common));+#ifdef REGEX_MATCH_VERBOSE+ if (compiler_common.flags & REGEX_MATCH_VERBOSE)+ printf("(%3d): ", compiler_common.search_states[ind].type);+#endif+ CHECK(compile_cond_tran(&compiler_common, compiler_common.search_states[ind].type));++ if (compiler_common.dfa_transitions[ind].type == type_char) {+ EMIT_LABEL(label);+ sljit_set_label(jump, label);+ }+ else if (compiler_common.dfa_transitions[ind].type == type_rng_end) {+ EMIT_LABEL(label);+ range_set_label(compiler_common.range_jump_list, label);+ }+ else {+ SLJIT_ASSERT(compiler_common.dfa_transitions[ind].type == type_newline);+ }++ /* Branch to the next item in the list. */+ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(compiler_common.search_states[ind].type, 1));+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(compiler_common.search_states[ind].type, 1), SLJIT_IMM, -1);+ CHECK(sljit_emit_ijump(compiler_common.compiler, SLJIT_JUMP, SLJIT_MEM2(R_CURR_STATE, R_TEMP), 0));+ }+ }++ if (ind == (sljit_sw)compiler_common.dfa_size - 1) {+ /* Generate an init stub function. */+ EMIT_LABEL(label);+ CHECK(sljit_emit_enter(compiler_common.compiler, 0, SLJIT_ARGS2(W, P, P), 3, 3, 0));++ if (empty_match_id == -1) {+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), SLJIT_OFFSETOF(struct regex_match, best_begin), SLJIT_IMM, -1);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), SLJIT_OFFSETOF(struct regex_match, best_id), SLJIT_IMM, 0);+ }+ else {+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), SLJIT_OFFSETOF(struct regex_match, best_begin), SLJIT_IMM, 0);+ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), SLJIT_OFFSETOF(struct regex_match, best_id), SLJIT_IMM, empty_match_id);+ }++ EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), SLJIT_OFFSETOF(struct regex_match, index), SLJIT_IMM, !(compiler_common.flags & REGEX_FAKE_MATCH_BEGIN) ? 1 : 2);++ if (!(compiler_common.flags & REGEX_MATCH_NON_GREEDY) || empty_match_id == -1) {+ /* The else is a really rare event, so we still generate an empty function instead of a runtime pointer check. */+ SLJIT_ASSERT(R_CURR_STATE == SLJIT_S0);+ if (!(compiler_common.flags & REGEX_MATCH_BEGIN)) {+ /* R_CURR_INDEX (put to R_TEMP) is zero. */+ EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_IMM, 0);+ }+ CHECK(compile_uncond_tran(&compiler_common, R_CURR_STATE));+ }+ else {+ EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, 0);+ }+ CHECK(sljit_emit_return(compiler_common.compiler, SLJIT_MOV, R_NEXT_HEAD, 0));++ compiler_common.machine->continue_match = sljit_generate_code(compiler_common.compiler, 0, NULL);+#ifndef SLJIT_INDIRECT_CALL+ compiler_common.machine->u.init_match = (void*)(sljit_sw)sljit_get_label_addr(label);+#else+ sljit_set_function_context(&compiler_common.machine->u.init_match, &compiler_common.machine->context, sljit_get_label_addr(label), regex_compile);+#endif+#ifdef REGEX_MATCH_VERBOSE+ if (compiler_common.flags & REGEX_MATCH_VERBOSE)+ printf("Continue match: %p Init match: %p\n\n", compiler_common.machine->continue_match, compiler_common.machine->u.init_match);+#endif+ if (compiler_common.machine->continue_match) {+ for (ind = 0; ind < compiler_common.terms_size; ++ind)+ compiler_common.machine->entry_addrs[ind] = sljit_get_label_addr((struct sljit_label*)compiler_common.machine->entry_addrs[ind]);+ done = 1;+ }+ }+ END_GUARD++ stack_destroy(&compiler_common.stack);+ stack_destroy(&compiler_common.depth);+ SLJIT_FREE(compiler_common.dfa_transitions, NULL);+ SLJIT_FREE(compiler_common.search_states, NULL);+ if (compiler_common.range_jump_list)+ SLJIT_FREE(compiler_common.range_jump_list, NULL);+ if (compiler_common.compiler)+ sljit_free_compiler(compiler_common.compiler);+ if (done)+ return compiler_common.machine;++ if (compiler_common.machine) {+ SLJIT_FREE(compiler_common.machine, NULL);+ }+ if (error)+ *error = REGEX_MEMORY_ERROR;+ return NULL;+}++#undef TERM_OFFSET_OF+#undef EMIT_OP1+#undef EMIT_OP2+#undef EMIT_LABEL+#undef EMIT_JUMP+#undef EMIT_CMP+#undef BEGIN_GUARD+#undef END_GUARD+#undef CHECK++void regex_free_machine(struct regex_machine *machine)+{+ sljit_free_code(machine->continue_match, NULL);+ SLJIT_FREE(machine, NULL);+}++const char* regex_get_platform_name(void)+{+ return sljit_get_platform_name();+}++/* --------------------------------------------------------------------- */+/* Mathching utilities */+/* --------------------------------------------------------------------- */++struct regex_match* regex_begin_match(struct regex_machine *machine)+{+ sljit_sw *ptr1;+ sljit_sw *ptr2;+ sljit_sw *end;+ sljit_sw *entry_addrs;++ struct regex_match *match = (struct regex_match*)SLJIT_MALLOC(sizeof(struct regex_match) + (sljit_uw)(machine->size * 2 - 1) * sizeof(sljit_sw), NULL);+ if (!match)+ return NULL;++ ptr1 = match->states;+ ptr2 = match->states + machine->size;+ end = ptr2;+ entry_addrs = (sljit_sw*)machine->entry_addrs;++ match->current = ptr1;+ match->next = ptr2;+ match->head = 0;+ match->machine = machine;++ /* Init machine states. */+ switch (machine->no_states) {+ case 2:+ while (ptr1 < end) {+ *ptr1++ = *entry_addrs;+ *ptr2++ = *entry_addrs++;+ *ptr1++ = -1;+ *ptr2++ = -1;+ }+ break;++ case 3:+ while (ptr1 < end) {+ *ptr1++ = *entry_addrs;+ *ptr2++ = *entry_addrs++;+ *ptr1++ = -1;+ *ptr2++ = -1;+ *ptr1++ = 0;+ *ptr2++ = 0;+ }+ break;++ case 4:+ while (ptr1 < end) {+ *ptr1++ = *entry_addrs;+ *ptr2++ = *entry_addrs++;+ *ptr1++ = -1;+ *ptr2++ = -1;+ *ptr1++ = 0;+ *ptr2++ = 0;+ *ptr1++ = 0;+ *ptr2++ = 0;+ }+ break;++ default:+ SLJIT_UNREACHABLE();+ break;+ }++ SLJIT_ASSERT(ptr1 == end);++ match->u.continue_match = machine->continue_match;++ regex_reset_match(match);+ return match;+}++void regex_reset_match(struct regex_match *match)+{+ struct regex_machine *machine = match->machine;+ sljit_sw current, ind;+ sljit_sw *current_ptr;++ match->best_end = 0;+ match->fast_quit = 0;+ match->fast_forward = 0;++ if (match->head != 0) {+ /* Clear the current state. */+ current = match->head;+ current_ptr = match->current;+ do {+ ind = (current / (sljit_sw)sizeof(sljit_sw)) + 1;+ current = current_ptr[ind];+ current_ptr[ind] = -1;+ } while (current != 0);+ }+ match->head = machine->u.call_init(match->current, match);+}++void regex_free_match(struct regex_match *match)+{+ SLJIT_FREE(match, NULL);+}++void regex_continue_match(struct regex_match *match, const regex_char_t *input_string, int length)+{+ match->u.call_continue(match, input_string, length);+}++int regex_get_result(struct regex_match *match, int *end, int *id)+{+ int flags = match->machine->flags;+ sljit_sw no_states;++ *end = (int)match->best_end;+ *id = (int)match->best_id;+ if (!(flags & (REGEX_MATCH_END | REGEX_FAKE_MATCH_END)))+ return (int)match->best_begin;++ if (flags & REGEX_FAKE_MATCH_END) {+ SLJIT_ASSERT(!(flags & (REGEX_MATCH_BEGIN | REGEX_MATCH_END)));+ if (match->best_begin != -1)+ return (int)match->best_begin;++ no_states = match->machine->no_states;+ if (match->current[no_states + 1] == -1)+ return -1;+ if (flags & REGEX_ID_CHECK)+ *id = (int)match->current[no_states + 3];+ if (!(flags & REGEX_FAKE_MATCH_BEGIN))+ *end = (int)match->index - 1;+ else+ *end = (int)match->index - 2;+ return (int)match->current[no_states + 2];+ }+ else {+ /* Check the status of the last code. */+ if (!(flags & REGEX_MATCH_BEGIN)) {+ /* No shortcut in this case. */+ if (!(flags & REGEX_ID_CHECK)) {+ if (match->current[1] == -1)+ return -1;+ *end = (int)match->index - 1;+ return (int)match->current[2];+ }++ if (match->current[1] == -1)+ return -1;+ *end = (int)match->index - 1;+ *id = (int)match->current[3];+ return (int)match->current[2];+ }++ /* Shortcut is possible in this case. */+ if (!(flags & REGEX_ID_CHECK)) {+ if (match->current[1] == -1 || match->head == -1)+ return -1;+ *end = (int)match->index - 1;+ return 0;+ }++ if (match->current[1] == -1 || match->head == -1)+ return -1;+ *end = (int)match->index - 1;+ *id = (int)match->current[2];+ return 0;+ }+}++int regex_is_match_finished(struct regex_match *match)+{+ return (int)match->fast_quit;+}++#ifdef REGEX_MATCH_VERBOSE+void regex_continue_match_debug(struct regex_match *match, const regex_char_t *input_string, int length)+{+ sljit_sw *ptr;+ sljit_sw *end;+ sljit_sw count;+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)+ sljit_sw current;+#endif+ sljit_sw no_states = match->machine->no_states;+ sljit_sw len = match->machine->size;++ while (length > 0) {+ match->u.call_continue(match, input_string, 1);++ if (match->fast_forward) {+ if (match->machine->flags & REGEX_MATCH_VERBOSE)+ printf("fast forward\n");+ }++ /* Verbose (first). */+ if (match->machine->flags & REGEX_MATCH_VERBOSE) {+ ptr = match->current;+ end = ptr + len;+ count = 0;+ printf("'%c' (%3ld->%3ld [%3ld]) ", *input_string, (long)match->best_begin, (long)match->best_end, (long)match->best_id);+ while (ptr < end) {+ printf("[%3ld:", (long)count++);+ switch (no_states) {+ case 2:+ if (ptr[1] != -1)+ printf("+] ");+ else+ printf(" ] ");+ break;++ case 3:+ if (ptr[1] != -1)+ printf("+,%3ld] ", (long)ptr[2]);+ else+ printf(" ,XXX] ");+ break;++ case 4:+ if (ptr[1] != -1)+ printf("+,%3ld,%3ld] ", (long)ptr[2], (long)ptr[3]);+ else+ printf(" ,XXX,XXX] ");+ break;+ }+ ptr += no_states;+ }+ printf("\n");+ }++#if (defined SLJIT_DEBUG && SLJIT_DEBUG)+ /* Sanity check (later). */+ ptr = match->next;+ end = ptr + len;+ while (ptr < end) {+ SLJIT_ASSERT(ptr[1] == -1);+ ptr += no_states;+ }++ /* Check number of active elements. */+ ptr = match->current + no_states;+ end = ptr + len - no_states;+ count = 0;+ while (ptr < end) {+ if (ptr[1] != -1)+ count++;+ ptr += no_states;+ }++ /* Check chain list. */+ current = match->head;+ ptr = match->current;+ while (current != 0) {+ SLJIT_ASSERT(current >= 0 && current < len * (sljit_sw)sizeof(sljit_sw));+ SLJIT_ASSERT((current % (no_states * (sljit_sw)sizeof(sljit_sw))) == 0);+ SLJIT_ASSERT(count > 0);+ current = ptr[(current / (sljit_sw)sizeof(sljit_sw)) + 1];+ count--;+ }+ SLJIT_ASSERT(count == 0);+#endif++ if (match->fast_quit) {+ /* the machine has stopped working. */+ if (match->machine->flags & REGEX_MATCH_VERBOSE)+ printf("Best match has found\n");+ break;+ }++ input_string++;+ length--;+ }+}+#endif
+ src/c/pcre2/deps/sljit/regex_src/regexJIT.h view
@@ -0,0 +1,106 @@+/*+ * 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 _REGEX_JIT_H_+#define _REGEX_JIT_H_++#ifdef __cplusplus+extern "C" {+#endif++/* Character type config. */+#define REGEX_USE_8BIT_CHARS++#ifdef REGEX_USE_8BIT_CHARS+typedef char regex_char_t;+#else+typedef wchar_t regex_char_t;+#endif++/* Error codes. */+#define REGEX_NO_ERROR 0+#define REGEX_MEMORY_ERROR 1+#define REGEX_INVALID_REGEX 2++/* Note: large, nested {a,b} iterations can blow up the memory consumption+ a{n,m} is replaced by aa...aaa?a?a?a?a? (n >= 0, m > 0)+ \__n__/\____m___/+ a{n,} is replaced by aa...aaa+ (n > 0)+ \_n-1_/+*/++/* The value returned by regex_compile. Can be used for multiple matching. */+struct regex_machine;++/* A matching state. */+struct regex_match;++/* Note: REGEX_MATCH_BEGIN and REGEX_MATCH_END does not change the parsing+ (Hence ^ and $ are parsed normally).+ Force matching to start from begining of the string (same as ^). */+#define REGEX_MATCH_BEGIN 0x01+/* Force matching to continue until the last character (same as $). */+#define REGEX_MATCH_END 0x02+/* Changes . to [^\r\n]+ Note: [...] and [^...] are NOT affected at all (as other regex engines do). */+#define REGEX_NEWLINE 0x04+/* Non greedy matching. In case of Thompson (non-recursive) algorithm,+ it (usually) does not have a significant speed gain. */+#define REGEX_MATCH_NON_GREEDY 0x08+/* Verbose. This define can be commented out, which disables all verbose features. */+#define REGEX_MATCH_VERBOSE 0x10++/* If error occures the function returns NULL, and the error code returned in error variable.+ You can pass NULL to error if you don't care about the error code.+ The re_flags argument contains the default REGEX_MATCH flags. See above. */+struct regex_machine* regex_compile(const regex_char_t *regex_string, int length, int re_flags, int *error);+void regex_free_machine(struct regex_machine *machine);++/* Create and init match structure for a given machine. */+struct regex_match* regex_begin_match(struct regex_machine *machine);+void regex_reset_match(struct regex_match *match);+void regex_free_match(struct regex_match *match);++/* Pattern matching.+ regex_continue_match does not support REGEX_MATCH_VERBOSE flag. */+void regex_continue_match(struct regex_match *match, const regex_char_t *input_string, int length);+int regex_get_result(struct regex_match *match, int *end, int *id);+/* Returns true, if the best match has already found. */+int regex_is_match_finished(struct regex_match *match);++/* Only exists if VERBOSE is defined in regexJIT.c+ Do both sanity check and verbose.+ (The latter only if REGEX_MATCH_VERBOSE was passed to regex_compile) */+void regex_continue_match_debug(struct regex_match *match, const regex_char_t *input_string, int length);++/* Misc. */+const char* regex_get_platform_name(void);++#ifdef __cplusplus+} /* extern "C" */+#endif++#endif
+ src/c/pcre2/deps/sljit/regex_src/regexMain.c view
@@ -0,0 +1,335 @@+/*+ * 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.+ */++/* Must be the first one. Must not depend on any other include. */+#include "sljitLir.h"+#include "regexJIT.h"++#include <stdio.h>++#if defined _WIN32 || defined _WIN64+#define COLOR_RED+#define COLOR_GREEN+#define COLOR_ARCH+#define COLOR_DEFAULT+#else+#define COLOR_RED "\33[31m"+#define COLOR_GREEN "\33[32m"+#define COLOR_ARCH "\33[33m"+#define COLOR_DEFAULT "\33[0m"+#endif++#ifdef REGEX_USE_8BIT_CHARS+#define S(str) str+#else+#define S(str) L##str+#endif++#ifdef REGEX_MATCH_VERBOSE+void verbose_test(regex_char_t *pattern, regex_char_t *string)+{+ int error;+ regex_char_t *ptr;+ struct regex_machine* machine;+ struct regex_match* match;+ int begin, end, id;++ ptr = pattern;+ while (*ptr)+ ptr++;++ printf("Start test '%s' matches to '%s'\n", pattern, string);+ machine = regex_compile(pattern, (int)(ptr - pattern), REGEX_MATCH_VERBOSE | REGEX_NEWLINE, &error);++ if (error) {+ printf("WARNING: Error %d\n", error);+ return;+ }+ if (!machine) {+ printf("ERROR: machine must be exists. Report this bug, please\n");+ return;+ }++ match = regex_begin_match(machine);+ if (!match) {+ printf("WARNING: Not enough memory for matching\n");+ regex_free_machine(machine);+ return;+ }++ ptr = string;+ while (*ptr)+ ptr++;++ regex_continue_match_debug(match, string, (int)(ptr - string));++ begin = regex_get_result(match, &end, &id);+ printf("Math returns: %3d->%3d [%3d]\n", begin, end, id);++ regex_free_match(match);+ regex_free_machine(machine);+}+#endif++struct test_case {+ int begin; /* Expected begin. */+ int end; /* Expected end. */+ int id; /* Expected id. */+ int finished; /* -1 : don't care, 0 : false, 1 : true. */+ int flags; /* REGEX_MATCH_* */+ const regex_char_t *pattern; /* NULL : use the previous pattern. */+ const regex_char_t *string; /* NULL : end of tests. */+};++static void run_tests(struct test_case* test, int verbose, int silent)+{+ int error;+ const regex_char_t *ptr;+ struct regex_machine* machine = NULL;+ struct regex_match* match;+ int begin, end, id, finished;+ int success = 0, fail = 0;++ if (!verbose && !silent)+ printf("Pass -v to enable verbose, -s to disable this hint.\n\n");++ for ( ; test->string ; test++) {+ if (verbose)+ printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string);+ fail++;++ if (test->pattern) {+ if (machine)+ regex_free_machine(machine);++ ptr = test->pattern;+ while (*ptr)+ ptr++;++ machine = regex_compile(test->pattern, (int)(ptr - test->pattern), test->flags, &error);++ if (error) {+ if (!verbose)+ printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string);+ printf("ABORT: Error %d\n", error);+ return;+ }+ if (!machine) {+ if (!verbose)+ printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string);+ printf("ABORT: machine must be exists. Report this bug, please\n");+ return;+ }+ }+ else if (test->flags != 0) {+ if (!verbose)+ printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string);+ printf("ABORT: flag must be 0 if no pattern\n");+ return;+ }++ ptr = test->string;+ while (*ptr)+ ptr++;++ match = regex_begin_match(machine);+#ifdef REGEX_MATCH_VERBOSE+ if (!match) {+ if (!verbose)+ printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string);+ printf("ABORT: Not enough memory for matching\n");+ regex_free_machine(machine);+ return;+ }+ regex_continue_match_debug(match, test->string, (int)(ptr - test->string));+ begin = regex_get_result(match, &end, &id);+ finished = regex_is_match_finished(match);++ if (begin != test->begin || end != test->end || id != test->id) {+ if (!verbose)+ printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string);+ printf("FAIL A: begin: %d != %d || end: %d != %d || id: %d != %d\n", test->begin, begin, test->end, end, test->id, id);+ continue;+ }+ if (test->finished != -1 && test->finished != !!finished) {+ if (!verbose)+ printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string);+ printf("FAIL A: finish check\n");+ continue;+ }+#endif++ regex_reset_match(match);+ regex_continue_match(match, test->string, (int)(ptr - test->string));+ begin = regex_get_result(match, &end, &id);+ finished = regex_is_match_finished(match);+ regex_free_match(match);++ if (begin != test->begin || end != test->end || id != test->id) {+ if (!verbose)+ printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string);+ printf("FAIL B: begin: %d != %d || end: %d != %d || id: %d != %d\n", test->begin, begin, test->end, end, test->id, id);+ continue;+ }+ if (test->finished != -1 && test->finished != !!finished) {+ if (!verbose)+ printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string);+ printf("FAIL B: finish check\n");+ continue;+ }++ if (verbose)+ printf("SUCCESS\n");+ fail--;+ success++;+ }+ if (machine)+ regex_free_machine(machine);++ printf("REGEX tests: ");+ if (fail == 0)+ printf("all tests " COLOR_GREEN "PASSED" COLOR_DEFAULT " ");+ else+ printf(COLOR_RED "%d" COLOR_DEFAULT " (" COLOR_RED "%d%%" COLOR_DEFAULT ") tests failed ", fail, fail * 100 / (success + fail));+ printf("on " COLOR_ARCH "%s" COLOR_DEFAULT "\n", regex_get_platform_name());+}++/* Testing. */++static struct test_case tests[] = {+{ 3, 7, 0, -1, 0,+ S("text"), S("is textile") },+{ 0, 10, 0, -1, 0,+ S("^(ab|c)*?d+(es)?"), S("abccabddeses") },+{ -1, 0, 0, 1, 0,+ S("^a+"), S("saaaa") },+{ 3, 6, 0, 0, 0,+ S("(a+|b+)$"), S("saabbb") },+{ 1, 6, 0, 0, 0,+ S("(a+|b+){,2}$"), S("saabbb") },+{ 1, 6, 0, 1, 0,+ S("(abcde|bc)(a+*|(b|c){2}+){0}"), S("babcdeaaaaaaaa") },+{ 1, 6, 0, 1, 0,+ S("(abc(aa)?|(cab+){2})"), S("cabcaa") },+{ -1, 0, 0, 1, 0,+ S("^(abc(aa)?|(cab+){2})$"), S("cabcaa") },+{ 0, 3, 1, -1, 0,+ S("^(ab{001!})?c"), S("abcde") },+{ 1, 15, 2, -1, 0,+ S("(c?(a|bb{2!}){2,3}()+d){2,3}"), S("ccabbadbbadcaadcaad") },+{ 2, 9, 0, -1, 0,+ NULL, S("cacaadaadaa") },+{ -1, 0, 0, -1, REGEX_MATCH_BEGIN,+ S("(((ab?c|d{1})))"), S("ad") },+{ 0, 9, 3, -1, REGEX_MATCH_BEGIN,+ S("^((a{1!}|b{2!}|c{3!}){3,6}d)+"), S("cabadbacddaa") },+{ 1, 6, 0, 0, REGEX_MATCH_END,+ S("(a+(bb|cc?)?){4,}"), S("maaaac") },+{ 3, 12, 1, 0, REGEX_MATCH_END,+ S("(x+x+{02,03}(x+|{1!})){03,06}$"), S("aaaxxxxxxxxx") },+{ 1, 2, 3, -1, 0,+ S("((c{1!})?|x+{2!}|{3!})(a|c)"), S("scs") },+{ 1, 4, 2, 1, 0,+ NULL, S("sxxaxxxaccacca") },+{ 0, 2, 1, 1, 0,+ NULL, S("ccdcdcdddddcdccccd") },+{ 0, 3, 0, -1, REGEX_MATCH_NON_GREEDY,+ S("^a+a+a+"), S("aaaaaa") },+{ 2, 5, 0, -1, REGEX_MATCH_NON_GREEDY,+ S("a+a+a+"), S("bbaaaaaa") },+{ 1, 4, 0, 1, 0,+ S("baa|a+"), S("sbaaaaaa") },+{ 0, 6, 0, 1, 0,+ S("baaa|baa|sbaaaa"), S("sbaaaaa") },+{ 1, 4, 0, 1, REGEX_MATCH_NON_GREEDY,+ S("baaa|baa"), S("xbaaa") },+{ 0, 0, 3, 1, 0,+ S("{3!}"), S("xx") },+{ 0, 0, 1, 1, 0,+ S("{1!}(a{2!})*"), S("xx") },+{ 0, 2, 2, 0, 0,+ NULL, S("aa") },+{ 0, 0, 1, 1, REGEX_MATCH_NON_GREEDY,+ S("{1!}(a{2!})*"), S("aaxx") },+{ 4, 12, 0, 1, 0,+ S("(.[]-]){3}[^]-]{2}"), S("ax-xs-[][]lmn") },+{ 3, 7, 1, 1, 0,+ S("([ABC]|[abc]{1!}){3,5}"), S("AbSAabbx") },+{ 0, 8, 3, 0, 0,+ S("^[x\\-y[\\]]+([[\\]]{3!})*$"), S("x-y[-][]") },+{ 0, 9, 0, 0, 0,+ NULL, S("x-y[-][]x") },+{ 2, 8, 0, 1, 0,+ S("<(/{1!})?[^>]+>"), S(" <html></html> ") },+{ 2, 9, 1, 1, 0,+ NULL, S(" </html><html> ") },+{ 2, 9, 0, 1, 0,+ S("[A-Z0-9a-z]+"), S("[(Iden9aA)]") },+{ 1, 4, 0, 1, 0,+ S("[^x-y]+[a-c_]{2,3}"), S("x_a_y") },+{ 4, 11, 0, 0, 0,+ NULL, S("ssaymmaa_ccl") },+{ 3, 6, 0, 1, REGEX_NEWLINE,+ S(".a[^k]"), S("\na\nxa\ns") },+{ 0, 2, 0, 1, REGEX_NEWLINE,+ S("^a+"), S("aa\n") },+{ 1, 4, 0, 1, 0 /* =REGEX_NEWLINE */,+ NULL, S("\naaa\n") },+{ 2, 3, 0, 1, 0 /* =REGEX_NEWLINE */,+ NULL, S("\n\na\n") },+{ 0, 2, 0, 1, REGEX_NEWLINE,+ S("a+$"), S("aa\n") },+{ 0, 3, 0, 0, 0 /* =REGEX_NEWLINE */,+ NULL, S("aaa") },+{ 2, 4, 1, 1, REGEX_NEWLINE,+ S("^a(a{1!})*$"), S("\n\naa\n\n") },+{ 0, 1, 0, 0, 0 /* REGEX_NEWLINE */,+ NULL, S("a") },+{ -1, 0, 0, -1, 0 /* REGEX_NEWLINE */,+ NULL, S("ab\nba") },+{ -1, 0, 0, 0, 0,+ NULL, NULL }+};++int main(int argc, char* argv[])+{+ int has_arg = (argc >= 2 && argv[1][0] == '-' && argv[1][2] == '\0');++/* verbose_test("a((b)((c|d))|)c|"); */+/* verbose_test("Xa{009,0010}Xb{,7}Xc{5,}Xd{,}Xe{1,}Xf{,1}X"); */+/* verbose_test("{3!}({3})({0!}){,"); */+/* verbose_test("(s(ab){2,4}t){2,}*S(a*(b)(c()|)d+){3,4}{0,0}*M"); */+/* verbose_test("^a({2!})*b+(a|{1!}b)+d$"); */+/* verbose_test("((a|b|c)*(xy)+)+", "asbcxyxy"); */++ run_tests(tests, has_arg && argv[1][1] == 'v', has_arg && argv[1][1] == 's');++#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)+ sljit_free_unused_memory_exec();+#endif /* !SLJIT_CONFIG_UNSUPPORTED */++ return 0;+}
+ src/c/pcre2/deps/sljit/sljit_src/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/deps/sljit/sljit_src/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 sljit_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* sljit_free_blocks;+static sljit_uw sljit_allocated_size;+static sljit_uw sljit_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 = sljit_free_blocks;+ free_block->prev = NULL;+ if (sljit_free_blocks)+ sljit_free_blocks->prev = free_block;+ sljit_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(sljit_free_blocks == free_block);+ sljit_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 = sljit_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;+ }+ sljit_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;+ sljit_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. */+ sljit_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. */+ sljit_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 */+ sljit_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 (sljit_allocated_size / 2) free space. */+ if (sljit_total_size - free_block->size > (sljit_allocated_size * 3 / 2)) {+ sljit_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 = sljit_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) {+ sljit_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(sljit_total_size || (!sljit_total_size && !sljit_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/deps/sljit/sljit_src/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/deps/sljit/sljit_src/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/deps/sljit/sljit_src/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/deps/sljit/sljit_src/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/deps/sljit/sljit_src/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/deps/sljit/sljit_src/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/deps/sljit/sljit_src/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/deps/sljit/sljit_src/sljitConfig.h 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.+ */++#ifndef SLJIT_CONFIG_H_+#define SLJIT_CONFIG_H_++#ifdef __cplusplus+extern "C" {+#endif /* __cplusplus */++/*+ This file contains the basic configuration options for the SLJIT compiler+ and their default values. These options can be overridden in the+ sljitConfigPre.h header file when SLJIT_HAVE_CONFIG_PRE is set to a+ non-zero value.+*/++/* --------------------------------------------------------------------- */+/* Utilities */+/* --------------------------------------------------------------------- */++/* Implements a stack like data structure (by using mmap / VirtualAlloc */+/* or a custom allocator). */+#ifndef SLJIT_UTIL_STACK+/* Enabled by default */+#define SLJIT_UTIL_STACK 1+#endif /* SLJIT_UTIL_STACK */++/* Uses user provided allocator to allocate the stack (see SLJIT_UTIL_STACK) */+#ifndef SLJIT_UTIL_SIMPLE_STACK_ALLOCATION+/* Disabled by default */+#define SLJIT_UTIL_SIMPLE_STACK_ALLOCATION 0+#endif /* SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */++/* Single threaded application. Does not require any locks. */+#ifndef SLJIT_SINGLE_THREADED+/* Disabled by default. */+#define SLJIT_SINGLE_THREADED 0+#endif /* SLJIT_SINGLE_THREADED */++/* --------------------------------------------------------------------- */+/* Configuration */+/* --------------------------------------------------------------------- */++/* If SLJIT_STD_MACROS_DEFINED is not defined, the application should+ define SLJIT_MALLOC, SLJIT_FREE, SLJIT_MEMCPY, and NULL. */+#ifndef SLJIT_STD_MACROS_DEFINED+/* Disabled by default. */+#define SLJIT_STD_MACROS_DEFINED 0+#endif /* SLJIT_STD_MACROS_DEFINED */++/* Executable code allocation:+ If SLJIT_EXECUTABLE_ALLOCATOR is not defined, the application should+ 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++/* When SLJIT_PROT_EXECUTABLE_ALLOCATOR is enabled SLJIT uses+ an allocator which does not set writable and executable+ permission flags at the same time.+ Instead, it creates a shared memory segment (usually backed by a file)+ and maps it twice, with different permissions, depending on the use+ case.+ The trade-off is increased use of virtual memory, incompatibility with+ fork(), and some possible additional security risks by the use of+ publicly accessible files for the generated code. */+#ifndef SLJIT_PROT_EXECUTABLE_ALLOCATOR+/* Disabled by default. */+#define SLJIT_PROT_EXECUTABLE_ALLOCATOR 0+#endif /* SLJIT_PROT_EXECUTABLE_ALLOCATOR */++/* When SLJIT_WX_EXECUTABLE_ALLOCATOR is enabled SLJIT uses an+ allocator which does not set writable and executable permission+ flags at the same time.+ Instead, it creates a new independent map on each invocation and+ switches permissions at the underlying pages as needed.+ The trade-off is increased memory use and degraded performance. */+#ifndef SLJIT_WX_EXECUTABLE_ALLOCATOR+/* Disabled by default. */+#define SLJIT_WX_EXECUTABLE_ALLOCATOR 0+#endif /* SLJIT_WX_EXECUTABLE_ALLOCATOR */++#endif /* !SLJIT_EXECUTABLE_ALLOCATOR */++/* Return with error when an invalid argument is passed. */+#ifndef SLJIT_ARGUMENT_CHECKS+/* Disabled by default */+#define SLJIT_ARGUMENT_CHECKS 0+#endif /* SLJIT_ARGUMENT_CHECKS */++/* Debug checks (assertions, etc.). */+#ifndef SLJIT_DEBUG+/* Enabled by default */+#define SLJIT_DEBUG 1+#endif /* SLJIT_DEBUG */++/* Verbose operations. */+#ifndef SLJIT_VERBOSE+/* Enabled by default */+#define SLJIT_VERBOSE 1+#endif /* SLJIT_VERBOSE */++/*+ SLJIT_IS_FPU_AVAILABLE+ The availability of the FPU can be controlled by SLJIT_IS_FPU_AVAILABLE.+ zero value - FPU is NOT present.+ nonzero value - FPU is present.+*/++/* For further configurations, see the beginning of sljitConfigInternal.h */++#ifdef __cplusplus+} /* extern "C" */+#endif /* __cplusplus */++#endif /* SLJIT_CONFIG_H_ */
+ src/c/pcre2/deps/sljit/sljit_src/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 /* SLJIT_CONFIG_ARM_V6 || SLJIT_CONFIG_ARM_V7 || SLJIT_CONFIG_ARM_THUMB2 */++#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/deps/sljit/sljit_src/sljitConfigInternal.h view
@@ -0,0 +1,1008 @@+/*+ * 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_INTERNAL_H_+#define SLJIT_CONFIG_INTERNAL_H_++/*+ SLJIT defines the following architecture dependent types and macros:++ Types:+ sljit_s8, sljit_u8 : signed and unsigned 8 bit integer type+ sljit_s16, sljit_u16 : signed and unsigned 16 bit integer type+ sljit_s32, sljit_u32 : signed and unsigned 32 bit integer type+ sljit_sw, sljit_uw : signed and unsigned machine word, enough to store a pointer+ sljit_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++ Macros for feature detection (boolean):+ SLJIT_32BIT_ARCHITECTURE : 32 bit architecture+ SLJIT_64BIT_ARCHITECTURE : 64 bit architecture+ SLJIT_LITTLE_ENDIAN : little endian architecture+ SLJIT_BIG_ENDIAN : big endian architecture+ 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+ SLJIT_UPPER_BITS_IGNORED : 32 bit operations ignores the upper bits of source registers+ SLJIT_UPPER_BITS_ZERO_EXTENDED : 32 bit operations clears the upper bits of destination registers+ SLJIT_UPPER_BITS_SIGN_EXTENDED : 32 bit operations replicates the sign bit in the upper bits of destination registers+ SLJIT_UPPER_BITS_PRESERVED : 32 bit operations preserves the upper bits of destination registers++ Constants:+ SLJIT_NUMBER_OF_REGISTERS : number of available registers+ SLJIT_NUMBER_OF_SCRATCH_REGISTERS : number of available scratch registers+ SLJIT_NUMBER_OF_SAVED_REGISTERS : number of available saved registers+ SLJIT_NUMBER_OF_FLOAT_REGISTERS : number of available floating point registers+ SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS : number of available scratch floating point registers+ SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS : number of available saved floating point registers+ SLJIT_NUMBER_OF_VECTOR_REGISTERS : number of available vector registers+ SLJIT_NUMBER_OF_SCRATCH_VECTOR_REGISTERS : number of available scratch vector registers+ SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS : number of available saved vector 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_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS : number of available temporary vector registers+ SLJIT_SEPARATE_VECTOR_REGISTERS : if this macro is defined, the vector registers do not+ overlap with floating point registers+ SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_sw/sljit_uw array by index+ SLJIT_POINTER_SHIFT : the shift required to apply when accessing a sljit_sp/sljit_up array by index+ SLJIT_F32_SHIFT : the shift required to apply when accessing+ a single precision floating point array by index+ SLJIT_F64_SHIFT : the shift required to apply when accessing+ a double precision floating point array by index+ SLJIT_PREF_SHIFT_REG : x86 systems prefers ecx for shifting by register+ 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_VR0 .. VR9 : accessing temporary vector registers+ SLJIT_TMP_VR(i) : accessing temporary vector registers+ SLJIT_TMP_DEST_REG : a temporary register for results, see the rules below+ SLJIT_TMP_DEST_FREG : a temporary register for float results, see the rules below+ SLJIT_TMP_DEST_VREG : a temporary register for vector results, see the rules below+ SLJIT_TMP_OPT_REG : a temporary register which might not be defined, see the rules below+ 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++ Temporary register rules (e.g. SLJIT_TMP_DEST_REG / SLJIT_TMP_OPT_REG):+ Sljit tries to emit instructions without using any temporary registers whenever it is possible.+ When a single temporary register is needed, it is always the "OPT" register. When two temporary+ registers are needed, both the "DEST" and "OPT" are used. The x86-32 does not define an "OPT"+ register, and handles all cases without an "OPT" register which requires an "OPT" register+ on other architectures.+*/++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \+ || (defined SLJIT_DEBUG && SLJIT_DEBUG && (!defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE)))+#include <stdio.h>+#endif++#if (defined SLJIT_DEBUG && SLJIT_DEBUG \+ && (!defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE) || !defined(SLJIT_HALT_PROCESS)))+#include <stdlib.h>+#endif++#ifdef __cplusplus+extern "C" {+#endif++/***********************************************************/+/* Intel Control-flow Enforcement Technology (CET) spport. */+/***********************************************************/++#ifdef SLJIT_CONFIG_X86++#if defined(__CET__) && !(defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET)+#define SLJIT_CONFIG_X86_CET 1+#endif++#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined(__GNUC__)+#include <x86intrin.h>+#endif++#endif /* SLJIT_CONFIG_X86 */++/**********************************/+/* External function definitions. */+/**********************************/++/* General macros:+ Note: SLJIT is designed to be independent from them as possible.++ In release mode (SLJIT_DEBUG is not defined) only the following+ external functions are needed:+*/++#ifndef SLJIT_MALLOC+#define SLJIT_MALLOC(size, allocator_data) (malloc(size))+#endif++#ifndef SLJIT_FREE+#define SLJIT_FREE(ptr, allocator_data) (free(ptr))+#endif++#ifndef SLJIT_MEMCPY+#define SLJIT_MEMCPY(dest, src, len) (memcpy(dest, src, len))+#endif++#ifndef SLJIT_MEMMOVE+#define SLJIT_MEMMOVE(dest, src, len) (memmove(dest, src, len))+#endif++#ifndef SLJIT_ZEROMEM+#define SLJIT_ZEROMEM(dest, len) (memset(dest, 0, len))+#endif++/***************************/+/* Compiler helper macros. */+/***************************/++#if !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY)++#if defined(__GNUC__) && (__GNUC__ >= 3)+#define SLJIT_LIKELY(x) __builtin_expect((x), 1)+#define SLJIT_UNLIKELY(x) __builtin_expect((x), 0)+#else+#define SLJIT_LIKELY(x) (x)+#define SLJIT_UNLIKELY(x) (x)+#endif++#endif /* !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY) */++#ifndef SLJIT_INLINE+/* Inline functions. Some old compilers do not support them. */+#ifdef __SUNPRO_C+#if __SUNPRO_C < 0x560+#define SLJIT_INLINE+#else+#define SLJIT_INLINE inline+#endif /* __SUNPRO_C */+#else+#define SLJIT_INLINE __inline+#endif+#endif /* !SLJIT_INLINE */++#ifndef SLJIT_NOINLINE+/* Not inline functions. */+#if defined(__GNUC__)+#define SLJIT_NOINLINE __attribute__ ((noinline))+#else+#define SLJIT_NOINLINE+#endif+#endif /* !SLJIT_INLINE */++#ifndef SLJIT_UNUSED_ARG+/* Unused arguments. */+#define SLJIT_UNUSED_ARG(arg) (void)arg+#endif++/*********************************/+/* Type of public API functions. */+/*********************************/++#ifndef SLJIT_API_FUNC_ATTRIBUTE+#if (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC)+/* Static ABI functions. For all-in-one programs. */++#if defined(__GNUC__)+/* Disable unused warnings in gcc. */+#define SLJIT_API_FUNC_ATTRIBUTE static __attribute__((unused))+#else+#define SLJIT_API_FUNC_ATTRIBUTE static+#endif++#else+#define SLJIT_API_FUNC_ATTRIBUTE+#endif /* (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC) */+#endif /* defined SLJIT_API_FUNC_ATTRIBUTE */++/****************************/+/* Instruction cache flush. */+/****************************/++#ifdef __APPLE__+#include <AvailabilityMacros.h>+#endif++/*+ * TODO:+ *+ * clang >= 15 could be safe to enable below+ * older versions are known to abort in some targets+ * https://github.com/PhilipHazel/pcre2/issues/92+ *+ * 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__)++/*+ * 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 is broken+ */+#if !defined(SLJIT_CONFIG_PPC)+#define SLJIT_CACHE_FLUSH(from, to) \+ __builtin___clear_cache((char*)(from), (char*)(to))+#endif++#endif /* gcc >= 10 */+#endif /* (!defined SLJIT_CACHE_FLUSH && defined __has_builtin) */++#ifndef SLJIT_CACHE_FLUSH++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \+ || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)++/* Not required to implement on archs with unified caches. */+#define SLJIT_CACHE_FLUSH(from, to)++#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,+ although the compilation is successful. */+#include <libkern/OSCacheControl.h>+#define SLJIT_CACHE_FLUSH(from, to) \+ sys_icache_invalidate((void*)(from), (size_t)((char*)(to) - (char*)(from)))++#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)++/* The __clear_cache() implementation of GCC is a dummy function on PowerPC. */+#define SLJIT_CACHE_FLUSH(from, to) \+ ppc_cache_flush((from), (to))+#define SLJIT_CACHE_FLUSH_OWN_IMPL 1++#elif defined(_WIN32)++#define SLJIT_CACHE_FLUSH(from, to) \+ FlushInstructionCache(GetCurrentProcess(), (void*)(from), (size_t)((char*)(to) - (char*)(from)))++#elif (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) || defined(__clang__)++#define SLJIT_CACHE_FLUSH(from, to) \+ __builtin___clear_cache((char*)(from), (char*)(to))++#elif defined __ANDROID__++/* Android ARMv7 with gcc lacks __clear_cache; use cacheflush instead. */+#include <sys/cachectl.h>+#define SLJIT_CACHE_FLUSH(from, to) \+ cacheflush((long)(from), (long)(to), 0)++#else++/* Call __ARM_NR_cacheflush on ARM-Linux or the corresponding MIPS syscall. */+#define SLJIT_CACHE_FLUSH(from, to) \+ __clear_cache((char*)(from), (char*)(to))++#endif++#endif /* !SLJIT_CACHE_FLUSH */++/******************************************************/+/* Integer and floating point type definitions. */+/******************************************************/++/* 8 bit byte type. */+typedef unsigned char sljit_u8;+typedef signed char sljit_s8;++/* 16 bit half-word type. */+typedef unsigned short int sljit_u16;+typedef signed short int sljit_s16;++/* 32 bit integer type. */+typedef unsigned int sljit_u32;+typedef signed int sljit_s32;++/* Machine word type. Enough for storing a pointer.+ 32 bit for 32 bit machines.+ 64 bit for 64 bit machines. */+#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)+/* Just to have something. */+#define SLJIT_WORD_SHIFT 0+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_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;+typedef int sljit_sw;+#else+#define SLJIT_64BIT_ARCHITECTURE 1+#define SLJIT_WORD_SHIFT 3+#ifdef _WIN32+#ifdef __GNUC__+/* These types do not require windows.h */+typedef unsigned long long sljit_uw;+typedef long long sljit_sw;+#else+typedef unsigned __int64 sljit_uw;+typedef __int64 sljit_sw;+#endif+#else /* !_WIN32 */+typedef unsigned long int sljit_uw;+typedef long int sljit_sw;+#endif /* _WIN32 */+#endif++typedef sljit_sw sljit_sp;+typedef sljit_uw sljit_up;++/* Floating point types. */+typedef float sljit_f32;+typedef double sljit_f64;++/* Shift for pointer sized data. */+#define SLJIT_POINTER_SHIFT SLJIT_WORD_SHIFT++/* Shift for double precision sized data. */+#define SLJIT_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_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)+#ifdef _WIN64+#define SLJIT_W(w) (w##ll)+#else /* !windows */+#define SLJIT_W(w) (w##l)+#endif /* windows */+#else /* 32 bit */+#define SLJIT_W(w) (w)+#endif /* unknown */++#endif /* !SLJIT_W */++/*************************/+/* Endianness detection. */+/*************************/++#if !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN)++/* These macros are mostly useful for the applications. */+#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)++#ifdef __LITTLE_ENDIAN__+#define SLJIT_LITTLE_ENDIAN 1+#else+#define SLJIT_BIG_ENDIAN 1+#endif++#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)++#ifdef __MIPSEL__+#define SLJIT_LITTLE_ENDIAN 1+#else+#define SLJIT_BIG_ENDIAN 1+#endif++#ifndef SLJIT_MIPS_REV++/* 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+#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).+ * It also sets the __mips macro to 64 or 32 for -mipsN when N <= 5+ * (should be set to N exactly) so we cannot rely on this too.+ */+#define SLJIT_MIPS_REV 1+#endif++#endif /* !SLJIT_MIPS_REV */++#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)++#define SLJIT_BIG_ENDIAN 1++#else+#define SLJIT_LITTLE_ENDIAN 1+#endif++#endif /* !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN) */++/* Sanity check. */+#if (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+#error "Exactly one endianness must be selected"+#endif++#if !(defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && !(defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+#error "Exactly one endianness must be selected"+#endif++#ifndef SLJIT_UNALIGNED++#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 && 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. */+#define SLJIT_DETECT_SSE2 1+#endif++/*****************************************************************************************/+/* Calling convention of functions generated by SLJIT or called from the generated code. */+/*****************************************************************************************/++#ifndef SLJIT_FUNC+#define SLJIT_FUNC+#endif /* !SLJIT_FUNC */++#ifndef SLJIT_INDIRECT_CALL+#if ((defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) && (!defined _CALL_ELF || _CALL_ELF == 1)) \+ || ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && defined _AIX)+/* It seems certain ppc compilers use an indirect addressing for functions+ which makes things complicated. */+#define SLJIT_INDIRECT_CALL 1+#endif+#endif /* SLJIT_INDIRECT_CALL */++/* The offset which needs to be subtracted from the return address to+determine the next executed instruction after return. */+#ifndef SLJIT_RETURN_ADDRESS_OFFSET+#define SLJIT_RETURN_ADDRESS_OFFSET 0+#endif /* SLJIT_RETURN_ADDRESS_OFFSET */++/***************************************************/+/* Functions of the built-in executable allocator. */+/***************************************************/++#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)+SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size);+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr);+/* Note: sljitLir.h also defines sljit_free_unused_memory_exec() function. */+#define SLJIT_BUILTIN_MALLOC_EXEC(size, exec_allocator_data) sljit_malloc_exec(size)+#define SLJIT_BUILTIN_FREE_EXEC(ptr, exec_allocator_data) sljit_free_exec(ptr)++#ifndef SLJIT_MALLOC_EXEC+#define SLJIT_MALLOC_EXEC(size, exec_allocator_data) SLJIT_BUILTIN_MALLOC_EXEC((size), (exec_allocator_data))+#endif /* SLJIT_MALLOC_EXEC */++#ifndef SLJIT_FREE_EXEC+#define SLJIT_FREE_EXEC(ptr, exec_allocator_data) SLJIT_BUILTIN_FREE_EXEC((ptr), (exec_allocator_data))+#endif /* SLJIT_FREE_EXEC */++#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)+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. */+/**********************************************/++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)++#define SLJIT_NUMBER_OF_REGISTERS 12+#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_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 1+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R0+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0+#define SLJIT_LOCALS_OFFSET_BASE (8 * (sljit_s32)sizeof(sljit_sw))+#define SLJIT_PREF_SHIFT_REG SLJIT_R2+#define SLJIT_MASKED_SHIFT 1+#define SLJIT_MASKED_SHIFT32 1+#define SLJIT_UPPER_BITS_IGNORED 1+#define SLJIT_UPPER_BITS_ZERO_EXTENDED 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+#define SLJIT_LOCALS_OFFSET_BASE 0+#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))+#endif /* !_WIN64 */+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R0+#define SLJIT_TMP_OPT_REG SLJIT_TMP_R1+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0+#define SLJIT_PREF_SHIFT_REG SLJIT_R3+#define SLJIT_MASKED_SHIFT 1+#define SLJIT_MASKED_SHIFT32 1+#define SLJIT_UPPER_BITS_IGNORED 1+#define SLJIT_UPPER_BITS_ZERO_EXTENDED 1++#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_OPT_REG SLJIT_TMP_R0+#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_OPT_REG SLJIT_TMP_R1+#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+#define SLJIT_UPPER_BITS_IGNORED 1+#define SLJIT_UPPER_BITS_ZERO_EXTENDED 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_OPT_REG SLJIT_TMP_R0+#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)+/* Add +1 for double alignment. */+#define SLJIT_LOCALS_OFFSET_BASE ((3 + 1) * (sljit_s32)sizeof(sljit_sw))+#else+#define SLJIT_LOCALS_OFFSET_BASE (3 * (sljit_s32)sizeof(sljit_sw))+#endif /* SLJIT_CONFIG_PPC_64 || _AIX */+#define SLJIT_UPPER_BITS_IGNORED 1++#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)++#define SLJIT_NUMBER_OF_REGISTERS 21+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+#define SLJIT_LOCALS_OFFSET_BASE (4 * (sljit_s32)sizeof(sljit_sw))+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 13+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 6+#else+#define SLJIT_LOCALS_OFFSET_BASE 0+#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_OPT_REG SLJIT_TMP_R0+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0+#define SLJIT_MASKED_SHIFT 1+#define SLJIT_MASKED_SHIFT32 1+#define SLJIT_UPPER_BITS_SIGN_EXTENDED 1++#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)++#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_SEPARATE_VECTOR_REGISTERS 1+#define SLJIT_NUMBER_OF_VECTOR_REGISTERS 30+#define SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS 0+#define SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS 2+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1+#define SLJIT_TMP_OPT_REG SLJIT_TMP_R0+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0+#define SLJIT_TMP_DEST_VREG SLJIT_TMP_VR0+#define SLJIT_LOCALS_OFFSET_BASE 0+#define SLJIT_MASKED_SHIFT 1+#define SLJIT_MASKED_SHIFT32 1+#define SLJIT_UPPER_BITS_IGNORED 1+#define SLJIT_UPPER_BITS_SIGN_EXTENDED 1++#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)++/*+ * https://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_zSeries.html#STACKFRAME+ *+ * 160+ * .. FR6+ * .. FR4+ * .. FR2+ * 128 FR0+ * 120 R15 (used for SP)+ * 112 R14+ * 104 R13+ * 96 R12+ * ..+ * 48 R6+ * ..+ * 16 R2+ * 8 RESERVED+ * 0 SP+ */+#define SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE 160++#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_R2+#define SLJIT_TMP_OPT_REG SLJIT_TMP_R1+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0+#define SLJIT_LOCALS_OFFSET_BASE SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE+#define SLJIT_MASKED_SHIFT 1+#define SLJIT_UPPER_BITS_IGNORED 1+#define SLJIT_UPPER_BITS_PRESERVED 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_OPT_REG SLJIT_TMP_R0+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0+#define SLJIT_LOCALS_OFFSET_BASE 0+#define SLJIT_MASKED_SHIFT 1+#define SLJIT_MASKED_SHIFT32 1+#define SLJIT_UPPER_BITS_SIGN_EXTENDED 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_DEST_FREG 0+#define SLJIT_LOCALS_OFFSET_BASE 0++#endif++#if !(defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS)+#define SLJIT_NUMBER_OF_VECTOR_REGISTERS (SLJIT_NUMBER_OF_FLOAT_REGISTERS)+#define SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS (SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS)+#define SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS (SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS)+#define SLJIT_TMP_DEST_VREG (SLJIT_TMP_DEST_FREG)+#endif /* !SLJIT_SEPARATE_VECTOR_REGISTERS */++#define SLJIT_LOCALS_OFFSET (SLJIT_LOCALS_OFFSET_BASE)++#define SLJIT_NUMBER_OF_SCRATCH_REGISTERS \+ (SLJIT_NUMBER_OF_REGISTERS - SLJIT_NUMBER_OF_SAVED_REGISTERS)++#define SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS \+ (SLJIT_NUMBER_OF_FLOAT_REGISTERS - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS)++#define SLJIT_NUMBER_OF_SCRATCH_VECTOR_REGISTERS \+ (SLJIT_NUMBER_OF_VECTOR_REGISTERS - SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS)++#if (defined SLJIT_UPPER_BITS_ZERO_EXTENDED && SLJIT_UPPER_BITS_ZERO_EXTENDED) \+ + (defined SLJIT_UPPER_BITS_SIGN_EXTENDED && SLJIT_UPPER_BITS_SIGN_EXTENDED) \+ + (defined SLJIT_UPPER_BITS_PRESERVED && SLJIT_UPPER_BITS_PRESERVED) > 1+#error "Invalid upper bits defintion"+#endif++#if (defined SLJIT_UPPER_BITS_PRESERVED && SLJIT_UPPER_BITS_PRESERVED) \+ && !(defined SLJIT_UPPER_BITS_IGNORED && SLJIT_UPPER_BITS_IGNORED)+#error "Upper bits preserved requires bits ignored"+#endif++/**********************************/+/* Temporary register management. */+/**********************************/++#define SLJIT_TMP_REGISTER_BASE (SLJIT_NUMBER_OF_REGISTERS + 2)+#define SLJIT_TMP_FREGISTER_BASE (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)+#define SLJIT_TMP_VREGISTER_BASE (SLJIT_NUMBER_OF_VECTOR_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))++#define SLJIT_TMP_VR0 (SLJIT_TMP_VREGISTER_BASE + 0)+#define SLJIT_TMP_VR1 (SLJIT_TMP_VREGISTER_BASE + 1)+#define SLJIT_TMP_VR2 (SLJIT_TMP_VREGISTER_BASE + 2)+#define SLJIT_TMP_VR3 (SLJIT_TMP_VREGISTER_BASE + 3)+#define SLJIT_TMP_VR4 (SLJIT_TMP_VREGISTER_BASE + 4)+#define SLJIT_TMP_VR5 (SLJIT_TMP_VREGISTER_BASE + 5)+#define SLJIT_TMP_VR6 (SLJIT_TMP_VREGISTER_BASE + 6)+#define SLJIT_TMP_VR7 (SLJIT_TMP_VREGISTER_BASE + 7)+#define SLJIT_TMP_VR8 (SLJIT_TMP_VREGISTER_BASE + 8)+#define SLJIT_TMP_VR9 (SLJIT_TMP_VREGISTER_BASE + 9)+#define SLJIT_TMP_VR(i) (SLJIT_TMP_VREGISTER_BASE + (i))++/********************************/+/* CPU status flags management. */+/********************************/++#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_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. */+/*************************************/++#if (defined SLJIT_DEBUG && SLJIT_DEBUG)++#if !defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE)++/* SLJIT_HALT_PROCESS must halt the process. */+#ifndef SLJIT_HALT_PROCESS+#define SLJIT_HALT_PROCESS() \+ abort();+#endif /* !SLJIT_HALT_PROCESS */++#endif /* !SLJIT_ASSERT || !SLJIT_UNREACHABLE */++/* Feel free to redefine these two macros. */+#ifndef SLJIT_ASSERT++#define SLJIT_ASSERT(x) \+ do { \+ if (SLJIT_UNLIKELY(!(x))) { \+ printf("Assertion failed at " __FILE__ ":%d\n", __LINE__); \+ SLJIT_HALT_PROCESS(); \+ } \+ } while (0)++#endif /* !SLJIT_ASSERT */++#ifndef SLJIT_UNREACHABLE++#define SLJIT_UNREACHABLE() \+ do { \+ printf("Should never been reached " __FILE__ ":%d\n", __LINE__); \+ SLJIT_HALT_PROCESS(); \+ } while (0)++#endif /* !SLJIT_UNREACHABLE */++#else /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */++/* Forcing empty, but valid statements. */+#undef SLJIT_ASSERT+#undef SLJIT_UNREACHABLE++#define SLJIT_ASSERT(x) \+ do { } while (0)+#define SLJIT_UNREACHABLE() \+ do { } while (0)++#endif /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */++#ifndef SLJIT_COMPILE_ASSERT++#define SLJIT_COMPILE_ASSERT(x, description) \+ switch(0) { case 0: case ((x) ? 1 : 0): break; }++#endif /* !SLJIT_COMPILE_ASSERT */++#ifndef SLJIT_FALLTHROUGH++#if defined(__cplusplus) && __cplusplus >= 202002L && \+ defined(__has_cpp_attribute)+/* Standards-compatible C++ variant. */+#if __has_cpp_attribute(fallthrough)+#define SLJIT_FALLTHROUGH [[fallthrough]];+#endif+#elif !defined(__cplusplus) && \+ defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L && \+ defined(__has_c_attribute)+/* Standards-compatible C variant. */+#if __has_c_attribute(fallthrough)+#define SLJIT_FALLTHROUGH [[fallthrough]];+#endif+#elif ((defined(__clang__) && __clang_major__ >= 10) || \+ (defined(__GNUC__) && __GNUC__ >= 7)) && \+ defined(__has_attribute)+/* Clang and GCC syntax. Rule out old versions because apparently Clang at+ least has a broken implementation of __has_attribute. */+#if __has_attribute(fallthrough)+#define SLJIT_FALLTHROUGH __attribute__((fallthrough));+#endif+#endif++#ifndef SLJIT_FALLTHROUGH+#define SLJIT_FALLTHROUGH+#endif++#endif /* !SLJIT_FALLTHROUGH */++#ifdef __cplusplus+} /* extern "C" */+#endif++#endif /* SLJIT_CONFIG_INTERNAL_H_ */
+ src/c/pcre2/deps/sljit/sljit_src/sljitLir.c view
@@ -0,0 +1,3925 @@+/*+ * 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 "sljitLir.h"++#ifdef _WIN32++#include <windows.h>++#endif /* _WIN32 */++#if !(defined SLJIT_STD_MACROS_DEFINED && SLJIT_STD_MACROS_DEFINED)++/* These libraries are needed for the macros below. */+#include <stdlib.h>+#include <string.h>++#endif /* SLJIT_STD_MACROS_DEFINED */++#define CHECK_ERROR() \+ do { \+ if (SLJIT_UNLIKELY(compiler->error)) \+ return compiler->error; \+ } while (0)++#define CHECK_ERROR_PTR() \+ do { \+ if (SLJIT_UNLIKELY(compiler->error)) \+ return NULL; \+ } while (0)++#define FAIL_IF(expr) \+ do { \+ if (SLJIT_UNLIKELY(expr)) \+ return compiler->error; \+ } while (0)++#define PTR_FAIL_IF(expr) \+ do { \+ if (SLJIT_UNLIKELY(expr)) \+ return NULL; \+ } while (0)++#define FAIL_IF_NULL(ptr) \+ do { \+ if (SLJIT_UNLIKELY(!(ptr))) { \+ compiler->error = SLJIT_ERR_ALLOC_FAILED; \+ return SLJIT_ERR_ALLOC_FAILED; \+ } \+ } while (0)++#define PTR_FAIL_IF_NULL(ptr) \+ do { \+ if (SLJIT_UNLIKELY(!(ptr))) { \+ compiler->error = SLJIT_ERR_ALLOC_FAILED; \+ return NULL; \+ } \+ } while (0)++#define PTR_FAIL_WITH_EXEC_IF(ptr) \+ do { \+ if (SLJIT_UNLIKELY(!(ptr))) { \+ compiler->error = SLJIT_ERR_EX_ALLOC_FAILED; \+ return NULL; \+ } \+ } while (0)++#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)++#define SSIZE_OF(type) ((sljit_s32)sizeof(sljit_ ## type))++#define VARIABLE_FLAG_SHIFT (10)+/* All variable flags are even. */+#define VARIABLE_FLAG_MASK (0x3e << VARIABLE_FLAG_SHIFT)+#define ALL_STATUS_FLAGS_MASK (VARIABLE_FLAG_MASK | SLJIT_SET_Z)+#define GET_FLAG_TYPE(op) ((op) >> VARIABLE_FLAG_SHIFT)+#define GET_FLAG_TYPE_MASK(op) (((op) >> VARIABLE_FLAG_SHIFT) & 0x3e)+#define GET_OPCODE(op) ((op) & 0xff)+#define HAS_FLAGS(op) ((op) & ALL_STATUS_FLAGS_MASK)+#define GET_ALL_FLAGS(op) ((op) & (SLJIT_32 | ALL_STATUS_FLAGS_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 /* !SLJIT_32BIT_ARCHITECTURE */+#define ABUF_SIZE 4096+#endif /* SLJIT_32BIT_ARCHITECTURE */++/* 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 ENTER_GET_REGS(regs) ((regs) & 0xff)+#define ENTER_GET_FLOAT_REGS(regs) (((regs) >> 8) & 0xff)+#define ENTER_GET_VECTOR_REGS(regs) (((regs) >> 16) & 0xff)+#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)))++/* Label definitions. */++#define SLJIT_LABEL_ALIGNED ((~(sljit_uw)0) - 1)++struct sljit_extended_label {+ struct sljit_label label;+ sljit_uw index;+ sljit_uw data;+};++/* Jump definitions. */++/* Jump flag bits. */+#define JUMP_ADDR 0x1+#define JUMP_MOV_ADDR 0x2+/* SLJIT_REWRITABLE_JUMP is 0x10000. */++#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 17+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)+/* Bits 7..15 is for debug jump size, SLJIT_REWRITABLE_JUMP is 0x10000 */+# define JUMP_SIZE_SHIFT 8+#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)+/* SLJIT_REWRITABLE_JUMP is 0x10000. */+# 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)+/* SLJIT_REWRITABLE_JUMP is 0x10000. */+# define IS_COND 0x04+# define IS_BL 0x08+ /* mov_addr does not use IS_BL */+# define IS_ABS IS_BL+ /* 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)+/* SLJIT_REWRITABLE_JUMP is 0x10000. */+# 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)+/* SLJIT_REWRITABLE_JUMP is 0x10000. */+# 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)+/* SLJIT_REWRITABLE_JUMP is 0x10000. */+# 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)+/* SLJIT_REWRITABLE_JUMP is 0x10000. */+# define IS_COND 0x0004+# define IS_CALL 0x0008++# define IS_COND16 0x0010+# define PATCH_B 0x0020+# define PATCH_J 0x0040+# define PATCH_16 0x0080++#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+# define PATCH_REL32 0x0100+# define PATCH_ABS32 0x0200+# define PATCH_ABS44 0x0400+# define PATCH_ABS52 0x0800+# define JUMP_SIZE_SHIFT 58+# define JUMP_MAX_SIZE ((sljit_uw)12)+#else /* !SLJIT_CONFIG_RISCV_64 */+# define JUMP_SIZE_SHIFT 26+# define JUMP_MAX_SIZE ((sljit_uw)4)+#endif /* SLJIT_CONFIG_RISCV_64 */+#endif /* SLJIT_CONFIG_RISCV */++#if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)+/* SLJIT_REWRITABLE_JUMP is 0x10000. */+# define PATCH_POOL 0x004+# define PATCH_IMM32 0x008+#endif /* SLJIT_CONFIG_S390X */++#if (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)+/* SLJIT_REWRITABLE_JUMP is 0x10000. */+# 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 /* !__NetBSD__ */+#include "allocator_src/sljitProtExecAllocatorPosix.c"+#endif /* __NetBSD__ */++#elif (defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR)++#if defined(_WIN32)+#include "allocator_src/sljitWXExecAllocatorWindows.c"+#else /* !_WIN32 */+#include "allocator_src/sljitWXExecAllocatorPosix.c"+#endif /* _WIN32 */++#else /* !SLJIT_PROT_EXECUTABLAE_ALLOCATOR && !SLJIT_WX_EXECUTABLE_ALLOCATOR */++#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 /* !_WIN32 && !__APPLE__ && !__FreeBSD__ */+#include "allocator_src/sljitExecAllocatorPosix.c"+#endif /* _WIN32 */++#endif /* SLJIT_PROT_EXECUTABLE_ALLOCATOR */++#else /* !SLJIT_EXECUTABLE_ALLOCATOR */++#ifndef SLJIT_UPDATE_WX_FLAGS+#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)+#endif /* SLJIT_UPDATE_WX_FLAGS */++#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 /* !SLJIT_PROT_EXECUTABLE_ALLOCATOR */+#define SLJIT_ADD_EXEC_OFFSET(ptr, exec_offset) ((sljit_u8 *)(ptr))+#endif /* SLJIT_PROT_EXECUTABLE_ALLOCATOR */++/* 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 /* !SLJIT_ARGUMENT_CHECKS && !SLJIT_DEBUG && !SLJIT_VERBOSE */++/* 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) || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)+#define SLJIT_NEEDS_COMPILER_INIT 1+static sljit_s32 compiler_initialized = 0;+/* A thread safe initialization. */+static void init_compiler(void);+#endif /* SLJIT_CONFIG_X86 || SLJIT_CONFIG_RISCV */++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) == 0+ && (ALL_STATUS_FLAGS_MASK & SLJIT_32) == 0+ && (SLJIT_REWRITABLE_JUMP & ALL_STATUS_FLAGS_MASK) == 0,+ rewritable_jump_and_status_flag_bits_and_sljit_32_must_not_have_common_bits);+ SLJIT_COMPILE_ASSERT((VARIABLE_FLAG_MASK & SLJIT_SET_Z) == 0,+ rewritable_jump_and_status_flag_bits_must_not_have_common_bits);+ 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;+#if (defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \+ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ compiler->vscratches = -1;+ compiler->vsaveds = -1;+#endif /* SLJIT_SEPARATE_VECTOR_REGISTERS || SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */+ 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)+ SLJIT_ASSERT(compiler->last_flags == 0 && compiler->logical_local_size == 0);+ compiler->last_return = -1;+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \+ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+#if !(defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS)+ compiler->real_fscratches = -1;+ compiler->real_fsaveds = -1;+#endif /* !SLJIT_SEPARATE_VECTOR_REGISTERS */+ SLJIT_ASSERT(compiler->skip_checks == 0);+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */++#if (defined SLJIT_NEEDS_COMPILER_INIT && SLJIT_NEEDS_COMPILER_INIT)+ if (!compiler_initialized) {+ init_compiler();+ compiler_initialized = 1;+ }+#endif /* SLJIT_NEEDS_COMPILER_INIT */++ 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_CONFIG_ARM_V6 */+ 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_CURRENT_FLAGS_OP2CMPZ)++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)+#if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)+ if (current_flags & SLJIT_CURRENT_FLAGS_OP2CMPZ) {+ current_flags |= SLJIT_SET_Z;+ }+#endif /* SLJIT_CONFIG_S390X */++ compiler->status_flags_state = current_flags;+#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->last_flags = 0;+ if ((current_flags & ~(ALL_STATUS_FLAGS_MASK | SLJIT_CURRENT_FLAGS_ALL)) == 0) {+ compiler->last_flags = GET_FLAG_TYPE(current_flags) | (current_flags & (SLJIT_32 | SLJIT_SET_Z));+ }+#endif /* SLJIT_ARGUMENT_CHECKS */+}++/* --------------------------------------------------------------------- */+/* 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 /* !SLJIT_64BIT_ARCHITECTURE */+ if (size <= 0 || size > 64)+ return NULL;+ size = (size + 3) & ~3;+#endif /* SLJIT_64BIT_ARCHITECTURE */+ 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 */++#if !(defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS)++static void update_float_register_count(struct sljit_compiler *compiler, sljit_s32 scratches, sljit_s32 saveds)+{+ sljit_s32 vscratches = ENTER_GET_VECTOR_REGS(scratches);+ sljit_s32 vsaveds = ENTER_GET_VECTOR_REGS(saveds);++ if (compiler->fscratches < vscratches)+ compiler->fscratches = vscratches;++ if (compiler->fsaveds < vsaveds)+ compiler->fsaveds = vsaveds;++ if (compiler->fsaveds + compiler->fscratches > SLJIT_NUMBER_OF_FLOAT_REGISTERS)+ compiler->fscratches = SLJIT_NUMBER_OF_FLOAT_REGISTERS - compiler->fsaveds;+}++#endif /* !SLJIT_SEPARATE_VECTOR_REGISTERS */++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 local_size)+{+ SLJIT_UNUSED_ARG(args);+ SLJIT_UNUSED_ARG(local_size);++ compiler->options = options;+ compiler->scratches = ENTER_GET_REGS(scratches);+ compiler->saveds = ENTER_GET_REGS(saveds);+ /* These members may be copied to real_* members below. */+ compiler->fscratches = ENTER_GET_FLOAT_REGS(scratches);+ compiler->fsaveds = ENTER_GET_FLOAT_REGS(saveds);+#if (defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS)+ compiler->vscratches = ENTER_GET_VECTOR_REGS(scratches);+ compiler->vsaveds = ENTER_GET_VECTOR_REGS(saveds);+#else /* !SLJIT_SEPARATE_VECTOR_REGISTERS */+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \+ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ compiler->real_fscratches = compiler->fscratches;+ compiler->real_fsaveds = compiler->fsaveds;+ compiler->vscratches = ENTER_GET_VECTOR_REGS(scratches);+ compiler->vsaveds = ENTER_GET_VECTOR_REGS(saveds);+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */+ update_float_register_count(compiler, scratches, saveds);+#endif /* SLJIT_SEPARATE_VECTOR_REGISTERS */+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ compiler->last_return = args & SLJIT_ARG_MASK;+ compiler->logical_local_size = local_size;+#endif /* SLJIT_ARGUMENT_CHECKS */+}++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_extended_label(struct sljit_extended_label *ext_label, struct sljit_compiler *compiler, sljit_uw type, sljit_uw data)+{+ set_label(&ext_label->label, compiler);+ ext_label->index = ext_label->label.u.index;+ ext_label->label.u.index = type;+ ext_label->data = data;+}++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 /* !SLJIT_CONFIG_X86_32 */+#define CHECK_IF_VIRTUAL_REGISTER(p) 0+#endif /* SLJIT_CONFIG_X86_32 */++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);+}++static sljit_s32 function_check_is_vreg(struct sljit_compiler *compiler, sljit_s32 vr, sljit_s32 type);++#define FUNCTION_CHECK_IS_VREG(vr, type) \+ function_check_is_vreg(compiler, (vr), (type))++#define FUNCTION_VCHECK(p, i, type) \+ CHECK_ARGUMENT(function_vcheck(compiler, (p), (i), (type)))++static sljit_s32 function_vcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i, sljit_s32 type)+{+ if (compiler->scratches == -1)+ return 0;++ if (FUNCTION_CHECK_IS_VREG(p, type))+ 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)+{+ sljit_s32 fscratches, fsaveds;++ if (compiler->scratches == -1)+ return 0;++#if (defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS)+ fscratches = compiler->fscratches;+ fsaveds = compiler->fsaveds;+#else /* SLJIT_SEPARATE_VECTOR_REGISTERS */+ fscratches = compiler->real_fscratches;+ fsaveds = compiler->real_fsaveds;+#endif /* !SLJIT_SEPARATE_VECTOR_REGISTERS */++ return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + fscratches))+ || (fr > (SLJIT_FS0 - 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 (function_check_is_freg(compiler, p))+ return (i == 0);++ return function_check_src_mem(compiler, p, i);+}++#define FUNCTION_CHECK_IS_VREG(vr, type) \+ function_check_is_vreg(compiler, (vr))++static sljit_s32 function_check_is_vreg(struct sljit_compiler *compiler, sljit_s32 vr)+{+ if (compiler->scratches == -1)+ return 0;++ return (vr >= SLJIT_VR0 && vr < (SLJIT_VR0 + compiler->vscratches))+ || (vr > (SLJIT_VS0 - compiler->vsaveds) && vr <= SLJIT_VS0)+ || (vr >= SLJIT_TMP_VREGISTER_BASE && vr < (SLJIT_TMP_VREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS));+}++#define FUNCTION_VCHECK(p, i, type) \+ CHECK_ARGUMENT(function_vcheck(compiler, (p), (i)))++static sljit_s32 function_vcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)+{+ if (compiler->scratches == -1)+ return 0;++ if (function_check_is_vreg(compiler, p))+ 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 /* !__GNUC__ */+# define SLJIT_PRINT_D "I64"+#endif /* __GNUC__ */+#else /* !_WIN64 */+# define SLJIT_PRINT_D "l"+#endif /* _WIN64 */+#else /* !SLJIT_64BIT_ARCHITECTURE */+# define SLJIT_PRINT_D ""+#endif /* SLJIT_64BIT_ARCHITECTURE */++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_vreg(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_VR0)) {+ fprintf(compiler->verbose, "^");+ r -= SLJIT_F64_SECOND(0);+ }+#endif /* SLJIT_CONFIG_ARM_32 || SLJIT_CONFIG_MIPS_32 */++ if (r < (SLJIT_VR0 + compiler->vscratches))+ fprintf(compiler->verbose, "vr%d", r - SLJIT_VR0);+ else if (r < SLJIT_TMP_VREGISTER_BASE)+ fprintf(compiler->verbose, "vs%d", SLJIT_NUMBER_OF_VECTOR_REGISTERS - r);+ else+ fprintf(compiler->verbose, "vt%d", r - SLJIT_TMP_VREGISTER_BASE);+}++static void sljit_verbose_mem(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)+{+ if (!(p & REG_MASK)) {+ fprintf(compiler->verbose, "[%" SLJIT_PRINT_D "d]", i);+ return;+ }++ 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);+}++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)+ sljit_verbose_mem(compiler, p, 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)+ sljit_verbose_mem(compiler, p, i);+ else+ sljit_verbose_freg(compiler, p);+}++static void sljit_verbose_vparam(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)+{+ if (p & SLJIT_MEM)+ sljit_verbose_mem(compiler, p, i);+ else+ sljit_verbose_vreg(compiler, p);+}++static const char* op0_names[] = {+ "breakpoint", "nop", "lmul.uw", "lmul.sw",+ "divmod.u", "divmod.s", "div.u", "div.s",+ "memory_barrier", "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", "shuffle"+};++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"+};++static const char* op_addr_types[] = {+ "mov_addr", "mov_abs_addr", "add_abs_addr"+};++#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+#define SLJIT_CHECK_OPCODE(op, flags) ((op) & ~(SLJIT_32 | ALL_STATUS_FLAGS_MASK | (flags)))++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ struct sljit_jump *jump;+#endif /* SLJIT_ARGUMENT_CHECKS */++ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(options);++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(compiler->size > 0);+ CHECK_ARGUMENT((options & ~(SLJIT_GENERATE_CODE_BUFFER | SLJIT_GENERATE_CODE_NO_CONTEXT)) == 0);++ jump = compiler->jumps;+ while (jump) {+ /* All jumps have target. */+ CHECK_ARGUMENT((jump->flags & JUMP_ADDR) || jump->u.label != NULL);+ jump = jump->next;+ }+#endif /* SLJIT_ARGUMENT_CHECKS */+ 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 local_size)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ sljit_s32 real_scratches = ENTER_GET_REGS(scratches);+ sljit_s32 real_saveds = ENTER_GET_REGS(saveds);+ sljit_s32 real_fscratches = ENTER_GET_FLOAT_REGS(scratches);+ sljit_s32 real_fsaveds = ENTER_GET_FLOAT_REGS(saveds);+ sljit_s32 real_vscratches = ENTER_GET_VECTOR_REGS(scratches);+ sljit_s32 real_vsaveds = ENTER_GET_VECTOR_REGS(saveds);+#endif /* SLJIT_ARGUMENT_CHECKS */+ 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 & ~0xffffff) == 0 && (saveds & ~0xffffff) == 0);+ CHECK_ARGUMENT(real_scratches >= 0 && real_scratches <= SLJIT_NUMBER_OF_REGISTERS);+ CHECK_ARGUMENT(real_saveds >= 0 && real_saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);+ CHECK_ARGUMENT(real_scratches + real_saveds <= SLJIT_NUMBER_OF_REGISTERS);+ CHECK_ARGUMENT(real_fscratches >= 0 && real_fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);+ CHECK_ARGUMENT(real_fsaveds >= 0 && real_fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS);+ CHECK_ARGUMENT(real_fscratches + real_fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);+ CHECK_ARGUMENT(real_vscratches >= 0 && real_vscratches <= SLJIT_NUMBER_OF_VECTOR_REGISTERS);+ CHECK_ARGUMENT(real_vsaveds >= 0 && real_vsaveds <= SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS);+ CHECK_ARGUMENT(real_vscratches + real_vsaveds <= SLJIT_NUMBER_OF_VECTOR_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, real_scratches,+ (options & SLJIT_ENTER_REG_ARG) ? 0 : real_saveds, real_fscratches));++ compiler->last_flags = 0;+#endif /* SLJIT_ARGUMENT_CHECKS */+#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, vscratches:%d, vsaveds:%d, local_size:%d\n",+ ENTER_GET_REGS(scratches), ENTER_GET_REGS(saveds), ENTER_GET_FLOAT_REGS(scratches), ENTER_GET_FLOAT_REGS(saveds),+ ENTER_GET_VECTOR_REGS(scratches), ENTER_GET_VECTOR_REGS(saveds), local_size);+ }+#endif /* SLJIT_VERBOSE */+ 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 local_size)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ sljit_s32 real_scratches = ENTER_GET_REGS(scratches);+ sljit_s32 real_saveds = ENTER_GET_REGS(saveds);+ sljit_s32 real_fscratches = ENTER_GET_FLOAT_REGS(scratches);+ sljit_s32 real_fsaveds = ENTER_GET_FLOAT_REGS(saveds);+ sljit_s32 real_vscratches = ENTER_GET_VECTOR_REGS(scratches);+ sljit_s32 real_vsaveds = ENTER_GET_VECTOR_REGS(saveds);+#endif /* SLJIT_ARGUMENT_CHECKS */+ 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 & ~0xffffff) == 0 && (saveds & ~0xffffff) == 0);+ CHECK_ARGUMENT(real_scratches >= 0 && real_scratches <= SLJIT_NUMBER_OF_REGISTERS);+ CHECK_ARGUMENT(real_saveds >= 0 && real_saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);+ CHECK_ARGUMENT(real_scratches + real_saveds <= SLJIT_NUMBER_OF_REGISTERS);+ CHECK_ARGUMENT(real_fscratches >= 0 && real_fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);+ CHECK_ARGUMENT(real_fsaveds >= 0 && real_fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS);+ CHECK_ARGUMENT(real_fscratches + real_fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);+ CHECK_ARGUMENT(real_vscratches >= 0 && real_vscratches <= SLJIT_NUMBER_OF_VECTOR_REGISTERS);+ CHECK_ARGUMENT(real_vsaveds >= 0 && real_vsaveds <= SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS);+ CHECK_ARGUMENT(real_vscratches + real_vsaveds <= SLJIT_NUMBER_OF_VECTOR_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, real_scratches,+ (options & SLJIT_ENTER_REG_ARG) ? 0 : real_saveds, real_fscratches));++ compiler->last_flags = 0;+#endif /* SLJIT_ARGUMENT_CHECKS */+#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, vscratches:%d, vsaveds:%d, local_size:%d\n",+ ENTER_GET_REGS(scratches), ENTER_GET_REGS(saveds), ENTER_GET_FLOAT_REGS(scratches), ENTER_GET_FLOAT_REGS(saveds),+ ENTER_GET_VECTOR_REGS(scratches), ENTER_GET_VECTOR_REGS(saveds), local_size);+ }+#endif /* SLJIT_VERBOSE */+ 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 /* SLJIT_ARGUMENT_CHECKS */++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " return_void\n");+ }+#endif /* SLJIT_VERBOSE */+ 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 (SLJIT_CHECK_OPCODE(op, 0) < SLJIT_MOV_F64) {+ FUNCTION_CHECK_SRC(src, srcw);+ } else {+ FUNCTION_FCHECK(src, srcw, op & SLJIT_32);+ }+ compiler->last_flags = 0;+#endif /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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_MEMORY_BARRIER && op <= SLJIT_SKIP_FRAMES_BEFORE_RETURN));+ CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) < SLJIT_LMUL_UW || SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_MEMORY_BARRIER || compiler->scratches >= 2);+ if ((SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_LMUL_UW && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_DIV_SW) || op == SLJIT_SKIP_FRAMES_BEFORE_RETURN)+ compiler->last_flags = 0;+#endif /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_MOV && SLJIT_CHECK_OPCODE(op, 0) <= 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 | ALL_STATUS_FLAGS_MASK)));+ break;+ default:+ /* Only SLJIT_32 is allowed. */+ CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_MASK));+ break;+ }++ FUNCTION_CHECK_DST(dst, dstw);+ FUNCTION_CHECK_SRC(src, srcw);+#endif /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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(SLJIT_CHECK_OPCODE(op, SLJIT_ATOMIC_TEST | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS | ALL_STATUS_FLAGS_MASK) >= SLJIT_MOV+ && SLJIT_CHECK_OPCODE(op, SLJIT_ATOMIC_TEST | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS | ALL_STATUS_FLAGS_MASK) <= SLJIT_MOV_P);+ CHECK_ARGUMENT((op & (SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS)) != (SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS));++ /* 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 (GET_OPCODE(op) < SLJIT_MOV_U8 || GET_OPCODE(op) > SLJIT_MOV_S16) {+ /* Nothing allowed. */+ CHECK_ARGUMENT(!(op & SLJIT_32));+ }++ compiler->last_flags = 0;+#endif /* SLJIT_ARGUMENT_CHECKS */+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ if (op & SLJIT_ATOMIC_TEST)+ CHECK_RETURN_OK;+ if (sljit_emit_atomic_load(compiler, op | SLJIT_ATOMIC_TEST, dst_reg, mem_reg)) {+ fprintf(compiler->verbose, " # atomic_load: unsupported form, no instructions are emitted\n");+ CHECK_RETURN_OK;+ }++ fprintf(compiler->verbose, " atomic_load");+ if (op & SLJIT_ATOMIC_USE_CAS)+ fprintf(compiler->verbose, "_cas");+ if (op & SLJIT_ATOMIC_USE_LS)+ fprintf(compiler->verbose, "_ls");++ fprintf(compiler->verbose, "%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(SLJIT_CHECK_OPCODE(op, SLJIT_ATOMIC_TEST | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS | SLJIT_SET_Z) >= SLJIT_MOV+ && SLJIT_CHECK_OPCODE(op, SLJIT_ATOMIC_TEST | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS | SLJIT_SET_Z) <= SLJIT_MOV_P);+ CHECK_ARGUMENT((op & (SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS)) != (SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS));++ /* 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 || (op & SLJIT_ATOMIC_USE_LS)));++ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK) || GET_FLAG_TYPE_MASK(op) == SLJIT_ATOMIC_STORED);++ if (GET_OPCODE(op) < SLJIT_MOV_U8 || GET_OPCODE(op) > SLJIT_MOV_S16) {+ /* Nothing allowed. */+ CHECK_ARGUMENT(!(op & SLJIT_32));+ }++ compiler->last_flags = GET_FLAG_TYPE_MASK(op) | (op & SLJIT_32);+#endif /* SLJIT_ARGUMENT_CHECKS */+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ if (op & SLJIT_ATOMIC_TEST)+ CHECK_RETURN_OK;+ if (sljit_emit_atomic_store(compiler, op | SLJIT_ATOMIC_TEST, src_reg, mem_reg, temp_reg)) {+ fprintf(compiler->verbose, " # atomic_store: unsupported form, no instructions are emitted\n");+ CHECK_RETURN_OK;+ }++ fprintf(compiler->verbose, " atomic_store");+ if (op & SLJIT_ATOMIC_USE_CAS)+ fprintf(compiler->verbose, "_cas");+ if (op & SLJIT_ATOMIC_USE_LS)+ fprintf(compiler->verbose, "_ls");++ fprintf(compiler->verbose, "%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;+}++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)++static sljit_s32 check_sljit_emit_op2_operation(struct sljit_compiler *compiler, sljit_s32 op)+{+ 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:+ return !(op & VARIABLE_FLAG_MASK);+ case SLJIT_MUL:+ return !(op & SLJIT_SET_Z) && (!(op & VARIABLE_FLAG_MASK) || GET_FLAG_TYPE(op) == SLJIT_OVERFLOW);+ case SLJIT_ADD:+ return !(op & VARIABLE_FLAG_MASK)+ || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)+ || GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;+ case SLJIT_SUB:+ return !(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);+ case SLJIT_ADDC:+ case SLJIT_SUBC:+ return (!(op & VARIABLE_FLAG_MASK) || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY))+ && (compiler->last_flags & 0xff) == GET_FLAG_TYPE(SLJIT_SET_CARRY)+ && (op & SLJIT_32) == (compiler->last_flags & SLJIT_32);+ break;+ case SLJIT_ROTL:+ case SLJIT_ROTR:+ return !(op & ALL_STATUS_FLAGS_MASK);+ }++ /* Operation type should be checked earlier. */+ SLJIT_UNREACHABLE();+ return 1;+}++#endif /* SLJIT_ARGUMENT_CHECKS */++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(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_ADD && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_ROTR);+ CHECK_ARGUMENT(check_sljit_emit_op2_operation(compiler, op));++ 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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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(SLJIT_CHECK_OPCODE(op, 0) == SLJIT_SHL || SLJIT_CHECK_OPCODE(op, 0) == SLJIT_LSHR+ || SLJIT_CHECK_OPCODE(op, 0) == SLJIT_MSHL || SLJIT_CHECK_OPCODE(op, 0) == 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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2_shift(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_sw shift_arg)+{+ SLJIT_UNUSED_ARG(shift_arg);+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT((op & ~SLJIT_SRC2_UNDEFINED) == (SLJIT_ADD | SLJIT_SHL_IMM));+ FUNCTION_CHECK_DST(dst, dstw);+ FUNCTION_CHECK_SRC(src1, src1w);+ FUNCTION_CHECK_SRC(src2, src2w);+ compiler->last_flags = 0;+#endif /* SLJIT_ARGUMENT_CHECKS */+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " %s.shl_imm%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE],+ (op & SLJIT_SRC2_UNDEFINED) ? ".src2und" : "");++ 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, ", #%" SLJIT_PRINT_D "d\n", shift_arg);+ }+#endif /* SLJIT_VERBOSE */+ 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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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)));+ }+#if (defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS)+ else if (((type >> 12) == 0 || ((type >> 12) >= 3 && (type >> 12) <= 6))) {+ CHECK_ARGUMENT((reg > 0 && reg <= SLJIT_NUMBER_OF_VECTOR_REGISTERS)+ || (reg >= SLJIT_TMP_VREGISTER_BASE && reg < (SLJIT_TMP_VREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS)));+ }+#endif /* SLJIT_SEPARATE_VECTOR_REGISTERS */+ else {+ CHECK_ARGUMENT(type == SLJIT_FLOAT_REGISTER || ((type >> 12) == 0 || ((type >> 12) >= 3 && (type >> 12) <= 6) || (type & (3 << 12)) || (type & (4 << 12)) || (type & (5 << 12)) || (type & (6 << 12))));+ 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 /* SLJIT_ARGUMENT_CHECKS */+ 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_VERBOSE */++ 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) || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)+ 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 /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_ARM_THUMB2 && !SLJIT_CONFIG_RISCV && !SLJIT_CONFIG_S390X */+ CHECK_ARGUMENT(size == 4 && (((sljit_sw)instruction) & 0x3) == 0);+#endif /* SLJIT_CONFIG_X86 */++ compiler->last_flags = 0;+#endif /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_MOV_F64 && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_ABS_F64);+ CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_MASK));+ FUNCTION_FCHECK(src, srcw, op & SLJIT_32);+ FUNCTION_FCHECK(dst, dstw, op & SLJIT_32);+#endif /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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 /* SLJIT_ARGUMENT_CHECKS */++ 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(SLJIT_CHECK_OPCODE(op, 0) == 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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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 & ALL_STATUS_FLAGS_MASK));+ FUNCTION_FCHECK(src, srcw, op & SLJIT_32);+ FUNCTION_CHECK_DST(dst, dstw);+#endif /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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 & ALL_STATUS_FLAGS_MASK));+ FUNCTION_CHECK_SRC(src, srcw);+ FUNCTION_FCHECK(dst, dstw, op & SLJIT_32);+#endif /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_ADD_F64 && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_DIV_F64);+ CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_MASK));+ FUNCTION_FCHECK(src1, src1w, op & SLJIT_32);+ FUNCTION_FCHECK(src2, src2w, op & SLJIT_32);+ FUNCTION_FCHECK(dst, dstw, op & SLJIT_32);+#endif /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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(SLJIT_CHECK_OPCODE(op, 0) == 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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_COPY_TO_F64 && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_COPY_FROM_F64);+ CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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 /* SLJIT_ARGUMENT_CHECKS */++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose))+ fprintf(compiler->verbose, "label:\n");+#endif /* SLJIT_VERBOSE */+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_aligned_label(struct sljit_compiler *compiler,+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(buffers);++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(alignment >= SLJIT_LABEL_ALIGN_1 && alignment <= SLJIT_LABEL_ALIGN_16);+ compiler->last_flags = 0;+#endif /* SLJIT_ARGUMENT_CHECKS */++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, "label.al%d:%s", 1 << alignment, buffers == NULL ? "\n" : " [");++ if (buffers != NULL) {+ fprintf(compiler->verbose, "%ld", (long int)buffers->size);+ buffers = buffers->next;++ while (buffers != NULL) {+ fprintf(compiler->verbose, ", %ld", (long int)buffers->size);+ buffers = buffers->next;+ }++ fprintf(compiler->verbose, "]\n");+ }+ }+#endif /* SLJIT_VERBOSE */+ 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 /* !SLJIT_CONFIG_X86 || SLJIT_CONFIG_ARM */+#define CHECK_UNORDERED(type, last_flags) 0+#endif /* SLJIT_CONFIG_X86 || SLJIT_CONFIG_ARM */+#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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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 (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_SIG_LESS_EQUAL);+ FUNCTION_CHECK_SRC(src1, src1w);+ FUNCTION_CHECK_SRC(src2, src2w);+ compiler->last_flags = 0;+#endif /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2cmpz(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_COMPILE_ASSERT((SLJIT_JUMP_IF_ZERO == SLJIT_SET_Z) && (SLJIT_JUMP_IF_NON_ZERO == 0),+ incorrect_values_for_sljit_jump_zero_or_non_zero);++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, SLJIT_REWRITABLE_JUMP) >= SLJIT_ADD && SLJIT_CHECK_OPCODE(op, SLJIT_REWRITABLE_JUMP) <= SLJIT_ROTR);+ /* Not all opcodes allow setting zero flags. */+ CHECK_ARGUMENT(check_sljit_emit_op2_operation(compiler, ((op | SLJIT_SET_Z) & ~SLJIT_REWRITABLE_JUMP)));+ 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);+#endif /* SLJIT_ARGUMENT_CHECKS */+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " cmp%sz.%s%s%s%s%s ", (op & SLJIT_JUMP_IF_ZERO) ? "" : "n",+ op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_32) ? "" : "32",+ !(op & VARIABLE_FLAG_MASK) ? "" : ".", !(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op & ~SLJIT_REWRITABLE_JUMP)],+ !(op & SLJIT_REWRITABLE_JUMP) ? "" : ".r");+ 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 /* SLJIT_VERBOSE */+ 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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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+ || (SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_AND && SLJIT_CHECK_OPCODE(op, 0) <= 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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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 | SLJIT_COMPARE_SELECT);+ CHECK_ARGUMENT((type & SLJIT_COMPARE_SELECT) ? (cond >= SLJIT_LESS && cond <= SLJIT_SET_SIG_LESS_EQUAL)+ : (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 (!(type & SLJIT_COMPARE_SELECT)) {+ 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));+ } else+ compiler->last_flags = 0;+#endif /* SLJIT_ARGUMENT_CHECKS */+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " %sselect%s %s, ",+ !(type & SLJIT_COMPARE_SELECT) ? "" : "cmp_",+ !(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 /* SLJIT_VERBOSE */+ 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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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;+ SLJIT_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 /* SLJIT_ARGUMENT_CHECKS */+#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)+ fprintf(compiler->verbose, ".unal");+ else if (type & SLJIT_MEM_ALIGNED_16)+ fprintf(compiler->verbose, ".al16");+ else if (type & SLJIT_MEM_ALIGNED_32)+ fprintf(compiler->verbose, ".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 /* SLJIT_VERBOSE */+ 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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ 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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg,+ 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_VREG(vreg, type));+ FUNCTION_VCHECK(srcdst, srcdstw, type);+#endif /* SLJIT_ARGUMENT_CHECKS */+#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, vreg, 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_vreg(compiler, vreg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_vparam(compiler, srcdst, srcdstw);+ fprintf(compiler->verbose, "\n");+ }+#endif /* SLJIT_VERBOSE */+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg,+ 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_VREG(vreg, type));++ 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 /* SLJIT_ARGUMENT_CHECKS */+#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, vreg, 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_vreg(compiler, vreg);+ 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 /* SLJIT_VERBOSE */+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg, 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_VREG(vreg, type));+ 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 /* SLJIT_ARGUMENT_CHECKS */+#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, vreg, 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_vreg(compiler, vreg);+ 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 /* SLJIT_VERBOSE */+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg,+ 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_VREG(vreg, type));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(src, type));+ CHECK_ARGUMENT(src_lane_index >= 0 && src_lane_index < (1 << (SLJIT_SIMD_GET_REG_SIZE(type) - SLJIT_SIMD_GET_ELEM_SIZE(type))));+#endif /* SLJIT_ARGUMENT_CHECKS */+#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, vreg, 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_vreg(compiler, vreg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_vreg(compiler, src);+ fprintf(compiler->verbose, "[%d]\n", src_lane_index);+ }+#endif /* SLJIT_VERBOSE */+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg,+ 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_VREG(vreg, type));+ FUNCTION_VCHECK(src, srcw, type);+#endif /* SLJIT_ARGUMENT_CHECKS */+#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, vreg, 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_vreg(compiler, vreg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_vparam(compiler, src, srcw);+ fprintf(compiler->verbose, "\n");+ }+#endif /* SLJIT_VERBOSE */+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg,+ 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_VREG(vreg, type));+ FUNCTION_CHECK_DST(dst, dstw);+#endif /* SLJIT_ARGUMENT_CHECKS */+#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, vreg, 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_vreg(compiler, vreg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_param(compiler, dst, dstw);+ fprintf(compiler->verbose, "\n");+ }+#endif /* SLJIT_VERBOSE */+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w)+{+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));+ CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK2(0)) >= SLJIT_SIMD_OP2_AND && (type & SLJIT_SIMD_TYPE_MASK2(0)) <= SLJIT_SIMD_OP2_SHUFFLE);+ 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_OPCODE(type) != SLJIT_SIMD_OP2_SHUFFLE || (SLJIT_SIMD_GET_ELEM_SIZE(type) == 0 && !(type & SLJIT_SIMD_FLOAT)));+ CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM2_SIZE(type) <= (src2 & SLJIT_MEM) ? SLJIT_SIMD_GET_REG_SIZE(type) : 0);+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(dst_vreg, type));+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(src1_vreg, type));+ FUNCTION_VCHECK(src2, src2w, type);+#endif /* SLJIT_ARGUMENT_CHECKS */+#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_vreg, src1_vreg, src2, src2w) == 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)));++ if ((type & 0x3f000000) != SLJIT_SIMD_MEM_UNALIGNED)+ fprintf(compiler->verbose, ".al%d", (8 << SLJIT_SIMD_GET_ELEM2_SIZE(type)));++ fprintf(compiler->verbose, " ");+ sljit_verbose_vreg(compiler, dst_vreg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_vreg(compiler, src1_vreg);+ fprintf(compiler->verbose, ", ");+ sljit_verbose_vparam(compiler, src2, src2w);+ fprintf(compiler->verbose, "\n");+ }+#endif /* SLJIT_VERBOSE */+ 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 /* SLJIT_ARGUMENT_CHECKS */+#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 /* SLJIT_VERBOSE */+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_sw init_value)+{+ SLJIT_UNUSED_ARG(init_value);++#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)+ CHECK_ARGUMENT(op == SLJIT_MOV || op == SLJIT_MOV_S32+ || op == SLJIT_MOV32 || (op | SLJIT_32) == SLJIT_MOV32_U8);+ FUNCTION_CHECK_DST(dst, dstw);+#endif /* SLJIT_ARGUMENT_CHECKS */+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " const%s%s ",+ !(op & SLJIT_32) ? "" : "32", op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE]);+ sljit_verbose_param(compiler, dst, dstw);+ fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", init_value);+ }+#endif /* SLJIT_VERBOSE */+ CHECK_RETURN_OK;+}++static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_addr(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_MOV_ADDR || op == SLJIT_MOV_ABS_ADDR || op == SLJIT_ADD_ABS_ADDR);+ FUNCTION_CHECK_DST(dst, dstw);+#endif /* SLJIT_ARGUMENT_CHECKS */+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {+ fprintf(compiler->verbose, " %s ", op_addr_types[op]);+ sljit_verbose_param(compiler, dst, dstw);+ fprintf(compiler->verbose, "\n");+ }+#endif /* SLJIT_VERBOSE */+ 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 */++static void sljit_reset_read_only_buffers(struct sljit_read_only_buffer *buffers)+{+ while (buffers != NULL) {+ buffers->u.label = NULL;+ buffers = buffers->next;+ }+}++/* 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 /* !SLJIT_32BIT_ARCHITECTURE && !SLJIT_64BIT_ARCHITECTURE */+#error "Internal error: CPU type info missing"+#endif /* SLJIT_32BIT_ARCHITECTURE */++#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 /* !SLJIT_LITTLE_ENDIAN && !SLJIT_BIG_ENDIAN */+#error "Internal error: CPU type info missing"+#endif /* SLJIT_LITTLE_ENDIAN */++#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED)+#define SLJIT_CPUINFO_PART3 "unaligned)"+#else /* !SLJIT_UNALIGNED */+#define SLJIT_CPUINFO_PART3 "aligned)"+#endif /* SLJIT_UNALIGNED */++#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 /* SLJIT_CONFIG_X86 */++#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 /* !SLJIT_64BIT_ARCHITECTURE */+ 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_64BIT_ARCHITECTURE */++ 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 /* SLJIT_CONFIG_ARM_64 */++ 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_RISCV && SLJIT_CONFIG_RISCV) \+ && !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \+ && !(defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op2cmpz(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_PTR();+ CHECK_PTR(check_sljit_emit_op2cmpz(compiler, op, dst, dstw, src1, src1w, src2, src2w));++ SLJIT_SKIP_CHECKS(compiler);+ PTR_FAIL_IF(sljit_emit_op2(compiler, ((op | SLJIT_SET_Z) & ~SLJIT_REWRITABLE_JUMP), dst, dstw, src1, src1w, src2, src2w));++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_jump(compiler, ((op & SLJIT_JUMP_IF_ZERO) ? SLJIT_ZERO : SLJIT_NOT_ZERO) | (op & SLJIT_REWRITABLE_JUMP));+}++#else /* SLJIT_CONFIG_RISCV || SLJIT_CONFIG_MIPS || SLJIT_CONFIG_LOONGARCH */++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op2cmpz(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 reg;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_op2cmpz(compiler, op, dst, dstw, src1, src1w, src2, src2w));++ SLJIT_SKIP_CHECKS(compiler);+ PTR_FAIL_IF(sljit_emit_op2(compiler, (op & ~(SLJIT_SET_Z | SLJIT_REWRITABLE_JUMP)), dst, dstw, src1, src1w, src2, src2w));++ /* When dst is a memory operand, its value is stored in SLJIT_TMP_DEST_FREG. */+ reg = FAST_IS_REG(dst) ? dst : SLJIT_TMP_DEST_REG;++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_cmp(compiler, ((op & SLJIT_JUMP_IF_ZERO) ? SLJIT_ZERO : SLJIT_NOT_ZERO) | (op & (SLJIT_32 | SLJIT_REWRITABLE_JUMP)), reg, 0, SLJIT_IMM, 0);+}++#endif /* !SLJIT_CONFIG_RISCV && !SLJIT_CONFIG_MIPS && !SLJIT_CONFIG_LOONGARCH */++#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_RISCV && SLJIT_CONFIG_RISCV) \+ && !(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 vreg,+ sljit_s32 srcdst, sljit_sw srcdstw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_mov(compiler, type, vreg, srcdst, srcdstw));+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(vreg);+ 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 vreg,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_replicate(compiler, type, vreg, src, srcw));+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(vreg);+ 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 vreg, sljit_s32 lane_index,+ sljit_s32 srcdst, sljit_sw srcdstw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_lane_mov(compiler, type, vreg, lane_index, srcdst, srcdstw));+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(vreg);+ 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 vreg,+ sljit_s32 src, sljit_s32 src_lane_index)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, vreg, src, src_lane_index));+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(vreg);+ 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 vreg,+ sljit_s32 src, sljit_sw srcw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_extend(compiler, type, vreg, src, srcw));+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(vreg);+ 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 vreg,+ sljit_s32 dst, sljit_sw dstw)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_sign(compiler, type, vreg, dst, dstw));+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(vreg);+ 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_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w));+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(type);+ SLJIT_UNUSED_ARG(dst_vreg);+ SLJIT_UNUSED_ARG(src1_vreg);+ SLJIT_UNUSED_ARG(src2);+ SLJIT_UNUSED_ARG(src2w);++ 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 */++SLJIT_API_FUNC_ATTRIBUTE void* sljit_read_only_buffer_start_writing(sljit_uw addr, sljit_uw size, sljit_sw executable_offset)+{+ SLJIT_UNUSED_ARG(size);+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + size), 0);+ return SLJIT_ADD_EXEC_OFFSET(addr, -executable_offset);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_read_only_buffer_end_writing(sljit_uw addr, sljit_uw size, sljit_sw executable_offset)+{+ SLJIT_UNUSED_ARG(addr);+ SLJIT_UNUSED_ARG(size);+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + size), 1);+ SLJIT_CACHE_FLUSH((void*)addr, (void*)(addr + size));+}++#endif /* !SLJIT_CONFIG_UNSUPPORTED */
+ src/c/pcre2/deps/sljit/sljit_src/sljitLir.h view
@@ -0,0 +1,2765 @@+/*+ * 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_LIR_H_+#define SLJIT_LIR_H_++/*+ ------------------------------------------------------------------------+ Stack-Less JIT compiler for multiple architectures (x86, ARM, PowerPC)+ ------------------------------------------------------------------------++ Short description+ 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, 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 /* __cplusplus */++/* 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 FS 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++/* --------------------------------------------------------------------- */+/* Vector registers */+/* --------------------------------------------------------------------- */++/* Vector registers are storage areas, which are used for Single Instruction+ Multiple Data (SIMD) computations. The VR and VS register sets overlap+ in the same way as R and S register sets. See above.++ The storage space of vector registers often overlap with floating point+ registers. In this case setting the value of SLJIT_VR(i) destroys the+ value of SLJIT_FR(i) and vice versa. See SLJIT_SEPARATE_VECTOR_REGISTERS+ macro. */++/* Vector scratch registers. */+#define SLJIT_VR0 1+#define SLJIT_VR1 2+#define SLJIT_VR2 3+#define SLJIT_VR3 4+#define SLJIT_VR4 5+#define SLJIT_VR5 6+#define SLJIT_VR6 7+#define SLJIT_VR7 8+#define SLJIT_VR8 9+#define SLJIT_VR9 10+/* All VR registers provided by the architecture can be accessed by SLJIT_VR(i)+ The i parameter must be >= 0 and < SLJIT_NUMBER_OF_VECTOR_REGISTERS. */+#define SLJIT_VR(i) (1 + (i))++/* Vector saved registers. */+#define SLJIT_VS0 (SLJIT_NUMBER_OF_VECTOR_REGISTERS)+#define SLJIT_VS1 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 1)+#define SLJIT_VS2 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 2)+#define SLJIT_VS3 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 3)+#define SLJIT_VS4 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 4)+#define SLJIT_VS5 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 5)+#define SLJIT_VS6 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 6)+#define SLJIT_VS7 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 7)+#define SLJIT_VS8 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 8)+#define SLJIT_VS9 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 9)+/* All VS registers provided by the architecture can be accessed by SLJIT_VS(i)+ The i parameter must be >= 0 and < SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS. */+#define SLJIT_VS(i) (SLJIT_NUMBER_OF_VECTOR_REGISTERS - (i))++/* Vector registers >= SLJIT_FIRST_SAVED_VECTOR_REG are saved registers. */+#define SLJIT_FIRST_SAVED_VECTOR_REG (SLJIT_VS0 - SLJIT_NUMBER_OF_SAVED_VECTOR_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.++ 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_read_only_buffer {+ struct sljit_read_only_buffer *next;+ sljit_uw size;+ /* Label can be replaced by address after sljit_generate_code. */+ union {+ struct sljit_label *label;+ sljit_uw addr;+ } u;+};++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;+#if (defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS) \+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \+ || (defined SLJIT_DEBUG && SLJIT_DEBUG) \+ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ /* Available vector scratch registers. */+ sljit_s32 vscratches;+ /* Available vector saved registers. */+ sljit_s32 vsaveds;+#endif /* SLJIT_SEPARATE_VECTOR_REGISTERS || SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG || SLJIT_VERBOSE */+ /* 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 */++ /* Note: SLJIT_DEBUG enables SLJIT_ARGUMENT_CHECKS. */+#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)+#if !(defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS)+ /* Available float scratch registers. */+ sljit_s32 real_fscratches;+ /* Available float saved registers. */+ sljit_s32 real_fsaveds;+#endif /* !SLJIT_SEPARATE_VECTOR_REGISTERS */++ /* 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 /* SLJIT_VERBOSE */++/* 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++/* When SLJIT_INDIRECT_CALL is defined, no function context is+created for the generated code (see sljit_set_function_context),+so the returned pointer cannot be directly called from C code.+The flag is ignored when SLJIT_INDIRECT_CALL is not defined. */+#define SLJIT_GENERATE_CODE_NO_CONTEXT 0x2++/* 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.++ Note: sljitConfigInternal.h also provides several feature detection macros. */++/* [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. */+#define SLJIT_HAS_ATOMIC 14+/* [Not emulated] Memory barrier support is available. */+#define SLJIT_HAS_MEMORY_BARRIER 15++#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 /* SLJIT_CONFIG_X86 */++#if (defined SLJIT_CONFIG_LOONGARCH)+/* [Not emulated] LASX support is available on LoongArch */+#define SLJIT_HAS_LASX 201+#endif /* SLJIT_CONFIG_LOONGARCH */++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 callable function from the viewpoint+ of the C language. Function calls must conform with the ABI+ (Application Binary Interface) of the target 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 an entry point for the+ executable code. This is often called as function prologue.++ The "options" argument can be used to pass configuration options+ to the sljit compiler which affects the generated code, until+ another sljit_emit_enter or sljit_set_context is called. 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.++ 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 are+ declared in a similar manner, but their count is specified+ by "saveds" argument. The floating point scratch and saved+ registers can be set by using "scratches" and "saveds" argument+ as well, but their value must be passed to the SLJIT_ENTER_FLOAT+ macro, see below.++ 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 alocated stack space is an+ uninitialized memory area.++ Floating point scratch and saved registers must be specified+ by the SLJIT_ENTER_FLOAT macro, which result value should be+ combined with scratches / saveds argument.++ Examples:+ To use three scratch and four floating point scratch+ registers, the "scratches" argument must be set to:+ 3 | SLJIT_ENTER_FLOAT(4)++ To use six saved and five floating point saved+ registers, the "saveds" argument must be set to:+ 6 | SLJIT_ENTER_FLOAT(5)++ 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 <= float scratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS+ 0 <= float saveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS+ float scratches + float saveds <= 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 following options are available for sljit_emit_enter. */++/* 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++#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 */++/* Macros for other sljit_emit_enter arguments. */++/* Floating point scratch and saved registers can be+ specified by SLJIT_ENTER_FLOAT. */+#define SLJIT_ENTER_FLOAT(regs) ((regs) << 8)++/* Vector scratch and saved registers can be specified+ by SLJIT_ENTER_VECTOR. */+#define SLJIT_ENTER_VECTOR(regs) ((regs) << 16)++/* The local_size must be >= 0 and <= SLJIT_MAX_LOCAL_SIZE. */+#define SLJIT_MAX_LOCAL_SIZE 1048576++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 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 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)+ May return with SLJIT_ERR_UNSUPPORTED if SLJIT_HAS_MEMORY_BARRIER+ feature is not supported (calling sljit_has_cpu_feature() with+ this feature option returns with 0). */+#define SLJIT_MEMORY_BARRIER (SLJIT_OP0_BASE + 8)+/* 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 + 9)+/* 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 + 10)++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);++/* The following options are used by sljit_emit_op2_shift. */++/* The src2 argument is shifted left by an immedate value. */+#define SLJIT_SHL_IMM (1 << 9)+/* When src2 argument is a register, its value is undefined after the operation. */+#define SLJIT_SRC2_UNDEFINED (1 << 10)++/* Emits an addition operation, where the second argument is shifted by a value.++ op must be SLJIT_ADD | SLJIT_SHL_IMM, where the immedate value is stored in shift_arg++ Flags: - (may destroy flags) */+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(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_sw shift_arg);++/* 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. */++/* Emits a label which can be the target of jump / mov_addr instructions. */++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler);++/* Alignment values for sljit_emit_aligned_label. */++#define SLJIT_LABEL_ALIGN_1 0+#define SLJIT_LABEL_ALIGN_2 1+#define SLJIT_LABEL_ALIGN_4 2+#define SLJIT_LABEL_ALIGN_8 3+#define SLJIT_LABEL_ALIGN_16 4+#define SLJIT_LABEL_ALIGN_W SLJIT_WORD_SHIFT+#define SLJIT_LABEL_ALIGN_P SLJIT_POINTER_SHIFT++/* Emits a label which address is aligned to a power of 2 value. When some+ extra space needs to be added to align the label, that space is filled+ with SLJIT_NOP instructions. These labels usually represent the end of a+ compilation block, and a new function or some read-only data (e.g. a+ jump table) follows it. In these typical cases the SLJIT_NOPs are never+ executed.++ Optionally, buffers for storing read-only data or code can be allocated+ by this operation. The buffers are passed as a chain list, and a separate+ memory area is allocated for each item in the list. All buffers are aligned+ to SLJIT_NOP instruction size, and their starting address is returned as+ as a label. The sljit_get_label_abs_addr function or the SLJIT_MOV_ABS_ADDR+ operation can be used to get the real address. The label of the first buffer+ is always the same as the returned label. The buffers are initially+ initialized with SLJIT_NOP instructions. The alignment of the buffers can+ be controlled by their starting address and sizes. If the starting address+ is aligned to N, and size is also divisible by N, the next buffer is aligned+ to N. I.e. if a buffer is 16 byte aligned, and its size is divisible by 4,+ the next buffer is 4 byte aligned. Note: if a buffer is N (>=2) byte aligned,+ it is also N/2 byte aligned.++ align represents the alignment, and its value can+ be specified by SLJIT_LABEL_* constants++ buffers is a list of read-only buffers stored in a chain list.+ After calling sljit_generate_code, these buffers can be+ modified by sljit_read_only_buffer_start_writing() /+ sljit_read_only_buffer_end_writing() functions++ Note: the constant pool (if present) may be stored before the label. */+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers);++/* 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 0x10000+/* 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 0x20000++/* Emit a jump instruction. The destination is not set, only the type of the jump.+ type must be between SLJIT_JUMP 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);++/* Integer comparison operation. In most architectures it is implemented+ as a compare (sljit_emit_op2u with SLJIT_SUB) operation followed by+ an sljit_emit_jump. However, some architectures (e.g: ARM64 or RISCV)+ may optimize the generated code further. 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_32 or 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);++/* Floating point comparison operation. 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+ (e.g: MIPS) may optimize the generated code further. 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_32 or SLJIT_REWRITABLE_JUMP++ Flags: destroy flags.+ Note: when any 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);++/* The following flags are used by sljit_emit_op2cmpz(). */+#define SLJIT_JUMP_IF_NON_ZERO 0+#define SLJIT_JUMP_IF_ZERO SLJIT_SET_Z++/* Perform an integer arithmetic operation, then its result is compared to+ zero. In most architectures it is implemented as an sljit_emit_op2+ followed by an sljit_emit_jump. However, some architectures (e.g: RISCV)+ may optimize the generated code further. It is suggested to use this+ operation form when appropriate (e.g. for loops with counters).++ op must be an sljit_emit_op2 operation where zero flag can be set,+ op can be combined with SLJIT_SET_* status flag setters except+ SLJIT_SET_Z, SLJIT_REWRITABLE_JUMP or SLJIT_JUMP_IF_* option bits.++ Note: SLJIT_JUMP_IF_NON_ZERO is the default operation if neither+ SLJIT_JUMP_IF_ZERO or SLJIT_JUMP_IF_NON_ZERO is specified.+ Flags: sets the variable flag depending on op argument, the+ zero flag is undefined. */+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op2cmpz(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);++/* 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 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);++/* The following flags are used by sljit_emit_select(). */++/* Compare src1 and src2_reg operands before executing select+ (i.e. converts the select operation to a min/max operation). */+#define SLJIT_COMPARE_SELECT SLJIT_SET_Z++/* Emit a conditional select instruction which moves src1 to dst_reg,+ if the conditional flag is set, or src2_reg to dst_reg otherwise.+ The conditional flag should be set before executing the select+ instruction unless SLJIT_COMPARE_SELECT is specified.++ type must be between SLJIT_EQUAL and SLJIT_ORDERED_LESS_EQUAL+ when SLJIT_COMPARE_SELECT option is NOT specified+ type must be between SLJIT_LESS and SLJIT_SET_SIG_LESS_EQUAL+ when SLJIT_COMPARE_SELECT option is specified+ type can be combined (or'ed) with SLJIT_32 to move 32 bit+ register values instead of word sized ones+ type can be combined (or'ed) with SLJIT_COMPARE_SELECT+ which compares src1 and src2_reg before executing the select+ 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++ Note: when SLJIT_COMPARE_SELECT is specified, the status flag+ bits might not represent the result of a normal compare+ operation, hence flags are not specified after the operation++ Note: if sljit_has_cpu_feature(SLJIT_HAS_CMOV) returns with a non-zero value:+ (a) conditional register move (dst_reg==src2_reg, src1 is register)+ can be performed using a single instruction, except on RISCV,+ where three instructions are needed+ (b) conditional clearing (dst_reg==src2_reg, src1==SLJIT_IMM,+ src1w==0) can be performed using a single instruction,+ except on x86, where two instructions are needed++ Flags:+ When SLJIT_COMPARE_SELECT is NOT specified: - (does not modify flags)+ When SLJIT_COMPARE_SELECT is specified: - (may destroy 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 conditional flag is set, or src2_reg to+ dst_reg otherwise. The conditional flag should be set before+ executing the select instruction.++ 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 vector register, this is the default */+#define SLJIT_SIMD_LOAD 0x000000+/* Store data from a vector register */+#define SLJIT_SIMD_STORE 0x000001+/* The vector 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 vector register */+#define SLJIT_SIMD_REG_64 (3 << 12)+/* Move data to/from a 128 bit (16 byte) long vector register */+#define SLJIT_SIMD_REG_128 (4 << 12)+/* Move data to/from a 256 bit (32 byte) long vector register */+#define SLJIT_SIMD_REG_256 (5 << 12)+/* Move data to/from a 512 bit (64 byte) long vector 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()+ and sljit_emit_simd_op2(). */++/* 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 vector 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+ vreg is the source or destination vector register+ of the operation+ srcdst must be a memory operand or a vector register++ Note:+ The alignment and element size must be+ less or equal than vector 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 vreg,+ sljit_s32 srcdst, sljit_sw srcdstw);++/* Replicates a scalar value to all lanes of a vector+ 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.+ vreg is the destination vector 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 vreg,+ 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 vector 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+ vreg is the source or destination vector 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 vreg, sljit_s32 lane_index,+ sljit_s32 srcdst, sljit_sw srcdstw);++/* Replicates a scalar value from a lane to all lanes+ of a vector 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.+ vreg is the destination vector register of the operation+ src is the vector 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 vreg,+ 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 vector 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+ vreg is the destination vector register of the operation+ src must be a memory operand or a vector 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 vreg,+ 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+ vreg is the source vector 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 vreg,+ sljit_s32 dst, sljit_sw dstw);++/* The following operations 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+/* Shuffle bytes of src1 using the indicies in src2 */+#define SLJIT_SIMD_OP2_SHUFFLE 0x000004++/* Perform simd operations using vector 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_*, SLJIT_SIMD_MEM_*+ and SLJIT_SIMD_OP2_* options except SLJIT_SIMD_LOAD+ and SLJIT_SIMD_STORE+ dst_vreg is the destination register of the operation+ src1_vreg is the first source register of the operation+ src2 is the second source operand 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_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w);++/* The following operations are used by sljit_emit_atomic_load() and+ sljit_emit_atomic_store() operations. */++/* Tests whether the atomic operation is available (does not generate+ any instructions). When a load from is allowed, its corresponding+ store form is allowed and vice versa. */+#define SLJIT_ATOMIC_TEST 0x10000+/* The compiler must generate compare and swap instruction.+ When this bit is set, calling sljit_emit_atomic_load() is optional. */+#define SLJIT_ATOMIC_USE_CAS 0x20000+/* The compiler must generate load-acquire and store-release instructions.+ When this bit is set, the temp_reg for sljit_emit_atomic_store is not used. */+#define SLJIT_ATOMIC_USE_LS 0x40000++/* 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.++ 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 operations are allowed between the load and store operations+ - 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)+ - a store must always follow a load for the same transaction.++ op must be between SLJIT_MOV and SLJIT_MOV_P+ 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+ 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 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.+ The temp_reg register preserves its value, if the memory store+ is successful. Otherwise, its value is undefined.++ Flags: ATOMIC_STORED+ if ATOMIC_STORED flag is set, it represents that the memory+ is updated with a new value. Otherwise the memory is 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 at runtime. The constant+ can be managed by sljit_get_const_addr and sljit_set_const.++ op must be SLJIT_MOV, SLJIT_MOV32, SLJIT_MOV_S32,+ SLJIT_MOV_U8, SLJIT_MOV32_U8++ Note: when SLJIT_MOV_U8 is used, and dst is a register,+ init_value supports a 9 bit signed value between [-256..255]++ Flags: - (does not modify flags) */+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_sw init_value);++/* Opcodes for sljit_emit_mov_addr. */++/* The address is suitable for jump/call target. */+#define SLJIT_MOV_ADDR 0+/* The address is suitable for reading memory. */+#define SLJIT_MOV_ABS_ADDR 1+/* Add absolute address. */+#define SLJIT_ADD_ABS_ADDR 2++/* 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_op_addr(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw);++/* Returns the address of a label after sljit_generate_code is called, and+ before the compiler is freed by sljit_free_compiler. It is recommended+ to save these addresses elsewhere before sljit_free_compiler is called.++ The address returned by sljit_get_label_addr is suitable for a jump/call+ target, and the address returned by sljit_get_label_abs_addr is suitable+ for reading memory. */++static SLJIT_INLINE sljit_uw sljit_get_label_addr(struct sljit_label *label) { return label->u.addr; }+#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)+static SLJIT_INLINE sljit_uw sljit_get_label_abs_addr(struct sljit_label *label) { return label->u.addr & ~(sljit_uw)1; }+#else /* !SLJIT_CONFIG_ARM_THUMB2 */+static SLJIT_INLINE sljit_uw sljit_get_label_abs_addr(struct sljit_label *label) { return label->u.addr; }+#endif /* SLJIT_CONFIG_ARM_THUMB2 */++/* Returns the address of jump and const instructions after sljit_generate_code+ is called, and before the compiler is freed by sljit_free_compiler. It is+ recommended to save these addresses elsewhere before sljit_free_compiler is called. */++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);+/* The op opcode must be set to the same value that was passed to sljit_emit_const. */+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset);++/* Only a single buffer is writable at a time, so sljit_read_only_buffer_end_writing()+ must be called before sljit_read_only_buffer_start_writing() is called again. */+SLJIT_API_FUNC_ATTRIBUTE void* sljit_read_only_buffer_start_writing(sljit_uw addr, sljit_uw size, sljit_sw executable_offset);+SLJIT_API_FUNC_ATTRIBUTE void sljit_read_only_buffer_end_writing(sljit_uw addr, sljit_uw size, 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 or SUBC 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++/* Flags were set by sljit_emit_op2cmpz operation. */+#define SLJIT_CURRENT_FLAGS_OP2CMPZ 0x08++/* 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 one has index 1, the third one+has index 2, and so on. The returned value is unspecified after+sljit_generate_code() is called.++It is recommended to use this function to get the creation index+of a label, since sljit_emit_label() may return with the last label,+if no code is generated since the last sljit_emit_label() call. */+SLJIT_API_FUNC_ATTRIBUTE sljit_uw sljit_get_label_index(struct sljit_label *label);++/* 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 /* SLJIT_EXECUTABLE_ALLOCATOR */++#ifdef __cplusplus+} /* extern "C" */+#endif /* __cplusplus */++#endif /* SLJIT_LIR_H_ */
+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeARM_32.c view
@@ -0,0 +1,4950 @@+/*+ * 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.+ */++#ifdef __SOFTFP__+#define ARM_ABI_INFO " ABI:softfp"+#else+#define ARM_ABI_INFO " ABI:hardfp"+#endif++SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)+{+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+ return "ARMv7" SLJIT_CPUINFO ARM_ABI_INFO;+#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))++/* --------------------------------------------------------------------- */+/* Instruction 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 DMB_SY 0xf57ff05f+#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+#define VTBL 0xf3b00800++#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->real_fscratches))+ || (fr > (SLJIT_FS0 - compiler->real_fsaveds) && fr <= SLJIT_FS0)+ || (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS));+}++static sljit_s32 function_check_is_vreg(struct sljit_compiler *compiler, sljit_s32 vr, sljit_s32 type)+{+ sljit_s32 vr_low = vr;++ if (compiler->scratches == -1)+ return 0;++ if (SLJIT_SIMD_GET_REG_SIZE(type) == 4) {+ vr += (vr & 0x1);+ vr_low = vr - 1;+ }++ return (vr >= SLJIT_VR0 && vr < (SLJIT_VR0 + compiler->vscratches))+ || (vr_low > (SLJIT_VS0 - compiler->vsaveds) && vr_low <= SLJIT_VS0)+ || (vr >= SLJIT_TMP_VREGISTER_BASE && vr < (SLJIT_TMP_VREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_VECTOR_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 & 0x0e4f0000) == 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;+ sljit_uw target_addr;+ sljit_uw jump_addr = (sljit_uw)code_ptr;+ sljit_uw orig_addr = jump->addr;+ SLJIT_UNUSED_ARG(executable_offset);++#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+ jump->addr = jump_addr;+#endif++ 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)+ target_addr = jump->u.target;+ else {+ SLJIT_ASSERT(jump->u.label != NULL);+ target_addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);++ if (jump->u.label->size > orig_addr)+ jump_addr = (sljit_uw)(code + orig_addr);+ }++ diff = (sljit_sw)target_addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr + 8, executable_offset);++ /* 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_uw jump_addr = (sljit_uw)code_ptr;+ 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);++ if (jump->u.label->size > jump->addr)+ jump_addr = (sljit_uw)(code + jump->addr);+ }++ /* The pc+8 offset is represented by the 2 * SSIZE_OF(ins) below. */+ diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, 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 */+}++static SLJIT_INLINE sljit_ins *process_extended_label(sljit_ins *code_ptr, struct sljit_extended_label *ext_label)+{+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);+ return (sljit_ins*)((sljit_uw)code_ptr & ~(ext_label->data));+}++#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 (jump->u.label->size > jump->addr) {+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);+ diff -= (sljit_sw)size_reduce;+ }++ 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 (jump->u.label->size > jump->addr) {+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);+ diff -= (sljit_sw)size_reduce;+ }++ 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, options));++ /* 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) {+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);+ *code_ptr = buf_ptr[-1];+ }++ 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;+ 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) {+ if (label->u.index >= SLJIT_LABEL_ALIGNED)+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);++ 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;++ /* Note: MVN = (MOV ^ 0x400000) */+ SLJIT_ASSERT((*buf_ptr & 0xfdb00000) == MOV || (*buf_ptr & 0xfd100000) == LDR);++ if ((*buf_ptr & 0x4000000) != 0) {+ 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:+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+ case SLJIT_HAS_MEMORY_BARRIER:+#endif /* SLJIT_CONFIG_ARM_V7 */+ 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 local_size)+{+ sljit_s32 fscratches;+ sljit_s32 fsaveds;+ 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, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);++ scratches = ENTER_GET_REGS(scratches);+ saveds = ENTER_GET_REGS(saveds);+ fscratches = compiler->fscratches;+ fsaveds = compiler->fsaveds;++ 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 local_size)+{+ sljit_s32 fscratches;+ sljit_s32 fsaveds;+ sljit_s32 size;++ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);++ scratches = ENTER_GET_REGS(scratches);+ saveds = ENTER_GET_REGS(saveds);+ fscratches = compiler->fscratches;+ fsaveds = compiler->fsaveds;+ 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;+ SLJIT_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_MEMORY_BARRIER:+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+ return push_inst(compiler, DMB_SY);+#else /* !SLJIT_CONFIG_ARM_V7 */+ return SLJIT_ERR_UNSUPPORTED;+#endif /* SLJIT_CONFIG_ARM_V7 */+ 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_op2_shift(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_sw shift_arg)+{+ sljit_s32 dst_r, tmp_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ shift_arg &= 0x1f;++ if (src2 == SLJIT_IMM) {+ src2w = src2w << shift_arg;+ shift_arg = 0;+ }++ if (shift_arg == 0) {+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);+ }++ if (src1 == SLJIT_IMM) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));+ src1 = TMP_REG1;+ } else if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));+ src1 = TMP_REG1;+ }++ if (src2 & SLJIT_MEM) {+ tmp_r = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, tmp_r, src2, src2w, tmp_r));+ src2 = tmp_r;+ }++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ FAIL_IF(push_inst(compiler, ADD | RD(dst_r) | RN(src1) | RM(src2) | ((sljit_ins)shift_arg << 7)));++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, WORD_SIZE, dst_r, dst, dstw, TMP_REG1);+ 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);++ switch (op) {+ case SLJIT_FAST_RETURN:+ SLJIT_ASSERT(reg_map[TMP_REG2] == 14);++ if (FAST_IS_REG(src)) {+ if (src != TMP_REG2)+ 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)) {+ if (dst == TMP_REG2)+ return SLJIT_SUCCESS;+ 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;+ SLJIT_FALLTHROUGH++ case SLJIT_LESS:+ return 0x30000000;++ case SLJIT_NOT_CARRY:+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)+ return 0x30000000;+ SLJIT_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;+ SLJIT_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;+ SLJIT_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_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)+{+ sljit_uw mask, i;+ struct sljit_label *label;+ struct sljit_label *next_label;+ struct sljit_extended_label *ext_label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));++ sljit_reset_read_only_buffers(buffers);++#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)+ if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY))+ PTR_FAIL_IF(push_cpool(compiler));+#endif /* SLJIT_CONFIG_ARM_V6 */++ if (alignment <= SLJIT_LABEL_ALIGN_4) {+ SLJIT_SKIP_CHECKS(compiler);+ label = sljit_emit_label(compiler);+ PTR_FAIL_IF(!label);+ } else {+ /* The used space is filled with NOPs. */+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_ins);++ for (i = (mask >> 2); i != 0; i--)+ PTR_FAIL_IF(push_inst(compiler, NOP));++ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));+ PTR_FAIL_IF(!ext_label);+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);+ label = &ext_label->label;+ }++ if (buffers == NULL)+ return label;++ next_label = label;++ while (1) {+ buffers->u.label = next_label;++ for (i = (buffers->size + 3) >> 2; i > 0; i--)+ PTR_FAIL_IF(push_inst(compiler, NOP));++ buffers = buffers->next;++ if (buffers == NULL)+ break;++ SLJIT_SKIP_CHECKS(compiler);+ next_label = sljit_emit_label(compiler);+ PTR_FAIL_IF(!next_label);+ }++ 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));++ 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));+ jump->addr = compiler->size - 1;++ 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, tmp2;++ 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;+ if (!(type & SLJIT_COMPARE_SELECT))+ 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;+ if (!(type & SLJIT_COMPARE_SELECT))+ 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)));++ if (type & SLJIT_COMPARE_SELECT)+ type ^= 0x1;++ cc = get_cc(compiler, type & ~(SLJIT_32 | SLJIT_COMPARE_SELECT));++ if (SLJIT_UNLIKELY(src1 == SLJIT_IMM)) {+ tmp = get_imm((sljit_uw)src1w);+ if (tmp) {+ if (type & SLJIT_COMPARE_SELECT)+ FAIL_IF(push_inst(compiler, (CMP | SET_FLAGS | RN(dst_reg) | tmp)));+ return push_inst(compiler, ((MOV | RD(dst_reg) | tmp) & ~COND_MASK) | cc);+ }++ tmp = get_imm(~(sljit_uw)src1w);+ if (tmp && (type & SLJIT_COMPARE_SELECT)) {+ tmp2 = get_imm((sljit_uw)-src1w);+ if (tmp2)+ FAIL_IF(push_inst(compiler, (CMN | SET_FLAGS | RN(dst_reg) | tmp2)));+ else+ tmp = 0;+ }++ if (tmp)+ return push_inst(compiler, ((MVN | RD(dst_reg) | tmp) & ~COND_MASK) | cc);++#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+ if (!(type & SLJIT_COMPARE_SELECT)) {+ 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));+ }+#endif /* SLJIT_CONFIG_ARM_V7 */++ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));+ src1 = TMP_REG1;+ }++ if (type & SLJIT_COMPARE_SELECT)+ FAIL_IF(push_inst(compiler, (CMP | SET_FLAGS | RN(dst_reg) | RM(src1))));++ 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 vreg,+ 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, vreg, 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)+ vreg = simd_get_quad_reg_index(vreg);++ if (!(srcdst & SLJIT_MEM)) {+ if (reg_size == 4)+ srcdst = simd_get_quad_reg_index(srcdst);++ if (type & SLJIT_SIMD_STORE)+ ins = VD(srcdst) | VN(vreg) | VM(vreg);+ else+ ins = VD(vreg) | 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(vreg)+ | (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 vreg,+ 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, vreg, 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)+ vreg = simd_get_quad_reg_index(vreg);++ if (src == SLJIT_IMM && srcw == 0)+ return push_inst(compiler, VMOV_i | ((reg_size == 4) ? (1 << 6) : 0) | VD(vreg));++ 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, vreg, src, srcw));+ src = vreg;+ } else if (vreg != src)+ FAIL_IF(push_inst(compiler, VORR | VD(vreg) | VN(src) | VM(src)));++ vreg += SLJIT_QUAD_OTHER_HALF(vreg);++ if (vreg != src)+ return push_inst(compiler, VORR | VD(vreg) | 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(vreg) | 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(vreg) | (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(vreg));+ }++ 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(vreg) | RD(src));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg, 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, vreg, 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)+ vreg = simd_get_quad_reg_index(vreg);++ 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)+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);++ if (srcdst != vreg)+ FAIL_IF(push_inst(compiler, VORR | VD(vreg) | VN(srcdst) | VM(srcdst)));++ vreg += SLJIT_QUAD_OTHER_HALF(vreg);+ return push_inst(compiler, VMOV_i | VD(vreg));+ }++ if (srcdst == vreg || (elem_size == 3 && srcdst == (vreg + SLJIT_QUAD_OTHER_HALF(vreg)))) {+ FAIL_IF(push_inst(compiler, VORR | ins | VD(TMP_FREG2) | VN(vreg) | VM(vreg)));+ srcdst = TMP_FREG2;+ srcdstw = 0;+ }+ }++ FAIL_IF(push_inst(compiler, VMOV_i | ins | VD(vreg)));+ }++ if (reg_size == 4 && lane_index >= (0x8 >> elem_size)) {+ lane_index -= (0x8 >> elem_size);+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);+ }++ if (srcdst & SLJIT_MEM) {+ if (elem_size == 3)+ return emit_fop_mem(compiler, ((type & SLJIT_SIMD_STORE) ? 0 : FPU_LOAD) | SLJIT_32, vreg, 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(vreg) | 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(vreg) | VM(vreg));+ return push_inst(compiler, VMOV_F32 | SLJIT_32 | VD(vreg) | VM(srcdst));+ }++ if (type & SLJIT_SIMD_STORE) {+ if (freg_ebit_map[vreg] == 0) {+ if (lane_index == 1)+ vreg = SLJIT_F64_SECOND(vreg);++ return push_inst(compiler, VMOV_F32 | VD(srcdst) | VM(vreg));+ }++ FAIL_IF(push_inst(compiler, VMOV_s | (1 << 20) | ((sljit_ins)lane_index << 21) | VN(vreg) | 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(vreg) | 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(vreg) | RD(srcdst));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg,+ 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, vreg, 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) {+ vreg = simd_get_quad_reg_index(vreg);+ 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 (vreg != src)+ FAIL_IF(push_inst(compiler, VORR | VD(vreg) | VN(src) | VM(src)));++ vreg += SLJIT_QUAD_OTHER_HALF(vreg);++ if (vreg != src)+ return push_inst(compiler, VORR | VD(vreg) | 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(vreg) | VM(src));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg,+ 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, vreg, 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)+ vreg = simd_get_quad_reg_index(vreg);++ 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(vreg) | RN(src) | 0xf));+ else+ FAIL_IF(push_inst(compiler, VLD1_s | (sljit_ins)((reg_size - elem2_size + elem_size) << 10) | VD(vreg) | RN(src) | 0xf));+ src = vreg;+ } else if (reg_size == 4)+ src = simd_get_quad_reg_index(src);++ if (!(type & SLJIT_SIMD_FLOAT)) {+ dst_reg = (reg_size == 4) ? vreg : 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(vreg) | VN(TMP_FREG2) | VM(TMP_FREG2));+ return SLJIT_SUCCESS;+ }++ /* No SIMD variant, must use VFP instead. */+ SLJIT_ASSERT(reg_size == 4);++ if (vreg == src) {+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);+ FAIL_IF(push_inst(compiler, VCVT_F64_F32 | VD(vreg) | VM(src) | 0x20));+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);+ return push_inst(compiler, VCVT_F64_F32 | VD(vreg) | VM(src));+ }++ FAIL_IF(push_inst(compiler, VCVT_F64_F32 | VD(vreg) | VM(src)));+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);+ return push_inst(compiler, VCVT_F64_F32 | VD(vreg) | VM(src) | 0x20);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg,+ 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, vreg, 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) {+ vreg = simd_get_quad_reg_index(vreg);+ ins |= (sljit_ins)1 << 6;+ }++ SLJIT_ASSERT((freg_map[TMP_FREG2] & 0x1) == 0);+ FAIL_IF(push_inst(compiler, ins | VD(TMP_FREG2) | VM(vreg)));++ 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_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_s32 alignment;+ sljit_ins ins = 0, load_ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w));+ ADJUST_LOCAL_OFFSET(src2, src2w);++ 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 (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;+ case SLJIT_SIMD_OP2_SHUFFLE:+ ins = VTBL;+ break;+ }++ if (src2 & SLJIT_MEM) {+ if (elem_size > 3)+ elem_size = 3;++ load_ins = VLD1 | (sljit_ins)((reg_size == 3) ? (0x7 << 8) : (0xa << 8));+ alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type);++ SLJIT_ASSERT(reg_size >= alignment);++ if (alignment == 3)+ load_ins |= 0x10;+ else if (alignment >= 4)+ load_ins |= 0x20;++ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src2, src2w));+ FAIL_IF(push_inst(compiler, load_ins | VD(TMP_FREG2) | RN(src2) | ((sljit_ins)elem_size) << 6 | 0xf));+ src2 = TMP_FREG2;+ }++ if (reg_size == 4) {+ dst_vreg = simd_get_quad_reg_index(dst_vreg);+ src1_vreg = simd_get_quad_reg_index(src1_vreg);+ src2 = simd_get_quad_reg_index(src2);++ if (SLJIT_SIMD_GET_OPCODE(type) == SLJIT_SIMD_OP2_SHUFFLE) {+ ins |= (sljit_ins)1 << 8;++ FAIL_IF(push_inst(compiler, ins | VD(dst_vreg != src1_vreg ? dst_vreg : TMP_FREG2) | VN(src1_vreg) | VM(src2)));+ src2 += SLJIT_QUAD_OTHER_HALF(src2);+ FAIL_IF(push_inst(compiler, ins | VD(dst_vreg + SLJIT_QUAD_OTHER_HALF(dst_vreg)) | VN(src1_vreg) | VM(src2)));++ if (dst_vreg == src1_vreg)+ return push_inst(compiler, VORR | VD(dst_vreg) | VN(TMP_FREG2) | VM(TMP_FREG2));+ return SLJIT_SUCCESS;+ }++ ins |= (sljit_ins)1 << 6;+ }++ return push_inst(compiler, ins | VD(dst_vreg) | VN(src1_vreg) | VM(src2));+}++#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));++ if (op & SLJIT_ATOMIC_USE_CAS)+ return SLJIT_ERR_UNSUPPORTED;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_S8:+ case SLJIT_MOV_S16:+ case SLJIT_MOV_S32:+ return SLJIT_ERR_UNSUPPORTED;++ case SLJIT_MOV_U8:+ ins = LDREXB;+ break;+ case SLJIT_MOV_U16:+ ins = LDREXH;+ break;+ default:+ ins = LDREX;+ break;+ }++ if (op & SLJIT_ATOMIC_TEST)+ return SLJIT_SUCCESS;++ 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));++ if (op & SLJIT_ATOMIC_USE_CAS)+ return SLJIT_ERR_UNSUPPORTED;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_S8:+ case SLJIT_MOV_S16:+ case SLJIT_MOV_S32:+ return SLJIT_ERR_UNSUPPORTED;++ case SLJIT_MOV_U8:+ ins = STREXB;+ break;+ case SLJIT_MOV_U16:+ ins = STREXH;+ break;+ default:+ ins = STREX;+ break;+ }++ if (op & SLJIT_ATOMIC_TEST)+ return SLJIT_SUCCESS;++ 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;+}++#define SLJIT_EMIT_CONST_U8(c) \+ (((c) & 0x100) != 0 ? (MVN | SRC2_IMM | (~(c) & 0xff)) : (MOV | SRC2_IMM | ((c) & 0xff)))++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_s32 dst_r;+ sljit_s32 mem_flags = WORD_SIZE;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, op, 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 (GET_OPCODE(op) == SLJIT_MOV_U8) {+ PTR_FAIL_IF(push_inst(compiler, SLJIT_EMIT_CONST_U8(init_value) | RD(dst_r)));+ mem_flags = BYTE_SIZE;+ } else {+#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, mem_flags, TMP_REG2, dst, dstw, TMP_REG1));++ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_jump *jump;+ sljit_s32 dst_r, target_r;+ SLJIT_UNUSED_ARG(op);++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;++ if (op != SLJIT_ADD_ABS_ADDR)+ target_r = dst_r;+ else {+ target_r = TMP_REG1;++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, dst, dstw, TMP_REG1));+ }++#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, target_r, TMP_PC, 0), 0));+ compiler->patches++;+#else /* !SLJIT_CONFIG_ARM_V6 */+ PTR_FAIL_IF(push_inst(compiler, RD(target_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 (op == SLJIT_ADD_ABS_ADDR)+ PTR_FAIL_IF(push_inst(compiler, ADD | RD(dst_r) | RN(dst_r) | RM(TMP_REG1)));++ 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_s32 op, sljit_sw new_constant, sljit_sw executable_offset)+{+ sljit_ins *inst;++ if (GET_OPCODE(op) != SLJIT_MOV_U8) {+ set_const_value(addr, executable_offset, (sljit_uw)new_constant, 1);+ return;+ }++ inst = (sljit_ins*)addr;+ SLJIT_ASSERT((inst[0] & 0xfff00000) == (MOV | SRC2_IMM) || (inst[0] & 0xfff00000) == (MVN | SRC2_IMM));++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);+ *inst = SLJIT_EMIT_CONST_U8(new_constant) | (*inst & 0xf000);+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);+ inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 1);+}
+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeARM_64.c view
@@ -0,0 +1,3805 @@+/*+ * 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.+ */++#ifdef __ARM_FEATURE_ATOMICS+#define ARM_ATOMIC_INFO " (LSE)"+#else+#define ARM_ATOMIC_INFO ""+#endif++SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)+{+ return "ARM-64" ARM_ATOMIC_INFO SLJIT_CPUINFO;+}++/* Length of an instruction word */+typedef sljit_u32 sljit_ins;++#define TMP_ZERO (0)++#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)+#define TMP_LR (SLJIT_NUMBER_OF_REGISTERS + 4)+#define TMP_FP (SLJIT_NUMBER_OF_REGISTERS + 5)++#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)+#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)++/* r18 - platform register, currently not used */+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 8] = {+ 31, 0, 1, 2, 3, 4, 5, 6, 7, 11, 12, 13, 14, 15, 16, 17, 8, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 31, 9, 10, 30, 29+};++static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {+ 0, 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 15, 14, 13, 12, 11, 10, 9, 8, 30, 31+};++#define W_OP ((sljit_ins)1 << 31)+#define RD(rd) ((sljit_ins)reg_map[rd])+#define RT(rt) ((sljit_ins)reg_map[rt])+#define RN(rn) ((sljit_ins)reg_map[rn] << 5)+#define RT2(rt2) ((sljit_ins)reg_map[rt2] << 10)+#define RM(rm) ((sljit_ins)reg_map[rm] << 16)+#define VD(vd) ((sljit_ins)freg_map[vd])+#define VT(vt) ((sljit_ins)freg_map[vt])+#define VT2(vt) ((sljit_ins)freg_map[vt] << 10)+#define VN(vn) ((sljit_ins)freg_map[vn] << 5)+#define VM(vm) ((sljit_ins)freg_map[vm] << 16)++/* --------------------------------------------------------------------- */+/* Instruction forms */+/* --------------------------------------------------------------------- */++#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 CSINV 0xda800000+#define DMB_SY 0xd5033fbf+#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 TBL_v 0x0e000000+#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;+ sljit_uw jump_addr = (sljit_uw)code_ptr;+ sljit_uw orig_addr = jump->addr;+ SLJIT_UNUSED_ARG(executable_offset);++ jump->addr = 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)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);++ if (jump->u.label->size > orig_addr)+ jump_addr = (sljit_uw)(code + orig_addr);+ }++ diff = (sljit_sw)target_addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, 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_uw jump_addr = (sljit_uw)code_ptr;+ 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);++ if (jump->u.label->size > jump->addr)+ jump_addr = (sljit_uw)(code + jump->addr);+ }++ diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, 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 SLJIT_INLINE sljit_ins *process_extended_label(sljit_ins *code_ptr, struct sljit_extended_label *ext_label)+{+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);+ return (sljit_ins*)((sljit_uw)code_ptr & ~(ext_label->data));+}++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->u.label->size > jump->addr) {+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);+ diff -= (sljit_sw)size_reduce;+ }++ 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 (jump->u.label->size > jump->addr) {+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);+ diff -= (sljit_sw)size_reduce;+ }++ 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, options));++ 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) {+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);+ *code_ptr = buf_ptr[-1];+ }++ 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);+ 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) {+ if (label->u.index >= SLJIT_LABEL_ALIGNED)+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);++ 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:+ case SLJIT_HAS_MEMORY_BARRIER:+ 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;+ SLJIT_FALLTHROUGH+ 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;+ }+ SLJIT_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;+ SLJIT_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;+ SLJIT_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 local_size)+{+ sljit_s32 fscratches;+ sljit_s32 fsaveds;+ 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, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);++ scratches = ENTER_GET_REGS(scratches);+ saveds = ENTER_GET_REGS(saveds);+ fscratches = compiler->fscratches;+ fsaveds = compiler->fsaveds;++ 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 local_size)+{+ sljit_s32 fscratches;+ sljit_s32 fsaveds;+ sljit_s32 saved_regs_size;++ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);++ scratches = ENTER_GET_REGS(scratches);+ saveds = ENTER_GET_REGS(saveds);+ fscratches = compiler->fscratches;+ fsaveds = compiler->fsaveds;+ 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 | (0xf000 << 5));+ 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_MEMORY_BARRIER:+ return push_inst(compiler, DMB_SY);+ 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_op2_shift(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_sw shift_arg)+{+ sljit_s32 dst_r, tmp_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ shift_arg &= 0x3f;++ if (src2 == SLJIT_IMM) {+ src2w = src2w << shift_arg;+ shift_arg = 0;+ }++ if (shift_arg == 0) {+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);+ }++ if (src1 == SLJIT_IMM) {+ 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;+ }++ if (src2 & SLJIT_MEM) {+ tmp_r = (src1 == TMP_REG2) ? TMP_REG1 : TMP_REG2;+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, tmp_r, src2, src2w, tmp_r));+ src2 = tmp_r;+ }++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;+ FAIL_IF(push_inst(compiler, ADD | RD(dst_r) | RN(src1) | RM(src2) | ((sljit_ins)shift_arg << 10)));++ 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_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)) {+ if (src != TMP_LR)+ 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)) {+ if (dst == TMP_LR)+ return SLJIT_SUCCESS;+ 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;+ SLJIT_FALLTHROUGH++ case SLJIT_LESS:+ return 0x2;++ case SLJIT_NOT_CARRY:+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)+ return 0x2;+ SLJIT_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;+ SLJIT_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;+ SLJIT_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_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)+{+ sljit_uw mask, i;+ struct sljit_label *label;+ struct sljit_label *next_label;+ struct sljit_extended_label *ext_label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));++ sljit_reset_read_only_buffers(buffers);++ if (alignment <= SLJIT_LABEL_ALIGN_4) {+ SLJIT_SKIP_CHECKS(compiler);+ label = sljit_emit_label(compiler);+ PTR_FAIL_IF(!label);+ } else {+ /* The used space is filled with NOPs. */+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_ins);++ for (i = (mask >> 2); i != 0; i--)+ PTR_FAIL_IF(push_inst(compiler, NOP));++ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));+ PTR_FAIL_IF(!ext_label);+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);+ label = &ext_label->label;+ }++ if (buffers == NULL)+ return label;++ next_label = label;++ while (1) {+ buffers->u.label = next_label;++ for (i = (buffers->size + 3) >> 2; i > 0; i--)+ PTR_FAIL_IF(push_inst(compiler, NOP));++ buffers = buffers->next;++ if (buffers == NULL)+ break;++ SLJIT_SKIP_CHECKS(compiler);+ next_label = sljit_emit_label(compiler);+ PTR_FAIL_IF(!next_label);+ }++ 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 op = CSEL;+ sljit_ins cmp = 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;++ if (src1w <= 1 && src1w >= -1) {+ src1 = TMP_ZERO;+ cmp = (SUBI ^ inv_bits) | (1 << 29) | RD(TMP_ZERO);++ if (src1w == 1) {+ op = CSINC;+ cmp = (SUBI ^ inv_bits) | (1 << 29) | RD(TMP_ZERO) | (1 << 10);+ } else if (src1w == -1) {+ op = CSINV;+ cmp = (ADDI ^ inv_bits) | (1 << 29) | RD(TMP_ZERO) | (1 << 10);+ }++ src1w = 0;+ } else {+ 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;+ }++ if (type & SLJIT_COMPARE_SELECT) {+ type ^= 0x1;+ if (cmp == 0)+ cmp = (SUB ^ inv_bits) | (1 << 29) | RD(TMP_ZERO) | RM(src1);+ FAIL_IF(push_inst(compiler, cmp | RN(src2_reg)));+ }++ cc = get_cc(compiler, type & ~(SLJIT_32 | SLJIT_COMPARE_SELECT));+ return push_inst(compiler, (op ^ 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;+ SLJIT_FALLTHROUGH+ case SLJIT_MOV_U8:+ inst = STURBI | (MEM_SIZE_SHIFT(BYTE_SIZE) << 30) | 0x400;+ break;+ case SLJIT_MOV_S16:+ sign = 1;+ SLJIT_FALLTHROUGH+ case SLJIT_MOV_U16:+ inst = STURBI | (MEM_SIZE_SHIFT(HALF_SIZE) << 30) | 0x400;+ break;+ case SLJIT_MOV_S32:+ sign = 1;+ SLJIT_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 vreg,+ 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, vreg, 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(vreg) | VM(vreg);+ else+ ins = VD(vreg) | 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(vreg));+}++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 vreg,+ 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, vreg, 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(vreg));+ }++ 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(vreg));++ return push_inst(compiler, DUP_e | ins | VD(vreg) | 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(vreg));+ }++ FAIL_IF(load_immediate(compiler, TMP_REG2, srcw));+ src = TMP_REG2;+ }++ return push_inst(compiler, DUP_g | ins | VD(vreg) | RN(src));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg, 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, vreg, 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) && vreg == srcdst) {+ FAIL_IF(push_inst(compiler, ORR_v | ins | VD(TMP_FREG1) | VN(vreg) | VM(vreg)));+ srcdst = TMP_FREG1;+ srcdstw = 0;+ }++ FAIL_IF(push_inst(compiler, MOVI | ins | VD(vreg)));+ }++ 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(vreg));+ }++ 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(vreg);+ else+ ins = INS_e | ((((sljit_ins)lane_index << 1) | 1) << (16 + elem_size)) | VD(vreg) | 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(vreg);++ 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(vreg) | 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 vreg,+ 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, vreg, 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(vreg) | VN(src));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg,+ 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, vreg, 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(vreg)));+ else+ FAIL_IF(push_inst(compiler, LD1_s | ((sljit_ins)0x2000 << (reg_size - elem2_size + elem_size)) | RN(src) | VT(vreg)));+ src = vreg;+ }++ if (type & SLJIT_SIMD_FLOAT) {+ SLJIT_ASSERT(reg_size == 4);+ return push_inst(compiler, FCVTL | (1 << 22) | VD(vreg) | VN(src));+ }++ do {+ FAIL_IF(push_inst(compiler, ((type & SLJIT_SIMD_EXTEND_SIGNED) ? SSHLL : USHLL)+ | ((sljit_ins)1 << (19 + elem_size)) | VD(vreg) | VN(src)));+ src = vreg;+ } 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 vreg,+ 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, vreg, 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(vreg)));++ 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_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w)+{+ 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_vreg, src1_vreg, src2, src2w));+ ADJUST_LOCAL_OFFSET(src2, src2w);++ 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 (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;+ case SLJIT_SIMD_OP2_SHUFFLE:+ ins = TBL_v;+ break;+ }++ if (src2 & SLJIT_MEM) {+ if (elem_size > 3)+ elem_size = 3;++ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src2, src2w));+ push_inst(compiler, LD1 | (reg_size == 4 ? (1 << 30) : 0) | ((sljit_ins)elem_size << 10) | RN(src2) | VT(TMP_FREG1));+ src2 = TMP_FREG1;+ }++ if (reg_size == 4)+ ins |= (sljit_ins)1 << 30;++ return push_inst(compiler, ins | VD(dst_vreg) | VN(src1_vreg) | VM(src2));+}++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));++#ifndef __ARM_FEATURE_ATOMICS+ if (op & SLJIT_ATOMIC_USE_CAS)+ return SLJIT_ERR_UNSUPPORTED;+#endif /* ARM_FEATURE_ATOMICS */++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_S8:+ case SLJIT_MOV_S16:+ case SLJIT_MOV_S32:+ return SLJIT_ERR_UNSUPPORTED;++ case SLJIT_MOV32:+ case SLJIT_MOV_U32:+#ifdef __ARM_FEATURE_ATOMICS+ if (!(op & SLJIT_ATOMIC_USE_LS))+ ins = LDR ^ (1 << 30);+ else+#endif /* ARM_FEATURE_ATOMICS */+ ins = LDXR ^ (1 << 30);+ break;+ case SLJIT_MOV_U8:+#ifdef __ARM_FEATURE_ATOMICS+ if (!(op & SLJIT_ATOMIC_USE_LS))+ ins = LDRB;+ else+#endif /* ARM_FEATURE_ATOMICS */+ ins = LDXRB;+ break;+ case SLJIT_MOV_U16:+#ifdef __ARM_FEATURE_ATOMICS+ if (!(op & SLJIT_ATOMIC_USE_LS))+ ins = LDRH;+ else+#endif /* ARM_FEATURE_ATOMICS */+ ins = LDXRH;+ break;+ default:+#ifdef __ARM_FEATURE_ATOMICS+ if (!(op & SLJIT_ATOMIC_USE_LS))+ ins = LDR;+ else+#endif /* ARM_FEATURE_ATOMICS */+ ins = LDXR;+ break;+ }++ if (op & SLJIT_ATOMIC_TEST)+ return SLJIT_SUCCESS;++ 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_ins cmp = 0;+ SLJIT_UNUSED_ARG(temp_reg); /* !__ARM_FEATURE_ATOMICS */++ CHECK_ERROR();+ CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));++#ifdef __ARM_FEATURE_ATOMICS+ if (!(op & SLJIT_ATOMIC_USE_LS)) {+ if (op & SLJIT_SET_ATOMIC_STORED)+ cmp = (SUBS ^ W_OP) | RD(TMP_ZERO);++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_S8:+ case SLJIT_MOV_S16:+ case SLJIT_MOV_S32:+ return SLJIT_ERR_UNSUPPORTED;++ 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;+ if (cmp)+ cmp ^= W_OP;+ break;+ }++ if (op & SLJIT_ATOMIC_TEST)+ return SLJIT_SUCCESS;++ if (cmp)+ FAIL_IF(push_inst(compiler, ((MOV ^ W_OP) ^ (cmp & W_OP)) | RM(temp_reg) | RD(TMP_REG2)));++ FAIL_IF(push_inst(compiler, ins | RM(temp_reg) | RN(mem_reg) | RD(src_reg)));+ if (!cmp)+ return SLJIT_SUCCESS;++ return push_inst(compiler, cmp | RM(TMP_REG2) | RN(temp_reg));+ }+#else /* !__ARM_FEATURE_ATOMICS */+ if (op & SLJIT_ATOMIC_USE_CAS)+ return SLJIT_ERR_UNSUPPORTED;+#endif /* __ARM_FEATURE_ATOMICS */++ if (op & SLJIT_SET_ATOMIC_STORED)+ cmp = (SUBI ^ W_OP) | (1 << 29);++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_S8:+ case SLJIT_MOV_S16:+ case SLJIT_MOV_S32:+ return SLJIT_ERR_UNSUPPORTED;++ 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;+ }++ if (op & SLJIT_ATOMIC_TEST)+ return SLJIT_SUCCESS;++ FAIL_IF(push_inst(compiler, ins | RM(TMP_REG2) | RN(mem_reg) | RT(src_reg)));+ if (!cmp)+ return SLJIT_SUCCESS;+ return push_inst(compiler, cmp | RD(TMP_ZERO) | RN(TMP_REG2));+}++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(dst, dstw);+ 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;+}++#define SLJIT_EMIT_CONST_U8(c) \+ (((c) & 0x100) != 0 ? (MOVN | (sljit_ins)((~(c) & 0xff) << 5)) : (MOVZ | (sljit_ins)(((c) & 0xff) << 5)))+#define SLJIT_EMIT_CONST_S32(c) \+ (((c) < 0) ? (MOVN | (sljit_ins)((~(c) & 0xffff) << 5)) : (MOVZ | (sljit_ins)(((c) & 0xffff) << 5)))++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_s32 dst_r;+ sljit_s32 mem_flags = WORD_SIZE | STORE;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, op, 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;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_U8:+ PTR_FAIL_IF(push_inst(compiler, SLJIT_EMIT_CONST_U8(init_value) | RD(dst_r)));+ mem_flags = BYTE_SIZE | STORE;+ break;++ case SLJIT_MOV32:+ case SLJIT_MOV_S32:+ if (GET_OPCODE(op) == SLJIT_MOV32) {+ init_value = (sljit_u32)init_value;+ mem_flags = INT_SIZE | STORE;+ } else+ init_value = (sljit_s32)init_value;++ PTR_FAIL_IF(push_inst(compiler, SLJIT_EMIT_CONST_S32(init_value) | RD(dst_r)));+ PTR_FAIL_IF(push_inst(compiler, MOVK | (1 << 21) | (sljit_ins)((init_value >> 11) & 0x1fffe0) | RD(dst_r)));+ break;++ default:+ PTR_FAIL_IF(emit_imm64_const(compiler, dst_r, (sljit_uw)init_value));+ break;+ }++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, mem_flags, dst_r, dst, dstw, TMP_REG2));+ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_jump *jump;+ sljit_s32 dst_r, target_r;+ SLJIT_UNUSED_ARG(op);++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;++ if (op != SLJIT_ADD_ABS_ADDR)+ target_r = dst_r;+ else {+ target_r = TMP_REG2;++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2));+ }++ PTR_FAIL_IF(push_inst(compiler, RD(target_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 (op == SLJIT_ADD_ABS_ADDR)+ PTR_FAIL_IF(push_inst(compiler, ADD | RD(dst_r) | RN(dst_r) | RM(TMP_REG2)));++ 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)+{+ sljit_ins* inst = (sljit_ins*)addr;+ sljit_u32 dst;+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 0);++ dst = inst[0] & 0x1f;+ SLJIT_ASSERT((inst[0] & 0xffe00000) == MOVZ && (inst[1] & 0xffe00000) == (MOVK | (1 << 21)));+ inst[0] = MOVZ | dst | (((sljit_u32)new_target & 0xffff) << 5);+ inst[1] = MOVK | dst | (((sljit_u32)(new_target >> 16) & 0xffff) << 5) | (1 << 21);+ inst[2] = MOVK | dst | (((sljit_u32)(new_target >> 32) & 0xffff) << 5) | (2 << 21);+ inst[3] = MOVK | dst | ((sljit_u32)(new_target >> 48) << 5) | (3 << 21);++ 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 void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)+{+ sljit_ins* inst;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_U8:+ inst = (sljit_ins*)addr;+ SLJIT_ASSERT((inst[0] & 0xffe00000) == MOVZ || (inst[0] & 0xffe00000) == MOVN);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);+ inst[0] = SLJIT_EMIT_CONST_U8(new_constant) | (inst[0] & 0x1f);+ 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;++ case SLJIT_MOV32:+ case SLJIT_MOV_S32:+ if (GET_OPCODE(op) == SLJIT_MOV32)+ new_constant = (sljit_u32)new_constant;+ else+ new_constant = (sljit_s32)new_constant;++ inst = (sljit_ins*)addr;+ SLJIT_ASSERT(((inst[0] & 0xffe00000) == MOVZ || (inst[0] & 0xffe00000) == MOVN) && (inst[1] & 0xffe00000) == (MOVK | (1 << 21)));++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);+ inst[0] = SLJIT_EMIT_CONST_S32(new_constant) | (inst[0] & 0x1f);+ inst[1] = MOVK | (1 << 21) | (sljit_ins)((new_constant >> 11) & 0x1fffe0) | (inst[1] & 0x1f);+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 2);+ return;++ default:+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);+ return;+ }+}
+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeARM_T2_32.c view
@@ -0,0 +1,4625 @@+/*+ * 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)+{+#ifdef __SOFTFP__+ return "ARM-Thumb2" SLJIT_CPUINFO " ABI:softfp";+#else+ return "ARM-Thumb2" SLJIT_CPUINFO " ABI:hardfp";+#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)++/* 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 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))++/* --------------------------------------------------------------------- */+/* Instruction 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 DMB_SY 0xf3bf8f5f+#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 MOVI 0x2000+#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+#define VTBL 0xffb00800++#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->real_fscratches))+ || (fr > (SLJIT_FS0 - compiler->real_fsaveds) && fr <= SLJIT_FS0)+ || (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS));+}++static sljit_s32 function_check_is_vreg(struct sljit_compiler *compiler, sljit_s32 vr, sljit_s32 type)+{+ sljit_s32 vr_low = vr;++ if (compiler->scratches == -1)+ return 0;++ if (SLJIT_SIMD_GET_REG_SIZE(type) == 4) {+ vr += (vr & 0x1);+ vr_low = vr - 1;+ }++ return (vr >= SLJIT_VR0 && vr < (SLJIT_VR0 + compiler->vscratches))+ || (vr_low > (SLJIT_VS0 - compiler->vsaveds) && vr_low <= SLJIT_VS0)+ || (vr >= SLJIT_TMP_VREGISTER_BASE && vr < (SLJIT_TMP_VREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_VECTOR_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;+ sljit_uw target_addr;+ sljit_uw jump_addr = (sljit_uw)code_ptr;+ sljit_uw orig_addr = jump->addr;+ SLJIT_UNUSED_ARG(executable_offset);++ jump->addr = jump_addr;+ 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;+ target_addr = jump->u.target;+ } else {+ SLJIT_ASSERT(jump->u.label != NULL);+ target_addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);++ if (jump->u.label->size > orig_addr)+ jump_addr = (sljit_uw)(code + orig_addr);+ }++ diff = (sljit_sw)target_addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr + 4, executable_offset);++ 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_uw jump_addr = (sljit_uw)code_ptr;+ 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);++ if (jump->u.label->size > jump->addr)+ jump_addr = (sljit_uw)(code + jump->addr);+ }++ /* The pc+4 offset is represented by the 2 * SSIZE_OF(sljit_u16) below. */+ diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, 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 ((jump->flags & (JUMP_MOV_ADDR | IS_ABS)) == (JUMP_MOV_ADDR | IS_ABS))+ diff &= ~(sljit_sw)1;++ 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 SLJIT_INLINE sljit_u16 *process_extended_label(sljit_u16 *code_ptr, struct sljit_extended_label *ext_label)+{+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);+ return (sljit_u16*)((sljit_uw)code_ptr & ~(ext_label->data));+}++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->u.label->size > jump->addr) {+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);+ diff -= (sljit_sw)size_reduce;+ }++ 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 (jump->u.label->size > jump->addr) {+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);+ diff -= (sljit_sw)size_reduce;+ }++ 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, options));++ 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) {+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);+ *code_ptr = buf_ptr[-1];+ }++ 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);+ 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) {+ if (label->u.index >= SLJIT_LABEL_ALIGNED)+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);++ 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:+ case SLJIT_HAS_MEMORY_BARRIER:+ 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;+ SLJIT_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;+ SLJIT_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;+ SLJIT_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;+ SLJIT_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;+ SLJIT_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 local_size)+{+ sljit_s32 fscratches;+ sljit_s32 fsaveds;+ 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, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);++ scratches = ENTER_GET_REGS(scratches);+ saveds = ENTER_GET_REGS(saveds);+ fscratches = compiler->fscratches;+ fsaveds = compiler->fsaveds;++ 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 local_size)+{+ sljit_s32 fscratches;+ sljit_s32 fsaveds;+ sljit_s32 size;++ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);++ scratches = ENTER_GET_REGS(scratches);+ saveds = ENTER_GET_REGS(saveds);+ fscratches = compiler->fscratches;+ fsaveds = compiler->fsaveds;+ 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_MEMORY_BARRIER:+ return push_inst32(compiler, DMB_SY);+ 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_op2_shift(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_sw shift_arg)+{+ sljit_s32 dst_r, tmp_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ shift_arg &= 0x1f;++ if (src2 == SLJIT_IMM) {+ src2w = src2w << shift_arg;+ shift_arg = 0;+ }++ if (shift_arg == 0) {+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);+ }++ if (src1 == SLJIT_IMM) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));+ src1 = TMP_REG1;+ } else if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src1, src1w, TMP_REG1));+ src1 = TMP_REG1;+ }++ if (src2 & SLJIT_MEM) {+ tmp_r = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, tmp_r, src2, src2w, tmp_r));+ src2 = tmp_r;+ }++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ FAIL_IF(push_inst32(compiler, ADD_W | RD4(dst_r) | RN4(src1) | RM4(src2) | ((sljit_ins)(shift_arg & 0x3) << 6) | ((sljit_ins)(shift_arg & 0x1c) << 10)));++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG1);+ 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);++ switch (op) {+ case SLJIT_FAST_RETURN:+ SLJIT_ASSERT(reg_map[TMP_REG2] == 14);++ if (FAST_IS_REG(src)) {+ if (src != TMP_REG2)+ 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)) {+ if (dst == TMP_REG2)+ return SLJIT_SUCCESS;+ 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;+ SLJIT_FALLTHROUGH++ case SLJIT_LESS:+ return 0x3;++ case SLJIT_NOT_CARRY:+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)+ return 0x3;+ SLJIT_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;+ SLJIT_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;+ SLJIT_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_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)+{+ sljit_uw mask, i;+ struct sljit_label *label;+ struct sljit_label *next_label;+ struct sljit_extended_label *ext_label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));++ sljit_reset_read_only_buffers(buffers);++ if (alignment <= SLJIT_LABEL_ALIGN_2) {+ SLJIT_SKIP_CHECKS(compiler);+ label = sljit_emit_label(compiler);+ PTR_FAIL_IF(!label);+ } else {+ /* The used space is filled with NOPs. */+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_u16);++ for (i = (mask >> 1); i != 0; i--)+ PTR_FAIL_IF(push_inst16(compiler, NOP));++ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));+ PTR_FAIL_IF(!ext_label);+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);+ label = &ext_label->label;+ }++ if (buffers == NULL)+ return label;++ next_label = label;++ while (1) {+ buffers->u.label = next_label;++ for (i = (buffers->size + 1) >> 1; i > 0; i--)+ PTR_FAIL_IF(push_inst16(compiler, NOP));++ buffers = buffers->next;++ if (buffers == NULL)+ break;++ SLJIT_SKIP_CHECKS(compiler);+ next_label = sljit_emit_label(compiler);+ PTR_FAIL_IF(!next_label);+ }++ 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, tmp2;++ 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;+ if (!(type & SLJIT_COMPARE_SELECT))+ 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;+ if (!(type & SLJIT_COMPARE_SELECT))+ 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)));++ if ((type & SLJIT_COMPARE_SELECT))+ type ^= 0x1;+ cc = get_cc(compiler, type & ~(SLJIT_32 | SLJIT_COMPARE_SELECT));++ if (src1 == SLJIT_IMM && (type & SLJIT_COMPARE_SELECT)) {+ tmp = (sljit_uw)src1w;+ if (tmp <= 0xff && reg_map[dst_reg] <= 7) {+ if (type & SLJIT_COMPARE_SELECT)+ FAIL_IF(push_inst16(compiler, CMPI | IMM8(tmp) | RDN3(dst_reg)));+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));+ return push_inst16(compiler, MOVI | IMM8(tmp) | RDN3(dst_reg));+ }++ tmp = get_imm((sljit_uw)src1w);+ if (tmp != INVALID_IMM) {+ if (type & SLJIT_COMPARE_SELECT)+ FAIL_IF(push_inst32(compiler, CMPI_W | RN4(dst_reg) | tmp));+ 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 && (type & SLJIT_COMPARE_SELECT)) {+ tmp2 = get_imm(NEGATE(src1w));+ if (tmp2 != INVALID_IMM)+ FAIL_IF(push_inst32(compiler, CMNI_W | RN4(dst_reg) | tmp2));+ else+ tmp = INVALID_IMM;+ }++ if (tmp != INVALID_IMM) {+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));+ return push_inst32(compiler, MVN_WI | RD4(dst_reg) | tmp);+ }++ if (type & SLJIT_COMPARE_SELECT) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));+ src1 = TMP_REG1;+ }+ }++ if (src1 != SLJIT_IMM) {+ if (type & SLJIT_COMPARE_SELECT) {+ if (IS_2_LO_REGS(dst_reg, src1))+ FAIL_IF(push_inst16(compiler, CMP | RD3(dst_reg) | RN3(src1)));+ else+ FAIL_IF(push_inst16(compiler, CMP_X | SET_REGS44(dst_reg, src1)));+ }++ 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));+ }++ 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 vreg,+ 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, vreg, 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)+ vreg = simd_get_quad_reg_index(vreg);++ if (!(srcdst & SLJIT_MEM)) {+ if (reg_size == 4)+ srcdst = simd_get_quad_reg_index(srcdst);++ if (type & SLJIT_SIMD_STORE)+ ins = VD4(srcdst) | VN4(vreg) | VM4(vreg);+ else+ ins = VD4(vreg) | 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(vreg)+ | (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 vreg,+ 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, vreg, 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)+ vreg = simd_get_quad_reg_index(vreg);++ if (src == SLJIT_IMM && srcw == 0)+ return push_inst32(compiler, VMOV_i | ((reg_size == 4) ? (1 << 6) : 0) | VD4(vreg));++ 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, vreg, src, srcw));+ src = vreg;+ } else if (vreg != src)+ FAIL_IF(push_inst32(compiler, VORR | VD4(vreg) | VN4(src) | VM4(src)));++ vreg += SLJIT_QUAD_OTHER_HALF(vreg);++ if (vreg != src)+ return push_inst32(compiler, VORR | VD4(vreg) | 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(vreg) | 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(vreg) | (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(vreg));+ }++ 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(vreg) | RT4(src));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg, 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, vreg, 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)+ vreg = simd_get_quad_reg_index(vreg);++ 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)+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);++ if (srcdst != vreg)+ FAIL_IF(push_inst32(compiler, VORR | VD4(vreg) | VN4(srcdst) | VM4(srcdst)));++ vreg += SLJIT_QUAD_OTHER_HALF(vreg);+ return push_inst32(compiler, VMOV_i | VD4(vreg));+ }++ if (srcdst == vreg || (elem_size == 3 && srcdst == (vreg + SLJIT_QUAD_OTHER_HALF(vreg)))) {+ FAIL_IF(push_inst32(compiler, VORR | ins | VD4(TMP_FREG2) | VN4(vreg) | VM4(vreg)));+ srcdst = TMP_FREG2;+ srcdstw = 0;+ }+ }++ FAIL_IF(push_inst32(compiler, VMOV_i | ins | VD4(vreg)));+ }++ if (reg_size == 4 && lane_index >= (0x8 >> elem_size)) {+ lane_index -= (0x8 >> elem_size);+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);+ }++ if (srcdst & SLJIT_MEM) {+ if (elem_size == 3)+ return emit_fop_mem(compiler, ((type & SLJIT_SIMD_STORE) ? 0 : FPU_LOAD) | SLJIT_32, vreg, 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(vreg) | 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(vreg) | VM4(vreg));+ return push_inst32(compiler, VMOV_F32 | SLJIT_32 | VD4(vreg) | VM4(srcdst));+ }++ if (type & SLJIT_SIMD_STORE) {+ if (freg_ebit_map[vreg] == 0) {+ if (lane_index == 1)+ vreg = SLJIT_F64_SECOND(vreg);++ return push_inst32(compiler, VMOV_F32 | VD4(srcdst) | VM4(vreg));+ }++ FAIL_IF(push_inst32(compiler, VMOV_s | (1 << 20) | ((sljit_ins)lane_index << 21) | VN4(vreg) | 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(vreg) | 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(vreg) | RT4(srcdst));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg,+ 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, vreg, 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) {+ vreg = simd_get_quad_reg_index(vreg);+ 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 (vreg != src)+ FAIL_IF(push_inst32(compiler, VORR | VD4(vreg) | VN4(src) | VM4(src)));++ vreg += SLJIT_QUAD_OTHER_HALF(vreg);++ if (vreg != src)+ return push_inst32(compiler, VORR | VD4(vreg) | 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(vreg) | VM4(src));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg,+ 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, vreg, 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)+ vreg = simd_get_quad_reg_index(vreg);++ 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(vreg) | RN4(src) | 0xf));+ else+ FAIL_IF(push_inst32(compiler, VLD1_s | (sljit_ins)((reg_size - elem2_size + elem_size) << 10) | VD4(vreg) | RN4(src) | 0xf));+ src = vreg;+ } else if (reg_size == 4)+ src = simd_get_quad_reg_index(src);++ if (!(type & SLJIT_SIMD_FLOAT)) {+ dst_reg = (reg_size == 4) ? vreg : 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(vreg) | VN4(TMP_FREG2) | VM4(TMP_FREG2));+ return SLJIT_SUCCESS;+ }++ /* No SIMD variant, must use VFP instead. */+ SLJIT_ASSERT(reg_size == 4);++ if (vreg == src) {+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);+ FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | VD4(vreg) | VM4(src) | 0x20));+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);+ return push_inst32(compiler, VCVT_F64_F32 | VD4(vreg) | VM4(src));+ }++ FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | VD4(vreg) | VM4(src)));+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);+ return push_inst32(compiler, VCVT_F64_F32 | VD4(vreg) | VM4(src) | 0x20);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg,+ 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, vreg, 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) {+ vreg = simd_get_quad_reg_index(vreg);+ ins |= (sljit_ins)1 << 6;+ }++ SLJIT_ASSERT((freg_map[TMP_FREG2] & 0x1) == 0);+ FAIL_IF(push_inst32(compiler, ins | VD4(TMP_FREG2) | VM4(vreg)));++ 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_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_s32 alignment;+ sljit_ins ins = 0, load_ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w));+ ADJUST_LOCAL_OFFSET(src2, src2w);++ 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 (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;+ case SLJIT_SIMD_OP2_SHUFFLE:+ ins = VTBL;+ break;+ }++ if (src2 & SLJIT_MEM) {+ if (elem_size > 3)+ elem_size = 3;++ load_ins = VLD1 | (sljit_ins)((reg_size == 3) ? (0x7 << 8) : (0xa << 8));+ alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type);++ SLJIT_ASSERT(reg_size >= alignment);++ if (alignment == 3)+ load_ins |= 0x10;+ else if (alignment >= 4)+ load_ins |= 0x20;++ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src2, src2w));+ FAIL_IF(push_inst32(compiler, load_ins | VD4(TMP_FREG2) | RN4(src2) | ((sljit_ins)elem_size) << 6 | 0xf));+ src2 = TMP_FREG2;+ }++ if (reg_size == 4) {+ dst_vreg = simd_get_quad_reg_index(dst_vreg);+ src1_vreg = simd_get_quad_reg_index(src1_vreg);+ src2 = simd_get_quad_reg_index(src2);++ if (SLJIT_SIMD_GET_OPCODE(type) == SLJIT_SIMD_OP2_SHUFFLE) {+ ins |= (sljit_ins)1 << 8;++ FAIL_IF(push_inst32(compiler, ins | VD4(dst_vreg != src1_vreg ? dst_vreg : TMP_FREG2) | VN4(src1_vreg) | VM4(src2)));+ src2 += SLJIT_QUAD_OTHER_HALF(src2);+ FAIL_IF(push_inst32(compiler, ins | VD4(dst_vreg + SLJIT_QUAD_OTHER_HALF(dst_vreg)) | VN4(src1_vreg) | VM4(src2)));++ if (dst_vreg == src1_vreg)+ return push_inst32(compiler, VORR | VD4(dst_vreg) | VN4(TMP_FREG2) | VM4(TMP_FREG2));+ return SLJIT_SUCCESS;+ }++ ins |= (sljit_ins)1 << 6;+ }++ return push_inst32(compiler, ins | VD4(dst_vreg) | VN4(src1_vreg) | VM4(src2));+}++#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));++ if (op & SLJIT_ATOMIC_USE_CAS)+ return SLJIT_ERR_UNSUPPORTED;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_S8:+ case SLJIT_MOV_S16:+ case SLJIT_MOV_S32:+ return SLJIT_ERR_UNSUPPORTED;++ case SLJIT_MOV_U8:+ ins = LDREXB;+ break;+ case SLJIT_MOV_U16:+ ins = LDREXH;+ break;+ default:+ ins = LDREX;+ break;+ }++ if (op & SLJIT_ATOMIC_TEST)+ return SLJIT_SUCCESS;++ 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));++ if (op & SLJIT_ATOMIC_USE_CAS)+ return SLJIT_ERR_UNSUPPORTED;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_S8:+ case SLJIT_MOV_S16:+ case SLJIT_MOV_S32:+ return SLJIT_ERR_UNSUPPORTED;++ 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;+ }++ if (op & SLJIT_ATOMIC_TEST)+ return SLJIT_SUCCESS;++ 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 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_s32 dst_r;+ sljit_s32 mem_flags = WORD_SIZE | STORE;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, op, 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;++ if (GET_OPCODE(op) == SLJIT_MOV_U8) {+ PTR_FAIL_IF(push_inst32(compiler,+ ((init_value & 0x100) != 0 ? (MVN_WI | (~init_value & 0xff)) : (MOV_WI | (init_value & 0xff))) | RD4(dst_r)));+ mem_flags = BYTE_SIZE | STORE;+ } else+ PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, (sljit_uw)init_value));++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, mem_flags, dst_r, dst, dstw, TMP_REG2));+ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_jump *jump;+ sljit_s32 dst_r, target_r;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;++ if (op != SLJIT_ADD_ABS_ADDR)+ target_r = dst_r;+ else {+ target_r = TMP_REG1;++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, dst_r, dst, dstw, TMP_REG1));+ }++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_mov_addr(jump, compiler, 0);++ if (op != SLJIT_MOV_ADDR)+ jump->flags |= IS_ABS;++ PTR_FAIL_IF(push_inst16(compiler, RDN3(target_r)));+ compiler->size += 3;++ if (op == SLJIT_ADD_ABS_ADDR)+ PTR_FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(dst_r, TMP_REG1)));++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, 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)+{+ sljit_u16 *inst = (sljit_u16*)addr;+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 0);+ modify_imm32_const(inst, new_target);+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 1);+ inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 4);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)+{+ sljit_u16 *inst;++ if (GET_OPCODE(op) != SLJIT_MOV_U8) {+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);+ return;+ }++ inst = (sljit_u16*)addr;+ SLJIT_ASSERT(inst[0] == (MOV_WI >> 16) || inst[0] == (MVN_WI >> 16));++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);++ if ((new_constant & 0x100) != 0) {+ inst[0] = (sljit_u16)(MVN_WI >> 16);+ new_constant = ~new_constant;+ } else+ inst[0] = (sljit_u16)(MOV_WI >> 16);++ inst[1] = (sljit_u16)((new_constant & 0xff) | (inst[1] & 0xf00));+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);+ inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst + 1, inst + 2);+}
+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeLOONGARCH_64.c view
@@ -0,0 +1,4123 @@+/*+ * 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+};++/* --------------------------------------------------------------------- */+/* Instruction 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)++/* Memory barrier instructions */+#define DBAR OPC_3R(0x70e4)++/* Other instructions */+#define BREAK OPC_3R(0x54)+#define DBGCALL OPC_3R(0x55)+#define NOP ANDI+#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 VSHUF_B OPC_4R(0xd5)+#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++#define LOONGARCH_SUPPORT_AMCAS (LOONGARCH_CFG2_LAMCAS & get_cpu_features(GET_CFG2))++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_ptr, sljit_ins *code, sljit_sw executable_offset)+{+ sljit_sw diff;+ sljit_uw target_addr;+ sljit_uw jump_addr = (sljit_uw)code_ptr;+ sljit_uw orig_addr = jump->addr;+ SLJIT_UNUSED_ARG(executable_offset);++ jump->addr = 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)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);++ if (jump->u.label->size > orig_addr)+ jump_addr = (sljit_uw)(code + orig_addr);+ }++ diff = (sljit_sw)target_addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset);++ if (jump->flags & IS_COND) {+ diff += SSIZE_OF(ins);++ if (diff >= BRANCH16_MIN && diff <= BRANCH16_MAX) {+ code_ptr--;+ code_ptr[0] = (code_ptr[0] & 0xfc0003ff) ^ 0x4000000;+ jump->flags |= PATCH_B;+ jump->addr = (sljit_uw)code_ptr;+ return code_ptr;+ }++ diff -= SSIZE_OF(ins);+ }++ if (diff >= JUMP_MIN && diff <= JUMP_MAX) {+ if (jump->flags & IS_COND) {+ code_ptr[-1] |= (sljit_ins)IMM_I16(2);+ }++ jump->flags |= PATCH_J;+ return code_ptr;+ }++ if (diff >= S32_MIN && diff <= S32_MAX) {+ if (jump->flags & IS_COND)+ code_ptr[-1] |= (sljit_ins)IMM_I16(3);++ jump->flags |= PATCH_REL32;+ code_ptr[1] = code_ptr[0];+ return code_ptr + 1;+ }++ if (target_addr <= (sljit_uw)S32_MAX) {+ if (jump->flags & IS_COND)+ code_ptr[-1] |= (sljit_ins)IMM_I16(3);++ jump->flags |= PATCH_ABS32;+ code_ptr[1] = code_ptr[0];+ return code_ptr + 1;+ }++ if (target_addr <= S52_MAX) {+ if (jump->flags & IS_COND)+ code_ptr[-1] |= (sljit_ins)IMM_I16(4);++ jump->flags |= PATCH_ABS52;+ code_ptr[2] = code_ptr[0];+ return code_ptr + 2;+ }++exit:+ if (jump->flags & IS_COND)+ code_ptr[-1] |= (sljit_ins)IMM_I16(5);+ code_ptr[3] = code_ptr[0];+ return code_ptr + 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_uw jump_addr = (sljit_uw)code_ptr;+ 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);++ if (jump->u.label->size > jump->addr)+ jump_addr = (sljit_uw)(code + jump->addr);+ }++ diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, 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 SLJIT_INLINE sljit_ins *process_extended_label(sljit_ins *code_ptr, struct sljit_extended_label *ext_label)+{+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);+ return (sljit_ins*)((sljit_uw)code_ptr & ~(ext_label->data));+}++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->u.label->size > jump->addr) {+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);+ diff -= (sljit_sw)size_reduce;+ }++ 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 (jump->u.label->size > jump->addr) {+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);+ diff -= (sljit_sw)size_reduce;+ }++ 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, options));++ 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) {+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);+ *code_ptr = buf_ptr[-1];+ }++ 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);+ code_ptr = detect_jump_type(jump, code_ptr, 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) {+ if (label->u.index >= SLJIT_LABEL_ALIGNED)+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);++ 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_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:+ case SLJIT_HAS_ATOMIC:+ case SLJIT_HAS_MEMORY_BARRIER:+ 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)));+ if (IMM_I12(imm) != 0)+ return push_inst(compiler, ORI | RD(dst_r) | RJ(dst_r) | IMM_I12(imm));+ return SLJIT_SUCCESS;+ } else if (imm <= 0x7ffffffffffffl && imm >= -0x8000000000000l) {+ FAIL_IF(push_inst(compiler, LU12I_W | RD(dst_r) | (sljit_ins)(((imm & 0xffffffff) >> 12) << 5)));+ if (IMM_I12(imm) != 0)+ 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)));+ if (IMM_I12(imm) != 0)+ 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 local_size)+{+ sljit_s32 fscratches;+ sljit_s32 fsaveds;+ 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, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);++ scratches = ENTER_GET_REGS(scratches);+ saveds = ENTER_GET_REGS(saveds);+ fscratches = compiler->fscratches;+ fsaveds = compiler->fsaveds;+ 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 local_size)+{+ sljit_s32 fscratches;+ sljit_s32 fsaveds;++ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);++ scratches = ENTER_GET_REGS(scratches);+ saveds = ENTER_GET_REGS(saveds);+ fscratches = compiler->fscratches;+ fsaveds = compiler->fsaveds;+ 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(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)));++ 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, NOP);+ 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_MEMORY_BARRIER:+ return push_inst(compiler, DBAR);+ 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_op2_shift(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_sw shift_arg)+{+ sljit_s32 dst_r, tmp_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ shift_arg &= (sljit_sw)((sizeof(sljit_sw) * 8) - 1);++ if (src2 == SLJIT_IMM) {+ src2w = src2w << shift_arg;+ shift_arg = 0;+ }++ if (shift_arg == 0) {+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);+ }++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));+ src2 = TMP_REG2;+ }++ if (src1 == SLJIT_IMM) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));+ src1 = TMP_REG1;+ } else if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));+ src1 = TMP_REG1;+ }++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ tmp_r = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;+ FAIL_IF(push_inst(compiler, SLLI_D | RD(tmp_r) | RJ(src2) | IMM_I12(shift_arg)));+ FAIL_IF(push_inst(compiler, ADD_D | RD(dst_r) | RJ(src1) | RK(tmp_r)));++ if (dst & SLJIT_MEM)+ return emit_op_mem2(compiler, WORD_DATA, dst_r, dst, dstw, 0, 0);+ 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)+{+ 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)) {+ if (src != RETURN_ADDR_REG)+ 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)) {+ if (dst == RETURN_ADDR_REG)+ return SLJIT_SUCCESS;+ 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;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)+{+ sljit_uw mask, i;+ struct sljit_label *label;+ struct sljit_label *next_label;+ struct sljit_extended_label *ext_label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));++ sljit_reset_read_only_buffers(buffers);++ if (alignment <= SLJIT_LABEL_ALIGN_4) {+ SLJIT_SKIP_CHECKS(compiler);+ label = sljit_emit_label(compiler);+ PTR_FAIL_IF(!label);+ } else {+ /* The used space is filled with NOPs. */+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_ins);++ for (i = (mask >> 2); i != 0; i--)+ PTR_FAIL_IF(push_inst(compiler, NOP));++ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));+ PTR_FAIL_IF(!ext_label);+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);+ label = &ext_label->label;+ }++ if (buffers == NULL)+ return label;++ next_label = label;++ while (1) {+ buffers->u.label = next_label;++ for (i = (buffers->size + 3) >> 2; i > 0; i--)+ PTR_FAIL_IF(push_inst(compiler, NOP));++ buffers = buffers->next;++ if (buffers == NULL)+ break;++ SLJIT_SKIP_CHECKS(compiler);+ next_label = sljit_emit_label(compiler);+ PTR_FAIL_IF(!next_label);+ }++ return label;+}++static sljit_ins get_jump_instruction(sljit_s32 type)+{+ switch (type) {+ case SLJIT_EQUAL:+ return BNE | RJ(EQUAL_FLAG) | RD(TMP_ZERO);+ case SLJIT_NOT_EQUAL:+ 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:+ case SLJIT_ATOMIC_STORED:+ 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:+ case SLJIT_ATOMIC_NOT_STORED:+ 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(OTHER_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 is_compare = (type & SLJIT_COMPARE_SELECT);+ 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 (src1 == SLJIT_IMM && type & SLJIT_32)+ src1w = (sljit_s32)src1w;++ type &= ~(SLJIT_32 | SLJIT_COMPARE_SELECT);++ if (dst_reg != src2_reg) {+ if (dst_reg == src1) {+ src1 = src2_reg;+ src1w = 0;+ if (!is_compare)+ type ^= 0x1;+ } else {+ if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {+ SLJIT_ASSERT(!(type & SLJIT_COMPARE_SELECT));+ 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)));+ }+ }++ if (is_compare) {+ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG3, src1, src1w));+ } else if (src1 == SLJIT_IMM) {+ FAIL_IF(load_immediate(compiler, TMP_REG3, src1w));+ } else+ FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG3) | RJ(src1) | 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) {+ FAIL_IF(load_immediate(compiler, dst_reg, src1w));+ } else+ FAIL_IF(push_inst(compiler, ADDI_D | RD(dst_reg) | RJ(src1) | IMM_I12(0)));++ if (is_compare) {+ switch (type) {+ case SLJIT_LESS:+ case SLJIT_LESS_EQUAL:+ *ptr = BGEU;+ break;+ case SLJIT_GREATER:+ case SLJIT_GREATER_EQUAL:+ *ptr = BLTU;+ break;+ case SLJIT_SIG_LESS:+ case SLJIT_SIG_LESS_EQUAL:+ *ptr = BGE;+ break;+ default:+ *ptr = BLT;+ break;+ }++ *ptr |= RJ(TMP_REG3) | RD(dst_reg);+ } else {+ *ptr = get_jump_instruction(type);+ }++ *ptr |= 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 vreg,+ 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, vreg, 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(vreg) | FRK(vreg);+ else+ ins = FRD(vreg) | 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(vreg) | RJ((sljit_u8)srcdst) | IMM_I12(srcdstw));+ else {+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw));+ return push_inst(compiler, ins | FRD(vreg) | RJ(srcdst) | IMM_I12(0));+ }+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg,+ 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, vreg, 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(vreg) | 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(vreg) | RJ(TMP_ZERO) | (sljit_ins)elem_size << 10);++ FAIL_IF(push_inst(compiler, VREPLVE | ins | FRD(vreg) | 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(vreg) | FRJ(vreg));+ }++ 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(vreg) | RJ(src));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg, 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, vreg, 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) && vreg == srcdst) {+ FAIL_IF(push_inst(compiler, VOR_V | ins | FRD(TMP_FREG1) | FRJ(vreg) | FRK(vreg)));+ srcdst = TMP_FREG1;+ srcdstw = 0;+ }++ FAIL_IF(push_inst(compiler, VXOR_V | ins | FRD(vreg) | FRJ(vreg) | FRK(vreg)));+ }++ 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(vreg) | 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(vreg) | FRK(vreg)));+ if (lane_index >= (2 << (3 - elem_size))) {+ FAIL_IF(push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(TMP_FREG1) | FRJ(vreg) | 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(vreg) | FRJ(TMP_FREG1) | IMM_I8(2));+ } else {+ FAIL_IF(push_inst(compiler, VINSGR2VR | ins | FRD(vreg) | RJ(srcdst) | IMM_V(lane_index)));+ return push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(vreg) | 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(vreg) | 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(vreg) | 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(vreg) | 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(vreg) | FRK(vreg)));+ FAIL_IF(push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(TMP_FREG1) | FRJ(vreg) | 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(vreg) | 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(vreg) | FRK(vreg)));+ if (lane_index >= (2 << (3 - elem_size))) {+ FAIL_IF(push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(TMP_FREG1) | FRJ(vreg) | 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(vreg) | FRJ(TMP_FREG1) | IMM_I8(2));+ } else {+ FAIL_IF(push_inst(compiler, VINSGR2VR | ins | FRD(vreg) | RJ(srcdst) | IMM_V(lane_index)));+ return push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(vreg) | 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(vreg) | 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 vreg,+ 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, vreg, 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(vreg) | 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(vreg) | FRJ(vreg));+ }++ return push_inst(compiler, VREPLVEI | ins | FRD(vreg) | 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 vreg,+ 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, vreg, 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(vreg) | RJ(src) | IMM_I12(srcw)));+ else {+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw));+ FAIL_IF(push_inst(compiler, ins | FRD(vreg) | RJ(src) | IMM_I12(0)));+ }+ src = vreg;+ }++ 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(vreg) | 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(vreg) | FRJ(src)));+ src = vreg;+ } 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 vreg,+ 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, vreg, 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(vreg)));++ 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_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w)+{+ 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_vreg, src1_vreg, src2, src2w));+ ADJUST_LOCAL_OFFSET(src2, src2w);++ 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;++ if (src2 & SLJIT_MEM) {+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src2, src2w));+ FAIL_IF(push_inst(compiler, (reg_size == 4 ? VLD : XVLD) | FRD(TMP_FREG1) | RJ(src2) | IMM_I12(0)));+ src2 = TMP_FREG1;+ }++ 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;+ case SLJIT_SIMD_OP2_SHUFFLE:+ if (reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ return push_inst(compiler, VSHUF_B | FRD(dst_vreg) | FRJ(src1_vreg) | FRK(src1_vreg) | FRA(src2));+ }++ if (reg_size == 5)+ ins |= (sljit_ins)1 << 26;++ return push_inst(compiler, ins | FRD(dst_vreg) | FRJ(src1_vreg) | FRK(src2));+}++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));++ if ((op & SLJIT_ATOMIC_USE_LS) || !LOONGARCH_SUPPORT_AMCAS) {+ if (op & SLJIT_ATOMIC_USE_CAS)+ return SLJIT_ERR_UNSUPPORTED;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+ ins = LL_D;+ break;+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+ ins = LL_W;+ break;++ default:+ return SLJIT_ERR_UNSUPPORTED;+ }++ if (op & SLJIT_ATOMIC_TEST)+ return SLJIT_SUCCESS;++ return push_inst(compiler, ins | RD(dst_reg) | RJ(mem_reg));+ }++ switch(GET_OPCODE(op)) {+ case SLJIT_MOV_S8:+ ins = LD_B;+ break;+ case SLJIT_MOV_U8:+ ins = LD_BU;+ break;+ case SLJIT_MOV_S16:+ ins = LD_H;+ break;+ case SLJIT_MOV_U16:+ ins = LD_HU;+ break;+ case SLJIT_MOV32:+ case SLJIT_MOV_S32:+ ins = LD_W;+ break;+ case SLJIT_MOV_U32:+ ins = LD_WU;+ break;+ default:+ ins = LD_D;+ break;+ }++ if (op & SLJIT_ATOMIC_TEST)+ return SLJIT_SUCCESS;++ 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));++ if ((op & SLJIT_ATOMIC_USE_LS) || !LOONGARCH_SUPPORT_AMCAS) {+ if (op & SLJIT_ATOMIC_USE_CAS)+ return SLJIT_ERR_UNSUPPORTED;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+ ins = SC_D;+ break;+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+ ins = SC_W;+ break;++ default:+ return SLJIT_ERR_UNSUPPORTED;+ }++ if (op & SLJIT_ATOMIC_TEST)+ return SLJIT_SUCCESS;++ FAIL_IF(push_inst(compiler, ADD_D | RD(OTHER_FLAG) | RJ(src_reg) | RK(TMP_ZERO)));+ return push_inst(compiler, ins | RD(OTHER_FLAG) | RJ(mem_reg));+ }++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_S8:+ ins = AMCAS_B;+ break;+ case SLJIT_MOV_U8:+ ins = AMCAS_B;+ unsign = BSTRPICK_D | (7 << 16);+ break;+ case SLJIT_MOV_S16:+ ins = AMCAS_H;+ break;+ case SLJIT_MOV_U16:+ ins = AMCAS_H;+ unsign = BSTRPICK_D | (15 << 16);+ break;+ case SLJIT_MOV32:+ case SLJIT_MOV_S32:+ 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_ATOMIC_TEST)+ return SLJIT_SUCCESS;++ if (op & SLJIT_SET_ATOMIC_STORED) {+ FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG3) | RJ(temp_reg) | RK(TMP_ZERO)));+ tmp = TMP_REG3;+ }+ 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(OTHER_FLAG) | RJ(tmp) | RK(temp_reg)));+ return push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RJ(OTHER_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 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_s32 dst_r;+ sljit_s32 mem_flags = WORD_DATA;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, op, 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;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_U8:+ if (init_value & 0x100)+ init_value |= 0xf00;+ else+ init_value &= 0xff;++ PTR_FAIL_IF(push_inst(compiler, ADDI_D | RD(dst_r) | RJ(TMP_ZERO) | IMM_I12(init_value)));+ mem_flags = BYTE_DATA;+ break;++ case SLJIT_MOV32:+ mem_flags = INT_DATA;+ SLJIT_FALLTHROUGH+ case SLJIT_MOV_S32:+ PTR_FAIL_IF(push_inst(compiler, LU12I_W | RD(dst_r) | (sljit_ins)((init_value >> 7) & 0x1ffffe0)));+ PTR_FAIL_IF(push_inst(compiler, ORI | RD(dst_r) | RJ(dst_r) | IMM_I12(init_value)));+ break;++ default:+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value, 0));+ break;+ }++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG2, dst, dstw));++ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_jump *jump;+ sljit_s32 dst_r, target_r;+ SLJIT_UNUSED_ARG(op);++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;++ if (op != SLJIT_ADD_ABS_ADDR)+ target_r = dst_r;+ else {+ target_r = TMP_REG1;++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, dst, dstw));+ }++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_mov_addr(jump, compiler, 0);++ PTR_FAIL_IF(push_inst(compiler, (sljit_ins)target_r));++ compiler->size += JUMP_MAX_SIZE - 1;++ if (op == SLJIT_ADD_ABS_ADDR)+ PTR_FAIL_IF(push_inst(compiler, ADD_D | RD(dst_r) | RJ(dst_r) | RK(TMP_REG1)));++ 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_s32 op, sljit_sw new_constant, sljit_sw executable_offset)+{+ sljit_ins* inst;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_U8:+ inst = (sljit_ins*)addr;+ SLJIT_ASSERT((inst[0] & OPC_2RI12(0xb)) == ADDI_D);++ if (new_constant & 0x100)+ new_constant |= 0xf00;+ else+ new_constant &= 0xff;++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);+ inst[0] = (inst[0] & 0xffc003ff) | (sljit_ins)((new_constant & 0xfff) << 10);+ 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;++ case SLJIT_MOV32:+ case SLJIT_MOV_S32:+ inst = (sljit_ins *)addr;+ SLJIT_ASSERT((inst[0] & OPC_1RI20(0xa)) == LU12I_W && (inst[1] & OPC_2RI12(0xe)) == ORI);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);+ inst[0] = (inst[0] & (OPC_1RI20(0xa) | 0x1f)) | (sljit_ins)((new_constant >> 7) & 0x1ffffe0);+ inst[1] = (inst[1] & (OPC_2RI12(0xe) | 0x3ff)) | (sljit_ins)((new_constant & 0xfff) << 10);+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 2);+ return;++ default:+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);+ return;+ }+}
+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_32.c view
@@ -0,0 +1,467 @@+/*+ * 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.+ */++/* 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))+ return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);++ if (imm < 0 && imm >= SIMM_MIN)+ return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);++ FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));+ return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : 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 >> 16), DR(dst)));+ return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));+}++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;++ CHECK_ERROR();+ CHECK(check_sljit_emit_fset64(compiler, freg, value));++ u.value = value;++ 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));++ 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;+}++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);++ CHECK_ERROR();+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));++ op = GET_OPCODE(op);+ if (reg & REG_PAIR_MASK) {+ reg2 = REG_PAIR_SECOND(reg);+ reg = REG_PAIR_FIRST(reg);++ inst |= T(reg2);++ 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)));++ 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);+ }+#endif /* SLJIT_MIPS_REV >= 2 */+ }++ 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 (op == SLJIT_COPY_TO_F64)+ FAIL_IF(push_inst(compiler, mthc | inst, MOVABLE_INS));+ else+ FAIL_IF(push_inst(compiler, mfhc | inst, DR(reg)));++#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)+{+ sljit_ins *inst = (sljit_ins *)addr;+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);+ SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI);+ inst[0] = (inst[0] & 0xffff0000) | IMM(new_target >> 16);+ inst[1] = (inst[1] & 0xffff0000) | IMM(new_target);+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 2);+}++static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr, sljit_u32 *extra_space)+{+ sljit_u32 is_tail_call = *extra_space & SLJIT_CALL_RETURN;+ sljit_u32 offset = 0;+ sljit_s32 float_arg_count = 0;+ sljit_s32 word_arg_count = 0;+ sljit_s32 types = 0;+ sljit_ins prev_ins = NOP;+ 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_REG2] == 4 && freg_map[TMP_FREG1] == 12);++ arg_types >>= SLJIT_ARG_SHIFT;++ /* See ABI description in sljit_emit_enter. */++ while (arg_types) {+ types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);+ *offsets_ptr = (sljit_u8)offset;++ switch (arg_types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ if (offset & 0x7) {+ offset += sizeof(sljit_sw);+ *offsets_ptr = (sljit_u8)offset;+ }++ if (word_arg_count == 0 && float_arg_count <= 1)+ *offsets_ptr = (sljit_u8)(254 + float_arg_count);++ offset += sizeof(sljit_f64);+ float_arg_count++;+ break;+ case SLJIT_ARG_TYPE_F32:+ if (word_arg_count == 0 && float_arg_count <= 1)+ *offsets_ptr = (sljit_u8)(254 + float_arg_count);++ offset += sizeof(sljit_f32);+ float_arg_count++;+ break;+ default:+ offset += sizeof(sljit_sw);+ word_arg_count++;+ break;+ }++ arg_types >>= SLJIT_ARG_SHIFT;+ offsets_ptr++;+ }++ /* Stack is aligned to 16 bytes. */+ SLJIT_ASSERT(offset <= 8 * sizeof(sljit_sw));++ if (offset > 4 * sizeof(sljit_sw) && (!is_tail_call || offset > compiler->args_size)) {+ if (is_tail_call) {+ offset = (offset + sizeof(sljit_sw) + 15) & ~(sljit_uw)0xf;+ FAIL_IF(emit_stack_frame_release(compiler, (sljit_s32)offset, &prev_ins));+ *extra_space = offset;+ } else {+ FAIL_IF(push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-16), DR(SLJIT_SP)));+ *extra_space = 16;+ }+ } else {+ if (is_tail_call)+ FAIL_IF(emit_stack_frame_release(compiler, 0, &prev_ins));+ *extra_space = 0;+ }++ while (types) {+ --offsets_ptr;++ switch (types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ 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);+ 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_fmt(FMT_D) | FS(SLJIT_FR0) | FD(TMP_FREG1);++ float_arg_count--;+ break;+ case SLJIT_ARG_TYPE_F32:+ if (*offsets_ptr < 4 * sizeof (sljit_sw))+ ins = MFC1 | TA(4 + (*offsets_ptr >> 2)) | FS(float_arg_count);+ else if (*offsets_ptr < 254)+ ins = SWC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(*offsets_ptr);+ else if (*offsets_ptr == 254)+ ins = MOV_fmt(FMT_S) | FS(SLJIT_FR0) | FD(TMP_FREG1);++ float_arg_count--;+ break;+ default:+ if (*offsets_ptr >= 4 * sizeof (sljit_sw))+ ins = SW | S(SLJIT_SP) | T(word_arg_count) | IMM(*offsets_ptr);+ else if ((*offsets_ptr >> 2) != word_arg_count - 1)+ ins = ADDU | S(word_arg_count) | TA(0) | DA(4 + (*offsets_ptr >> 2));+ else if (*offsets_ptr == 0)+ ins = ADDU | S(SLJIT_R0) | TA(0) | DA(4);++ word_arg_count--;+ break;+ }++ if (ins != NOP) {+ if (prev_ins != NOP)+ FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));+ prev_ins = ins;+ ins = NOP;+ }++ types >>= SLJIT_ARG_SHIFT;+ }++ *ins_ptr = prev_ins;++ 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_u32 extra_space = 0;+ sljit_ins ins = NOP;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);++ 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);++ if (ins == NOP && compiler->delay_slot != UNMOVABLE_INS)+ jump->flags |= IS_MOVABLE;++ if (!(type & SLJIT_CALL_RETURN) || extra_space > 0) {+ 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));++ 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;++ if (type & SLJIT_CALL_RETURN)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG,+ SLJIT_MEM1(SLJIT_SP), (sljit_sw)(extra_space - sizeof(sljit_sw))));++ if (type & SLJIT_CALL_RETURN)+ PTR_FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));++ PTR_FAIL_IF(push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(extra_space),+ (type & SLJIT_CALL_RETURN) ? UNMOVABLE_INS : DR(SLJIT_SP)));+ 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_u32 extra_space = (sljit_u32)type;+ sljit_ins ins;++ 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, 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));++ /* Register input. */+ if (!(type & SLJIT_CALL_RETURN) || extra_space > 0)+ FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));+ else+ FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));+ FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));++ if (extra_space == 0)+ return SLJIT_SUCCESS;++ if (type & SLJIT_CALL_RETURN)+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG,+ SLJIT_MEM1(SLJIT_SP), (sljit_sw)(extra_space - sizeof(sljit_sw))));++ if (type & SLJIT_CALL_RETURN)+ FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));++ return push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(extra_space),+ (type & SLJIT_CALL_RETURN) ? UNMOVABLE_INS : DR(SLJIT_SP));+}
+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_64.c view
@@ -0,0 +1,382 @@+/*+ * 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.+ */++/* 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;+ sljit_s32 shift2;+ sljit_s32 inv = 0;+ sljit_ins ins;+ sljit_uw uimm;++ if (!(imm & ~0xffff))+ return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);++ if (imm < 0 && imm >= SIMM_MIN)+ return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);++ if (imm <= 0x7fffffffl && imm >= -0x80000000l) {+ FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));+ return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;+ }++ /* Zero extended number. */+ uimm = (sljit_uw)imm;+ if (imm < 0) {+ uimm = ~(sljit_uw)imm;+ inv = 1;+ }++ while (!(uimm & 0xff00000000000000l)) {+ shift -= 8;+ uimm <<= 8;+ }++ if (!(uimm & 0xf000000000000000l)) {+ shift -= 4;+ uimm <<= 4;+ }++ if (!(uimm & 0xc000000000000000l)) {+ shift -= 2;+ uimm <<= 2;+ }++ if ((sljit_sw)uimm < 0) {+ uimm >>= 1;+ shift += 1;+ }+ SLJIT_ASSERT(((uimm & 0xc000000000000000l) == 0x4000000000000000l) && (shift > 0) && (shift <= 32));++ if (inv)+ uimm = ~uimm;++ FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(uimm >> 48), dst_ar));+ if (uimm & 0x0000ffff00000000l)+ FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 32), dst_ar));++ imm &= (1l << shift) - 1;+ if (!(imm & ~0xffff)) {+ ins = (shift == 32) ? DSLL32 : DSLL;+ if (shift < 32)+ ins |= SH_IMM(shift);+ FAIL_IF(push_inst(compiler, ins | TA(dst_ar) | DA(dst_ar), dst_ar));+ return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);+ }++ /* Double shifts needs to be performed. */+ uimm <<= 32;+ shift2 = shift - 16;++ while (!(uimm & 0xf000000000000000l)) {+ shift2 -= 4;+ uimm <<= 4;+ }++ if (!(uimm & 0xc000000000000000l)) {+ shift2 -= 2;+ uimm <<= 2;+ }++ if (!(uimm & 0x8000000000000000l)) {+ shift2--;+ uimm <<= 1;+ }++ SLJIT_ASSERT((uimm & 0x8000000000000000l) && (shift2 > 0) && (shift2 <= 16));++ FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift - shift2), dst_ar));+ FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 48), dst_ar));+ FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift2), dst_ar));++ imm &= (1l << shift2) - 1;+ return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);+}++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 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(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;+ }++ 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;+}++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));++ inst = T(reg) | FS(freg);++ 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)));++#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;+}++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 + 6, 0);+ inst[0] = (inst[0] & 0xffff0000) | IMM(new_target >> 48);+ inst[1] = (inst[1] & 0xffff0000) | IMM(new_target >> 32);+ inst[3] = (inst[3] & 0xffff0000) | IMM(new_target >> 16);+ inst[5] = (inst[5] & 0xffff0000) | IMM(new_target);+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 1);+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 6);+}++static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr)+{+ sljit_s32 arg_count = 0;+ sljit_s32 word_arg_count = 0;+ sljit_s32 float_arg_count = 0;+ sljit_s32 types = 0;+ sljit_ins prev_ins = *ins_ptr;+ sljit_ins ins = NOP;++ SLJIT_ASSERT(reg_map[TMP_REG2] == 4 && freg_map[TMP_FREG1] == 12);++ 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:+ case SLJIT_ARG_TYPE_F32:+ arg_count++;+ float_arg_count++;+ break;+ default:+ arg_count++;+ word_arg_count++;+ break;+ }++ arg_types >>= SLJIT_ARG_SHIFT;+ }++ while (types) {+ switch (types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ if (arg_count != float_arg_count)+ ins = MOV_fmt(FMT_D) | FS(float_arg_count) | FD(arg_count);+ else if (arg_count == 1)+ 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_fmt(FMT_S) | FS(float_arg_count) | FD(arg_count);+ else if (arg_count == 1)+ ins = MOV_fmt(FMT_S) | FS(SLJIT_FR0) | FD(TMP_FREG1);+ arg_count--;+ float_arg_count--;+ break;+ default:+ if (arg_count != word_arg_count)+ ins = DADDU | S(word_arg_count) | TA(0) | D(arg_count);+ else if (arg_count == 1)+ ins = DADDU | S(SLJIT_R0) | TA(0) | DA(4);+ arg_count--;+ word_arg_count--;+ break;+ }++ if (ins != NOP) {+ if (prev_ins != NOP)+ FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));+ prev_ins = ins;+ ins = NOP;+ }++ types >>= SLJIT_ARG_SHIFT;+ }++ *ins_ptr = prev_ins;++ 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_ins ins = NOP;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);++ if (type & SLJIT_CALL_RETURN)+ PTR_FAIL_IF(emit_stack_frame_release(compiler, 0, &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);++ if (ins == NOP && compiler->delay_slot != UNMOVABLE_INS)+ jump->flags |= IS_MOVABLE;++ if (!(type & SLJIT_CALL_RETURN)) {+ 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));++ 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;+}++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_ins ins = NOP;++ 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, 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));++ FAIL_IF(call_with_args(compiler, arg_types, &ins));++ /* Register input. */+ if (!(type & SLJIT_CALL_RETURN))+ FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));+ else+ FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));+ return push_inst(compiler, ins, UNMOVABLE_INS);+}
+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_common.c view
@@ -0,0 +1,4597 @@+/*+ * 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.+ */++/* Latest MIPS architecture. */++#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 */++/* --------------------------------------------------------------------- */+/* Instruction 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 LL (HI(48))+#define LLD (HI(52))+#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 SC (HI(56))+#define SCD (HI(60))+#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 SYNC (HI(0) | LO(15))+#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->real_fscratches))+ || (fr > (SLJIT_FS0 - compiler->real_fsaveds) && fr <= SLJIT_FS0)+ || (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS));+}++static sljit_s32 function_check_is_vreg(struct sljit_compiler *compiler, sljit_s32 vr, sljit_s32 type)+{+ SLJIT_UNUSED_ARG(compiler);+ SLJIT_UNUSED_ARG(vr);+ SLJIT_UNUSED_ARG(type);++ /* SIMD is not supported. */+ return 0;+}++#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);+}++static SLJIT_INLINE sljit_ins *process_extended_label(sljit_ins *code_ptr, struct sljit_extended_label *ext_label)+{+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);+ return (sljit_ins*)((sljit_uw)code_ptr & ~(ext_label->data));+}++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, options));+ 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) {+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);+ *code_ptr = buf_ptr[-1];+ }++ 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) {+ if (label->u.index >= SLJIT_LABEL_ALIGNED)+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);++ 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:+ case SLJIT_HAS_ATOMIC:+ case SLJIT_HAS_MEMORY_BARRIER:+ 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 local_size)+{+ sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);+ sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);+ 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, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);++ scratches = ENTER_GET_REGS(scratches);+ saveds = ENTER_GET_REGS(saveds);++ 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 local_size)+{+ sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);+ sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);++ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);++ scratches = ENTER_GET_REGS(scratches);+ saveds = ENTER_GET_REGS(saveds);++ 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_ar, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)+{+ if (getput_arg_fast(compiler, flags, reg_ar, arg1, arg1w))+ return compiler->error;+ return getput_arg(compiler, flags, reg_ar, 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;+ }+ SLJIT_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_MEMORY_BARRIER:+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)+ return push_inst(compiler, SYNC, UNMOVABLE_INS);+#else /* SLJIT_MIPS_REV < 1 */+ return SLJIT_ERR_UNSUPPORTED;+#endif /* SLJIT_MIPS_REV >= 1 */+ 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);+ }+ SLJIT_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));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(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_sw shift_arg)+{+ sljit_s32 dst_r, tmp_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ shift_arg &= (sljit_sw)((sizeof(sljit_sw) * 8) - 1);++ if (src2 == SLJIT_IMM) {+ src2w = src2w << shift_arg;+ shift_arg = 0;+ }++ if (shift_arg == 0) {+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);+ }++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG2), src2, src2w, src1, src1w));+ src2 = TMP_REG2;+ }++ if (src1 == SLJIT_IMM) {+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));+ src1 = TMP_REG1;+ } else if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));+ src1 = TMP_REG1;+ }++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ tmp_r = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ FAIL_IF(push_inst(compiler, (shift_arg >= 32 ? DSLL32 : DSLL) | T(src2) | D(tmp_r) | SH_IMM(shift_arg & 0x1f), DR(tmp_r)));+#else /* !SLJIT_CONFIG_MIPS_64 */+ FAIL_IF(push_inst(compiler, SLL | T(src2) | D(tmp_r) | SH_IMM(shift_arg), DR(tmp_r)));+#endif /* SLJIT_CONFIG_MIPS_64 */+ FAIL_IF(push_inst(compiler, ADDU_W | S(src1) | T(tmp_r) | D(dst_r), DR(dst_r)));++ if (dst & SLJIT_MEM)+ return emit_op_mem2(compiler, WORD_DATA, DR(dst_r), dst, dstw, 0, 0);+ return SLJIT_SUCCESS;+}++#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)) {+ if (DR(src) != RETURN_ADDR_REG)+ 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)) {+ if (DR(dst) == RETURN_ADDR_REG)+ return SLJIT_SUCCESS;+ 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;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)+{+ sljit_uw mask, i;+ struct sljit_label *label;+ struct sljit_label *next_label;+ struct sljit_extended_label *ext_label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));++ sljit_reset_read_only_buffers(buffers);++ if (alignment <= SLJIT_LABEL_ALIGN_4) {+ SLJIT_SKIP_CHECKS(compiler);+ label = sljit_emit_label(compiler);+ PTR_FAIL_IF(!label);+ } else {+ /* The used space is filled with NOPs. */+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_ins);++ for (i = (mask >> 2); i != 0; i--)+ PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));++ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));+ PTR_FAIL_IF(!ext_label);+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);+ label = &ext_label->label;+ }++ if (buffers == NULL)+ return label;++ next_label = label;++ while (1) {+ buffers->u.label = next_label;++ for (i = (buffers->size + 3) >> 2; i > 0; i--)+ PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));++ buffers = buffers->next;++ if (buffers == NULL)+ break;++ SLJIT_SKIP_CHECKS(compiler);+ next_label = sljit_emit_label(compiler);+ PTR_FAIL_IF(!next_label);+ }++ 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:+ case SLJIT_ATOMIC_STORED:+ 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:+ case SLJIT_ATOMIC_NOT_STORED:+ 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) {+ 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_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ if (src1 == SLJIT_IMM && (type & SLJIT_32))+ src1w = (sljit_s32)src1w;+#endif++ type &= ~SLJIT_32;++ if (type & SLJIT_COMPARE_SELECT) {+ type ^= SLJIT_COMPARE_SELECT;++ 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 (src1w == 0) {+ src1 = 0;+ } else {+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));+ src1 = TMP_REG1;+ }+ }++ src1w = 0;+ FAIL_IF(emit_op(compiler, SLJIT_SUB | SLJIT_SET(type & ~0x1), IMM_OP, 0, 0, src1, 0, src2_reg, 0));+ }++#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) {+ 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 ^ 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) {+ 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 & ~SLJIT_32, 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 ^ 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 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));++ if (op & SLJIT_ATOMIC_USE_CAS)+ return SLJIT_ERR_UNSUPPORTED;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ ins = LLD;+ break;+#endif /* SLJIT_CONFIG_MIPS_64 */+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+ ins = LL;+ break;++ default:+ return SLJIT_ERR_UNSUPPORTED;+ }++ if (op & SLJIT_ATOMIC_TEST)+ return SLJIT_SUCCESS;++ return push_inst(compiler, ins | T(dst_reg) | S(mem_reg), DR(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));++ if (op & SLJIT_ATOMIC_USE_CAS)+ return SLJIT_ERR_UNSUPPORTED;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ ins = SCD;+ break;+#endif /* SLJIT_CONFIG_MIPS_64 */+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+ op |= SLJIT_32;+ ins = SC;+ break;++ default:+ return SLJIT_ERR_UNSUPPORTED;+ }++ if (op & SLJIT_ATOMIC_TEST)+ return SLJIT_SUCCESS;++ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src_reg) | TA(0) | DA(OTHER_FLAG), OTHER_FLAG));+ return push_inst(compiler, ins | TA(OTHER_FLAG) | S(mem_reg), OTHER_FLAG);+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_s32 dst_r;+ sljit_s32 mem_flags = WORD_DATA;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, op, 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;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_U8:+ if (init_value & 0x100)+ init_value |= 0xff00;+ else+ init_value &= 0xff;++ PTR_FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(dst_r) | IMM(init_value), DR(dst_r)));+ mem_flags = BYTE_DATA;+ break;++#if (defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64)+ case SLJIT_MOV32:+ mem_flags = INT_DATA;+ SLJIT_FALLTHROUGH+ case SLJIT_MOV_S32:+ PTR_FAIL_IF(push_inst(compiler, LUI | T(dst_r) | IMM(init_value >> 16), DR(dst_r)));+ PTR_FAIL_IF(push_inst(compiler, ORI | S(dst_r) | T(dst_r) | IMM(init_value), DR(dst_r)));+ break;+#endif /* SLJIT_CONFIG_MIPS_64 */++ default:+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));+ break;+ }++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, mem_flags, DR(TMP_REG2), dst, dstw));++ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_jump *jump;+ sljit_s32 dst_r, target_r;+ SLJIT_UNUSED_ARG(op);++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;++ if (op != SLJIT_ADD_ABS_ADDR)+ target_r = dst_r;+ else {+ target_r = TMP_REG1;++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG2), dst, dstw));+ }++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_mov_addr(jump, compiler, 0);++ PTR_FAIL_IF(push_inst(compiler, (sljit_ins)target_r, UNMOVABLE_INS));+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ compiler->size += 1;+#else+ compiler->size += 5;+#endif++ if (op == SLJIT_ADD_ABS_ADDR)+ PTR_FAIL_IF(push_inst(compiler, ADDU_W | S(dst_r) | T(TMP_REG1) | D(dst_r), DR(dst_r)));++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, DR(TMP_REG2), dst, dstw));++ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)+{+ sljit_ins *inst;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_U8:+ inst = (sljit_ins *)addr;+ SLJIT_ASSERT((inst[0] & 0xfc000000) == ADDIU);++ if (new_constant & 0x100)+ new_constant |= 0xff00;+ else+ new_constant &= 0xff;++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);+ inst[0] = (inst[0] & 0xffff0000) | IMM(new_constant);+ 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 (defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64)+ case SLJIT_MOV32:+ case SLJIT_MOV_S32:+ inst = (sljit_ins *)addr;+ SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);+ inst[0] = (inst[0] & 0xffff0000) | IMM(new_constant >> 16);+ inst[1] = (inst[1] & 0xffff0000) | IMM(new_constant);+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 2);+ return;+#endif /* SLJIT_CONFIG_MIPS_64 */++ default:+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);+ return;+ }+}
+ src/c/pcre2/deps/sljit/sljit_src/sljitNativePPC_32.c view
@@ -0,0 +1,485 @@+/*+ * 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.+ */++/* ppc 32-bit arch dependent functions. */++static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)+{+ if (imm <= SIMM_MAX && imm >= SIMM_MIN)+ return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));++ if (!(imm & ~0xffff))+ return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));++ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));+ 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) | 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:+ case SLJIT_MOV_S32:+ case SLJIT_MOV_P:+ SLJIT_ASSERT(src1 == TMP_REG1);+ if (dst != src2)+ return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U8:+ case SLJIT_MOV_S8:+ SLJIT_ASSERT(src1 == TMP_REG1);+ 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));+ }+ else if ((flags & REG_DEST) && op == SLJIT_MOV_S8)+ return push_inst(compiler, EXTSB | S(src2) | A(dst));+ else {+ SLJIT_ASSERT(dst == src2);+ }+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U16:+ case SLJIT_MOV_S16:+ SLJIT_ASSERT(src1 == TMP_REG1);+ 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));+ }+ else {+ SLJIT_ASSERT(dst == src2);+ }+ return SLJIT_SUCCESS;++ 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. */+ return push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));+ }++ if (flags & ALT_FORM2) {+ /* Flags does not set: BIN_IMM_EXTS unnecessary. */+ SLJIT_ASSERT(src2 == TMP_REG2);++ 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) | (((imm >> 16) & 0xffff) + ((imm >> 15) & 0x1))));+ src1 = dst;+ }++ return push_inst(compiler, ADDI | D(dst) | A(src1) | (imm & 0xffff));+ }+ if (flags & ALT_FORM3) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);+ }+ SLJIT_ASSERT(!(flags & ALT_FORM4));+ if (!(flags & ALT_SET_FLAGS))+ return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));+ if (flags & ALT_FORM5)+ return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));+ return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));++ case SLJIT_ADDC:+ return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));++ case SLJIT_SUB:+ if (flags & ALT_FORM1) {+ if (flags & ALT_FORM2) {+ FAIL_IF(push_inst(compiler, CMPLI | CRD(0) | A(src1) | compiler->imm));+ if (!(flags & ALT_FORM3))+ return SLJIT_SUCCESS;+ return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));+ }+ FAIL_IF(push_inst(compiler, CMPL | CRD(0) | A(src1) | B(src2)));+ if (!(flags & ALT_FORM3))+ return SLJIT_SUCCESS;+ return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));+ }++ if (flags & ALT_FORM2) {+ if (flags & ALT_FORM3) {+ FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm));+ if (!(flags & ALT_FORM4))+ return SLJIT_SUCCESS;+ return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));+ }+ FAIL_IF(push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2)));+ if (!(flags & ALT_FORM4))+ return SLJIT_SUCCESS;+ return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));+ }++ if (flags & ALT_FORM3) {+ /* Setting XER SO is not enough, CR SO is also needed. */+ if (src1 != TMP_ZERO)+ return push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));+ return push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2));+ }++ if (flags & ALT_FORM4) {+ /* Flags does not set: BIN_IMM_EXTS unnecessary. */+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);+ }++ if (!(flags & ALT_SET_FLAGS)) {+ SLJIT_ASSERT(src1 != TMP_ZERO);+ return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));+ }++ if (flags & ALT_FORM5)+ return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));++ if (src1 != TMP_ZERO)+ return push_inst(compiler, SUBF | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));+ return push_inst(compiler, NEG | RC(ALT_SET_FLAGS) | D(dst) | A(src2));++ case SLJIT_SUBC:+ return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));++ case SLJIT_MUL:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);+ }+ return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));++ case SLJIT_AND:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);+ }+ if (flags & ALT_FORM2) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);+ }+ return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));++ case SLJIT_OR:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);+ }+ if (flags & ALT_FORM2) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);+ }+ if (flags & ALT_FORM3) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ 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));++ case SLJIT_XOR:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);+ }+ if (flags & ALT_FORM2) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);+ }+ if (flags & ALT_FORM3) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ 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);+ 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);+ 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);+ 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();+ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value)+{+ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 16)));+ return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));+}++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;+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);+ SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDIS && (inst[1] & 0xfc000000) == ORI);+ inst[0] = (inst[0] & 0xffff0000) | IMM(new_target >> 16);+ inst[1] = (inst[1] & 0xffff0000) | IMM(new_target);+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 2);+}
+ src/c/pcre2/deps/sljit/sljit_src/sljitNativePPC_64.c view
@@ -0,0 +1,719 @@+/*+ * 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.+ */++/* ppc 64-bit arch dependent functions. */++#if defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM)+#define ASM_SLJIT_CLZ(src, dst) \+ __asm__ volatile ( "cntlzd %0, %1" : "=r"(dst) : "r"(src) )+#elif defined(__xlc__)+#error "Please enable GCC syntax for inline assembly statements"+#else+#error "Must implement count leading zeroes"+#endif++/* 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)+{+ sljit_uw tmp;+ sljit_uw shift;+ sljit_uw tmp2;+ sljit_uw shift2;++ if (imm <= SIMM_MAX && imm >= SIMM_MIN)+ return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));++ if (((sljit_uw)imm >> 16) == 0)+ return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));++ if (imm <= 0x7fffffffl && imm >= -0x80000000l) {+ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));+ 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);+ SLJIT_ASSERT(shift > 0);+ shift--;+ tmp = ((sljit_uw)imm << shift);++ if ((tmp & ~0xffff000000000000ul) == 0) {+ FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));+ shift += 15;+ 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_SLDI_NEG(reg, shift);+ }++ /* Cut out the 16 bit from immediate. */+ shift += 15;+ tmp2 = (sljit_uw)imm & (((sljit_uw)1 << (63 - shift)) - 1);++ if (tmp2 <= 0xffff) {+ FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));+ 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_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;+ }++ ASM_SLJIT_CLZ(tmp2, shift2);+ tmp2 <<= shift2;++ if ((tmp2 & ~0xffff000000000000ul) == 0) {+ FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));+ shift2 += 15;+ shift += (63 - shift2);+ FAIL_IF(PUSH_SLDI_NEG(reg, shift));+ FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | (sljit_ins)(tmp2 >> 48)));+ 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_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));+}++#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)) { \+ FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \+ src2 = TMP_REG2; \+ }++#define BIN_EXTS() \+ if (flags & ALT_SIGN_EXT) { \+ if (flags & REG1_SOURCE) { \+ FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \+ src1 = TMP_REG1; \+ } \+ if (flags & REG2_SOURCE) { \+ FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \+ src2 = TMP_REG2; \+ } \+ }++#define BIN_IMM_EXTS() \+ if ((flags & (ALT_SIGN_EXT | REG1_SOURCE)) == (ALT_SIGN_EXT | REG1_SOURCE)) { \+ FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \+ src1 = TMP_REG1; \+ }++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:+ SLJIT_ASSERT(src1 == TMP_REG1);+ if (dst != src2)+ return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U32:+ case SLJIT_MOV_S32:+ SLJIT_ASSERT(src1 == TMP_REG1);+ 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, CLRLDI(dst, src2, 32));+ }+ else {+ SLJIT_ASSERT(dst == src2);+ }+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U8:+ case SLJIT_MOV_S8:+ SLJIT_ASSERT(src1 == TMP_REG1);+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+ if (op == SLJIT_MOV_S8)+ return push_inst(compiler, EXTSB | S(src2) | A(dst));+ 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));+ else {+ SLJIT_ASSERT(dst == src2);+ }+ return SLJIT_SUCCESS;++ case SLJIT_MOV_U16:+ case SLJIT_MOV_S16:+ SLJIT_ASSERT(src1 == TMP_REG1);+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {+ if (op == SLJIT_MOV_S16)+ return push_inst(compiler, EXTSH | S(src2) | A(dst));+ return push_inst(compiler, CLRLDI(dst, src2, 48));+ }+ else {+ SLJIT_ASSERT(dst == src2);+ }+ return SLJIT_SUCCESS;++ case SLJIT_CLZ:+ SLJIT_ASSERT(src1 == TMP_REG1);+ return push_inst(compiler, ((flags & ALT_FORM1) ? CNTLZW : CNTLZD) | 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, ((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, SLDI(32) | S(src1) | A(TMP_REG1)));+ src1 = TMP_REG1;+ 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, SRDI(32) | S(dst) | A(dst));+ return SLJIT_SUCCESS;+ }++ if (flags & ALT_FORM2) {+ /* Flags does not set: BIN_IMM_EXTS unnecessary. */+ SLJIT_ASSERT(src2 == TMP_REG2);++ 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) | (((imm >> 16) & 0xffff) + ((imm >> 15) & 0x1))));+ src1 = dst;+ }++ return push_inst(compiler, ADDI | D(dst) | A(src1) | (imm & 0xffff));+ }+ if (flags & ALT_FORM3) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ BIN_IMM_EXTS();+ return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);+ }+ if (flags & ALT_FORM4) {+ if (flags & ALT_FORM5)+ FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm));+ else+ FAIL_IF(push_inst(compiler, ADD | D(dst) | A(src1) | B(src2)));+ return push_inst(compiler, CMPI | A(dst) | 0);+ }+ if (!(flags & ALT_SET_FLAGS))+ return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));+ BIN_EXTS();+ if (flags & ALT_FORM5)+ return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));+ return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));++ case SLJIT_ADDC:+ BIN_EXTS();+ return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));++ case SLJIT_SUB:+ if (flags & ALT_FORM1) {+ if (flags & ALT_FORM2) {+ FAIL_IF(push_inst(compiler, CMPLI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));+ if (!(flags & ALT_FORM3))+ return SLJIT_SUCCESS;+ return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));+ }+ FAIL_IF(push_inst(compiler, CMPL | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));+ if (!(flags & ALT_FORM3))+ return SLJIT_SUCCESS;+ return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));+ }++ if (flags & ALT_FORM2) {+ if (flags & ALT_FORM3) {+ FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));+ if (!(flags & ALT_FORM4))+ return SLJIT_SUCCESS;+ return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));+ }+ FAIL_IF(push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));+ if (!(flags & ALT_FORM4))+ return SLJIT_SUCCESS;+ return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));+ }++ if (flags & ALT_FORM3) {+ if (flags & ALT_SIGN_EXT) {+ if (src1 != TMP_ZERO) {+ FAIL_IF(push_inst(compiler, SLDI(32) | S(src1) | A(TMP_REG1)));+ src1 = TMP_REG1;+ }+ if (src2 != TMP_ZERO) {+ 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. */+ if (src1 != TMP_ZERO)+ FAIL_IF(push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)));+ else+ 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, SRDI(32) | S(dst) | A(dst));+ return SLJIT_SUCCESS;+ }++ if (flags & ALT_FORM4) {+ /* Flags does not set: BIN_IMM_EXTS unnecessary. */+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);+ }++ if (!(flags & ALT_SET_FLAGS)) {+ SLJIT_ASSERT(src1 != TMP_ZERO);+ return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));+ }++ BIN_EXTS();+ if (flags & ALT_FORM5)+ return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));++ if (src1 != TMP_ZERO)+ return push_inst(compiler, SUBF | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));+ return push_inst(compiler, NEG | RC(ALT_SET_FLAGS) | D(dst) | A(src2));++ case SLJIT_SUBC:+ BIN_EXTS();+ return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));++ case SLJIT_MUL:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);+ }+ BIN_EXTS();+ if (flags & ALT_FORM2)+ return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));+ return push_inst(compiler, MULLD | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));++ case SLJIT_AND:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);+ }+ if (flags & ALT_FORM2) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);+ }+ return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));++ case SLJIT_OR:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);+ }+ if (flags & ALT_FORM2) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);+ }+ if (flags & ALT_FORM3) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ 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));++ case SLJIT_XOR:+ if (flags & ALT_FORM1) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);+ }+ if (flags & ALT_FORM2) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);+ }+ if (flags & ALT_FORM3) {+ SLJIT_ASSERT(src2 == TMP_REG2);+ 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) {+ imm &= 0x1f;+ return push_inst(compiler, SLWI(imm) | RC(flags) | S(src1) | A(dst));+ }++ 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) {+ 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));+ }++ 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) {+ imm &= 0x1f;+ return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (imm << 11));+ }++ 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();+ return SLJIT_SUCCESS;+}++static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src)+{+ sljit_s32 arg_count = 0;+ sljit_s32 word_arg_count = 0;+ sljit_s32 types = 0;+ sljit_s32 reg = 0;++ if (src)+ reg = *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:+ case SLJIT_ARG_TYPE_F32:+ arg_count++;+ break;+ default:+ arg_count++;+ word_arg_count++;++ if (arg_count != word_arg_count && arg_count == reg) {+ FAIL_IF(push_inst(compiler, OR | S(reg) | A(TMP_CALL_REG) | B(reg)));+ *src = TMP_CALL_REG;+ }+ break;+ }++ arg_types >>= SLJIT_ARG_SHIFT;+ }++ while (types) {+ switch (types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ case SLJIT_ARG_TYPE_F32:+ arg_count--;+ break;+ default:+ if (arg_count != word_arg_count)+ FAIL_IF(push_inst(compiler, OR | S(word_arg_count) | A(arg_count) | B(word_arg_count)));++ arg_count--;+ word_arg_count--;+ break;+ }++ types >>= SLJIT_ARG_SHIFT;+ }++ return SLJIT_SUCCESS;+}++static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value)+{+ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 48)));+ FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value >> 32)));+ 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;+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 0);+ inst[0] = (inst[0] & 0xffff0000u) | IMM(new_target >> 48);+ inst[1] = (inst[1] & 0xffff0000u) | IMM(new_target >> 32);+ inst[3] = (inst[3] & 0xffff0000u) | IMM(new_target >> 16);+ inst[4] = (inst[4] & 0xffff0000u) | IMM(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/deps/sljit/sljit_src/sljitNativePPC_common.c view
@@ -0,0 +1,3513 @@+/*+ * 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 "PowerPC" SLJIT_CPUINFO;+}++/* Length of an instruction word.+ Both for ppc-32 and ppc-64. */+typedef sljit_u32 sljit_ins;++#if ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && (defined _AIX)) \+ || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+#define SLJIT_PPC_STACK_FRAME_V2 1+#endif++#ifdef _AIX+#include <sys/cache.h>+#endif++#if (defined _CALL_ELF && _CALL_ELF == 2)+#define SLJIT_PASS_ENTRY_ADDR_TO_CALL 1+#endif++#if (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL)++static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)+{+#ifdef _AIX+ _sync_cache_range((caddr_t)from, (int)((size_t)to - (size_t)from));+#elif defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM)+# if defined(_ARCH_PWR) || defined(_ARCH_PWR2)+ /* Cache flush for POWER architecture. */+ while (from < to) {+ __asm__ volatile (+ "clf 0, %0\n"+ "dcs\n"+ : : "r"(from)+ );+ from++;+ }+ __asm__ volatile ( "ics" );+# elif defined(_ARCH_COM) && !defined(_ARCH_PPC)+# error "Cache flush is not implemented for PowerPC/POWER common mode."+# else+ /* Cache flush for PowerPC architecture. */+ while (from < to) {+ __asm__ volatile (+ "dcbf 0, %0\n"+ "sync\n"+ "icbi 0, %0\n"+ : : "r"(from)+ );+ from++;+ }+ __asm__ volatile ( "isync" );+# endif+# ifdef __xlc__+# warning "This file may fail to compile if -qfuncsect is used"+# endif+#elif defined(__xlc__)+#error "Please enable GCC syntax for inline assembly statements with -qasm=gcc"+#else+#error "This platform requires a cache flush implementation."+#endif /* _AIX */+}++#endif /* (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL) */++#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)+#define TMP_ZERO (SLJIT_NUMBER_OF_REGISTERS + 4)++#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_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+};++/* --------------------------------------------------------------------- */+/* Instruction 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))+#define LDARX (HI(31) | LO(84))+#if defined(_ARCH_PWR7) && _ARCH_PWR7+#define LDBRX (HI(31) | LO(532))+#endif /* POWER7 */+#define LHBRX (HI(31) | LO(790))+#define LWARX (HI(31) | LO(20))+#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 STDCX (HI(31) | LO(214))+#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 STWCX (HI(31) | LO(150))+#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 SYNC (HI(31) | LO(598))+#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;+ sljit_uw jump_addr = (sljit_uw)code_ptr;+ sljit_uw orig_addr = jump->addr;+ SLJIT_UNUSED_ARG(executable_offset);++ jump->addr = jump_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 (jump->u.label->size > orig_addr)+ jump_addr = (sljit_uw)(code + orig_addr);+ }++#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)SLJIT_ADD_EXEC_OFFSET(jump_addr, 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 SLJIT_INLINE sljit_ins *process_extended_label(sljit_ins *code_ptr, struct sljit_extended_label *ext_label)+{+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);+ return (sljit_ins*)((sljit_uw)code_ptr & ~(ext_label->data));+}++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->u.label->size > jump->addr) {+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);+ diff -= (sljit_sw)size_reduce;+ }++ 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;+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)+ sljit_uw jump_addr;+#endif+ 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, options));++ reduce_code_size(compiler);++#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)+ if (!(options & SLJIT_GENERATE_CODE_NO_CONTEXT)) {+ /* 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 /* !SLJIT_CONFIG_PPC_64 */+ compiler->size += (sizeof(struct sljit_function_context) / sizeof(sljit_ins));+#endif /* SLJIT_CONFIG_PPC_64 */+ }+#endif /* SLJIT_INDIRECT_CALL */+ 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) {+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);+ *code_ptr = buf_ptr[-1];+ }++ /* 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;+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)+ jump_addr = (sljit_uw)code_ptr;+#endif+ 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) {+ if (label->u.index >= SLJIT_LABEL_ALIGNED)+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);++ 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 -+ ((options & SLJIT_GENERATE_CODE_NO_CONTEXT) ? 0 : (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 (!(options & SLJIT_GENERATE_CODE_NO_CONTEXT)) {+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if (((sljit_sw)code_ptr) & 0x4)+ code_ptr++;+#endif /* SLJIT_CONFIG_PPC_64 */+ sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_uw)code, (void*)sljit_generate_code);+ }+#endif /* SLJIT_INDIRECT_CALL */++ 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)+ if (!(options & SLJIT_GENERATE_CODE_NO_CONTEXT)) {+ compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins) + sizeof(struct sljit_function_context);+ return code_ptr;+ }+#endif /* SLJIT_INDIRECT_CALL */++ compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);+ 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_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:+ case SLJIT_HAS_ATOMIC:+ case SLJIT_HAS_MEMORY_BARRIER:+ 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 local_size)+{+ sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);+ sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);+ 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, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);++ scratches = ENTER_GET_REGS(scratches);+ saveds = ENTER_GET_REGS(saveds);+ 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 local_size)+{+ sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);+ sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);++ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);++ scratches = ENTER_GET_REGS(scratches);+ saveds = ENTER_GET_REGS(saveds);+ 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_MEMORY_BARRIER:+ return push_inst(compiler, SYNC);+ 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 */+ SLJIT_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);+ }+ SLJIT_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));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(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_sw shift_arg)+{+ sljit_s32 dst_r, tmp_r;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ shift_arg &= (sljit_sw)((sizeof(sljit_sw) * 8) - 1);++ if (src2 == SLJIT_IMM) {+ src2w = src2w << shift_arg;+ shift_arg = 0;+ }++ if (shift_arg == 0) {+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);+ }++ if (src1 == SLJIT_IMM) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));+ src1 = TMP_REG1;+ } else if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));+ src1 = TMP_REG1;+ }++ tmp_r = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, tmp_r, src2, src2w, tmp_r));+ src2 = tmp_r;+ }++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ FAIL_IF(push_inst(compiler, SLWI_W(shift_arg) | S(src2) | A(tmp_r)));+ FAIL_IF(push_inst(compiler, ADD | D(dst_r) | A(src1) | B(tmp_r)));++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, WORD_DATA, dst_r, dst, dstw, TMP_REG1);+ 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)));++ 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;+ }+ SLJIT_FALLTHROUGH+ 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;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)+{+ sljit_uw mask, i;+ struct sljit_label *label;+ struct sljit_label *next_label;+ struct sljit_extended_label *ext_label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));++ sljit_reset_read_only_buffers(buffers);++ if (alignment <= SLJIT_LABEL_ALIGN_4) {+ SLJIT_SKIP_CHECKS(compiler);+ label = sljit_emit_label(compiler);+ PTR_FAIL_IF(!label);+ } else {+ /* The used space is filled with NOPs. */+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_ins);++ for (i = (mask >> 2); i != 0; i--)+ PTR_FAIL_IF(push_inst(compiler, NOP));++ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));+ PTR_FAIL_IF(!ext_label);+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);+ label = &ext_label->label;+ }++ if (buffers == NULL)+ return label;++ next_label = label;++ while (1) {+ buffers->u.label = next_label;++ for (i = (buffers->size + 3) >> 2; i > 0; i--)+ PTR_FAIL_IF(push_inst(compiler, NOP));++ buffers = buffers->next;++ if (buffers == NULL)+ break;++ SLJIT_SKIP_CHECKS(compiler);+ next_label = sljit_emit_label(compiler);+ PTR_FAIL_IF(!next_label);+ }++ 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);+ SLJIT_FALLTHROUGH++ case SLJIT_EQUAL:+ case SLJIT_ATOMIC_STORED:+ return (12 << 21) | (2 << 16);++ case SLJIT_CARRY:+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)+ return (12 << 21) | (2 << 16);+ SLJIT_FALLTHROUGH++ case SLJIT_NOT_EQUAL:+ case SLJIT_ATOMIC_NOT_STORED:+ 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:+ case SLJIT_ATOMIC_STORED:+ bit = 2;+ break;++ case SLJIT_NOT_EQUAL:+ case SLJIT_ATOMIC_NOT_STORED:+ 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;+ sljit_s32 is_compare = (type & SLJIT_COMPARE_SELECT);+ sljit_ins ins;+#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 (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if (src1 == SLJIT_IMM && (type & SLJIT_32))+ src1w = (sljit_s32)src1w;+#endif /* SLJIT_CONFIG_PPC_64 */++ type &= ~(SLJIT_32 | SLJIT_COMPARE_SELECT);++ if (is_compare) {+ ins = 0;++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG1, src1, src1w, TMP_REG1));+ src1 = TMP_REG1;+ src1w = 0;+ }++ if (src1 == SLJIT_IMM) {+ if (type >= SLJIT_LESS && type <= SLJIT_LESS_EQUAL && src1w >= 0 && src1w <= UIMM_MAX)+ ins = CMPLI | CRD(0) | IMM(src1w);+ else if (type >= SLJIT_SIG_LESS && type <= SLJIT_SIG_LESS_EQUAL && src1w >= SIMM_MIN && src1w <= SIMM_MAX)+ ins = CMPI | CRD(0) | IMM(src1w);+ else {+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));+ src1 = TMP_REG1;+ src1w = 0;+ }+ }++ if (ins == 0)+ ins = ((type >= SLJIT_LESS && type <= SLJIT_LESS_EQUAL) ? CMPL : CMP) | CRD(0) | B(src1);++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ if (inp_flags == (WORD_DATA | LOAD_DATA))+ ins |= CRD(1);+#endif /* SLJIT_CONFIG_PPC_64 */+ FAIL_IF(push_inst(compiler, ins | A(src2_reg)));+ type ^= 0x1;+ }++ 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 | 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) {+ 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_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 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));++ if (op & SLJIT_ATOMIC_USE_CAS)+ return SLJIT_ERR_UNSUPPORTED;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ ins = LDARX;+ break;+#endif /* SLJIT_CONFIG_PPC_64 */+ case SLJIT_MOV_U32:+ case SLJIT_MOV32:+ ins = LWARX;+ break;++ default:+ return SLJIT_ERR_UNSUPPORTED;+ }++ if (op & SLJIT_ATOMIC_TEST)+ return SLJIT_SUCCESS;++ return push_inst(compiler, ins | D(dst_reg) | B(mem_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));++ if (op & SLJIT_ATOMIC_USE_CAS)+ return SLJIT_ERR_UNSUPPORTED;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ ins = STDCX | 0x1;+ break;+#endif /* SLJIT_CONFIG_PPC_64 */+ case SLJIT_MOV_U32:+ case SLJIT_MOV32:+ ins = STWCX | 0x1;+ break;++ default:+ return SLJIT_ERR_UNSUPPORTED;+ }++ if (op & SLJIT_ATOMIC_TEST)+ return SLJIT_SUCCESS;++ return push_inst(compiler, ins | D(src_reg) | B(mem_reg));+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_s32 dst_r;+ sljit_s32 mem_flags = WORD_DATA;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, op, 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;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_U8:+ if (init_value & 0x100)+ init_value |= 0xff00;+ else+ init_value &= 0xff;++ PTR_FAIL_IF(push_inst(compiler, ADDI | D(dst_r) | A(0) | IMM(init_value)));+ mem_flags = BYTE_DATA;+ break;++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ case SLJIT_MOV32:+ mem_flags = INT_DATA;+ SLJIT_FALLTHROUGH+ case SLJIT_MOV_S32:+ PTR_FAIL_IF(push_inst(compiler, ADDIS | D(dst_r) | A(0) | IMM(init_value >> 16)));+ PTR_FAIL_IF(push_inst(compiler, ORI | S(dst_r) | A(dst_r) | IMM(init_value)));+ break;+#endif /* SLJIT_CONFIG_PPC_64 */++ default:+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));+ break;+ }++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, mem_flags, dst_r, dst, dstw, TMP_REG1));++ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_jump *jump;+ sljit_s32 dst_r, target_r;+ SLJIT_UNUSED_ARG(op);++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;++ if (op != SLJIT_ADD_ABS_ADDR)+ target_r = dst_r;+ else {+ target_r = TMP_REG1;++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_r, dst, dstw, TMP_REG1));+ }++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_mov_addr(jump, compiler, 0);++ PTR_FAIL_IF(push_inst(compiler, (sljit_ins)target_r));+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ compiler->size++;+#else+ compiler->size += 4;+#endif++ if (op == SLJIT_ADD_ABS_ADDR)+ PTR_FAIL_IF(push_inst(compiler, ADD | D(dst_r) | A(dst_r) | B(TMP_REG1)));++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, dst_r, dst, dstw, TMP_REG1));++ return jump;+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)+{+ sljit_ins *inst;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_U8:+ inst = (sljit_ins *)addr;+ SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDI);++ if (new_constant & 0x100)+ new_constant |= 0xff00;+ else+ new_constant &= 0xff;++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);+ inst[0] = (inst[0] & 0xffff0000) | IMM(new_constant);+ 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 (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ case SLJIT_MOV32:+ case SLJIT_MOV_S32:+ inst = (sljit_ins *)addr;+ SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDIS && (inst[1] & 0xfc000000) == ORI);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);+ inst[0] = (inst[0] & 0xffff0000) | IMM(new_constant >> 16);+ inst[1] = (inst[1] & 0xffff0000) | IMM(new_constant);+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 2);+ return;+#endif /* SLJIT_CONFIG_PPC_64 */++ default:+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);+ return;+ }+}
+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_32.c view
@@ -0,0 +1,154 @@+/*+ * 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 (RISCV_HAS_COMPRESSED(200) && imm <= SIMM16_MAX && imm >= SIMM16_MIN)+ return push_inst16(compiler, C_LI | C_RD(dst_r) | C_IMM_I(imm));++ 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;++ if (RISCV_HAS_COMPRESSED(200) && imm <= 0x1ffff && imm >= -0x20000)+ FAIL_IF(push_inst16(compiler, C_LUI | C_RD(dst_r) | ((sljit_u16)(((imm) & 0x1f000) >> 10) | ((imm) & 0x20000) >> 5)));+ else+ FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~(sljit_sw)0xfff)));++ imm &= 0xfff;++ if (imm == 0)+ return SLJIT_SUCCESS;++ if (RISCV_HAS_COMPRESSED(200) && (imm <= 0x1f || imm >= 0xfe0))+ return push_inst16(compiler, C_ADDI | C_RD(dst_r) | C_IMM_I(imm));++ 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_u16 *inst = (sljit_u16*)addr;+ SLJIT_UNUSED_ARG(executable_offset);++ if ((new_target & 0x800) != 0)+ new_target += 0x1000;++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 0);++ SLJIT_ASSERT((inst[0] & 0x7f) == LUI);+ inst[0] = (sljit_u16)((inst[0] & 0xfff) | (new_target & 0xf000));+ inst[1] = (sljit_u16)(new_target >> 16);+ SLJIT_ASSERT((inst[2] & 0x707f) == ADDI || (inst[2] & 0x707f) == JALR);+ inst[3] = (sljit_u16)((inst[3] & 0xf) | (new_target << 4));++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 1);+ inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 4);+}
+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_64.c view
@@ -0,0 +1,291 @@+/*+ * 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_immediate32(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm)+{+ SLJIT_ASSERT((imm <= 0x7fffffffl && imm > SIMM_MAX) || (imm >= S32_MIN && imm < SIMM_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 (RISCV_HAS_COMPRESSED(200) && imm <= 0x1ffff && imm >= -0x20000) {+ if (imm > 0x1f7ff) {+ SLJIT_ASSERT((imm & 0x800) != 0);+ FAIL_IF(push_inst16(compiler, C_LUI | C_RD(dst_r) | (sljit_u16)0x1000));+ return push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));+ }++ if ((imm & 0x800) != 0)+ imm += 0x1000;++ FAIL_IF(push_inst16(compiler, C_LUI | C_RD(dst_r) | ((sljit_u16)(((imm) & 0x1f000) >> 10) | ((imm) & 0x20000) >> 5)));+ } else {+ if ((imm & 0x800) != 0)+ imm += 0x1000;++ FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~(sljit_sw)0xfff)));+ }++ imm &= 0xfff;++ if (imm == 0)+ return SLJIT_SUCCESS;++ if (RISCV_HAS_COMPRESSED(200) && (imm <= 0x1f || imm >= 0xfe0))+ return push_inst16(compiler, C_ADDI | C_RD(dst_r) | C_IMM_I(imm));++ return push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));+}++static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm, sljit_s32 tmp_r)+{+ sljit_sw high, shift;++ if (RISCV_HAS_COMPRESSED(200) && imm <= SIMM16_MAX && imm >= SIMM16_MIN)+ return push_inst16(compiler, C_LI | C_RD(dst_r) | C_IMM_I(imm));++ 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)+ return load_immediate32(compiler, dst_r, imm);++ /* Shifted small immediates. */++ high = imm;+ shift = 0;+ while ((high & 0xff) == 0) {+ high >>= 8;+ shift += 8;+ }++ if ((high & 0xf) == 0) {+ high >>= 4;+ shift += 4;+ }++ if ((high & 0x3) == 0) {+ high >>= 2;+ shift += 2;+ }++ if ((high & 0x1) == 0) {+ high >>= 1;+ shift += 1;+ }++ if (high <= 0x7fffffffl && high >= S32_MIN) {+ load_immediate(compiler, dst_r, high, tmp_r);++ if (RISCV_HAS_COMPRESSED(200))+ return push_inst16(compiler, C_SLLI | C_RD(dst_r) | C_IMM_I(shift));+ return push_inst(compiler, SLLI | RD(dst_r) | RS1(dst_r) | IMM_I(shift));+ }++ /* Trailing zeroes could be used to produce shifted immediates. */++ if (imm <= 0x7ffffffffffl && imm >= -0x80000000000l) {+ high = imm >> 12;++ if (imm & 0x800)+ high = ~high;++ FAIL_IF(load_immediate32(compiler, dst_r, high));++ if (RISCV_HAS_COMPRESSED(200))+ FAIL_IF(push_inst16(compiler, C_SLLI | C_RD(dst_r) | (sljit_u16)(12 << 2)));+ else+ FAIL_IF(push_inst(compiler, SLLI | RD(dst_r) | RS1(dst_r) | IMM_I(12)));++ SLJIT_ASSERT((imm & 0xfff) != 0);+ return push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));+ }++ 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) {+ if (RISCV_HAS_COMPRESSED(200) && imm <= 0x1f && imm >= -0x20)+ FAIL_IF(push_inst16(compiler, C_LI | C_RD(dst_r) | C_IMM_I(imm)));+ else+ 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;++ if (RISCV_HAS_COMPRESSED(200) && imm <= 0x1ffff && imm >= -0x20000)+ FAIL_IF(push_inst16(compiler, C_LUI | C_RD(dst_r) | ((sljit_u16)(((imm) & 0x1f000) >> 10) | ((imm) & 0x20000) >> 5)));+ else+ FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~0xfff)));+ imm &= 0xfff;+ }++ if ((high & 0xfff) != 0) {+ SLJIT_ASSERT(high <= 0xfff);+ if (RISCV_HAS_COMPRESSED(200) && (high <= 0x1f || high >= 0xfe0))+ FAIL_IF(push_inst16(compiler, C_ADDI | C_RD(tmp_r) | C_IMM_I(high)));+ else+ 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) {+ SLJIT_ASSERT(imm <= 0xfff);+ if (RISCV_HAS_COMPRESSED(200) && (imm <= 0x1f || imm >= 0xfe0))+ FAIL_IF(push_inst16(compiler, C_ADDI | C_RD(dst_r) | C_IMM_I(imm)));+ else+ FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm)));+ }++ if (RISCV_HAS_COMPRESSED(200))+ FAIL_IF(push_inst16(compiler, C_SLLI | C_RD(tmp_r) | (sljit_u16)((high & 0x1000) ? (20 << 2) : (1 << 12))));+ else+ 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_u16 *inst = (sljit_u16*)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 + 12, 0);++ SLJIT_ASSERT((inst[0] & 0x7f) == LUI);+ inst[0] = (sljit_u16)((inst[0] & 0xfff) | (high & 0xf000));+ inst[1] = (sljit_u16)(high >> 16);+ SLJIT_ASSERT((inst[2] & 0x707f) == ADDI);+ inst[3] = (sljit_u16)((inst[3] & 0xf) | (high << 4));+ SLJIT_ASSERT((inst[4] & 0x7f) == LUI);+ inst[4] = (sljit_u16)((inst[4] & 0xfff) | (new_target & 0xf000));+ inst[5] = (sljit_u16)(new_target >> 16);+ SLJIT_ASSERT((inst[10] & 0x707f) == ADDI || (inst[10] & 0x707f) == JALR);+ inst[11] = (sljit_u16)((inst[11] & 0xf) | (new_target << 4));+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 12, 1);++ inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 12);+}
+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_common.c view
@@ -0,0 +1,4855 @@+/*+ * 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.+ */++#if !(defined SLJIT_CONFIG_RISCV_ATOMIC) && defined(__riscv_atomic)+/* Auto detect atomic instruction support. */+#define SLJIT_CONFIG_RISCV_ATOMIC 200+#endif /* !SLJIT_CONFIG_RISCV_ATOMIC && __riscv_atomic */++/* SLJIT_CONFIG_RISCV_ATOMIC enables/disables atomic instruction+ support. Non-zero values represents the highest version of the feature+ that is supported by the CPU.+ Allowed values: 0 - disabled, 200 - 2.00 */+#if (defined SLJIT_CONFIG_RISCV_ATOMIC && SLJIT_CONFIG_RISCV_ATOMIC != 0)+#if SLJIT_CONFIG_RISCV_ATOMIC != 200+#error "Unsupported value for SLJIT_CONFIG_RISCV_ATOMIC"+#endif+#define RISCV_HAS_ATOMIC(x) ((SLJIT_CONFIG_RISCV_ATOMIC) >= (x))+#define RISCV_ATOMIC_INFO "a"+#else /* !SLJIT_CONFIG_RISCV_ATOMIC || SLJIT_CONFIG_RISCV_ATOMIC == 0 */+#define RISCV_HAS_ATOMIC(x) 0+#define RISCV_ATOMIC_INFO ""+#endif /* SLJIT_CONFIG_RISCV_ATOMIC && SLJIT_CONFIG_RISCV_ATOMIC != 0 */++#if !(defined SLJIT_CONFIG_RISCV_COMPRESSED) && defined(__riscv_compressed)+/* Auto detect compressed instruction support. */+#define SLJIT_CONFIG_RISCV_COMPRESSED 200+#endif /* !SLJIT_CONFIG_RISCV_COMPRESSED && __riscv_compressed */++/* SLJIT_CONFIG_RISCV_COMPRESSED enables/disables compressed instruction+ support. Non-zero values represents the highest version of the feature+ that is supported by the CPU.+ Allowed values: 0 - disabled, 200 - 2.00 */+#if (defined SLJIT_CONFIG_RISCV_COMPRESSED && SLJIT_CONFIG_RISCV_COMPRESSED != 0)+#if SLJIT_CONFIG_RISCV_COMPRESSED != 200+#error "Unsupported value for SLJIT_CONFIG_RISCV_COMPRESSED"+#endif+#define RISCV_HAS_COMPRESSED(x) ((SLJIT_CONFIG_RISCV_COMPRESSED) >= (x))+#define RISCV_COMPRESSED_CHECK(x) (x)+#define RISCV_COMPRESSED_INFO "c"+#else /* !SLJIT_CONFIG_RISCV_COMPRESSED || SLJIT_CONFIG_RISCV_COMPRESSED == 0 */+#define RISCV_HAS_COMPRESSED(x) 0+#define RISCV_COMPRESSED_CHECK(x) 0+#define RISCV_COMPRESSED_INFO ""+#endif /* SLJIT_CONFIG_RISCV_COMPRESSED && SLJIT_CONFIG_RISCV_COMPRESSED != 0 */++#if !(defined SLJIT_CONFIG_RISCV_VECTOR) && defined(__riscv_vector)+/* Auto detect vector instruction support. */+#define SLJIT_CONFIG_RISCV_VECTOR 100+#endif /* !SLJIT_CONFIG_RISCV_VECTOR && __riscv_vector */++/* SLJIT_CONFIG_RISCV_VECTOR enables/disables vector instruction+ support. Non-zero values represents the highest version of the feature+ that is supported by the CPU.+ Allowed values: 0 - disabled, 100 - 1.00 */+#if (defined SLJIT_CONFIG_RISCV_VECTOR && SLJIT_CONFIG_RISCV_VECTOR != 0)+#if SLJIT_CONFIG_RISCV_VECTOR != 100+#error "Unsupported value for SLJIT_CONFIG_RISCV_VECTOR"+#endif+#define RISCV_HAS_VECTOR(x) ((SLJIT_CONFIG_RISCV_VECTOR) >= (x))+#define RISCV_VECTOR_INFO "v"+#else /* !SLJIT_CONFIG_RISCV_VECTOR || SLJIT_CONFIG_RISCV_VECTOR == 0 */+#define RISCV_HAS_VECTOR(x) 0+#define RISCV_VECTOR_INFO ""+#endif /* SLJIT_CONFIG_RISCV_VECTOR && SLJIT_CONFIG_RISCV_VECTOR != 0 */++#if !(defined SLJIT_CONFIG_RISCV_BITMANIP_A) && defined(__riscv_zba)+/* Auto detect bit manipulation extension A instruction support. */+#define SLJIT_CONFIG_RISCV_BITMANIP_A 93+#endif /* !SLJIT_CONFIG_RISCV_BITMANIP_A && __riscv_zba */++/* SLJIT_CONFIG_RISCV_BITMANIP_A enables/disables bit manipulation extension A+ instruction support. Non-zero values represents the highest version of the+ feature that is supported by the CPU.+ Allowed values: 0 - disabled, 93 - 0.93 */+#if (defined SLJIT_CONFIG_RISCV_BITMANIP_A && SLJIT_CONFIG_RISCV_BITMANIP_A != 0)+#if SLJIT_CONFIG_RISCV_BITMANIP_A != 93+#error "Unsupported value for SLJIT_CONFIG_RISCV_BITMANIP_A"+#endif+#define RISCV_HAS_BITMANIP_A(x) ((SLJIT_CONFIG_RISCV_BITMANIP_A) >= (x))+#define RISCV_BITMANIP_A_INFO "_zba"+#else /* !SLJIT_CONFIG_RISCV_BITMANIP_A || SLJIT_CONFIG_RISCV_BITMANIP_A == 0 */+#define RISCV_HAS_BITMANIP_A(x) 0+#define RISCV_BITMANIP_A_INFO ""+#endif /* SLJIT_CONFIG_RISCV_BITMANIP_A && SLJIT_CONFIG_RISCV_BITMANIP_A != 0 */++#if !(defined SLJIT_CONFIG_RISCV_BITMANIP_B) && defined(__riscv_zbb)+/* Auto detect bit manipulation extension B instruction support. */+#define SLJIT_CONFIG_RISCV_BITMANIP_B 93+#endif /* !SLJIT_CONFIG_RISCV_BITMANIP_B && __riscv_zbb */++/* SLJIT_CONFIG_RISCV_BITMANIP_B enables/disables bit manipulation extension B+ instruction support. Non-zero values represents the highest version of the+ feature that is supported by the CPU.+ Allowed values: 0 - disabled, 93 - 0.93 */+#if (defined SLJIT_CONFIG_RISCV_BITMANIP_B && SLJIT_CONFIG_RISCV_BITMANIP_B != 0)+#if SLJIT_CONFIG_RISCV_BITMANIP_B != 93+#error "Unsupported value for SLJIT_CONFIG_RISCV_BITMANIP_B"+#endif+#define RISCV_HAS_BITMANIP_B(x) ((SLJIT_CONFIG_RISCV_BITMANIP_B) >= (x))+#define RISCV_BITMANIP_B_INFO "_zbb"+#else /* !SLJIT_CONFIG_RISCV_BITMANIP_B || SLJIT_CONFIG_RISCV_BITMANIP_B == 0 */+#define RISCV_HAS_BITMANIP_B(x) 0+#define RISCV_BITMANIP_B_INFO ""+#endif /* SLJIT_CONFIG_RISCV_BITMANIP_B && SLJIT_CONFIG_RISCV_BITMANIP_B != 0 */++#if !(defined SLJIT_CONFIG_RISCV_ICOND) && defined(__riscv_zicond)+/* Auto detect integer conditional instruction support. */+#define SLJIT_CONFIG_RISCV_ICOND 100+#endif /* !SLJIT_CONFIG_RISCV_ICOND && __riscv_zicond */++/* SLJIT_CONFIG_RISCV_ICOND enables/disables integer conditional+ instruction support. Non-zero values represents the highest version of the+ feature that is supported by the CPU.+ Allowed values: 0 - disabled, 100 - 1.00 */+#if (defined SLJIT_CONFIG_RISCV_ICOND && SLJIT_CONFIG_RISCV_ICOND != 0)+#if SLJIT_CONFIG_RISCV_ICOND != 100+#error "Unsupported value for SLJIT_CONFIG_RISCV_ICOND"+#endif+#define RISCV_HAS_ICOND(x) ((SLJIT_CONFIG_RISCV_ICOND) >= (x))+#define RISCV_ICOND_INFO "_zicond"+#else /* !SLJIT_CONFIG_RISCV_ICOND || SLJIT_CONFIG_RISCV_ICOND == 0 */+#define RISCV_HAS_ICOND(x) 0+#define RISCV_ICOND_INFO ""+#endif /* SLJIT_CONFIG_RISCV_ICOND && SLJIT_CONFIG_RISCV_ICOND != 0 */++#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+#define RISCV_CHECK_COMPRESSED_JUMP(jump, diff, unit) \+ (!((jump)->flags & IS_CALL) && (diff) >= (JUMP16_MIN / SSIZE_OF(unit)) && (diff) <= (JUMP16_MAX / SSIZE_OF(unit)))+#else /* !SLJIT_CONFIG_RISCV_64 */+#define RISCV_CHECK_COMPRESSED_JUMP(jump, diff, unit) \+ ((diff) >= (JUMP16_MIN / SSIZE_OF(unit)) && (diff) <= (JUMP16_MAX / SSIZE_OF(unit)))+#endif /* SLJIT_CONFIG_RISCV_64 */++SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)+{+ /* The arch string is not entirely correct since 'g' contains 'a'. */+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ return "RISC-V-32 (rv32g" RISCV_ATOMIC_INFO RISCV_COMPRESSED_INFO RISCV_VECTOR_INFO RISCV_BITMANIP_A_INFO RISCV_BITMANIP_B_INFO RISCV_ICOND_INFO ")" SLJIT_CPUINFO;+#else /* !SLJIT_CONFIG_RISCV_32 */+ return "RISC-V-64 (rv64g" RISCV_ATOMIC_INFO RISCV_COMPRESSED_INFO RISCV_VECTOR_INFO RISCV_BITMANIP_A_INFO RISCV_BITMANIP_B_INFO RISCV_ICOND_INFO ")" SLJIT_CPUINFO;+#endif /* SLJIT_CONFIG_RISCV_32 */+}++/* Most instructions are 32 bit long on RISCV.+ Code is processed as 16 bit units. */+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)++#define TMP_VREG1 (SLJIT_NUMBER_OF_VECTOR_REGISTERS + 1)+#define TMP_VREG2 (SLJIT_NUMBER_OF_VECTOR_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,+};++static const sljit_u8 vreg_map[SLJIT_NUMBER_OF_VECTOR_REGISTERS + 3] = {+ 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31+};++/* --------------------------------------------------------------------- */+/* Instruction 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 VRD(rd) ((sljit_ins)vreg_map[rd] << 7)+#define VRS1(rs1) ((sljit_ins)vreg_map[rs1] << 15)+#define VRS2(rs2) ((sljit_ins)vreg_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))+#define C_RD(rd) ((sljit_u16)((sljit_u16)reg_map[rd] << 7))+#define C_RS2(rd) ((sljit_u16)((sljit_u16)reg_map[rd] << 2))+#define C_FRD(rd) ((sljit_u16)((sljit_u16)freg_map[rd] << 7))+#define C_FRS2(rd) ((sljit_u16)((sljit_u16)freg_map[rd] << 2))+#define C_RS1_R3(rs1) ((sljit_u16)((sljit_u16)(reg_map[rs1] & 0x7) << 7))+#define C_RS2_R3(rs2) ((sljit_u16)((sljit_u16)(reg_map[rs2] & 0x7) << 2))+#define C_FRS2_R3(rs2) ((sljit_u16)((sljit_u16)(freg_map[rs2] & 0x7) << 2))+#define C_IS_R3(r) ((reg_map[r] & 0x18) == 0x08)+#define C_IS_FR3(r) ((freg_map[r] & 0x18) == 0x08)+#define C_IMM_I(imm) ((sljit_u16)((((imm) & 0x1f) << 2) | (((imm) & 0x20) << 7)))+#define C_LD32_SP(imm) ((sljit_u16)((((imm) & 0x1c) << 2) | (((imm) & 0x20) << 7) | (((imm) & 0xc0) >> 4)))+#define C_ST32_SP(imm) ((sljit_u16)((((imm) & 0x3c) << 7) | (((imm) & 0xc0) << 1)))+#define C_LD64_SP(imm) ((sljit_u16)((((imm) & 0x18) << 2) | (((imm) & 0x20) << 7) | (((imm) & 0x1c0) >> 4)))+#define C_ST64_SP(imm) ((sljit_u16)((((imm) & 0x38) << 7) | (((imm) & 0x1c0) << 1)))+#define C_MEM32(imm) ((sljit_u16)((((imm) & 0x4) << 4) | (((imm) & 0x38) << 7) | (((imm) & 0x40) >> 1)))+#define C_MEM64(imm) ((sljit_u16)((((imm) & 0x38) << 7) | (((imm) & 0xc0) >> 1)))+#define C_BRN16(imm) ((sljit_u16)((((imm) & 0x6) << 2) | (((imm) & 0x18) << 7) | (((imm) & 0x20) >> 3) | (((imm) & 0xc0) >> 1) | (((imm) & 0x100) << 4)))+#define C_JMP16(imm) ((sljit_u16)((((imm) & 0xb40) << 1) | (((imm) & 0xe) << 2) | (((imm) & 0x10) << 7) | (((imm) & 0x20) >> 3) | (((imm) & 0x80) >> 1) | (((imm) & 0x400) >> 2)))++/* Represents funct(i) parts of the instructions. */+#define OPC(o) ((sljit_ins)(o))+#define C_OPC(o1, o2) ((sljit_u16)((o1) | ((o2) << 13)))+#define F3(f) ((sljit_ins)(f) << 12)+#define F12(f) ((sljit_ins)(f) << 20)+#define F7(f) ((sljit_ins)(f) << 25)++/* Vector instruction types. */+#define OPFVF (F3(0x5) | OPC(0x57))+#define OPFVV (F3(0x1) | OPC(0x57))+#define OPIVI (F3(0x3) | OPC(0x57))+#define OPIVV (F3(0x0) | OPC(0x57))+#define OPIVX (F3(0x4) | OPC(0x57))+#define OPMVV (F3(0x2) | OPC(0x57))+#define OPMVX (F3(0x6) | OPC(0x57))++#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))+/* C_*: compressed */+#define C_ADD (C_OPC(0x2, 0x4) | (sljit_u16)(1 << 12))+#define C_ADDI (C_OPC(0x1, 0x0))+#define C_ADDIW (C_OPC(0x1, 0x1))+#define C_ADDW (C_OPC(0x1, 0x4) | (sljit_u16)(7 << 10) | (sljit_u16)(1 << 5))+#define C_ADDI16SP (C_OPC(0x1, 0x3) | (sljit_u16)(2 << 7))+#define C_AND (C_OPC(0x1, 0x4) | (sljit_u16)(3 << 10) | (sljit_u16)(3 << 5))+#define C_ANDI (C_OPC(0x1, 0x4) | (sljit_u16)(2 << 10))+#define C_BEQZ (C_OPC(0x1, 0x6))+#define C_BNEZ (C_OPC(0x1, 0x7))+#define C_EBREAK (C_OPC(0x2, 0x4) | (sljit_u16)(1 << 12))+#define C_FLDSP (C_OPC(0x2, 0x1))+#define C_FLWSP (C_OPC(0x2, 0x3))+#define C_FSD (C_OPC(0x0, 0x5))+#define C_FSDSP (C_OPC(0x2, 0x5))+#define C_FSW (C_OPC(0x0, 0x7))+#define C_FSWSP (C_OPC(0x2, 0x7))+#define C_J (C_OPC(0x1, 0x5))+#define C_JR (C_OPC(0x2, 0x4))+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+#define C_JAL (C_OPC(0x1, 0x1))+#endif+#define C_JALR (C_OPC(0x2, 0x4) | (sljit_u16)(1 << 12))+#define C_LI (C_OPC(0x1, 0x2))+#define C_LUI (C_OPC(0x1, 0x3))+#define C_LDSP (C_OPC(0x2, 0x3))+#define C_LWSP (C_OPC(0x2, 0x2))+#define C_MV (C_OPC(0x2, 0x4))+#define C_NOP (C_OPC(0x1, 0x0))+#define C_SD (C_OPC(0x0, 0x7))+#define C_SDSP (C_OPC(0x2, 0x7))+#define C_SLLI (C_OPC(0x2, 0x0))+#define C_OR (C_OPC(0x1, 0x4) | (sljit_u16)(3 << 10) | (sljit_u16)(2 << 5))+#define C_SRAI (C_OPC(0x1, 0x4) | (sljit_u16)(1 << 10))+#define C_SRLI (C_OPC(0x1, 0x4) | (sljit_u16)(0 << 10))+#define C_SUB (C_OPC(0x1, 0x4) | (sljit_u16)(3 << 10) | (sljit_u16)(0 << 5))+#define C_SW (C_OPC(0x0, 0x6))+#define C_SWSP (C_OPC(0x2, 0x6))+#define C_XOR (C_OPC(0x1, 0x4) | (sljit_u16)(3 << 10) | (sljit_u16)(1 << 5))+/* CLZ / CTZ: zbb */+#define CLZ (F7(0x30) | F3(0x1) | OPC(0x13))+#define CTZ (F7(0x30) | F12(0x1) | F3(0x1) | OPC(0x13))+#define CZERO_EQZ (F7(0x7) | F3(0x5) | OPC(0x33))+#define CZERO_NEZ (F7(0x7) | F3(0x7) | OPC(0x33))+#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 FENCE (F3(0x0) | OPC(0xf))+#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))+/* LR: atomic */+#define LR (F7(0x8) | OPC(0x2f))+#define MAX (F7(0x5) | F3(0x6) | OPC(0x33))+#define MAXU (F7(0x5) | F3(0x7) | OPC(0x33))+#define MIN (F7(0x5) | F3(0x4) | OPC(0x33))+#define MINU (F7(0x5) | F3(0x5) | OPC(0x33))+#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 NOP ADDI+#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))+/* REV8 / ROL / ROR / RORI: zbb */+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+#define REV8 (F12(0x698) | F3(0x5) | OPC(0x13))+#elif (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+#define REV8 (F12(0x6b8) | F3(0x5) | OPC(0x13))+#endif /* SLJIT_CONFIG_RISCV_32 */+#define ROL (F7(0x30) | F3(0x1) | OPC(0x33))+#define ROR (F7(0x30) | F3(0x5) | OPC(0x33))+#define RORI (F7(0x30) | F3(0x5) | OPC(0x13))+/* SC: atomic */+#define SC (F7(0xc) | OPC(0x2f))+#define SD (F3(0x3) | OPC(0x23))+/* SEXTB / SEXTH: zbb */+#define SEXTB (F7(0x30) | F12(0x4) | F3(0x1) | OPC(0x13))+#define SEXTH (F7(0x30) | F12(0x5) | F3(0x1) | OPC(0x13))+/* SH1ADD / SH2ADD / SH3ADD: zba */+#define SH1ADD (F7(0x10) | F3(0x2) | OPC(0x33))+#define SH2ADD (F7(0x10) | F3(0x4) | OPC(0x33))+#define SH3ADD (F7(0x10) | F3(0x6) | OPC(0x33))+#define SLL (F7(0x0) | F3(0x1) | OPC(0x33))+#define SLLI (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 (F3(0x5) | OPC(0x13))+#define SRA (F7(0x20) | F3(0x5) | OPC(0x33))+#define SRAI (F7(0x20) | F3(0x5) | OPC(0x13))+#define SUB (F7(0x20) | F3(0x0) | OPC(0x33))+#define SW (F3(0x2) | OPC(0x23))+/* V*: vector */+#define VAND_VV (F7(0x13) | OPIVV)+#define VFMV_FS (F7(0x21) | OPFVV)+#define VFMV_SF (F7(0x21) | OPFVF)+#define VFMV_VF (F7(0x2f) | OPFVF)+#define VFWCVT_FFV (F7(0x25) | (0xc << 15) | OPFVV)+#define VL (F7(0x1) | OPC(0x7))+#define VMSLE_VI (F7(0x3b) | OPIVI)+#define VMV_SX (F7(0x21) | OPMVX)+#define VMV_VI (F7(0x2f) | OPIVI)+#define VMV_VV (F7(0x2f) | OPIVV)+#define VMV_VX (F7(0x2f) | OPIVX)+#define VMV_XS (F7(0x21) | OPMVV)+#define VOR_VV (F7(0x15) | OPIVV)+#define VSETVLI (F7(0x0) | F3(0x7) | OPC(0x57))+#define VSETIVLI (F7(0x60) | F3(0x7) | OPC(0x57))+#define VS (F7(0x1) | OPC(0x27))+#define VSLIDEDOWN_VX (F7(0x1f) | OPIVX)+#define VSLIDEDOWN_VI (F7(0x1f) | OPIVI)+#define VSLIDEUP_VX (F7(0x1d) | OPIVX)+#define VSLIDEUP_VI (F7(0x1d) | OPIVI)+#define VRGATHER_VI (F7(0x19) | OPIVI)+#define VRGATHER_VV (F7(0x19) | OPIVV)+#define VXOR_VV (F7(0x17) | OPIVV)+#define VZEXT_VF2 (F7(0x25) | (0x6 << 15) | OPMVV)+#define VZEXT_VF4 (F7(0x25) | (0x4 << 15) | OPMVV)+#define VZEXT_VF8 (F7(0x25) | (0x2 << 15) | OPMVV)+#define XOR (F7(0x0) | F3(0x4) | OPC(0x33))+#define XORI (F3(0x4) | OPC(0x13))+/* ZEXTH: zbb */+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+#define ZEXTH (F7(0x4) | F3(0x4) | OPC(0x33))+#else /* SLJIT_CONFIG_RISCV_64 */+#define ZEXTH (F7(0x4) | F3(0x4) | OPC(0x3B))+#endif /* SLJIT_CONFIG_RISCV_32 */++#define SIMM_MAX (0x7ff)+#define SIMM_MIN (-0x800)+#define SIMM16_MAX (0x1f)+#define SIMM16_MIN (-0x20)+#define BRANCH_MAX (0xfff)+#define BRANCH_MIN (-0x1000)+#define BRANCH16_MAX (0xff)+#define BRANCH16_MIN (-0x100)+#define JUMP_MAX (0xfffff)+#define JUMP_MIN (-0x100000)+#define JUMP16_MAX SIMM_MAX+#define JUMP16_MIN SIMM_MIN++#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 /* SLJIT_CONFIG_RISCV_64 */++#define C_ADDI_W(word) (C_ADDI | (sljit_u16)((word) << 10))+#define C_SUB_W(word) (C_SUB | (sljit_u16)((word) << 9))++#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+#define BRANCH_LENGTH ((sljit_ins)(3 * sizeof(sljit_ins)) << 7)+#define BRANCH16_LENGTH C_BRN16(5 * sizeof(sljit_u16))+#else /* !SLJIT_CONFIG_RISCV_32 */+#define BRANCH_LENGTH ((sljit_ins)(7 * sizeof(sljit_ins)) << 7)+#define BRANCH16_LENGTH C_BRN16(13 * sizeof(sljit_u16))+#endif /* SLJIT_CONFIG_RISCV_32 */++static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)+{+ sljit_u16 *ptr = (sljit_u16*)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!ptr);+ ptr[0] = (sljit_u16)ins;+ ptr[1] = (sljit_u16)(ins >> 16);+ compiler->size += 2;+ return SLJIT_SUCCESS;+}++static sljit_s32 push_inst16(struct sljit_compiler *compiler, sljit_u16 ins)+{+ sljit_u16 *ptr = (sljit_u16*)ensure_buf(compiler, sizeof(sljit_u16));+ 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_u16* detect_jump_type(struct sljit_jump *jump, sljit_u16 *code_ptr, sljit_u16 *code, sljit_sw executable_offset)+{+ sljit_sw diff, cond_diff;+ sljit_uw target_addr;+ sljit_uw jump_addr = (sljit_uw)code_ptr;+ sljit_uw orig_addr = jump->addr;+ sljit_ins ins;+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ sljit_s32 jalr_offset = JUMP_MAX_SIZE - 1;+#endif /* SLJIT_CONFIG_RISCV_64 */+ SLJIT_UNUSED_ARG(executable_offset);++ jump->addr = 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)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);++ if (jump->u.label->size > orig_addr)+ jump_addr = (sljit_uw)(code + orig_addr);+ }++ diff = (sljit_sw)target_addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset);++ if (jump->flags & IS_COND) {+ cond_diff = diff + SSIZE_OF(ins);++ if (RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16))) {+ SLJIT_ASSERT((code_ptr[-1] & 0xe003) == C_BEQZ || (code_ptr[-1] & 0xe003) == C_BNEZ);++ cond_diff = diff + SSIZE_OF(u16);++ if (diff >= BRANCH16_MIN && diff <= BRANCH16_MAX) {+ code_ptr--;+ code_ptr[0] = (sljit_u16)((code_ptr[0] & 0xe383) ^ 0x2000);+ jump->flags |= PATCH_B | PATCH_16;+ jump->addr = (sljit_uw)code_ptr;+ return code_ptr;+ }+ }++ if (cond_diff >= BRANCH_MIN && cond_diff <= BRANCH_MAX) {+ if (RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16))) {+ /* Converting 16 bit branch to 32 bit branch. */+ code_ptr--;+ code_ptr[1] = (sljit_u16)(((code_ptr[0] & 0x300) >> 8) | 0x4);+ code_ptr[0] = (sljit_u16)((BNE ^ ((code_ptr[0] & 0x2000) >> 1)) | ((code_ptr[0] & 0x80) << 8));+ } else {+ code_ptr -= 2;+ code_ptr[0] = (sljit_u16)((code_ptr[0] & 0xf07f) ^ 0x1000);+ code_ptr[1] = (sljit_u16)(code_ptr[1] & 0x1ff);+ }++ jump->flags |= PATCH_B;+ jump->addr = (sljit_uw)code_ptr;+ return code_ptr + 1;+ }+ }++ if (RISCV_HAS_COMPRESSED(200) && RISCV_CHECK_COMPRESSED_JUMP(jump, diff, u8)) {+ /* A conditional instruction has larger max offset+ than a 16 bit jump instruction. */+ SLJIT_ASSERT(!(jump->flags & IS_COND));+ jump->flags |= PATCH_J | PATCH_16;+ return code_ptr;+ }++ if (diff >= JUMP_MIN && diff <= JUMP_MAX) {+ if (jump->flags & IS_COND) {+ if (RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16)))+ code_ptr[-1] ^= (sljit_u16)(BRANCH16_LENGTH ^ C_BRN16(3 * sizeof(sljit_u16)));+ else+ code_ptr[-2] ^= (sljit_u16)(BRANCH_LENGTH ^ (2 * sizeof(sljit_ins) << 7));+ }++ jump->flags |= PATCH_J;+ return code_ptr + 1;+ }++#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ if (diff >= S32_MIN && diff <= S32_MAX) {+ if (jump->flags & IS_COND) {+ if (RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16)))+ code_ptr[-1] ^= (sljit_u16)(BRANCH16_LENGTH ^ C_BRN16(5 * sizeof(sljit_u16)));+ else+ code_ptr[-2] ^= (sljit_u16)(BRANCH_LENGTH ^ (3 * sizeof(sljit_ins) << 7));+ }++ jump->flags |= PATCH_REL32;+ jalr_offset = 3;+ } else if (target_addr <= (sljit_uw)S32_MAX) {+ if (jump->flags & IS_COND) {+ if (RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16)))+ code_ptr[-1] ^= (sljit_u16)(BRANCH16_LENGTH ^ C_BRN16(5 * sizeof(sljit_u16)));+ else+ code_ptr[-2] ^= (sljit_u16)(BRANCH_LENGTH ^ (3 * sizeof(sljit_ins) << 7));+ }++ jump->flags |= PATCH_ABS32;+ jalr_offset = 3;+ } else if (target_addr <= S44_MAX) {+ if (jump->flags & IS_COND) {+ if (RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16)))+ code_ptr[-1] ^= (sljit_u16)(BRANCH16_LENGTH ^ C_BRN16(9 * sizeof(sljit_u16)));+ else+ code_ptr[-2] ^= (sljit_u16)(BRANCH_LENGTH ^ (5 * sizeof(sljit_ins) << 7));+ }++ jump->flags |= PATCH_ABS44;+ jalr_offset = 7;+ } else if (target_addr <= S52_MAX) {+ if (jump->flags & IS_COND) {+ if (RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16)))+ code_ptr[-1] ^= (sljit_u16)(BRANCH16_LENGTH ^ C_BRN16(11 * sizeof(sljit_u16)));+ else+ code_ptr[-2] ^= (sljit_u16)(BRANCH_LENGTH ^ (6 * sizeof(sljit_ins) << 7));+ }++ jump->flags |= PATCH_ABS52;+ jalr_offset = 9;+ }+#endif /* SLJIT_CONFIG_RISCV_64 */++exit:+ ins = JALR | RS1(TMP_REG1) | IMM_I(0);+ if (jump->flags & IS_CALL)+ ins |= RD(RETURN_ADDR_REG);++#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ code_ptr[2] = (sljit_u16)ins;+ code_ptr[3] = (sljit_u16)(ins >> 16);+ return code_ptr + 3;+#else /* !SLJIT_CONFIG_RISCV_32 */+ code_ptr += jalr_offset;+ code_ptr[-1] = (sljit_u16)ins;+ code_ptr[0] = (sljit_u16)(ins >> 16);+ return code_ptr;+#endif /* SLJIT_CONFIG_RISCV_32 */+}++#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)++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_uw jump_addr = (sljit_uw)code_ptr;+ sljit_sw diff;+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_ASSERT(jump->flags < (JUMP_MAX_SIZE << 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 (jump->u.label->size > jump->addr)+ jump_addr = (sljit_uw)(code + jump->addr);+ }++ diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset);++ if (diff >= S32_MIN && diff <= S32_MAX) {+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));+ jump->flags |= PATCH_REL32;+ return 3;+ }++ if (addr <= S32_MAX) {+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));+ jump->flags |= PATCH_ABS32;+ return 3;+ }++ if (addr <= S44_MAX) {+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)7 << JUMP_SIZE_SHIFT));+ jump->flags |= PATCH_ABS44;+ return 7;+ }++ if (addr <= S52_MAX) {+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)9 << JUMP_SIZE_SHIFT));+ jump->flags |= PATCH_ABS52;+ return 9;+ }++ SLJIT_ASSERT(jump->flags >= ((sljit_uw)11 << JUMP_SIZE_SHIFT));+ return 11;+}++#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_u16 *buf = (sljit_u16 *)jump->addr;+ sljit_u32 reg = (flags & JUMP_MOV_ADDR) ? *buf : TMP_REG1;+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ sljit_sw high;+#endif /* SLJIT_CONFIG_RISCV_64 */+ 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(buf, executable_offset);++ SLJIT_ASSERT((sljit_sw)addr >= S32_MIN && (sljit_sw)addr <= S32_MAX);++ if ((addr & 0x800) != 0)+ addr += 0x1000;++ ins = AUIPC | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);+ buf[0] = (sljit_u16)ins;+ buf[1] = (sljit_u16)(ins >> 16);++ if (!(flags & JUMP_MOV_ADDR)) {+ ins = JALR | RS1(reg) | IMM_I(addr);+ if (jump->flags & IS_CALL)+ ins |= RD(RETURN_ADDR_REG);+ } else+ ins = ADDI | RD(reg) | RS1(reg) | IMM_I(addr);++ buf[2] = (sljit_u16)ins;+ buf[3] = (sljit_u16)(ins >> 16);+ return;+ }+#endif /* SLJIT_CONFIG_RISCV_64 */++ if ((addr & 0x800) != 0)+ addr += 0x1000;++#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ ins = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);+ buf[0] = (sljit_u16)ins;+ buf[1] = (sljit_u16)(ins >> 16);+#else /* !SLJIT_CONFIG_RISCV_32 */++ if (flags & PATCH_ABS32) {+ SLJIT_ASSERT(addr <= S32_MAX);+ ins = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);+ buf[0] = (sljit_u16)ins;+ buf[1] = (sljit_u16)(ins >> 16);+ } 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 = LUI | RD(reg) | (sljit_ins)0x80000000u;+ buf[0] = (sljit_u16)ins;+ buf[1] = (sljit_u16)(ins >> 16);+ ins = XORI | RD(reg) | RS1(reg) | IMM_I(high);+ buf[2] = (sljit_u16)ins;+ buf[3] = (sljit_u16)(ins >> 16);+ } else {+ if ((high & 0x800) != 0)+ high += 0x1000;++ ins = LUI | RD(reg) | (sljit_ins)(high & ~0xfff);+ buf[0] = (sljit_u16)ins;+ buf[1] = (sljit_u16)(ins >> 16);+ ins = ADDI | RD(reg) | RS1(reg) | IMM_I(high);+ buf[2] = (sljit_u16)ins;+ buf[3] = (sljit_u16)(ins >> 16);+ }++ ins = SLLI | RD(reg) | RS1(reg) | IMM_I(12);+ buf[4] = (sljit_u16)ins;+ buf[5] = (sljit_u16)(ins >> 16);+ buf += 4;+ } else {+ high = (sljit_sw)addr >> 32;++ if ((addr & 0x80000000l) != 0)+ high = ~high;++ if (flags & PATCH_ABS52) {+ SLJIT_ASSERT(addr <= S52_MAX);+ ins = LUI | RD(TMP_REG3) | (sljit_ins)(high << 12);+ buf[0] = (sljit_u16)ins;+ buf[1] = (sljit_u16)(ins >> 16);+ } else {+ if ((high & 0x800) != 0)+ high += 0x1000;+ ins = LUI | RD(TMP_REG3) | (sljit_ins)(high & ~0xfff);+ buf[0] = (sljit_u16)ins;+ buf[1] = (sljit_u16)(ins >> 16);+ ins = ADDI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(high);+ buf[2] = (sljit_u16)ins;+ buf[3] = (sljit_u16)(ins >> 16);+ buf += 2;+ }++ ins = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);+ buf[2] = (sljit_u16)ins;+ buf[3] = (sljit_u16)(ins >> 16);+ ins = SLLI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I((flags & PATCH_ABS52) ? 20 : 32);+ buf[4] = (sljit_u16)ins;+ buf[5] = (sljit_u16)(ins >> 16);+ ins = XOR | RD(reg) | RS1(reg) | RS2(TMP_REG3);+ buf[6] = (sljit_u16)ins;+ buf[7] = (sljit_u16)(ins >> 16);+ buf += 6;+ }+#endif /* !SLJIT_CONFIG_RISCV_32 */++ if (!(flags & JUMP_MOV_ADDR)) {+ ins = JALR | RS1(reg) | IMM_I(addr);+ if (jump->flags & IS_CALL)+ ins |= RD(RETURN_ADDR_REG);+ } else+ ins = ADDI | RD(reg) | RS1(reg) | IMM_I(addr);++ buf[2] = (sljit_u16)ins;+ buf[3] = (sljit_u16)(ins >> 16);+}++static SLJIT_INLINE sljit_u16 *process_extended_label(sljit_u16 *code_ptr, struct sljit_extended_label *ext_label)+{+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);+ return (sljit_u16*)((sljit_uw)code_ptr & ~(ext_label->data));+}++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, cond_size, cond_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 = 4;+ else if (jump->u.target <= S44_MAX)+ total_size = 8;+ else if (jump->u.target <= S52_MAX)+ total_size = 10;+#endif /* SLJIT_CONFIG_RISCV_64 */+ } else {+ /* Unit size: instruction. */+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;+ if (jump->u.label->size > jump->addr) {+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);+ diff -= (sljit_sw)size_reduce;+ }++ cond_size = RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16) != 0);+ cond_diff = diff + 2 - cond_size;++ if (RISCV_COMPRESSED_CHECK(cond_size) && diff >= (BRANCH16_MIN / SSIZE_OF(u16)) && diff <= (BRANCH16_MAX / SSIZE_OF(u16)))+ total_size = 0;+ else if ((jump->flags & IS_COND) && cond_diff <= (BRANCH_MAX / SSIZE_OF(u16)) && cond_diff >= (BRANCH_MIN / SSIZE_OF(u16)))+ total_size = (sljit_uw)cond_size;+ else if (RISCV_HAS_COMPRESSED(200) && RISCV_CHECK_COMPRESSED_JUMP(jump, diff, u16))+ total_size = 1;+ else if (diff >= (JUMP_MIN / SSIZE_OF(u16)) && diff <= (JUMP_MAX / SSIZE_OF(u16)))+ total_size = 2;+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ else if (diff >= (S32_MIN / SSIZE_OF(u16)) && diff <= (S32_MAX / SSIZE_OF(u16)))+ total_size = 4;+#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 = 11;++ if (!(jump->flags & JUMP_ADDR)) {+ /* Real size minus 1. Unit size: 16 bit. */+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;+ if (jump->u.label->size > jump->addr) {+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);+ diff -= (sljit_sw)size_reduce;+ }++ if (diff >= (S32_MIN / SSIZE_OF(u16)) && diff <= (S32_MAX / SSIZE_OF(u16)))+ total_size = 3;+ } else if (jump->u.target < S32_MAX)+ total_size = 3;+ else if (jump->u.target < S44_MAX)+ total_size = 7;+ else if (jump->u.target <= S52_MAX)+ total_size = 9;++ size_reduce += 11 - 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_u16 *code;+ sljit_u16 *code_ptr;+ sljit_u16 *buf_ptr;+ sljit_u16 *buf_end;+ sljit_uw half_count;+ SLJIT_NEXT_DEFINE_TYPES;+ sljit_sw executable_offset;+ sljit_uw addr;+ sljit_ins ins;++ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_generate_code(compiler, options));++ 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) {+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);+ *code_ptr = buf_ptr[-1];+ }++ 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)) {+ half_count = half_count - 1 + (jump->flags >> JUMP_SIZE_SHIFT);+ code_ptr = detect_jump_type(jump, code_ptr, 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)+ half_count += 3;+ jump->addr = (sljit_uw)code_ptr;+ code_ptr += 3;+#else /* !SLJIT_CONFIG_RISCV_32 */+ half_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++;+ half_count++;+ } while (buf_ptr < buf_end);++ buf = buf->next;+ } while (buf);++ if (label && label->size == half_count) {+ if (label->u.index >= SLJIT_LABEL_ALIGNED)+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);++ 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_u16 *)jump->addr;+ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);++ if (jump->flags & PATCH_B) {+ SLJIT_ASSERT(RISCV_HAS_COMPRESSED(200) || !(jump->flags & PATCH_16));+ SLJIT_ASSERT((sljit_sw)addr >= BRANCH_MIN && (sljit_sw)addr <= BRANCH_MAX);++ if (RISCV_COMPRESSED_CHECK(jump->flags & PATCH_16)) {+ buf_ptr[0] |= C_BRN16(addr);+ break;+ }++ buf_ptr[0] |= (sljit_u16)(((addr & 0x800) >> 4) | ((addr & 0x1e) << 7));+ buf_ptr[1] |= (sljit_u16)(((addr & 0x7e0) << 4) | ((addr & 0x1000) << 3));+ break;+ }++ SLJIT_ASSERT(RISCV_HAS_COMPRESSED(200) || !(jump->flags & PATCH_16));+ if (RISCV_COMPRESSED_CHECK(jump->flags & PATCH_16)) {+ SLJIT_ASSERT((sljit_sw)addr >= JUMP16_MIN && (sljit_sw)addr <= JUMP16_MAX);+#if defined SLJIT_CONFIG_RISCV_32+ ins = ((jump->flags & IS_CALL) ? C_JAL : C_J) | C_JMP16(addr);+#else /* !SLJIT_CONFIG_RISCV_32 */+ SLJIT_ASSERT(!(jump->flags & IS_CALL));+ ins = C_J | C_JMP16(addr);+#endif /* SLJIT_CONFIG_RISCV_32 */+ buf_ptr[0] = (sljit_u16)ins;+ 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);+ ins = JAL | RD((jump->flags & IS_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | (sljit_ins)addr;+ buf_ptr[0] = (sljit_u16)ins;+ buf_ptr[1] = (sljit_u16)(ins >> 16);+ } 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_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)+{+ 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 /* !SLJIT_IS_FPU_AVAILABLE && !__riscv_float_abi_soft */+ 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 */+ case SLJIT_HAS_ATOMIC:+ return RISCV_HAS_ATOMIC(200) ? 1 : 0;+ case SLJIT_HAS_MEMORY_BARRIER:+ return 1;+ case SLJIT_HAS_CLZ:+ case SLJIT_HAS_CTZ:+ case SLJIT_HAS_REV:+ case SLJIT_HAS_ROT:+ return RISCV_HAS_BITMANIP_B(93) ? 1 : 0;+ case SLJIT_HAS_CMOV:+ return RISCV_HAS_ICOND(100) ? 2 : 0;+ case SLJIT_HAS_SIMD:+ return RISCV_HAS_VECTOR(100) ? 1 : 0;+ 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+#define C_STACK_OFFSET_CHECK(offset) ((offset) <= 0xfc)+#define C_STACK_LOAD(offset) (C_LWSP | C_LD32_SP(offset))+#define C_STACK_STORE(offset) (C_SWSP | C_ST32_SP(offset))+#else /* !SLJIT_CONFIG_RISCV_32 */+#define STACK_STORE SD+#define STACK_LOAD LD+#define C_STACK_OFFSET_CHECK(offset) ((offset) <= 0x1f8)+#define C_STACK_LOAD(offset) (C_LDSP | C_LD64_SP(offset))+#define C_STACK_STORE(offset) (C_SDSP | C_ST64_SP(offset))+#endif /* SLJIT_CONFIG_RISCV_32 */++#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+#include "sljitNativeRISCV_32.c"+#else /* !SLJIT_CONFIG_RISCV_32 */+#include "sljitNativeRISCV_64.c"+#endif /* SLJIT_CONFIG_RISCV_32 */++#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 local_size)+{+ sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);+ sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);+ 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, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);++ scratches = ENTER_GET_REGS(scratches);+ saveds = ENTER_GET_REGS(saveds);+ 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 /* !SLJIT_CONFIG_RISCV_32 */+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);+#endif /* SLJIT_CONFIG_RISCV_32 */+ local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;+ compiler->local_size = local_size;++ if (local_size <= STACK_MAX_DISTANCE) {+ /* Frequent case. */+ offset = local_size - SSIZE_OF(sw);+ local_size = -local_size;+ if (RISCV_HAS_COMPRESSED(200) && local_size >= -0x200) {+ SLJIT_ASSERT((local_size & 0x200) != 0 && (local_size & 0xf) == 0);+ FAIL_IF(push_inst16(compiler, C_ADDI16SP | (sljit_u16)(((local_size & 0x10) << 2) | ((local_size & 0x20) >> 3) | ((local_size & 0x40) >> 1) | ((local_size & 0x180) >> 4) | (1 << 12))));+ } else+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(local_size)));+ 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);+ }++ if (RISCV_HAS_COMPRESSED(200) && C_STACK_OFFSET_CHECK(offset))+ FAIL_IF(push_inst16(compiler, C_STACK_STORE(offset) | C_RS2(RETURN_ADDR_REG)));+ else+ 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);+ if (RISCV_HAS_COMPRESSED(200) && C_STACK_OFFSET_CHECK(offset))+ FAIL_IF(push_inst16(compiler, C_STACK_STORE(offset) | C_RS2(i)));+ else+ 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);+ if (RISCV_HAS_COMPRESSED(200) && C_STACK_OFFSET_CHECK(offset))+ FAIL_IF(push_inst16(compiler, C_STACK_STORE(offset) | C_RS2(i)));+ else+ 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 /* SLJIT_CONFIG_RISCV_32 */++ tmp = SLJIT_FS0 - fsaveds;+ for (i = SLJIT_FS0; i > tmp; i--) {+ offset -= SSIZE_OF(f64);+ if (RISCV_HAS_COMPRESSED(200) && offset <= 0x1f8)+ FAIL_IF(push_inst16(compiler, C_FSDSP | C_FRS2(i) | C_ST64_SP(offset)));+ else+ 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);+ if (RISCV_HAS_COMPRESSED(200) && offset <= 0x1f8)+ FAIL_IF(push_inst16(compiler, C_FSDSP | C_FRS2(i) | C_ST64_SP(offset)));+ else+ 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)) {+ if (RISCV_HAS_COMPRESSED(200))+ FAIL_IF(push_inst16(compiler, C_MV | C_RD(SLJIT_S0 - saved_arg_count) | C_RS2(tmp)));+ else+ 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 local_size)+{+ sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);+ sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);++ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);++ scratches = ENTER_GET_REGS(scratches);+ saveds = ENTER_GET_REGS(saveds);+ 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 /* !SLJIT_CONFIG_RISCV_32 */+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);+#endif /* SLJIT_CONFIG_RISCV_32 */+ 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) {+ if (RISCV_HAS_COMPRESSED(200) && C_STACK_OFFSET_CHECK(offset))+ FAIL_IF(push_inst16(compiler, C_STACK_LOAD(offset) | C_RD(RETURN_ADDR_REG)));+ else+ 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);+ if (RISCV_HAS_COMPRESSED(200) && C_STACK_OFFSET_CHECK(offset))+ FAIL_IF(push_inst16(compiler, C_STACK_LOAD(offset) | C_RD(i)));+ else+ 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);+ if (RISCV_HAS_COMPRESSED(200) && C_STACK_OFFSET_CHECK(offset))+ FAIL_IF(push_inst16(compiler, C_STACK_LOAD(offset) | C_RD(i)));+ else+ 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 /* SLJIT_CONFIG_RISCV_32 */++ tmp = SLJIT_FS0 - compiler->fsaveds;+ for (i = SLJIT_FS0; i > tmp; i--) {+ offset -= SSIZE_OF(f64);+ if (RISCV_HAS_COMPRESSED(200) && offset <= 0x1f8)+ FAIL_IF(push_inst16(compiler, C_FLDSP | C_FRD(i) | C_LD64_SP(offset)));+ else+ 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);+ if (RISCV_HAS_COMPRESSED(200) && offset <= 0x1f8)+ FAIL_IF(push_inst16(compiler, C_FLDSP | C_FRD(i) | C_LD64_SP(offset)));+ else+ FAIL_IF(push_inst(compiler, FLD | FRD(i) | RS1(SLJIT_SP) | IMM_I(offset)));+ }++ if (RISCV_HAS_COMPRESSED(200) && local_size <= 0x1f0) {+ SLJIT_ASSERT((local_size & 0xf) == 0);+ return push_inst16(compiler, C_ADDI16SP | (sljit_u16)(((local_size & 0x10) << 2) | ((local_size & 0x20) >> 3) | ((local_size & 0x40) >> 1) | ((local_size & 0x180) >> 4)));+ }++ 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 /* !SLJIT_CONFIG_RISCV_32 */+#define ARCH_32_64(a, b) b+#endif /* SLJIT_CONFIG_RISCV_32 */++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_s32 signed_flags;+ sljit_s32 load_flags;++ SLJIT_ASSERT(FAST_IS_REG(base) && offset <= 0xfff && offset >= SIMM_MIN);++ flags &= MEM_MASK;++ if (RISCV_HAS_COMPRESSED(200) && offset >= 0) {+ if (base == SLJIT_SP) {+ signed_flags = flags | SIGNED_DATA;++ if ((offset & 0x3) == 0 && offset <= 0xfc) {+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ if ((signed_flags == (SIGNED_DATA | LOAD_DATA) || signed_flags == (INT_DATA | SIGNED_DATA | LOAD_DATA)))+ return push_inst16(compiler, C_LWSP | C_RD(reg) | C_LD32_SP(offset));+ if ((signed_flags == SIGNED_DATA || signed_flags == (INT_DATA | SIGNED_DATA)))+ return push_inst16(compiler, C_SWSP | C_RS2(reg) | C_ST32_SP(offset));+ if (flags == (SINGLE_DATA | LOAD_DATA))+ return push_inst16(compiler, C_FLWSP | C_FRD(reg) | C_LD32_SP(offset));+ if (flags == SINGLE_DATA)+ return push_inst16(compiler, C_FSWSP | C_FRS2(reg) | C_ST32_SP(offset));+#else /* !SLJIT_CONFIG_RISCV_32 */+ if (flags == (INT_DATA | SIGNED_DATA | LOAD_DATA))+ return push_inst16(compiler, C_LWSP | C_RD(reg) | C_LD32_SP(offset));+ if (signed_flags == (INT_DATA | SIGNED_DATA))+ return push_inst16(compiler, C_SWSP | C_RS2(reg) | C_ST32_SP(offset));+#endif /* SLJIT_CONFIG_RISCV_32 */+ }++ if ((offset & 0x7) == 0 && offset <= 0x1f8) {+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ if (signed_flags == (SIGNED_DATA | LOAD_DATA))+ return push_inst16(compiler, C_LDSP | C_RD(reg) | C_LD64_SP(offset));+ if (signed_flags == SIGNED_DATA)+ return push_inst16(compiler, C_SDSP | C_RS2(reg) | C_ST64_SP(offset));+#endif /* SLJIT_CONFIG_RISCV_64 */+ if (flags == (DOUBLE_DATA | LOAD_DATA))+ return push_inst16(compiler, C_FLDSP | C_FRD(reg) | C_LD64_SP(offset));+ if (flags == DOUBLE_DATA)+ return push_inst16(compiler, C_FSDSP | C_FRS2(reg) | C_ST64_SP(offset));+ }+ } else if (C_IS_R3(base) && (flags <= GPR_REG ? C_IS_R3(reg) : C_IS_FR3(reg))) {+ SLJIT_COMPILE_ASSERT(LOAD_DATA == 1, load_data_bit_error);+ signed_flags = flags | LOAD_DATA | SIGNED_DATA;+ load_flags = flags | LOAD_DATA;++ if ((offset & 0x3) == 0 && offset <= 0x7c) {+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ if (signed_flags == (SIGNED_DATA | LOAD_DATA) || signed_flags == (INT_DATA | SIGNED_DATA | LOAD_DATA))+ return push_inst16(compiler, (C_SW ^ (sljit_u16)((flags & LOAD_DATA) << 15)) | C_RS1_R3(base) | C_RS2_R3(reg) | C_MEM32(offset));+ if (load_flags == (SINGLE_DATA | LOAD_DATA))+ return push_inst16(compiler, (C_FSW ^ (sljit_u16)((flags & LOAD_DATA) << 15)) | C_RS1_R3(base) | C_FRS2_R3(reg) | C_MEM32(offset));+#else /* !SLJIT_CONFIG_RISCV_32 */+ if (load_flags == (INT_DATA | SIGNED_DATA | LOAD_DATA))+ return push_inst16(compiler, (C_SW ^ (sljit_u16)((flags & LOAD_DATA) << 15)) | C_RS1_R3(base) | C_RS2_R3(reg) | C_MEM32(offset));+#endif /* SLJIT_CONFIG_RISCV_32 */+ }++ if ((offset & 0x7) == 0 && offset <= 0xf8) {+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ if (signed_flags == (SIGNED_DATA | LOAD_DATA))+ return push_inst16(compiler, (C_SD ^ (sljit_u16)((flags & LOAD_DATA) << 15)) | C_RS1_R3(base) | C_RS2_R3(reg) | C_MEM64(offset));+#endif /* SLJIT_CONFIG_RISCV_64 */+ if (load_flags == (DOUBLE_DATA | LOAD_DATA))+ return push_inst16(compiler, (C_FSD ^ (sljit_u16)((flags & LOAD_DATA) << 15)) | C_RS1_R3(base) | C_FRS2_R3(reg) | C_MEM64(offset));+ }+ }+ }++ ins = data_transfer_insts[flags] | RS1(base);+ if (flags & LOAD_DATA)+ ins |= (flags <= GPR_REG ? RD(reg) : FRD(reg)) | IMM_I(offset);+ else+ ins |= (flags <= 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_ins ins = ADD;++ 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 (RISCV_HAS_BITMANIP_A(93)) {+ switch (argw) {+ case 1:+ ins = SH1ADD;+ break;+ case 2:+ ins = SH2ADD;+ break;+ case 3:+ ins = SH3ADD;+ break;+ }+ FAIL_IF(push_inst(compiler, ins | RD(tmp_r) | RS1(OFFS_REG(arg)) | RS2(base)));+ return push_mem_inst(compiler, flags, reg, tmp_r, 0);+ }++ /* 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_add(struct sljit_compiler *compiler, sljit_ins word, sljit_s32 dst, sljit_s32 src1, sljit_sw src2)+{+ SLJIT_UNUSED_ARG(word);++ if (dst == src2) {+ src2 = src1;+ src1 = dst;+ }++ if (RISCV_HAS_COMPRESSED(200) && dst == src1) {+ if (WORD == 0 && src2 != 0)+ return push_inst16(compiler, C_ADD | C_RD(dst) | C_RS2(src2));++ if (WORD == 0x8 && C_IS_R3(dst) && C_IS_R3(src2))+ return push_inst16(compiler, C_ADDW | C_RS1_R3(dst) | C_RS2_R3(src2));+ }++ return push_inst(compiler, ADD | WORD | RD(dst) | RS1(src1) | RS2(src2));+}++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)));+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ FAIL_IF(push_inst(compiler, SLLI | (GET_OPCODE(op) == SLJIT_REV_S32 ? WORD_32 : 0) | RD(dst) | RS1(dst) | IMM_I(8)));+#else /* !SLJIT_CONFIG_RISCV_64 */+ FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(8)));+#endif /* SLJIT_CONFIG_RISCV_64 */+ 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_c_imm, op_reg, op_c_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)) { \+ if (op_c_imm != 0 && RISCV_HAS_COMPRESSED(200) && dst == src1 && src2 <= SIMM16_MAX && src2 >= SIMM16_MIN && C_IS_R3(dst)) \+ FAIL_IF(push_inst16(compiler, op_c_imm | C_RS1_R3(dst) | C_IMM_I(src2))); \+ else \+ FAIL_IF(push_inst(compiler, op_imm | RD(dst) | RS1(src1) | IMM_I(src2))); \+ } \+ } else { \+ if (dst == src2) { \+ src2 = src1; \+ src1 = dst; \+ } \+ \+ if (op & SLJIT_SET_Z) \+ FAIL_IF(push_inst(compiler, op_reg | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2))); \+ if (!(flags & UNUSED_DEST)) { \+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && C_IS_R3(dst) && C_IS_R3(src2)) \+ FAIL_IF(push_inst16(compiler, op_c_reg | C_RS1_R3(dst) | C_RS2_R3(src2))); \+ else \+ FAIL_IF(push_inst(compiler, op_reg | RD(dst) | RS1(src1) | RS2(src2))); \+ } \+ }++static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,+ sljit_s32 dst, sljit_s32 src1, sljit_sw src2)+{+ sljit_s32 is_overflow, is_carry, 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 SLJIT_SUCCESS;++ if (!RISCV_HAS_COMPRESSED(200))+ return push_inst(compiler, ADDI | RD(dst) | RS1(src2) | IMM_I(0));++ /* Revert the x0 to immediate 0. */+ if (src2 == 0)+ return push_inst16(compiler, C_LI | C_RD(dst));+ return push_inst16(compiler, C_MV | C_RD(dst) | C_RS2(src2));++ 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:+ if (RISCV_HAS_BITMANIP_B(93))+ return push_inst(compiler, SEXTB | RD(dst) | RS1(src2));++ 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:+ if (RISCV_HAS_BITMANIP_B(93))+ return push_inst(compiler, ZEXTH | RD(dst) | RS1(src2));++ 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:+ if (RISCV_HAS_BITMANIP_B(93))+ return push_inst(compiler, SEXTH | RD(dst) | RS1(src2));++ 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)) {+ if (RISCV_HAS_COMPRESSED(200) && dst == src2)+ return push_inst16(compiler, C_ADDIW | C_RD(dst));+ 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));+ if (RISCV_HAS_BITMANIP_B(93))+ return push_inst(compiler, ((GET_OPCODE(op) == SLJIT_CLZ) ? CLZ : CTZ) | WORD | RD(dst) | RS1(src2));++ return emit_clz_ctz(compiler, op, dst, src2);++ case SLJIT_REV:+ case SLJIT_REV_S32:+ case SLJIT_REV_U32:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ if (RISCV_HAS_BITMANIP_B(93)) {+#if defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64+ FAIL_IF(push_inst(compiler, REV8 | RD(dst) | RS1(src2)));+ if ((op & SLJIT_32) || GET_OPCODE(op) != SLJIT_REV)+ return push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U32 ? SRLI : SRAI)| RD(dst) | RS1(dst) | IMM_I(32));+ return SLJIT_SUCCESS;+#else /* !SLJIT_CONFIG_RISCV_64 */+ return push_inst(compiler, REV8 | RD(dst) | RS1(src2));+#endif /* SLJIT_CONFIG_RISCV_64 */+ }++ return emit_rev(compiler, op, dst, src2);++ case SLJIT_REV_U16:+ case SLJIT_REV_S16:+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));+ if (RISCV_HAS_BITMANIP_B(93)) {+ FAIL_IF(push_inst(compiler, REV8 | RD(dst) | RS1(src2)));+#if defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64+ return push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SRLI : SRAI)| RD(dst) | RS1(dst) | IMM_I(48));+#else /* !SLJIT_CONFIG_RISCV_64 */+ return push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SRLI : SRAI) | RD(dst) | RS1(dst) | IMM_I(16));+#endif /* SLJIT_CONFIG_RISCV_64 */+ }++ 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_r = GET_FLAG_TYPE(op) == SLJIT_CARRY;++ if (flags & SRC2_IMM) {+ if (is_overflow) {+ if (src2 >= 0) {+ if (RISCV_HAS_COMPRESSED(200))+ FAIL_IF(push_inst16(compiler, C_MV | C_RD(EQUAL_FLAG) | C_RS2(src1)));+ else+ 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)) {+ SLJIT_ASSERT(src2 != 0);+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && src2 <= SIMM16_MAX && src2 >= SIMM16_MIN)+ FAIL_IF(push_inst16(compiler, C_ADDI_W(WORD) | C_RD(dst) | C_IMM_I(src2)));+ else+ 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(emit_add(compiler, WORD, dst, src1, 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) {+ if (RISCV_HAS_COMPRESSED(200))+ FAIL_IF(push_inst16(compiler, C_MV | C_RD(EQUAL_FLAG) | C_RS2(dst)));+ else+ 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) {+ SLJIT_ASSERT(src2 != 0);+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && src2 <= SIMM16_MAX && src2 >= SIMM16_MIN)+ FAIL_IF(push_inst16(compiler, C_ADDI_W(WORD) | C_RD(dst) | C_IMM_I(src2)));+ else+ 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 {+ if (RISCV_HAS_COMPRESSED(200))+ FAIL_IF(push_inst16(compiler, C_MV | C_RD(EQUAL_FLAG) | C_RS2(src1)));+ else+ FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));+ carry_src_r = EQUAL_FLAG;+ }+ }++ FAIL_IF(emit_add(compiler, WORD, dst, src1, 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)));+ }++ if (RISCV_HAS_COMPRESSED(200) && WORD == 0)+ FAIL_IF(push_inst16(compiler, C_ADD | C_RD(dst) | C_RS2(OTHER_FLAG)));+ else+ 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;+ if (RISCV_HAS_COMPRESSED(200) && src2 <= SIMM16_MAX && src2 >= SIMM16_MIN)+ FAIL_IF(push_inst16(compiler, C_LI | C_RD(reg) | C_IMM_I(src2)));+ else+ 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)) {+ src2 = -src2;+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && src2 <= SIMM16_MAX && src2 >= SIMM16_MIN)+ return push_inst16(compiler, C_ADDI_W(WORD) | C_RD(dst) | C_IMM_I(src2));++ 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)) {+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && C_IS_R3(dst) && C_IS_R3(src2))+ return push_inst16(compiler, C_SUB_W(WORD) | C_RS1_R3(dst) | C_RS2_R3(src2));++ 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) {+ if (RISCV_HAS_COMPRESSED(200))+ FAIL_IF(push_inst16(compiler, C_MV | C_RD(EQUAL_FLAG) | C_RS2(src1)));+ else+ 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)) {+ src2 = -src2;+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && src2 <= SIMM16_MAX && src2 >= SIMM16_MIN)+ FAIL_IF(push_inst16(compiler, C_ADDI_W(WORD) | C_RD(dst) | C_IMM_I(src2)));+ else+ 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)) {+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && C_IS_R3(dst) && C_IS_R3(src2))+ FAIL_IF(push_inst16(compiler, C_SUB_W(WORD) | C_RS1_R3(dst) | C_RS2_R3(src2)));+ else+ 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) {+ if (RISCV_HAS_COMPRESSED(200))+ FAIL_IF(push_inst16(compiler, C_MV | C_RD(EQUAL_FLAG) | C_RS2(dst)));+ else+ 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)));++ src2 = -src2;+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && src2 <= SIMM16_MAX && src2 >= SIMM16_MIN)+ FAIL_IF(push_inst16(compiler, C_ADDI_W(WORD) | C_RD(dst) | C_IMM_I(src2)));+ else+ 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)));++ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && C_IS_R3(dst) && C_IS_R3(src2))+ FAIL_IF(push_inst16(compiler, C_SUB_W(WORD) | C_RS1_R3(dst) | C_RS2_R3(src2)));+ else+ 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, C_ANDI, AND, C_AND);+ return SLJIT_SUCCESS;++ case SLJIT_OR:+ EMIT_LOGICAL(ORI, 0, OR, C_OR);+ return SLJIT_SUCCESS;++ case SLJIT_XOR:+ EMIT_LOGICAL(XORI, 0, XOR, C_XOR);+ return SLJIT_SUCCESS;++ case SLJIT_SHL:+ case SLJIT_MSHL:+ op_imm = SLLI;+ op_reg = SLL;+ break;++ case SLJIT_LSHR:+ case SLJIT_MLSHR:+ op_imm = SRLI;+ op_reg = SRL;+ break;++ case SLJIT_ASHR:+ case SLJIT_MASHR:+ op_imm = SRAI;+ op_reg = SRA;+ break;++ case SLJIT_ROTL:+ case SLJIT_ROTR:+ if (flags & SRC2_IMM) {+ SLJIT_ASSERT(src2 != 0);++ if (RISCV_HAS_BITMANIP_B(93)) {+ if (GET_OPCODE(op) == SLJIT_ROTL) {+#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 */+ }+ return push_inst(compiler, RORI | WORD | RD(dst) | RS1(src1) | IMM_I(src2));+ }++ 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 (RISCV_HAS_BITMANIP_B(93))+ return push_inst(compiler, (GET_OPCODE(op) == SLJIT_ROTL ? ROL : ROR) | WORD | RD(dst) | RS1(src1) | RS2(src2));++ 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;++ if (RISCV_HAS_COMPRESSED(200) && WORD == 0 && dst == src1) {+ if (op_imm == SLLI)+ return push_inst16(compiler, C_SLLI | C_RD(dst) | C_IMM_I(src2));++ if (C_IS_R3(dst))+ return push_inst16(compiler, (op_imm == SRLI ? C_SRLI : C_SRAI) | C_RS1_R3(dst) | C_IMM_I(src2));+ }++ 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:+ if (RISCV_HAS_COMPRESSED(200))+ return push_inst16(compiler, C_EBREAK);+ return push_inst(compiler, EBREAK);+ case SLJIT_NOP:+ if (RISCV_HAS_COMPRESSED(200))+ return push_inst16(compiler, C_NOP);+ return push_inst(compiler, NOP);+ 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_MEMORY_BARRIER:+ return push_inst(compiler, FENCE | 0x0ff00000);+ 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 /* SLJIT_CONFIG_RISCV_64 */++ 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 /* SLJIT_CONFIG_RISCV_32 */+ 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 /* SLJIT_CONFIG_RISCV_64 */++ 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 /* SLJIT_CONFIG_RISCV_64 */++ 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_op2_shift(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_sw shift_arg)+{+ sljit_s32 dst_r, tmp_r;+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ shift_arg &= (sljit_sw)((sizeof(sljit_sw) * 8) - 1);++ if (src2 == SLJIT_IMM) {+ src2w = src2w << shift_arg;+ shift_arg = 0;+ }++ if (shift_arg == 0) {+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);+ }++ if (src2 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));+ src2 = TMP_REG2;+ }++ if (src1 == SLJIT_IMM) {+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3));+ src1 = TMP_REG1;+ } else if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));+ src1 = TMP_REG1;+ }++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;+ ins = 0;++ if (RISCV_HAS_BITMANIP_A(93)) {+ switch (shift_arg) {+ case 1:+ ins = SH1ADD;+ break;+ case 2:+ ins = SH2ADD;+ break;+ case 3:+ ins = SH3ADD;+ break;+ }+ }++ if (ins == 0) {+ tmp_r = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;+ FAIL_IF(push_inst(compiler, SLLI | RD(tmp_r) | RS1(src2) | IMM_I(shift_arg)));+ FAIL_IF(push_inst(compiler, ADD | RD(dst_r) | RS1(src1) | RS2(tmp_r)));+ } else {+ FAIL_IF(push_inst(compiler, ins | RD(dst_r) | RS1(src2) | RS2(src1)));+ }++ if (dst & SLJIT_MEM)+ return emit_op_mem2(compiler, WORD_DATA, dst_r, dst, dstw, 0, 0);+ 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);++ switch (op) {+ case SLJIT_FAST_RETURN:+ if (FAST_IS_REG(src)) {+ if (src != RETURN_ADDR_REG)+ 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)) {+ if (dst == RETURN_ADDR_REG)+ return SLJIT_SUCCESS;+ 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 freg_map[reg];++ return vreg_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));++ if (size == 2)+ return push_inst16(compiler, *(sljit_u16*)instruction);++ 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_CONFIG_RISCV_32 */+ sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)) << 21;+#endif /* SLJIT_CONFIG_RISCV_32 */+ 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 /* !SLJIT_CONFIG_RISCV_32 */+ return emit_op_mem2(compiler, flags ? WORD_DATA : INT_DATA, TMP_REG2, dst, dstw, 0, 0);+#endif /* SLJIT_CONFIG_RISCV_32 */+ }+ return SLJIT_SUCCESS;++#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+# undef flags+#endif /* SLJIT_CONFIG_RISCV_32 */+}++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;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)+{+ sljit_uw mask = 0, i;+ struct sljit_label *label = NULL;+ struct sljit_label *next_label;+ struct sljit_extended_label *ext_label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));++ sljit_reset_read_only_buffers(buffers);++ if (RISCV_HAS_COMPRESSED(200)) {+ if (alignment <= SLJIT_LABEL_ALIGN_2) {+ SLJIT_SKIP_CHECKS(compiler);+ label = sljit_emit_label(compiler);+ PTR_FAIL_IF(!label);+ } else {+ /* The used space is filled with NOPs. */+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_u16);++ for (i = (mask >> 1); i != 0; i--)+ PTR_FAIL_IF(push_inst16(compiler, C_NOP));+ }+ } else {+ if (alignment <= SLJIT_LABEL_ALIGN_4) {+ SLJIT_SKIP_CHECKS(compiler);+ label = sljit_emit_label(compiler);+ PTR_FAIL_IF(!label);+ } else {+ /* The used space is filled with NOPs. */+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_ins);++ for (i = (mask >> 2); i != 0; i--)+ PTR_FAIL_IF(push_inst(compiler, NOP));+ }+ }++ if (label == NULL) {+ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));+ PTR_FAIL_IF(!ext_label);+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);+ label = &ext_label->label;+ }++ if (buffers == NULL)+ return label;++ next_label = label;++ while (1) {+ buffers->u.label = next_label;++ if (RISCV_HAS_COMPRESSED(200)) {+ for (i = (buffers->size + 1) >> 1; i > 0; i--)+ PTR_FAIL_IF(push_inst16(compiler, C_NOP));+ } else {+ for (i = (buffers->size + 3) >> 2; i > 0; i--)+ PTR_FAIL_IF(push_inst(compiler, NOP));+ }++ buffers = buffers->next;++ if (buffers == NULL)+ break;++ SLJIT_SKIP_CHECKS(compiler);+ next_label = sljit_emit_label(compiler);+ PTR_FAIL_IF(!next_label);+ }++ return label;+}++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_ATOMIC_NOT_STORED:+ 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_ATOMIC_STORED:+ 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;++ if (type >= SLJIT_FAST_CALL)+ jump->flags |= IS_CALL;++ PTR_FAIL_IF(push_inst16(compiler, 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 (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 | (src1 == TMP_REG1 ? MEM_USE_TMP2 : 0), 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:+ if (RISCV_HAS_COMPRESSED(200)) {+ if (src1 == TMP_ZERO && C_IS_R3(src2)) {+ inst = C_BNEZ | C_RS1_R3(src2) | BRANCH16_LENGTH;+ jump->flags |= IS_COND16;+ break;+ }++ if (src2 == TMP_ZERO && C_IS_R3(src1)) {+ inst = C_BNEZ | C_RS1_R3(src1) | BRANCH16_LENGTH;+ jump->flags |= IS_COND16;+ break;+ }+ }++ inst = BNE | RS1(src1) | RS2(src2) | BRANCH_LENGTH;+ break;+ case SLJIT_NOT_EQUAL:+ if (RISCV_HAS_COMPRESSED(200)) {+ if (src1 == TMP_ZERO && C_IS_R3(src2)) {+ inst = C_BEQZ | C_RS1_R3(src2) | BRANCH16_LENGTH;+ jump->flags |= IS_COND16;+ break;+ }++ if (src2 == TMP_ZERO && C_IS_R3(src1)) {+ inst = C_BEQZ | C_RS1_R3(src1) | BRANCH16_LENGTH;+ jump->flags |= IS_COND16;+ break;+ }+ }++ 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;+ default: /* SLJIT_SIG_LESS_EQUAL */+ inst = BLT | RS1(src2) | RS2(src1) | BRANCH_LENGTH;+ break;+ }++ SLJIT_COMPILE_ASSERT((C_BEQZ & 0x2) == 0 && (C_BNEZ & 0x2) == 0, branch16_bit_error);+ if (RISCV_COMPRESSED_CHECK((inst & 0x2) == 0))+ PTR_FAIL_IF(push_inst16(compiler, (sljit_u16)inst));+ else+ PTR_FAIL_IF(push_inst(compiler, inst));++ jump->addr = compiler->size;+ PTR_FAIL_IF(push_inst16(compiler, 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;+ }++ if (RISCV_HAS_COMPRESSED(200))+ return push_inst16(compiler, ((type >= SLJIT_FAST_CALL) ? C_JALR : C_JR) | C_RD(src));++ 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_inst16(compiler, 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_CONFIG_RISCV_32 */+ sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;+#endif /* SLJIT_CONFIG_RISCV_32 */++ 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;+ case SLJIT_ATOMIC_STORED:+ case SLJIT_ATOMIC_NOT_STORED:+ 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_u16 *ptr;+ sljit_uw size;+ sljit_ins ins;+ sljit_s32 cond_is_1;+ sljit_s32 is_compare = (type & SLJIT_COMPARE_SELECT);+#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 (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ if (src1 == SLJIT_IMM && word)+ src1w = (sljit_s32)src1w;+#endif /* SLJIT_CONFIG_RISCV_64 */++ type &= ~(SLJIT_32 | SLJIT_COMPARE_SELECT);++ if (is_compare || RISCV_HAS_ICOND(100)) {+ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG1, src1, src1w));+ src1 = TMP_REG1;+ src1w = 0;+ } else if (src1 == SLJIT_IMM) {+ if (src1w == 0) {+ src1 = TMP_ZERO;+ } else {+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3));+ src1 = TMP_REG1;+ src1w = 0;+ }+ }++ if (RISCV_HAS_BITMANIP_B(93) && is_compare) {+ switch (type) {+ case SLJIT_LESS:+ case SLJIT_LESS_EQUAL:+ return push_inst(compiler, MINU | RD(dst_reg) | RS1(src1) | RS2(src2_reg));+ case SLJIT_GREATER:+ case SLJIT_GREATER_EQUAL:+ return push_inst(compiler, MAXU | RD(dst_reg) | RS1(src1) | RS2(src2_reg));+ case SLJIT_SIG_LESS:+ case SLJIT_SIG_LESS_EQUAL:+ return push_inst(compiler, MIN | RD(dst_reg) | RS1(src1) | RS2(src2_reg));+ default:+ return push_inst(compiler, MAX | RD(dst_reg) | RS1(src1) | RS2(src2_reg));+ }+ }++ if (RISCV_HAS_ICOND(100)) {+ if (is_compare) {+ cond_is_1 = 0;++ switch (type) {+ case SLJIT_LESS:+ case SLJIT_LESS_EQUAL:+ cond_is_1 = 1;+ SLJIT_FALLTHROUGH+ case SLJIT_GREATER:+ case SLJIT_GREATER_EQUAL:+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src1) | RS2(src2_reg)));+ break;+ case SLJIT_SIG_LESS:+ case SLJIT_SIG_LESS_EQUAL:+ cond_is_1 = 1;+ SLJIT_FALLTHROUGH+ default:+ FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RS1(src1) | RS2(src2_reg)));+ break;+ }++ type = OTHER_FLAG;+ } else {+ /* BEQ instruction (type is inverted). */+ cond_is_1 = (get_jump_instruction(type) & F3(0x1)) == 0;+ type = (type == SLJIT_EQUAL || type == SLJIT_NOT_EQUAL) ? EQUAL_FLAG : OTHER_FLAG;+ }++ if (src1 == TMP_ZERO)+ return push_inst(compiler, (cond_is_1 ? CZERO_NEZ : CZERO_EQZ) | RD(dst_reg) | RS1(src2_reg) | RS2(type));++ FAIL_IF(push_inst(compiler, (cond_is_1 ? CZERO_EQZ : CZERO_NEZ) | RD(TMP_REG1) | RS1(src1) | RS2(type)));+ FAIL_IF(push_inst(compiler, (cond_is_1 ? CZERO_NEZ : CZERO_EQZ) | RD(dst_reg) | RS1(src2_reg) | RS2(type)));+ return push_inst(compiler, OR | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1));+ }+ }++ if (dst_reg != src2_reg) {+ if (dst_reg == src1) {+ src1 = src2_reg;+ src1w = 0;+ src2_reg = dst_reg;+ if (!is_compare)+ type ^= 0x1;+ } else {+ if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {+ SLJIT_ASSERT(!(type & SLJIT_COMPARE_SELECT));+ 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)));+ }+ }++ if (src1 == SLJIT_IMM && (src1w <= 0 && src1w >= -1)) {+ src1 = OTHER_FLAG;++ if (type == SLJIT_EQUAL || type == SLJIT_NOT_EQUAL) {+ FAIL_IF(push_inst(compiler, SLTUI | RD(TMP_REG1) | RS1(EQUAL_FLAG) | IMM_I(1)));+ src1 = TMP_REG1;+ cond_is_1 = (type == SLJIT_EQUAL);+ } else {+ /* BEQ instruction (type is inverted). */+ cond_is_1 = (get_jump_instruction(type) & F3(0x1)) == 0;+ }++ if (src1w == 0) {+ if (cond_is_1)+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src1) | IMM_I(-1)));+ else+ FAIL_IF(push_inst(compiler, SUB | RD(TMP_REG1) | RS1(TMP_ZERO) | RS2(src1)));++ return push_inst(compiler, AND | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1));+ }++ if (cond_is_1)+ FAIL_IF(push_inst(compiler, SUB | RD(TMP_REG1) | RS1(TMP_ZERO) | RS2(src1)));+ else+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src1) | IMM_I(-1)));++ return push_inst(compiler, OR | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1));+ }++ size = compiler->size;++ ptr = (sljit_u16 *)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!ptr);+ compiler->size += 2;++ if (src1 & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, inp_flags, dst_reg, src1, src1w));+ } else if (src1 == SLJIT_IMM) {+ 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;++ if (is_compare) {+ switch (type) {+ case SLJIT_LESS:+ case SLJIT_LESS_EQUAL:+ ins = BGEU;+ break;+ case SLJIT_GREATER:+ case SLJIT_GREATER_EQUAL:+ ins = BLTU;+ break;+ case SLJIT_SIG_LESS:+ case SLJIT_SIG_LESS_EQUAL:+ ins = BGE;+ break;+ default:+ ins = BLT;+ break;+ }++ ins |= RS1(src1) | RS2(src2_reg);+ } else {+ ins = get_jump_instruction(type);+ }++ ins |= (sljit_ins)((size & 0xf) << 8) | (sljit_ins)((size >> 4) << 25);+ ptr[0] = (sljit_u16)ins;+ ptr[1] = (sljit_u16)(ins >> 16);+ 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_u16 *ptr;+ sljit_ins ins;+ 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_u16 *)ensure_buf(compiler, sizeof(sljit_ins));+ FAIL_IF(!ptr);+ compiler->size += 2;++ 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;+ ins = get_jump_instruction(type & ~SLJIT_32) | (sljit_ins)((size & 0xf) << 8) | (sljit_ins)((size >> 4) << 25);+ ptr[0] = (sljit_u16)ins;+ ptr[1] = (sljit_u16)(ins >> 16);+ 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 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));++ if (!RISCV_HAS_ATOMIC(200) || (op & SLJIT_ATOMIC_USE_CAS))+ return SLJIT_ERR_UNSUPPORTED;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ ins = LR | (3 << 12);+ break;+#endif /* SLJIT_CONFIG_RISCV_64 */+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+ ins = LR | (2 << 12);+ break;++ default:+ return SLJIT_ERR_UNSUPPORTED;+ }++ if (op & SLJIT_ATOMIC_TEST)+ return SLJIT_SUCCESS;++ return push_inst(compiler, ins | RD(dst_reg) | RS1(mem_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));++ if (!RISCV_HAS_ATOMIC(200) || (op & SLJIT_ATOMIC_USE_CAS))+ return SLJIT_ERR_UNSUPPORTED;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV:+ case SLJIT_MOV_P:+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ ins = SC | (3 << 12);+ break;+#endif /* SLJIT_CONFIG_RISCV_64 */+ case SLJIT_MOV_S32:+ case SLJIT_MOV32:+ ins = SC | (2 << 12);+ break;++ default:+ return SLJIT_ERR_UNSUPPORTED;+ }++ if (op & SLJIT_ATOMIC_TEST)+ return SLJIT_SUCCESS;++ return push_inst(compiler, ins | RD(OTHER_FLAG) | RS1(mem_reg) | RS2(src_reg));+}++static sljit_s32 sljit_max_vector_length = 0;++static void init_compiler(void)+{+ sljit_sw vector_length;+ sljit_s32 vector_length_log2;++ if (!RISCV_HAS_VECTOR(100))+ return;++ __asm__ __volatile__ ("csrr %0, 0xc22" : "=r" (vector_length));++ /* Probably something is wrong. */+ if (vector_length < (1 << 3))+ return;++ vector_length_log2 = 3;+ if (vector_length_log2 < 6 && vector_length > (1 << vector_length_log2))+ vector_length_log2++;+ sljit_max_vector_length = vector_length_log2;+}++/*+ SEW = Selected element width+ LMUL = Vector register group multiplier++ VLMUL values (in binary):+ 100 : reserved+ 101 : 1/8+ 110 : 1/4+ 111 : 1/2+ 000 : 1+ 001 : 2+ 010 : 4+ 011 : 8+*/++static SLJIT_INLINE sljit_s32 sljit_emit_vsetivli(struct sljit_compiler *compiler, sljit_s32 type, sljit_ins vlmul)+{+ sljit_ins elem_size = (sljit_ins)SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_ins avl = (sljit_ins)1 << (SLJIT_SIMD_GET_REG_SIZE(type) - elem_size);++ if (avl < 31)+ return push_inst(compiler, VSETIVLI | RD(TMP_REG1) | (elem_size << 23) | (vlmul << 20) | (avl << 15));++ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(TMP_ZERO) | IMM_I(avl)));+ return push_inst(compiler, VSETVLI | RD(TMP_REG1) | (elem_size << 23) | (vlmul << 20) | RS1(TMP_REG1));+}++static SLJIT_INLINE sljit_s32 sljit_emit_vsetivli_size(struct sljit_compiler *compiler, sljit_s32 reg_size, sljit_s32 elem_size)+{+ sljit_ins avl = (sljit_ins)1 << (reg_size - elem_size);++ if (avl < 31)+ return push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | (avl << 15));++ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(TMP_ZERO) | IMM_I(avl)));+ return push_inst(compiler, VSETVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | RS1(TMP_REG1));+}++static sljit_s32 sljit_emit_vmem(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 elem_size, sljit_s32 mem, sljit_sw memw)+{+ sljit_s32 base = mem & REG_MASK;++ if (elem_size > 0)+ ins |= (1 << 14) | ((sljit_ins)elem_size << 12);++ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {+ memw &= 0x3;++ if (SLJIT_UNLIKELY(memw)) {+ 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(base) | RS2(!memw ? OFFS_REG(mem) : TMP_REG1)));+ return push_inst(compiler, ins | RS1(TMP_REG1));+ }++ if (memw == 0)+ return push_inst(compiler, ins | RS1(base));++ if (memw <= SIMM_MAX && memw >= SIMM_MIN) {+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(base) | IMM_I(memw)));+ return push_inst(compiler, ins | RS1(TMP_REG1));+ }++ FAIL_IF(load_immediate(compiler, TMP_REG1, memw, TMP_REG3));++ if (base != 0)+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(base)));++ return push_inst(compiler, ins | RS1(TMP_REG1));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg,+ 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, vreg, srcdst, srcdstw));++ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);++ if (reg_size < 3 || reg_size > sljit_max_vector_length)+ return SLJIT_ERR_UNSUPPORTED;++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (elem_size > 3)+ elem_size = 3;++ FAIL_IF(sljit_emit_vsetivli_size(compiler, reg_size, elem_size));++ if (srcdst & SLJIT_MEM) {+ ins = (type & SLJIT_SIMD_STORE) ? VS : VL;+ return sljit_emit_vmem(compiler, ins | VRD(vreg), elem_size, srcdst, srcdstw);+ }++ if (type & SLJIT_SIMD_STORE)+ ins = VRD(srcdst) | VRS1(vreg);+ else+ ins = VRD(vreg) | VRS1(srcdst);++ return push_inst(compiler, VMV_VV | ins);+}++static sljit_s32 sljit_simd_get_mem_flags(sljit_s32 elem_size)+{+ switch (elem_size) {+ case 0:+ return BYTE_DATA;+ case 1:+ return HALF_DATA;+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ case 2:+ return INT_DATA;+#endif /* SLJIT_CONFIG_RISCV_64 */+ default:+ return WORD_DATA;+ }+}++static sljit_sw sljit_simd_get_imm(sljit_s32 elem_size, sljit_sw imm)+{+ switch (elem_size) {+ case 0:+ return (sljit_s8)imm;+ case 1:+ return (sljit_s16)imm;+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ case 2:+ return (sljit_s32)imm;+#endif /* SLJIT_CONFIG_RISCV_64 */+ default:+ return imm;+ }+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg,+ 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 flags;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_replicate(compiler, type, vreg, src, srcw));++ ADJUST_LOCAL_OFFSET(src, srcw);++ if (reg_size < 3 || reg_size > sljit_max_vector_length)+ return SLJIT_ERR_UNSUPPORTED;++#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : elem_size > 2)+ return SLJIT_ERR_UNSUPPORTED;+#else /* !SLJIT_CONFIG_RISCV_32 */+ if (((type & SLJIT_SIMD_FLOAT) && elem_size < 2) || elem_size > 3)+ return SLJIT_ERR_UNSUPPORTED;+#endif /* SLJIT_CONFIG_RISCV_32 */++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ FAIL_IF(sljit_emit_vsetivli(compiler, type, 0));++ if (type & SLJIT_SIMD_FLOAT) {+ if (src == SLJIT_IMM)+ return push_inst(compiler, VMV_VI | VRD(vreg) | ((sljit_ins)(srcw & 0x1f) << 15));++ if (src & SLJIT_MEM) {+ flags = (elem_size == 2) ? SINGLE_DATA : DOUBLE_DATA;+ FAIL_IF(emit_op_mem(compiler, flags | LOAD_DATA, TMP_FREG1, src, srcw));+ src = TMP_FREG1;+ }++ return push_inst(compiler, VFMV_VF | VRD(vreg) | FRS1(src));+ }++ if (src == SLJIT_IMM) {+ srcw = sljit_simd_get_imm(elem_size, srcw);++ if (srcw >= -0x10 && srcw <= 0xf)+ return push_inst(compiler, VMV_VI | VRD(vreg) | ((sljit_ins)(srcw & 0x1f) << 15));++ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw, TMP_REG3));+ src = TMP_REG1;+ } else if (src & SLJIT_MEM) {+ FAIL_IF(emit_op_mem(compiler, sljit_simd_get_mem_flags(elem_size) | LOAD_DATA, TMP_REG1, src, srcw));+ src = TMP_REG1;+ }++ return push_inst(compiler, VMV_VX | VRD(vreg) | RS1(src));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg, 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 flags;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_lane_mov(compiler, type, vreg, lane_index, srcdst, srcdstw));++ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);++ if (reg_size < 3 || reg_size > sljit_max_vector_length)+ return SLJIT_ERR_UNSUPPORTED;++#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : elem_size > 2)+ return SLJIT_ERR_UNSUPPORTED;+#else /* !SLJIT_CONFIG_RISCV_32 */+ if (((type & SLJIT_SIMD_FLOAT) && elem_size < 2) || elem_size > 3)+ return SLJIT_ERR_UNSUPPORTED;+#endif /* SLJIT_CONFIG_RISCV_32 */++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if (type & SLJIT_SIMD_STORE) {+ FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | (1 << 15)));++ if (lane_index > 0) {+ FAIL_IF(push_inst(compiler, VSLIDEDOWN_VI | VRD(TMP_VREG1) | ((sljit_ins)lane_index << 15) | VRS2(vreg)));+ vreg = TMP_VREG1;+ }++ if (srcdst & SLJIT_MEM)+ return sljit_emit_vmem(compiler, VS | VRD(vreg), elem_size, srcdst, srcdstw);++ if (type & SLJIT_SIMD_FLOAT)+ return push_inst(compiler, VFMV_FS | FRD(srcdst) | VRS2(vreg));++ FAIL_IF(push_inst(compiler, VMV_XS | RD(srcdst) | VRS2(vreg)));++#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ if ((type & SLJIT_SIMD_LANE_SIGNED) || elem_size >= 2)+ return SLJIT_SUCCESS;+#else /* !SLJIT_CONFIG_RISCV_32 */+ if ((type & SLJIT_SIMD_LANE_SIGNED) || elem_size >= 3 || (elem_size == 2 && (type & SLJIT_32)))+ return SLJIT_SUCCESS;+#endif /* SLJIT_CONFIG_RISCV_32 */++ if (elem_size == 0)+ return push_inst(compiler, ANDI | RD(srcdst) | RS1(srcdst) | IMM_I(0xff));++#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ flags = 16;+#else /* !SLJIT_CONFIG_RISCV_32 */+ flags = (elem_size == 1) ? 48 : 32;+#endif /* SLJIT_CONFIG_RISCV_32 */++ FAIL_IF(push_inst(compiler, SLLI | RD(srcdst) | RS1(srcdst) | IMM_I(flags)));+ return push_inst(compiler, SRLI | RD(srcdst) | RS1(srcdst) | IMM_I(flags));+ }++ if (type & SLJIT_SIMD_LANE_ZERO) {+ FAIL_IF(sljit_emit_vsetivli(compiler, type, 0));+ FAIL_IF(push_inst(compiler, VMV_VI | VRD(vreg)));+ }++ if (srcdst & SLJIT_MEM) {+ FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | (1 << 15)));+ FAIL_IF(sljit_emit_vmem(compiler, VL | VRD(lane_index > 0 ? TMP_VREG1 : vreg), elem_size, srcdst, srcdstw));++ if (lane_index == 0)+ return SLJIT_SUCCESS;++ FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | ((sljit_ins)(lane_index + 1) << 15)));+ return push_inst(compiler, VSLIDEUP_VI | VRD(vreg) | ((sljit_ins)lane_index << 15) | VRS2(TMP_VREG1));+ }++ if (!(type & SLJIT_SIMD_LANE_ZERO) || lane_index > 0)+ FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | ((sljit_ins)(lane_index + 1) << 15)));++ if (type & SLJIT_SIMD_FLOAT) {+ FAIL_IF(push_inst(compiler, VFMV_SF | VRD(lane_index > 0 ? TMP_VREG1 : vreg) | FRS1(srcdst)));++ if (lane_index == 0)+ return SLJIT_SUCCESS;++ return push_inst(compiler, VSLIDEUP_VI | VRD(vreg) | ((sljit_ins)lane_index << 15) | VRS2(TMP_VREG1));+ }++ if (srcdst == SLJIT_IMM) {+ srcdstw = sljit_simd_get_imm(elem_size, srcdstw);+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcdstw, TMP_REG3));+ srcdst = TMP_REG1;+ }++ FAIL_IF(push_inst(compiler, VMV_SX | VRD(lane_index > 0 ? TMP_VREG1 : vreg) | RS1(srcdst)));++ if (lane_index == 0)+ return SLJIT_SUCCESS;++ return push_inst(compiler, VSLIDEUP_VI | VRD(vreg) | ((sljit_ins)lane_index << 15) | VRS2(TMP_VREG1));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg,+ 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, vreg, src, src_lane_index));++ if (reg_size < 3 || reg_size > sljit_max_vector_length)+ 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;++ FAIL_IF(sljit_emit_vsetivli(compiler, type, 0));++ FAIL_IF(push_inst(compiler, VRGATHER_VI | VRD(vreg != src ? vreg : TMP_VREG1) | ((sljit_ins)src_lane_index << 15) | VRS2(src)));+ if (vreg == src)+ return push_inst(compiler, VMV_VV | VRD(vreg) | VRS1(TMP_VREG1));+ return SLJIT_SUCCESS;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg,+ 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;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_extend(compiler, type, vreg, src, srcw));++ ADJUST_LOCAL_OFFSET(src, srcw);++ if (reg_size < 3 || reg_size > sljit_max_vector_length)+ return SLJIT_ERR_UNSUPPORTED;++#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)+ if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : elem_size > 2)+ return SLJIT_ERR_UNSUPPORTED;+#else /* !SLJIT_CONFIG_RISCV_32 */+ if (((type & SLJIT_SIMD_FLOAT) && elem_size < 2) || elem_size > 3)+ return SLJIT_ERR_UNSUPPORTED;+#endif /* SLJIT_CONFIG_RISCV_32 */++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if ((src & SLJIT_MEM) || vreg == src) {+ ins = (sljit_ins)1 << (reg_size - elem2_size);+ FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | (ins << 15)));++ if (src & SLJIT_MEM)+ FAIL_IF(sljit_emit_vmem(compiler, VL | VRD(TMP_VREG1), elem_size, src, srcw));+ else+ FAIL_IF(push_inst(compiler, VMV_VV | VRD(TMP_VREG1) | VRS1(src)));++ src = TMP_VREG1;+ }++ if (type & SLJIT_SIMD_FLOAT) {+ FAIL_IF(sljit_emit_vsetivli(compiler, type, 0x7));+ return push_inst(compiler, VFWCVT_FFV | VRD(vreg) | VRS2(src));+ }++ ins = (sljit_ins)1 << (reg_size - elem2_size);+ FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem2_size << 23) | (ins << 15)));++ switch (elem2_size - elem_size) {+ case 1:+ ins = VZEXT_VF2;+ break;+ case 2:+ ins = VZEXT_VF4;+ break;+ default:+ ins = VZEXT_VF8;+ break;+ }++ if (type & SLJIT_SIMD_EXTEND_SIGNED)+ ins |= 1 << 15;++ return push_inst(compiler, ins | VRD(vreg) | VRS2(src));+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg,+ 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 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_sign(compiler, type, vreg, dst, dstw));++ ADJUST_LOCAL_OFFSET(dst, dstw);++ if (reg_size < 3 || reg_size > sljit_max_vector_length)+ return SLJIT_ERR_UNSUPPORTED;++ if (((type & SLJIT_SIMD_FLOAT) && elem_size < 2) || elem_size > 3)+ return SLJIT_ERR_UNSUPPORTED;++ FAIL_IF(sljit_emit_vsetivli(compiler, type, 0));+ FAIL_IF(push_inst(compiler, VMV_VI | VRD(TMP_VREG1) | (0x0 << 15)));+ FAIL_IF(push_inst(compiler, VMSLE_VI | VRD(TMP_VREG1) | (0x1f << 15) | VRS2(vreg)));++ FAIL_IF(sljit_emit_vsetivli_size(compiler, 2, 2));+ FAIL_IF(push_inst(compiler, VMV_XS | RD(dst_r) | VRS2(TMP_VREG1)));++ if (dst & SLJIT_MEM)+ return emit_op_mem(compiler, (type & SLJIT_32) ? INT_DATA : WORD_DATA, dst_r, 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_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w)+{+ 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_vreg, src1_vreg, src2, src2w));++ ADJUST_LOCAL_OFFSET(src2, src2w);++ if (reg_size < 3 || reg_size > sljit_max_vector_length)+ 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_VV;+ break;+ case SLJIT_SIMD_OP2_OR:+ ins = VOR_VV;+ break;+ case SLJIT_SIMD_OP2_XOR:+ ins = VXOR_VV;+ break;+ case SLJIT_SIMD_OP2_SHUFFLE:+ ins = VRGATHER_VV;+ elem_size = 0;+ break;+ }++ if (elem_size > 3)+ elem_size = 3;++ FAIL_IF(sljit_emit_vsetivli_size(compiler, reg_size, elem_size));++ if (src2 & SLJIT_MEM) {+ FAIL_IF(sljit_emit_vmem(compiler, VL | VRD(TMP_VREG1), elem_size, src2, src2w));+ src2 = TMP_VREG1;+ }++ if (SLJIT_SIMD_GET_OPCODE(type) != SLJIT_SIMD_OP2_SHUFFLE)+ return push_inst(compiler, ins | VRD(dst_vreg) | VRS1(src1_vreg) | VRS2(src2));++ if (dst_vreg == src2) {+ FAIL_IF(push_inst(compiler, VMV_VV | VRD(TMP_VREG1) | VRS1(src2)));+ src2 = TMP_VREG1;+ }++ if (dst_vreg == src1_vreg) {+ FAIL_IF(push_inst(compiler, VMV_VV | VRD(TMP_VREG2) | VRS1(src1_vreg)));+ src1_vreg = TMP_VREG2;+ }++ return push_inst(compiler, ins | VRD(dst_vreg) | VRS1(src2) | VRS2(src1_vreg));+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_s32 dst_r;+ sljit_s32 mem_flags = WORD_DATA;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, op, 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;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_U8:+ if (init_value & 0x100)+ init_value |= 0xf00;+ else+ init_value &= 0xff;++ PTR_FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | IMM_I(init_value)));+ mem_flags = BYTE_DATA;+ break;++#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ case SLJIT_MOV32:+ mem_flags = INT_DATA;+ SLJIT_FALLTHROUGH+ case SLJIT_MOV_S32:+ if ((init_value & 0x800) != 0)+ init_value ^= ~(sljit_sw)0xfff;++ PTR_FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(init_value & ~(sljit_sw)0xfff)));+ PTR_FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(init_value)));+ break;+#endif /* SLJIT_CONFIG_RISCV_64 */++ default:+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value, ADDI | RD(dst_r)));+ break;+ }++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG2, dst, dstw));++ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_jump *jump;+ sljit_s32 dst_r, target_r;+ SLJIT_UNUSED_ARG(op);++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;++ if (op != SLJIT_ADD_ABS_ADDR)+ target_r = dst_r;+ else {+ target_r = TMP_REG1;++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, dst, dstw));+ }++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_mov_addr(jump, compiler, 0);++ PTR_FAIL_IF(push_inst16(compiler, (sljit_u16)target_r));+ compiler->size += JUMP_MAX_SIZE - 1;++ if (op == SLJIT_ADD_ABS_ADDR) {+ if (RISCV_HAS_COMPRESSED(200))+ PTR_FAIL_IF(push_inst16(compiler, C_ADD | C_RD(dst_r) | C_RS2(TMP_REG1)));+ else+ PTR_FAIL_IF(push_inst(compiler, ADD | RD(dst_r) | RS1(dst_r) | RS2(TMP_REG1)));+ }++ 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_s32 op, sljit_sw new_constant, sljit_sw executable_offset)+{+ sljit_u16 *inst;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_U8:+ inst = (sljit_u16*)addr;+ SLJIT_ASSERT((inst[0] & 0x707f) == ADDI);++ if (new_constant & 0x100)+ new_constant |= 0xf00;+ else+ new_constant &= 0xff;++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);+ inst[1] = (sljit_u16)(new_constant << 4) | (inst[1] & 0xf);+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);+ inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 2);+ return;++#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)+ case SLJIT_MOV32:+ case SLJIT_MOV_S32:+ inst = (sljit_u16*)addr;+ SLJIT_ASSERT((inst[0] & 0x7f) == LUI && (inst[2] & 0x707f) == XORI);++ if ((new_constant & 0x800) != 0)+ new_constant ^= ~(sljit_sw)0xfff;++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 0);+ inst[0] = (sljit_u16)((inst[0] & 0xfff) | (new_constant & 0xf000));+ inst[1] = (sljit_u16)(new_constant >> 16);+ inst[3] = (sljit_u16)(new_constant << 4) | (inst[3] & 0xf);+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 1);+ inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 4);+ return;+#endif /* SLJIT_CONFIG_RISCV_64 */++ default:+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);+ return;+ }+}
+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeS390X.c view
@@ -0,0 +1,4822 @@+/*+ * 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/auxv.h>++#ifdef __ARCH__+#define ENABLE_STATIC_FACILITY_DETECTION 1+#else+#define ENABLE_STATIC_FACILITY_DETECTION 0+#endif+#define ENABLE_DYNAMIC_FACILITY_DETECTION 1++SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)+{+ return "s390x" SLJIT_CPUINFO;+}++/* 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++/* 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]))++/* 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 flag_type = GET_FLAG_TYPE(compiler->status_flags_state);+ if (flag_type >= SLJIT_SIG_LESS && flag_type <= SLJIT_SIG_LESS_EQUAL)+ return cc0;+ if (flag_type == SLJIT_OVERFLOW)+ return (cc0 | cc3);+ return (cc0 | cc2);+ }+ SLJIT_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 flag_type = GET_FLAG_TYPE(compiler->status_flags_state);+ if (flag_type >= SLJIT_SIG_LESS && flag_type <= SLJIT_SIG_LESS_EQUAL)+ return (cc1 | cc2 | cc3);+ if (flag_type == SLJIT_OVERFLOW)+ return (cc1 | cc2);+ return (cc1 | cc3);+ }+ SLJIT_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);+ SLJIT_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);+ SLJIT_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);+ SLJIT_FALLTHROUGH++ case SLJIT_UNORDERED:+ return cc3;++ case SLJIT_NOT_OVERFLOW:+ if (compiler->status_flags_state & SLJIT_SET_Z)+ return (cc0 | cc1);+ SLJIT_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(void)+{+ 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(void)+{+ 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) ((sljit_sw)(d) == (sljit_s8)(d))+#define is_s16(d) ((sljit_sw)(d) == (sljit_s16)(d))+#define is_s20(d) CHECK_SIGNED((d), 20)+#define is_s32(d) ((sljit_sw)(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 store_byte_forms[3] = {+ 0x42000000 /* stc */,+ 0xe30000000072 /* stcy */,+ 0+};++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);+}++/* May clobber tmp1. */+static SLJIT_INLINE sljit_s32 store_byte(struct sljit_compiler *compiler, sljit_gpr src_r,+ sljit_s32 dst, sljit_sw dstw)+{+ return load_store_op(compiler, src_r, dst, dstw, 1, store_byte_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(!FAST_IS_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);+}++static SLJIT_INLINE sljit_u16 *process_extended_label(sljit_u16 *code_ptr, struct sljit_extended_label *ext_label)+{+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);+ return (sljit_u16*)((sljit_uw)code_ptr & ~(ext_label->data));+}++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, options));+ reverse_buf(compiler);++ jump = compiler->jumps;+ while (jump != NULL) {+ if (jump->flags & (SLJIT_REWRITABLE_JUMP | 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) */+ if (((jump->flags & SLJIT_REWRITABLE_JUMP) || !is_s32(jump->u.target)))+ pool_size += sizeof(sljit_uw);+ else+ jump->flags |= PATCH_IMM32;++ if (!(jump->flags & JUMP_MOV_ADDR))+ ins_size += 2;+ }+ jump = jump->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) {+ if (label->u.index >= SLJIT_LABEL_ALIGNED)+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);++ 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) {+ jump->addr = (sljit_uw)code_ptr;++ if (SLJIT_UNLIKELY(jump->flags & JUMP_MOV_ADDR)) {+ if (jump->flags & PATCH_IMM32) {+ SLJIT_ASSERT((jump->flags & JUMP_ADDR) && is_s32(jump->u.target));+ ins = 0xc00100000000 /* lgfi */ | (ins & 0xf000000000);+ } else if (jump->flags & JUMP_ADDR) {+ source = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);+ offset = (sljit_sw)(jump->u.target - (sljit_uw)source);++ if ((offset & 0x1) != 0 || offset > 0xffffffffl || offset < -0x100000000l) {+ jump->addr = (sljit_uw)pool_ptr;+ jump->flags |= PATCH_POOL;++ /* 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 = 0xc40800000000 /* lgrl */ | (ins & 0xf000000000) | (sljit_ins)(offset & 0xffffffff);+ }+ }+ } else if (jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR)) {+ source = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);++ if (jump->flags & PATCH_IMM32) {+ SLJIT_ASSERT((jump->flags & JUMP_ADDR) && is_s32(jump->u.target));+ code_ptr[0] = (sljit_u16)(0xc001 /* lgfi */ | R4A(tmp1));+ code_ptr += 3;+ } else if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) {+ offset = (sljit_sw)(jump->u.target - (sljit_uw)source);++ if ((offset & 0x1) != 0 || offset > 0xffffffffl || offset < -0x100000000l)+ jump->flags |= PATCH_POOL;+ } else+ jump->flags |= PATCH_POOL;++ if (jump->flags & PATCH_POOL) {+ jump->addr = (sljit_uw)pool_ptr;++ /* load address into tmp1 */+ 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 /* lgrl */ | R4A(tmp1));+ code_ptr[1] = (sljit_u16)(offset >> 16);+ code_ptr[2] = (sljit_u16)offset;+ code_ptr += 3;+ pool_ptr++;+ }++ if (jump->flags & (PATCH_POOL | PATCH_IMM32)) {+ /* branch to tmp1 */+ if (((ins >> 32) & 0xf) == 4) {+ /* brcl -> bcr */+ ins = 0x0700 /* bcr */ | ((ins >> 32) & 0xf0) | R0A(tmp1);+ } else {+ SLJIT_ASSERT(((ins >> 32) & 0xf) == 5);+ /* brasl -> basr */+ ins = 0x0d00 /* basr */ | ((ins >> 32) & 0xf0) | R0A(tmp1);+ }++ /* Adjust half_count. */+ half_count += 2;+ }+ }++ 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();+ }++ 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) {+ if (label->u.index >= SLJIT_LABEL_ALIGNED)+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);++ 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_ptr <= code + (ins_size >> 1));+ SLJIT_ASSERT((sljit_u8 *)pool_ptr <= (sljit_u8 *)pool + pool_size);++ jump = compiler->jumps;+ while (jump != NULL) {+ offset = (sljit_sw)((jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr);++ if (!(jump->flags & (PATCH_POOL | PATCH_IMM32))) {+ 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;+ } else if (jump->flags & PATCH_POOL) {+ /* Store jump target into pool. */+ *(sljit_uw*)(jump->addr) = (sljit_uw)offset;+ } else {+ SLJIT_ASSERT(is_s32(offset));+ code_ptr = (sljit_u16*)jump->addr;+ 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:+ case SLJIT_HAS_MEMORY_BARRIER:+ 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 local_size)+{+ sljit_s32 fscratches;+ sljit_s32 fsaveds;+ 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, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);++ /* Saved registers are stored in callee allocated save area. */+ SLJIT_ASSERT(gpr(SLJIT_FIRST_SAVED_REG) == r6 && gpr(SLJIT_S0) == r13);++ scratches = ENTER_GET_REGS(scratches);+ saveds = ENTER_GET_REGS(saveds);+ fscratches = compiler->fscratches;+ fsaveds = compiler->fsaveds;++ 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 local_size)+{+ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, 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, 0xeb00000000dc /* srak */ | R36A(tmp0) | R32A(arg0) | (31 << 16)));+ 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_MEMORY_BARRIER:+ return push_inst(compiler, 0x0700 /* bcr */ | (0xe << 4) | 0);+ 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)) {+ 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)) {+ 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;+ SLJIT_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);+ }+ }+ 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 (FAST_IS_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_op2_shift(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_sw shift_arg)+{+ sljit_gpr dst_r, tmp_r, src_r;+ struct addr addr;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ shift_arg &= 0x3f;++ if (src2 == SLJIT_IMM) {+ src2w = src2w << shift_arg;+ shift_arg = 0;+ }++ if (shift_arg == 0) {+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);+ }++ tmp_r = FAST_IS_REG(dst) && (dst != src1) ? gpr(dst) : tmp0;++ if (src2 & SLJIT_MEM) {+ FAIL_IF(load_word(compiler, tmp_r, src2, src2w, 0 /* 64-bit */));+ src_r = tmp_r;+ } else {+ src_r = gpr(src2);+ }++ FAIL_IF(push_inst(compiler, 0xeb000000000d /* sllg */ | R36A(tmp_r) | R32A(src_r) | ((sljit_ins)shift_arg << 16)));++ if (src1 & SLJIT_MEM) {+ FAIL_IF(make_addr_bxy(compiler, &addr, src1, src1w, tmp1));+ FAIL_IF(push_inst(compiler, 0xe30000000008 /* ag */ | R36A(tmp_r) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset)));+ src_r = tmp_r;+ } else if (src1 == SLJIT_IMM) {+ if (is_s32(src1w)) {+ FAIL_IF(push_inst(compiler, 0xc20800000000 /* agfi */ | R36A(tmp_r) | (sljit_u32)src1w));+ src_r = tmp_r;+ } else {+ src_r = tmp_r != tmp0 ? tmp0 : tmp1;+ FAIL_IF(push_load_imm_inst(compiler, src_r, src1w));+ }+ } else {+ src_r = gpr(src1);+ }++ dst_r = (FAST_IS_REG(dst) ? gpr(dst) : tmp0);++ if (src_r != tmp_r) {+ if (src_r == dst_r) {+ FAIL_IF(push_inst(compiler, 0xb9080000 /* agr */ | R4A(dst_r) | R0A(tmp_r)));+ } else {+ FAIL_IF(push_inst(compiler, 0xb9e80000 /* agrk */ | R12A(tmp_r) | R4A(dst_r) | R0A(src_r)));+ }+ }++ if (dst & SLJIT_MEM)+ return store_word(compiler, dst_r, dst, dstw, 0 /* 64-bit */);+ 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)+{+ 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:+ if (FAST_IS_REG(src)) {+ src_r = gpr(src);+ if (src_r != link_r)+ FAIL_IF(push_inst(compiler, lgr(link_r, src_r)));+ } else+ FAIL_IF(load_word(compiler, link_r, src, srcw, 0));++ return push_inst(compiler, br(link_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)) {+ dst_r = gpr(dst);++ if (dst_r == link_r)+ return SLJIT_SUCCESS;+ return push_inst(compiler, lgr(dst_r, 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 && type != SLJIT_SIMD_REG_128)+ 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_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)+{+ sljit_uw mask, i;+ struct sljit_label *label;+ struct sljit_label *next_label;+ struct sljit_extended_label *ext_label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));++ sljit_reset_read_only_buffers(buffers);++ if (alignment <= SLJIT_LABEL_ALIGN_2) {+ SLJIT_SKIP_CHECKS(compiler);+ label = sljit_emit_label(compiler);+ PTR_FAIL_IF(!label);+ } else {+ /* The used space is filled with NOPs. */+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_u16);++ for (i = (mask >> 1); i != 0; i--)+ PTR_FAIL_IF(push_inst(compiler, 0x0700 /* 2-byte nop */));++ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));+ PTR_FAIL_IF(!ext_label);+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);+ label = &ext_label->label;+ }++ if (buffers == NULL)+ return label;++ next_label = label;++ while (1) {+ buffers->u.label = next_label;++ for (i = (buffers->size + 1) >> 1; i > 0; i--)+ PTR_FAIL_IF(push_inst(compiler, 0x0700 /* 2-byte nop */));++ buffers = buffers->next;++ if (buffers == NULL)+ break;++ SLJIT_SKIP_CHECKS(compiler);+ next_label = sljit_emit_label(compiler);+ PTR_FAIL_IF(!next_label);+ }++ 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)+{+ struct sljit_jump *jump;+ 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) {+ 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));+ }++ jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump));+ FAIL_IF(!jump);+ set_jump(jump, compiler, JUMP_ADDR);+ jump->addr = compiler->size;+ jump->u.target = (sljit_uw)srcw;++ type &= 0xff;+ if (type >= SLJIT_FAST_CALL)+ return push_inst(compiler, brasl(link_r, 0));++ return push_inst(compiler, brcl(0xf, 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));++ 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;+ SLJIT_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_s32 is_32bit = (type & SLJIT_32) != 0;+ sljit_ins ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));++ ADJUST_LOCAL_OFFSET(src1, src1w);++ type &= ~SLJIT_32;+ if (src1 == SLJIT_IMM && is_32bit)+ src1w = (sljit_s32)src1w;++ if (type & SLJIT_COMPARE_SELECT) {+ type ^= SLJIT_COMPARE_SELECT;+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_COMPARE;++ if (src1 & SLJIT_MEM) {+ FAIL_IF(load_word(compiler, tmp0, src1, src1w, is_32bit));+ src1 = TMP_REG1;+ src1w = 0;+ } else if (src1 == SLJIT_IMM) {+ if (type >= SLJIT_LESS && type <= SLJIT_LESS_EQUAL && src1w >= 0 && src1w <= 0x7fff) {+ ins = is_32bit ? 0xc20f00000000 /* clfi */ : 0xc20e00000000 /* clgfi */;+ FAIL_IF(push_inst(compiler, ins | R36A(gpr(src2_reg)) | (sljit_ins)src1w));+ type ^= 0x1;+ } else if (type >= SLJIT_SIG_LESS && type <= SLJIT_SIG_LESS_EQUAL && is_s20(src1w)) {+ ins = is_32bit ? 0xc20d00000000 /* cfi */ : 0xc20c00000000 /* cgfi */;+ FAIL_IF(push_inst(compiler, ins | R36A(gpr(src2_reg)) | ((sljit_ins)src1w & 0xffffffff)));+ type ^= 0x1;+ } else {+ FAIL_IF(push_load_imm_inst(compiler, tmp0, src1w));+ src1 = TMP_REG1;+ src1w = 0;+ }+ }++ if (FAST_IS_REG(src1)) {+ if (type >= SLJIT_LESS && type <= SLJIT_LESS_EQUAL)+ ins = is_32bit ? 0x1500 /* clr */ : 0xb9210000 /* clgr */;+ else+ ins = is_32bit ? 0x1900 /* cr */ : 0xb9200000 /* cgr */;+ FAIL_IF(push_inst(compiler, ins | R4A(gpr(src1)) | R0A(gpr(src2_reg))));+ }+ }++ 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, is_32bit));+ src1 = src2_reg;+ src1w = 0;+ type ^= 0x1;+ } else+ FAIL_IF(push_inst(compiler, (is_32bit ? 0x1800 /* lr */ : 0xb9040000 /* lgr */) | R4A(dst_r) | R0A(gpr(src2_reg))));+ }+ }++ mask = get_cc(compiler, type);++ 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, 0xb9080000 /* agr */ | R4A(tmp1) | R0A(gpr(src1 & REG_MASK))));++ src_r = tmp1;+ src1w = 0;+ } else+ src_r = gpr(src1 & REG_MASK);++ ins = is_32bit ? 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 (have_lscond2() && is_s16(src1w)) {+ ins = is_32bit ? 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 = is_32bit ? 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 vreg,+ 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, vreg, 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(vreg);+ else+ ins = F36(vreg) | F32(srcdst);++ return push_inst(compiler, 0xe70000000056 /* vlr */ | ins);+ }++ FAIL_IF(make_addr_bx(compiler, &addr, srcdst, srcdstw, tmp1));+ ins = F36(vreg) | 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 vreg,+ 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, vreg, 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(vreg)+ | 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(vreg));++ return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(vreg) | 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(vreg)+ | (sign_ext == 0 ? 0 : ((sljit_ins)0xffff << 16)));++ return push_inst(compiler, 0xe70000000045 /* vrepi */ | F36(vreg)+ | ((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(vreg) | R32A(reg) | ((sljit_ins)elem_size << 12)));+ return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(vreg) | F32(vreg) | ((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 vreg, 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, vreg, 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(vreg) | 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) && vreg == srcdst) {+ FAIL_IF(push_inst(compiler, 0xe70000000056 /* vlr */ | F36(TMP_FREG1) | F32(vreg)));+ srcdst = TMP_FREG1;+ srcdstw = 0;+ }++ FAIL_IF(push_inst(compiler, 0xe70000000044 /* vgbm */ | F36(vreg)));+ }++ 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(vreg) | ((sljit_ins)lane_index << 16) | ((sljit_ins)elem_size << 12));++ if (elem_size == 3) {+ if (lane_index == 0)+ ins = F32(srcdst) | F28(vreg) | (1 << 12);+ else+ ins = F32(vreg) | F28(srcdst);++ return push_inst(compiler, 0xe70000000084 /* vpdi */ | F36(vreg) | ins);+ }++ FAIL_IF(push_inst(compiler, 0xe70000000021 /* vlgv */ | R36A(tmp0) | F32(srcdst) | ((sljit_ins)2 << 12)));+ return push_inst(compiler, 0xe70000000022 /* vlvg */ | F36(vreg) | 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(vreg) | ((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(vreg) | R32A(reg) | ins);++ FAIL_IF(push_inst(compiler, 0xe70000000021 /* vlgv */ | R36A(reg) | F32(vreg) | 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 vreg,+ 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, vreg, 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(vreg) | 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 vreg,+ 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, vreg, 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(vreg) | 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 = vreg;+ }++ if (type & SLJIT_SIMD_FLOAT) {+ FAIL_IF(push_inst(compiler, 0xe700000000d5 /* vuplh */ | F36(vreg) | F32(src) | (2 << 12)));+ FAIL_IF(push_inst(compiler, 0xe70000000030 /* vesl */ | F36(vreg) | F32(vreg) | (32 << 16) | (3 << 12)));+ return push_inst(compiler, 0xe700000000c4 /* vfll */ | F36(vreg) | F32(vreg) | (2 << 12));+ }++ ins = ((type & SLJIT_SIMD_EXTEND_SIGNED) ? 0xe700000000d7 /* vuph */ : 0xe700000000d5 /* vuplh */) | F36(vreg);++ do {+ FAIL_IF(push_inst(compiler, ins | F32(src) | ((sljit_ins)elem_size << 12)));+ src = vreg;+ } 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 vreg,+ 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, vreg, 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(vreg) | 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_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w)+{+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);+ sljit_s32 alignment;+ struct addr addr;+ sljit_ins ins = 0, load_ins;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w));+ ADJUST_LOCAL_OFFSET(src2, src2w);++ 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;+ case SLJIT_SIMD_OP2_SHUFFLE:+ ins = 0xe7000000008c /* vperm */;+ break;+ }++ if (src2 & SLJIT_MEM) {+ FAIL_IF(make_addr_bx(compiler, &addr, src2, src2w, tmp1));+ load_ins = 0xe70000000006 /* vl */ | F36(TMP_FREG1) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset);+ alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type);++ if (alignment >= 4)+ load_ins |= 4 << 12;+ else if (alignment == 3)+ load_ins |= 3 << 12;++ FAIL_IF(push_inst(compiler, load_ins));+ src2 = TMP_FREG1;+ }++ if (SLJIT_SIMD_GET_OPCODE(type) == SLJIT_SIMD_OP2_SHUFFLE)+ return push_inst(compiler, ins | F36(dst_vreg) | F32(src1_vreg) | F28(src1_vreg) | F12(src2));++ return push_inst(compiler, ins | F36(dst_vreg) | F32(src1_vreg) | F28(src2));+}++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));++ if (op & SLJIT_ATOMIC_USE_LS)+ return SLJIT_ERR_UNSUPPORTED;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV32:+ case SLJIT_MOV_U32:+ case SLJIT_MOV:+ case SLJIT_MOV_P:+ if (op & SLJIT_ATOMIC_TEST)+ return SLJIT_SUCCESS;++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op1(compiler, op & ~SLJIT_ATOMIC_USE_CAS, dst_reg, 0, SLJIT_MEM1(mem_reg), 0);+ default:+ 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_ins ins;+ 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));++ if (op & SLJIT_ATOMIC_USE_LS)+ return SLJIT_ERR_UNSUPPORTED;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV32:+ case SLJIT_MOV_U32:+ ins = 0xba000000 /* cs */ | R20A(tmp_r) | R16A(gpr(src_reg)) | R12A(mem_r);+ break;+ case SLJIT_MOV:+ case SLJIT_MOV_P:+ ins = 0xeb0000000030 /* csg */ | R36A(tmp_r) | R32A(gpr(src_reg)) | R28A(mem_r);+ break;+ default:+ return SLJIT_ERR_UNSUPPORTED;+ }++ if (op & SLJIT_ATOMIC_TEST)+ return SLJIT_SUCCESS;++ return push_inst(compiler, ins);+}++/* --------------------------------------------------------------------- */+/* Other instructions */+/* --------------------------------------------------------------------- */++SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_sw init_value)+{+ struct sljit_const *const_;+ sljit_gpr dst_r;+ int is_32 = 0;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, op, 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((struct sljit_const*)const_, compiler);++ dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_U8:+ if (init_value & 0x100)+ init_value |= 0xff00;+ else+ init_value &= 0xff;++ PTR_FAIL_IF(push_inst(compiler, 0xa7090000 /* lghi */ | R20A(dst_r) | (sljit_ins)(init_value & 0xffff)));++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(store_byte(compiler, dst_r, dst, dstw));+ return (struct sljit_const*)const_;++ case SLJIT_MOV32:+ is_32 = 1;+ SLJIT_FALLTHROUGH+ case SLJIT_MOV_S32:+ PTR_FAIL_IF(push_inst(compiler, 0xc00100000000 /* lgfi */ | R36A(dst_r) | (sljit_ins)(init_value & 0xffffffff)));+ break;++ default:+ PTR_FAIL_IF(push_inst(compiler, 0xc00f00000000 /* llilf */ | R36A(dst_r) | (sljit_ins)(init_value & 0xffffffff)));+ PTR_FAIL_IF(push_inst(compiler, 0xc00800000000 /* iihf */ | R36A(dst_r) | (sljit_ins)((init_value >> 32) & 0xffffffff)));+ break;+ }++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(store_word(compiler, dst_r, dst, dstw, is_32));++ 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_s32 op, sljit_sw new_constant, sljit_sw executable_offset)+{+ sljit_u16 *inst = (sljit_u16*)addr;+ SLJIT_UNUSED_ARG(executable_offset);++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_U8:+ SLJIT_ASSERT((inst[0] & 0xff0f) == 0xa709 /* lghi */);++ if (new_constant & 0x100)+ new_constant |= 0xff00;+ else+ new_constant &= 0xff;++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);+ inst[1] = (sljit_u16)new_constant;+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);+ inst = (sljit_u16*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 2);+ return;++ case SLJIT_MOV32:+ case SLJIT_MOV_S32:+ SLJIT_ASSERT((inst[0] & 0xff0f) == 0xc001 /* lgfi */);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 3, 0);+ inst[1] = (sljit_u16)(new_constant >> 16);+ inst[2] = (sljit_u16)new_constant;+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 3, 1);+ inst = (sljit_u16*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 3);+ return;++ default:+ SLJIT_ASSERT((inst[0] & 0xff0f) == 0xc00f /* llilf */ && (inst[3] & 0xff0f) == 0xc008 /* iihf */);++ SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 0);+ inst[1] = (sljit_u16)(new_constant >> 16);+ inst[2] = (sljit_u16)new_constant;+ inst[4] = (sljit_u16)(new_constant >> 48);+ inst[5] = (sljit_u16)(new_constant >> 32);+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 1);+ inst = (sljit_u16*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);+ SLJIT_CACHE_FLUSH(inst, inst + 6);+ return;+ }+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,+ sljit_s32 dst, sljit_sw dstw)+{+ struct sljit_jump *jump;+ sljit_gpr dst_r, target_r;+ SLJIT_UNUSED_ARG(op);++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;++ if (op != SLJIT_ADD_ABS_ADDR)+ target_r = dst_r;+ else {+ target_r = tmp1;++ if (dst & SLJIT_MEM)+ PTR_FAIL_IF(load_word(compiler, dst_r, dst, dstw, 0));+ }++ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));+ PTR_FAIL_IF(!jump);+ set_mov_addr(jump, compiler, 0);++ /* Might be converted to lgrl. */+ PTR_FAIL_IF(push_inst(compiler, 0xc00000000000 /* larl */ | R36A(target_r)));++ if (op == SLJIT_ADD_ABS_ADDR)+ PTR_FAIL_IF(push_inst(compiler, 0xb90a0000 /* algr */ | R4A(dst_r) | R0A(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 */+#undef WHEN2+#undef EVAL++#undef tmp1+#undef tmp0++/* TODO(carenas): undef other macros that spill like is_u12? */
+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeX86_32.c view
@@ -0,0 +1,1707 @@+/*+ * 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.+ */++/* x86 32-bit arch dependent functions. */++/* --------------------------------------------------------------------- */+/* Operators */+/* --------------------------------------------------------------------- */++static sljit_s32 emit_do_imm(struct sljit_compiler *compiler, sljit_u8 opcode, sljit_sw imm)+{+ sljit_u8 *inst;++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_sw));+ FAIL_IF(!inst);+ INC_SIZE(1 + sizeof(sljit_sw));+ *inst++ = opcode;+ sljit_unaligned_store_sw(inst, imm);+ return SLJIT_SUCCESS;+}++/* Size contains the flags as well. */+static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw size,+ /* The register or immediate operand. */+ sljit_s32 a, sljit_sw imma,+ /* The general operand (not immediate). */+ sljit_s32 b, sljit_sw immb)+{+ sljit_u8 *inst;+ sljit_u8 *buf_ptr;+ sljit_u8 reg_map_b;+ sljit_uw flags = size;+ sljit_uw inst_size;++ /* 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. */+ SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0);+ /* 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_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 += sizeof(sljit_s8);+ flags |= EX86_BYTE_ARG;+ } else+ inst_size += sizeof(sljit_sw);+ } else if (flags & EX86_SHIFT_INS) {+ SLJIT_ASSERT(imma <= 0x1f);+ if (imma != 1) {+ inst_size += sizeof(sljit_s8);+ flags |= EX86_BYTE_ARG;+ }+ } else if (flags & EX86_BYTE_ARG)+ inst_size += sizeof(sljit_s8);+ else if (flags & EX86_HALF_ARG)+ inst_size += sizeof(sljit_s16);+ 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 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, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);++ scratches = ENTER_GET_REGS(scratches);++ /* 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 local_size)+{+ sljit_s32 args_size;++ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);++ scratches = ENTER_GET_REGS(scratches);++ 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);++ 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;+ if (!(type & SLJIT_COMPARE_SELECT))+ 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;+ if (!(type & SLJIT_COMPARE_SELECT))+ type ^= 0x1;+ } else if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {+ EMIT_MOV(compiler, dst_reg, 0, src1, src1w);+ src1 = src2_reg;+ src1w = src2w;+ if (!(type & SLJIT_COMPARE_SELECT))+ type ^= 0x1;+ } else+ EMIT_MOV(compiler, dst_reg, 0, src2_reg, src2w);+ }++ if (type & SLJIT_COMPARE_SELECT) {+ if (dst_reg != TMP_REG1 && !FAST_IS_REG(src1)) {+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ src1 = TMP_REG1;+ src1w = 0;+ }++ type ^= 0x1;+ FAIL_IF(emit_cmp_binary(compiler, dst_reg, 0, src1, src1w));+ }++ type &= ~(SLJIT_32 | SLJIT_COMPARE_SELECT);++ if (sljit_has_cpu_feature(SLJIT_HAS_CMOV)) {+ if (SLJIT_UNLIKELY(src1 == SLJIT_IMM)) {+ if (dst_reg != TMP_REG1) {+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, src1w);+ src1 = TMP_REG1;+ src1w = 0;+ } else {+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, src1w);+ src1 = SLJIT_MEM1(SLJIT_SP);+ 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;+}++static sljit_s32 skip_frames_before_return(struct sljit_compiler *compiler)+{+ sljit_sw size;++ /* Don't adjust shadow stack if it isn't enabled. */+ if (!cpu_has_shadow_stack())+ return SLJIT_SUCCESS;++ SLJIT_ASSERT(compiler->args_size >= 0);+ SLJIT_ASSERT(compiler->local_size > 0);++ size = compiler->local_size;+ size += (1 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0)+ + (compiler->saveds <= 3 ? compiler->saveds : 3)) * SSIZE_OF(sw);++ return adjust_shadow_stack(compiler, SLJIT_MEM1(SLJIT_SP), size);+}
+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeX86_64.c view
@@ -0,0 +1,1430 @@+/*+ * 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.+ */++/* x86 64-bit arch dependent functions. */++/* --------------------------------------------------------------------- */+/* Operators */+/* --------------------------------------------------------------------- */++static sljit_s32 emit_load_imm64(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)+{+ sljit_u8 *inst;++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_sw));+ FAIL_IF(!inst);+ INC_SIZE(2 + sizeof(sljit_sw));+ 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;+}++static sljit_s32 emit_do_imm32(struct sljit_compiler *compiler, sljit_u8 rex, sljit_u8 opcode, sljit_sw imm)+{+ sljit_u8 *inst;+ sljit_uw length = (rex ? 2 : 1) + sizeof(sljit_s32);++ inst = (sljit_u8*)ensure_buf(compiler, 1 + length);+ FAIL_IF(!inst);+ INC_SIZE(length);+ if (rex)+ *inst++ = rex;+ *inst++ = opcode;+ sljit_unaligned_store_s32(inst, (sljit_s32)imm);+ return SLJIT_SUCCESS;+}++static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw size,+ /* The register or immediate operand. */+ sljit_s32 a, sljit_sw imma,+ /* The general operand (not immediate). */+ sljit_s32 b, sljit_sw immb)+{+ sljit_u8 *inst;+ sljit_u8 *buf_ptr;+ sljit_u8 rex = 0;+ sljit_u8 reg_lmap_b;+ sljit_uw flags = size;+ sljit_uw inst_size;++ /* The immediate operand must be 32 bit. */+ 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. */+ SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0);+ /* 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_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 (!compiler->mode32 && !(flags & EX86_NO_REXW))+ rex |= REX_W;+ else if (flags & EX86_REX)+ rex |= REX;++ if (flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66))+ inst_size++;++ /* Calculate size of b. */+ if (b & SLJIT_MEM) {+ 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 (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);+ }++ 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)) {+ if (reg_map[b] >= 8)+ rex |= REX_B;+ } else if (freg_map[b] >= 8)+ rex |= REX_B;++ 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 += sizeof(sljit_s8);+ flags |= EX86_BYTE_ARG;+ } else+ inst_size += sizeof(sljit_s32);+ } else if (flags & EX86_SHIFT_INS) {+ SLJIT_ASSERT(imma <= (compiler->mode32 ? 0x1f : 0x3f));+ if (imma != 1) {+ inst_size += sizeof(sljit_s8);+ flags |= EX86_BYTE_ARG;+ }+ } else if (flags & EX86_BYTE_ARG)+ inst_size += sizeof(sljit_s8);+ else if (flags & EX86_HALF_ARG)+ inst_size += sizeof(sljit_s16);+ else+ inst_size += sizeof(sljit_s32);+ } 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)) {+ if (reg_map[a] >= 8)+ rex |= REX_R;+ }+ else if (freg_map[a] >= 8)+ rex |= REX_R;+ }++ if (rex)+ inst_size++;++ inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size);+ PTR_FAIL_IF(!inst);++ /* Encoding prefixes. */+ 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;++ /* 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)+ *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_lmap[a] << 3);+ else+ *buf_ptr = U8(freg_lmap[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_lmap[b] : freg_lmap[b]));+ buf_ptr++;+ } 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)) {+ if (immb != 0 || reg_lmap_b == 5) {+ if (immb <= 127 && immb >= -128)+ *buf_ptr |= 0x40;+ else+ *buf_ptr |= 0x80;+ }++ if (!(b & OFFS_REG_MASK))+ *buf_ptr++ |= reg_lmap_b;+ else {+ 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) {+ if (immb <= 127 && immb >= -128)+ *buf_ptr++ = U8(immb); /* 8 bit displacement. */+ else {+ sljit_unaligned_store_s32(buf_ptr, (sljit_s32)immb); /* 32 bit displacement. */+ buf_ptr += sizeof(sljit_s32);+ }+ }+ } 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[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 (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_s32(buf_ptr, (sljit_s32)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);++ 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* 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_ADDR)) == JUMP_ADDR) && (jump->u.target <= 0xffffffff);++ /* The relative jump below specialized for this case. */+ SLJIT_ASSERT(reg_map[TMP_REG2] >= 8 && TMP_REG2 != SLJIT_TMP_DEST_REG);++ if (type < SLJIT_JUMP) {+ /* Invert type. */+ code_ptr[0] = U8(get_jump_code(type ^ 0x1) - 0x10);+ code_ptr[1] = short_addr ? (6 + 3) : (10 + 3);+ code_ptr += 2;+ }++ 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_ADDR))+ jump->flags |= PATCH_MD;+ else if (short_addr)+ sljit_unaligned_store_s32(code_ptr, (sljit_s32)jump->u.target);+ else+ sljit_unaligned_store_sw(code_ptr, (sljit_sw)jump->u.target);++ code_ptr += short_addr ? sizeof(sljit_s32) : sizeof(sljit_sw);++ 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 + 3;+}++static sljit_u8* generate_mov_addr_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_sw executable_offset)+{+ sljit_uw addr;+ sljit_sw diff;+ SLJIT_UNUSED_ARG(executable_offset);++ 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;++ if (addr > 0xffffffffl) {+ diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);++ 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;+ }++ jump->flags |= PATCH_MD;+ return code_ptr;+ }++ 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[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);+ }++ 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 local_size)+{+ sljit_uw size;+ sljit_s32 word_arg_count = 0;+ sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);+ sljit_s32 saved_regs_size, tmp, i;+#ifdef _WIN64+ sljit_s32 fscratches;+ sljit_s32 fsaveds;+ sljit_s32 saved_float_regs_size;+ sljit_s32 saved_float_regs_offset = 0;+ sljit_s32 float_arg_count = 0;+#endif /* _WIN64 */+ sljit_u8 *inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);++ scratches = ENTER_GET_REGS(scratches);+#ifdef _WIN64+ saveds = ENTER_GET_REGS(saveds);+ fscratches = compiler->fscratches;+ fsaveds = compiler->fsaveds;+#endif /* _WIN64 */++ 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 - saved_arg_count, 1);++ tmp = SLJIT_S0 - saveds;+ 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);+ INC_SIZE(size);+ if (reg_map[i] >= 8)+ *inst++ = REX_B;+ PUSH_REG(reg_lmap[i]);+ }++ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {+ size = reg_map[i] >= 8 ? 2 : 1;+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);+ INC_SIZE(size);+ if (reg_map[i] >= 8)+ *inst++ = REX_B;+ PUSH_REG(reg_lmap[i]);+ }++#ifdef _WIN64+ local_size += SLJIT_LOCALS_OFFSET;+ 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);+ local_size = saved_float_regs_offset + saved_float_regs_size;+ }+#else /* !_WIN64 */+ SLJIT_ASSERT(SLJIT_LOCALS_OFFSET == 0);+#endif /* _WIN64 */++ arg_types >>= SLJIT_ARG_SHIFT;++ while (arg_types > 0) {+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {+ tmp = 0;+#ifndef _WIN64+ switch (word_arg_count) {+ case 0:+ tmp = SLJIT_R2;+ break;+ case 1:+ tmp = SLJIT_R1;+ break;+ case 2:+ tmp = TMP_REG1;+ break;+ default:+ tmp = SLJIT_R3;+ break;+ }+#else /* !_WIN64 */+ switch (word_arg_count + float_arg_count) {+ case 0:+ tmp = SLJIT_R3;+ break;+ case 1:+ tmp = SLJIT_R1;+ break;+ case 2:+ tmp = SLJIT_R2;+ break;+ default:+ tmp = TMP_REG1;+ break;+ }+#endif /* _WIN64 */+ if (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) {+ if (tmp != SLJIT_R0 + word_arg_count)+ EMIT_MOV(compiler, SLJIT_R0 + word_arg_count, 0, tmp, 0);+ } else {+ EMIT_MOV(compiler, SLJIT_S0 - saved_arg_count, 0, tmp, 0);+ saved_arg_count++;+ }+ word_arg_count++;+ } else {+#ifdef _WIN64+ SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);+ float_arg_count++;+ if (float_arg_count != float_arg_count + word_arg_count)+ FAIL_IF(emit_sse2_load(compiler, (arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F32,+ float_arg_count, float_arg_count + word_arg_count, 0));+#endif /* _WIN64 */+ }+ arg_types >>= SLJIT_ARG_SHIFT;+ }++ local_size = ((local_size + saved_regs_size + 0xf) & ~0xf) - saved_regs_size;+ compiler->local_size = local_size;++#ifdef _WIN64+ if (local_size > 0) {+ if (local_size <= 4 * 4096) {+ if (local_size > 4096)+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096);+ if (local_size > 2 * 4096)+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 2);+ if (local_size > 3 * 4096)+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 3);+ }+ else {+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, local_size >> 12);++ EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_MEM1(SLJIT_SP), -4096);+ BINARY_IMM32(SUB, 4096, SLJIT_SP, 0);+ BINARY_IMM32(SUB, 1, TMP_REG1, 0);++ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);+ FAIL_IF(!inst);++ INC_SIZE(2);+ inst[0] = JNE_i8;+ inst[1] = (sljit_u8)-21;+ local_size &= 0xfff;+ }++ if (local_size > 0)+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -local_size);+ }+#endif /* _WIN64 */++ if (local_size > 0)+ BINARY_IMM32(SUB, local_size, SLJIT_SP, 0);++#ifdef _WIN64+ if (saved_float_regs_size > 0) {+ compiler->mode32 = 1;++ tmp = SLJIT_FS0 - fsaveds;+ for (i = SLJIT_FS0; i > tmp; i--) {+ 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--) {+ FAIL_IF(emit_groupf(compiler, MOVAPS_xm_x | EX86_SSE2, i, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset));+ saved_float_regs_offset += 16;+ }+ }+#endif /* _WIN64 */++ 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 local_size)+{+ sljit_s32 saved_regs_size;+#ifdef _WIN64+ sljit_s32 fscratches;+ sljit_s32 fsaveds;+ sljit_s32 saved_float_regs_size;+#endif /* _WIN64 */++ CHECK_ERROR();+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);++ scratches = ENTER_GET_REGS(scratches);++#ifdef _WIN64+ saveds = ENTER_GET_REGS(saveds);+ fscratches = compiler->fscratches;+ fsaveds = compiler->fsaveds;++ local_size += SLJIT_LOCALS_OFFSET;+ 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;+#else /* !_WIN64 */+ SLJIT_ASSERT(SLJIT_LOCALS_OFFSET == 0);+#endif /* _WIN64 */++ /* Including the return address saved by the call instruction. */+ 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, sljit_s32 is_return_to)+{+ sljit_uw size;+ sljit_s32 local_size, i, tmp;+ sljit_u8 *inst;+#ifdef _WIN64+ sljit_s32 saved_float_regs_offset;+ sljit_s32 fscratches = compiler->fscratches;+ sljit_s32 fsaveds = compiler->fsaveds;+#endif /* _WIN64 */++#ifdef _WIN64+ saved_float_regs_offset = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sse2_reg);++ if (saved_float_regs_offset > 0) {+ compiler->mode32 = 1;+ saved_float_regs_offset = (compiler->local_size - saved_float_regs_offset) & ~0xf;++ tmp = SLJIT_FS0 - fsaveds;+ for (i = SLJIT_FS0; i > tmp; i--) {+ 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--) {+ 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 */++ 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;+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);+ INC_SIZE(size);+ if (reg_map[i] >= 8)+ *inst++ = REX_B;+ POP_REG(reg_lmap[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);+ INC_SIZE(size);+ if (reg_map[i] >= 8)+ *inst++ = REX_B;+ 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)+{+ CHECK_ERROR();+ CHECK(check_sljit_emit_return_void(compiler));++ compiler->mode32 = 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)+{+ 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 */+/* --------------------------------------------------------------------- */++#ifndef _WIN64++static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src_ptr)+{+ sljit_s32 src = src_ptr ? (*src_ptr) : 0;+ sljit_s32 word_arg_count = 0;++ SLJIT_ASSERT(reg_map[SLJIT_R1] == 6 && reg_map[SLJIT_R3] == 1 && reg_map[TMP_REG1] == 2);+ SLJIT_ASSERT(!(src & SLJIT_MEM));++ /* Remove return value. */+ 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 == 0)+ return SLJIT_SUCCESS;++ if (word_arg_count >= 3 || src == SLJIT_R2) {+ if (src == SLJIT_R2)+ *src_ptr = TMP_REG1;+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R2, 0);+ }++ return emit_mov(compiler, SLJIT_R2, 0, SLJIT_R0, 0);+}++#else++static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src_ptr)+{+ sljit_s32 src = src_ptr ? (*src_ptr) : 0;+ sljit_s32 arg_count = 0;+ sljit_s32 word_arg_count = 0;+ sljit_s32 float_arg_count = 0;+ sljit_s32 types = 0;+ sljit_s32 data_trandfer = 0;+ static sljit_u8 word_arg_regs[5] = { 0, SLJIT_R3, SLJIT_R1, SLJIT_R2, TMP_REG1 };++ SLJIT_ASSERT(reg_map[SLJIT_R3] == 1 && reg_map[SLJIT_R1] == 2 && reg_map[SLJIT_R2] == 8 && reg_map[TMP_REG1] == 9);+ SLJIT_ASSERT(!(src & SLJIT_MEM));++ 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:+ case SLJIT_ARG_TYPE_F32:+ arg_count++;+ float_arg_count++;++ if (arg_count != float_arg_count)+ data_trandfer = 1;+ break;+ default:+ arg_count++;+ word_arg_count++;++ if (arg_count != word_arg_count || arg_count != word_arg_regs[arg_count]) {+ data_trandfer = 1;++ if (src == word_arg_regs[arg_count]) {+ EMIT_MOV(compiler, TMP_REG2, 0, src, 0);+ *src_ptr = TMP_REG2;+ }+ }+ break;+ }++ arg_types >>= SLJIT_ARG_SHIFT;+ }++ if (!data_trandfer)+ return SLJIT_SUCCESS;++ while (types) {+ switch (types & SLJIT_ARG_MASK) {+ case SLJIT_ARG_TYPE_F64:+ if (arg_count != float_arg_count)+ FAIL_IF(emit_sse2_load(compiler, 0, arg_count, float_arg_count, 0));+ arg_count--;+ float_arg_count--;+ break;+ case SLJIT_ARG_TYPE_F32:+ if (arg_count != float_arg_count)+ FAIL_IF(emit_sse2_load(compiler, 1, arg_count, float_arg_count, 0));+ arg_count--;+ float_arg_count--;+ break;+ default:+ if (arg_count != word_arg_count || arg_count != word_arg_regs[arg_count])+ EMIT_MOV(compiler, word_arg_regs[arg_count], 0, word_arg_count, 0);+ arg_count--;+ word_arg_count--;+ break;+ }++ 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)+{+ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));++ compiler->mode32 = 0;++ 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, 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_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));++ compiler->mode32 = 0;++ if (src & SLJIT_MEM) {+ ADJUST_LOCAL_OFFSET(src, srcw);+ EMIT_MOV(compiler, TMP_REG2, 0, src, srcw);+ src = TMP_REG2;+ }++ if (type & SLJIT_CALL_RETURN) {+ 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, 0));+ }++ if ((type & 0xff) != SLJIT_CALL_REG_ARG)+ FAIL_IF(call_with_args(compiler, arg_types, &src));++ if (type & SLJIT_CALL_RETURN)+ type = SLJIT_JUMP;++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_ijump(compiler, type, src, srcw);+}++static sljit_s32 emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)+{+ sljit_u8 *inst;++ if (FAST_IS_REG(dst)) {+ 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);+ INC_SIZE(2);+ *inst++ = REX_B;+ POP_REG(reg_lmap[dst]);+ return SLJIT_SUCCESS;+ }++ /* REX_W is not necessary (src is not immediate). */+ compiler->mode32 = 1;+ 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;++ if (FAST_IS_REG(src)) {+ if (reg_map[src] < 8) {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 1);+ FAIL_IF(!inst);++ INC_SIZE(1 + 1);+ PUSH_REG(reg_lmap[src]);+ }+ else {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2 + 1);+ FAIL_IF(!inst);++ INC_SIZE(2 + 1);+ *inst++ = REX_B;+ PUSH_REG(reg_lmap[src]);+ }+ }+ else {+ /* REX_W is not necessary (src is not immediate). */+ compiler->mode32 = 1;+ 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 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);+}++/* --------------------------------------------------------------------- */+/* 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_u8* inst;++ 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;++ if (type & SLJIT_COMPARE_SELECT) {+ if (!FAST_IS_REG(src1)) {+ EMIT_MOV(compiler, TMP_REG2, 0, src1, src1w);+ src1 = TMP_REG2;+ src1w = 0;+ }++ inst = emit_x86_instruction(compiler, 1, src1, 0, src2_reg, 0);+ FAIL_IF(!inst);+ *inst = CMP_r_rm;+ }++ type &= ~(SLJIT_32 | SLJIT_COMPARE_SELECT);++ 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)+{+ sljit_u8* inst;+ sljit_s32 dst_r;++ compiler->mode32 = 0;++ if (src == SLJIT_IMM) {+ if (FAST_IS_REG(dst)) {+ 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);+ FAIL_IF(!inst);+ *inst = MOV_rm_i32;+ compiler->mode32 = 0;+ return SLJIT_SUCCESS;+ }++ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;++ if ((dst & SLJIT_MEM) && FAST_IS_REG(src))+ dst_r = src;+ else {+ if (sign) {+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);+ FAIL_IF(!inst);+ *inst = MOVSXD_r_rm;+ } else {+ compiler->mode32 = 1;+ EMIT_MOV(compiler, dst_r, 0, src, srcw);+ compiler->mode32 = 0;+ }+ }++ if (dst & SLJIT_MEM) {+ compiler->mode32 = 1;+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);+ FAIL_IF(!inst);+ *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;+}++static sljit_s32 skip_frames_before_return(struct sljit_compiler *compiler)+{+ sljit_s32 tmp, size;++ /* Don't adjust shadow stack if it isn't enabled. */+ if (!cpu_has_shadow_stack())+ return SLJIT_SUCCESS;++ size = compiler->local_size;+ tmp = compiler->scratches;+ if (tmp >= SLJIT_FIRST_SAVED_REG)+ size += (tmp - SLJIT_FIRST_SAVED_REG + 1) * SSIZE_OF(sw);+ tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;+ if (SLJIT_S0 >= tmp)+ size += (SLJIT_S0 - tmp + 1) * SSIZE_OF(sw);++ return adjust_shadow_stack(compiler, SLJIT_MEM1(SLJIT_SP), size);+}
+ src/c/pcre2/deps/sljit/sljit_src/sljitNativeX86_common.c view
@@ -0,0 +1,5434 @@+/*+ * 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 "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 MOVDQU_x_xm 0x6f+#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>+#elif defined(__INTEL_COMPILER)+#include <cpuid.h>+#endif++#if (defined(_MSC_VER) && _MSC_VER >= 1400) || defined(__INTEL_COMPILER) \+ || (defined(__INTEL_LLVM_COMPILER) && defined(__XSAVE__))+#include <immintrin.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) \+ || (defined(__INTEL_COMPILER) && __INTEL_COMPILER == 2021 && __INTEL_COMPILER_UPDATE >= 7)++ __cpuidex((int*)info, (int)info[0], (int)info[2]);++#elif (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1900)++ __get_cpuid_count(info[0], info[2], info, info + 1, info + 2, info + 3);++#elif (defined(_MSC_VER) || defined(__INTEL_COMPILER)) \+ && (defined(SLJIT_CONFIG_X86_32) && SLJIT_CONFIG_X86_32)++ /* Intel syntax. */+ __asm {+ 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++ __asm__ __volatile__ (+ "cpuid\n"+ : "=a" (info[0]), "=b" (info[1]), "=c" (info[2]), "=d" (info[3])+ : "0" (info[0]), "2" (info[2])+ );++#endif+}++static sljit_u32 execute_get_xcr0_low(void)+{+ sljit_u32 xcr0;++#if (defined(_MSC_VER) && _MSC_VER >= 1400) || defined(__INTEL_COMPILER) \+ || (defined(__INTEL_LLVM_COMPILER) && defined(__XSAVE__))++ xcr0 = (sljit_u32)_xgetbv(0);++#elif defined(__TINYC__)++ __asm__ (+ "xorl %%ecx, %%ecx\n"+ ".byte 0x0f\n"+ ".byte 0x01\n"+ ".byte 0xd0\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 */+ );++#elif (defined(__INTEL_LLVM_COMPILER) && __INTEL_LLVM_COMPILER < 20220100) \+ || (defined(__clang__) && __clang_major__ < 14) \+ || (defined(__GNUC__) && __GNUC__ < 3) \+ || defined(__SUNPRO_C) || defined(__SUNPRO_CC)++ /* 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 */+ );++#elif defined(_MSC_VER)++ /* Intel syntax. */+ __asm {+ xor ecx, ecx+ xgetbv+ mov xcr0, eax+ }++#else++ __asm__ (+ "xor{l %%ecx, %%ecx | 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 */+ );++#endif+ 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;+#if defined(SLJIT_CONFIG_X86_32) && SLJIT_CONFIG_X86_32+ /* Winchip 2 and Cyrix MII bugs */+ info[1] = info[2] = 0;+#endif+ 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] = 0x80000000;+ execute_cpu_id(info);+ max_id = info[0];++ if (max_id >= 0x80000001) {+ 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;+ sljit_uw jump_addr;++ jump_addr = (sljit_uw)code_ptr;+ if (!(jump->flags & JUMP_ADDR)) {+ label_addr = (sljit_uw)(code + jump->u.label->size);++ if (jump->u.label->size > jump->addr)+ jump_addr = (sljit_uw)(code + jump->addr);+ } else+ label_addr = jump->u.target - (sljit_uw)executable_offset;++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if ((sljit_sw)(label_addr - (jump_addr + 6)) > HALFWORD_MAX || (sljit_sw)(label_addr - (jump_addr + 5)) < HALFWORD_MIN)+ return detect_far_jump_type(jump, code_ptr);+#endif /* SLJIT_CONFIG_X86_64 */++ short_jump = (sljit_sw)(label_addr - (jump_addr + 2)) >= -0x80 && (sljit_sw)(label_addr - (jump_addr + 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 sljit_u8 *process_extended_label(sljit_u8 *code_ptr, struct sljit_extended_label *ext_label)+{+ sljit_uw mask;+ sljit_u8 *ptr = code_ptr;++ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);+ mask = ext_label->data;++ code_ptr = (sljit_u8*)(((sljit_uw)code_ptr + mask) & ~mask);++ while (ptr < code_ptr)+ *ptr++ = NOP;++ return code_ptr;+}++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;++ jump->addr -= size_reduce;+ 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;+ if (jump->u.label->size > jump->addr) {+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);+ diff -= (sljit_sw)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 - 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, options));++ 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:+ if (label->u.index >= SLJIT_LABEL_ALIGNED)+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)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) & 0xff));+ 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;+ 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:+ case SLJIT_HAS_MEMORY_BARRIER:+ 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_MEMORY_BARRIER:+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 3);+ FAIL_IF(!inst);+ INC_SIZE(3);+ inst[0] = GROUP_0F;+ inst[1] = 0xae;+ inst[2] = 0xf0;+ return SLJIT_SUCCESS;+ 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_op2_shift(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_sw shift_arg)+{+ sljit_s32 dst_r;+ int use_lea = 0;+ sljit_u8* inst;++ CHECK_ERROR();+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));+ ADJUST_LOCAL_OFFSET(dst, dstw);+ ADJUST_LOCAL_OFFSET(src1, src1w);+ ADJUST_LOCAL_OFFSET(src2, src2w);++ shift_arg &= (sljit_sw)((sizeof(sljit_sw) * 8) - 1);++ if (src2 == SLJIT_IMM) {+ src2w = src2w << shift_arg;+ shift_arg = 0;+ }++ if (shift_arg == 0) {+ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, 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 = 0;+#endif++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (shift_arg <= 3) {+ use_lea = 1;+ if (!FAST_IS_REG(src2)) {+ EMIT_MOV(compiler, TMP_REG1, 0, src2, src2w);+ src2 = TMP_REG1;+ }++ if (!FAST_IS_REG(src1)) {+ EMIT_MOV(compiler, src2 == TMP_REG1 ? TMP_REG2 : TMP_REG1, 0, src1, src1w);+ src1 = src2 == TMP_REG1 ? TMP_REG2 : TMP_REG1;+ }+ }+#else /* !SLJIT_CONFIG_X86_64 */+ if (shift_arg <= 3 && (FAST_IS_REG(src1) || (FAST_IS_REG(src2) && src2 != TMP_REG1))) {+ use_lea = 1;+ if (!FAST_IS_REG(src2)) {+ EMIT_MOV(compiler, TMP_REG1, 0, src2, src2w);+ src2 = TMP_REG1;+ }++ if (!FAST_IS_REG(src1)) {+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);+ src1 = TMP_REG1;+ }+ }+#endif /* SLJIT_CONFIG_X86_64 */++ if (use_lea) {+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;++ inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM2(src1, src2), shift_arg);+ FAIL_IF(!inst);+ *inst = LEA_r_m;++ if (!FAST_IS_REG(dst))+ return emit_mov(compiler, dst, dstw, dst_r, 0);++ return SLJIT_SUCCESS;+ }++ if ((op & SLJIT_SRC2_UNDEFINED) != 0 && FAST_IS_REG(src2) && src1 != src2)+ dst_r = src2;+ else {+ dst_r = FAST_IS_REG(dst) && (dst != src1) ? dst : TMP_REG1;++ if (src2 != dst_r) {+ EMIT_MOV(compiler, dst_r, 0, src2, src2w);+ }+ }++ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, shift_arg, dst_r, 0);+ FAIL_IF(!inst);+ inst[1] |= SHL;++ if (dst == src1 && dstw == src1w) {+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);+ FAIL_IF(!inst);+ *inst = ADD_rm_r;+ return SLJIT_SUCCESS;+ }++ if (FAST_IS_REG(dst) && FAST_IS_REG(src1)) {+ inst = emit_x86_instruction(compiler, 1, dst, 0, SLJIT_MEM2(src1, dst_r), 0);+ FAIL_IF(!inst);+ *inst = LEA_r_m;+ return SLJIT_SUCCESS;+ }++ if (src1 == SLJIT_IMM) {+ BINARY_IMM(ADD, ADD_rm_r, src1w, dst_r, 0);+ } else {+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);+ FAIL_IF(!inst);+ *inst = ADD_r_rm;+ }++ if (dst != dst_r)+ return emit_mov(compiler, dst, dstw, dst_r, 0);++ 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_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)+{+ sljit_uw mask, size;+ sljit_u8 *inst;+ struct sljit_label *label;+ struct sljit_label *next_label;+ struct sljit_extended_label *ext_label;++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));++ sljit_reset_read_only_buffers(buffers);++ if (alignment <= SLJIT_LABEL_ALIGN_1) {+ SLJIT_SKIP_CHECKS(compiler);+ label = sljit_emit_label(compiler);+ PTR_FAIL_IF(!label);+ } else {+ /* The used space is filled with NOPs. */+ mask = ((sljit_uw)1 << alignment) - 1;+ compiler->size += mask;++ inst = (sljit_u8*)ensure_buf(compiler, 1);+ PTR_FAIL_IF(!inst);+ inst[0] = SLJIT_INST_LABEL;++ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));+ PTR_FAIL_IF(!ext_label);+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);+ label = &ext_label->label;+ }++ if (buffers == NULL)+ return label;++ next_label = label;++ while (1) {+ buffers->u.label = next_label;+ size = buffers->size;++ while (size >= 4) {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);+ PTR_FAIL_IF(!inst);+ INC_SIZE(4);+ inst[0] = NOP;+ inst[1] = NOP;+ inst[2] = NOP;+ inst[3] = NOP;+ size -= 4;+ }++ if (size > 0) {+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ PTR_FAIL_IF(!inst);+ INC_SIZE(size);++ do {+ *inst++ = NOP;+ } while (--size != 0);+ }++ buffers = buffers->next;++ if (buffers == NULL)+ break;++ SLJIT_SKIP_CHECKS(compiler);+ next_label = sljit_emit_label(compiler);+ PTR_FAIL_IF(!next_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;+ sljit_uw size;+#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)) {+ size = 3 + 2;+ if (reg_map[TMP_REG1] >= 4)+ size += 1 + 1;+ else if (reg_map[dst] >= 4)+ size++;++ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);+ INC_SIZE(size);+ /* Set low register to conditional flag. */+ if (reg_map[TMP_REG1] >= 4)+ *inst++ = (reg_map[TMP_REG1] <= 7) ? REX : REX_B;++ inst[0] = GROUP_0F;+ inst[1] = cond_set;+ inst[2] = MOD_REG | reg_lmap[TMP_REG1];+ inst += 3;++ if (reg_map[TMP_REG1] >= 4 || reg_map[dst] >= 4)+ *inst++ = U8(REX | (reg_map[TMP_REG1] <= 7 ? 0 : REX_R) | (reg_map[dst] <= 7 ? 0 : REX_B));++ inst[0] = OR_rm8_r8;+ inst[1] = 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;++ size = 3 + (reg_map[reg] >= 4) + 4;+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);+ FAIL_IF(!inst);+ INC_SIZE(size);+ /* Set low register to conditional flag. */++ if (reg_map[reg] >= 4)+ *inst++ = (reg_map[reg] <= 7) ? REX : REX_B;++ inst[0] = GROUP_0F;+ inst[1] = cond_set;+ inst[2] = MOD_REG | reg_lmap[reg];++ inst[3] = REX_W | (reg_map[reg] <= 7 ? 0 : (REX_B | REX_R));+ /* The movzx instruction does not affect flags. */+ inst[4] = GROUP_0F;+ inst[5] = MOVZX_r_rm8;+ inst[6] = 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 vreg,+ 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, vreg, 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, vreg, 0, srcdst, srcdstw);++ return emit_groupf(compiler, op, vreg, srcdst, srcdstw);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg,+ 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, vreg, 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, vreg, 0, src, srcw));+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 1;+#endif /* SLJIT_CONFIG_X86_64 */+ src = vreg;+ srcw = 0;+ }++ if (reg_size == 5)+ op |= VEX_256;++ return emit_vex_instruction(compiler, op, vreg, 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, vreg, vreg, vreg, 0);++ return emit_groupf(compiler, XORPD_x_xm | (elem_size == 3 ? EX86_PREF_66 : 0) | EX86_SSE2, vreg, vreg, 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, vreg, 0, src, srcw);++ SLJIT_ASSERT(!(src & SLJIT_MEM));+ FAIL_IF(emit_vex_instruction(compiler, SHUFPS_x_xm | EX86_SSE2 | VEX_SSE2_OPV, vreg, src, src, 0));+ return emit_byte(compiler, 0);+ }++ if (elem_size == 2 && vreg != src) {+ FAIL_IF(emit_sse2_load(compiler, 1, vreg, src, srcw));+ src = vreg;+ 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, vreg, 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, vreg, vreg, vreg, 0);++ return emit_groupf(compiler, (srcw == 0 ? PXOR_x_xm : PCMPEQD_x_xm) | EX86_PREF_66 | EX86_SSE2, vreg, vreg, 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, vreg, vreg, src, srcw));+ } else+ FAIL_IF(emit_vex_instruction(compiler, MOVD_x_rm | VEX_AUTO_W | EX86_PREF_66 | EX86_SSE2_OP1, vreg, 0, src, srcw));+ } else {+ inst = emit_x86_instruction(compiler, op | EX86_PREF_66 | EX86_SSE2_OP1, vreg, 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 ((cpu_feature_list & CPU_FEATURE_AVX2) && 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, vreg, 0, vreg, 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, vreg, vreg, 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, vreg, TMP_FREG, 0);+ case 1:+ if (use_vex)+ FAIL_IF(emit_vex_instruction(compiler, PSHUFLW_x_xm | EX86_PREF_F2 | EX86_SSE2, vreg, 0, vreg, 0));+ else+ FAIL_IF(emit_groupf(compiler, PSHUFLW_x_xm | EX86_PREF_F2 | EX86_SSE2, vreg, vreg, 0));+ FAIL_IF(emit_byte(compiler, 0));+ SLJIT_FALLTHROUGH+ default:+ if (use_vex)+ FAIL_IF(emit_vex_instruction(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, vreg, 0, vreg, 0));+ else+ FAIL_IF(emit_groupf(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, vreg, vreg, 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, vreg, 0, vreg, 0));+ else+ FAIL_IF(emit_groupf(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, vreg, vreg, 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 vreg, 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 vreg_orig = vreg;+#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, vreg, 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, vreg, 0, srcdst, srcdstw);+ return emit_groupf(compiler, MOVD_x_rm | EX86_PREF_66 | EX86_SSE2_OP1, vreg, 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, vreg, 0, srcdst, srcdstw);+ return emit_groupf(compiler, MOVSD_x_xm | (elem_size == 2 ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, vreg, srcdst, srcdstw);+ } else if (elem_size == 3) {+ if (use_vex)+ return emit_vex_instruction(compiler, MOVQ_x_xm | EX86_PREF_F3 | EX86_SSE2, vreg, 0, srcdst, 0);+ return emit_groupf(compiler, MOVQ_x_xm | EX86_PREF_F3 | EX86_SSE2, vreg, 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, vreg, TMP_FREG, srcdst, 0);+ }+ }++ if (reg_size == 5 && lane_index >= (1 << (4 - elem_size))) {+ vreg = TMP_FREG;+ lane_index -= (1 << (4 - elem_size));+ } else if ((type & SLJIT_SIMD_FLOAT) && vreg == 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, vreg, vreg, vreg, 0));+ else+ FAIL_IF(emit_groupf(compiler, op, vreg, vreg, 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, vreg, 0, TMP_FREG, 0));+ FAIL_IF(emit_byte(compiler, 1));++ vreg = 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 || vreg == TMP_FREG))+ FAIL_IF(emit_vex_instruction(compiler, op | EX86_PREF_66 | EX86_SSE2+ | ((type & SLJIT_SIMD_STORE) ? 0 : VEX_SSE2_OPV), vreg, (type & SLJIT_SIMD_STORE) ? 0 : vreg, srcdst, srcdstw));+ else+ FAIL_IF(emit_groupf(compiler, op | EX86_PREF_66 | EX86_SSE2, vreg, srcdst, srcdstw));++ /* In case of store, vreg 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, vreg, 0);+ return emit_groupf(compiler, MOVHLPS_x_x | EX86_SSE2, srcdst, vreg, 0);+ }+ if (use_vex)+ return emit_vex_instruction(compiler, MOVSD_x_xm | EX86_PREF_F2 | EX86_SSE2 | VEX_SSE2_OPV, srcdst, srcdst, vreg, 0);+ return emit_sse2_load(compiler, 0, srcdst, vreg, 0);+ } else if (use_vex && (reg_size == 4 || vreg == TMP_FREG)) {+ if (lane_index == 1)+ FAIL_IF(emit_vex_instruction(compiler, MOVLHPS_x_x | EX86_SSE2 | VEX_SSE2_OPV, vreg, vreg, srcdst, 0));+ else+ FAIL_IF(emit_vex_instruction(compiler, MOVSD_x_xm | EX86_PREF_F2 | EX86_SSE2 | VEX_SSE2_OPV, vreg, vreg, srcdst, 0));+ } else {+ if (lane_index == 1)+ FAIL_IF(emit_groupf(compiler, MOVLHPS_x_x | EX86_SSE2, vreg, srcdst, 0));+ else+ FAIL_IF(emit_sse2_load(compiler, 0, vreg, srcdst, 0));+ }+ } else if (type & SLJIT_SIMD_STORE) {+ if (lane_index == 0) {+ if (use_vex)+ return emit_vex_instruction(compiler, MOVSD_xm_x | EX86_PREF_F3 | EX86_SSE2 | ((srcdst & SLJIT_MEM) ? 0 : VEX_SSE2_OPV),+ vreg, ((srcdst & SLJIT_MEM) ? 0 : srcdst), srcdst, srcdstw);+ return emit_sse2_store(compiler, 1, srcdst, srcdstw, vreg);+ }++ if (srcdst & SLJIT_MEM) {+ if (use_vex)+ FAIL_IF(emit_vex_instruction(compiler, EXTRACTPS_x_xm | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, vreg, 0, srcdst, srcdstw));+ else+ FAIL_IF(emit_groupf_ext(compiler, EXTRACTPS_x_xm | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, vreg, 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, vreg, vreg, 0));+ return emit_byte(compiler, U8(lane_index));+ }++ if (srcdst == vreg)+ 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, vreg, 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, vreg, srcdst, srcdstw));+ FAIL_IF(emit_byte(compiler, U8(lane_index << 4)));+ } else+ FAIL_IF(emit_sse2_store(compiler, 1, vreg, 0, srcdst));+ }++ if (vreg != 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, vreg_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, vreg_orig, vreg_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, vreg, 0, srcdst, srcdstw));+ } else {+ inst = emit_x86_instruction(compiler, op | EX86_PREF_66 | EX86_SSE2_OP1, vreg, 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 (vreg == 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, vreg_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, vreg_orig, vreg_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 vreg,+ 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, vreg, 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, vreg, 0, src, 0);++ FAIL_IF(emit_vex_instruction(compiler, VPERMPD_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, vreg, 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, vreg, 0, src, 0);+ return emit_groupf(compiler, MOVDDUP_x_xm | EX86_PREF_F2 | EX86_SSE2, vreg, 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, vreg, 0, src, 0);++ FAIL_IF(emit_vex_instruction(compiler, VPERMPD_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, vreg, 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, vreg, vreg, vreg, 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, vreg, src, src, 0));+ } else {+ if (vreg != src)+ FAIL_IF(emit_groupf(compiler, MOVAPS_x_xm | pref | EX86_SSE2, vreg, src, 0));++ FAIL_IF(emit_groupf(compiler, SHUFPS_x_xm | pref | EX86_SSE2, vreg, vreg, 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, vreg, 0, src, 0));+ FAIL_IF(emit_byte(compiler, src_lane_index >= 24 ? 0xff : 0xaa));+ src_lane_index &= 0x7;+ src = vreg;+ }++ if (src_lane_index != 0 || (vreg != 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 (vreg != src)+ FAIL_IF(emit_groupf(compiler, MOVDQA_x_xm | EX86_PREF_66 | EX86_SSE2, vreg, src, 0));++ FAIL_IF(emit_groupf(compiler, PSRLDQ_x | EX86_PREF_66 | EX86_SSE2_OP2, opcode3, vreg, 0));+ } else+ FAIL_IF(emit_vex_instruction(compiler, PSRLDQ_x | EX86_PREF_66 | EX86_SSE2_OP2 | VEX_SSE2_OPV, opcode3, vreg, 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, vreg, 0, src, 0));+ else+ FAIL_IF(emit_groupf(compiler, PSHUFLW_x_xm | pref | EX86_SSE2, vreg, src, 0));+ FAIL_IF(emit_byte(compiler, byte));+ }++ src = vreg;+ }++ 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, vreg, 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, vreg, 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, vreg, 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, vreg, 0, src, 0));+ return emit_byte(compiler, U8(src_lane_index == 0 ? 0x44 : 0xee));+ }++ if (pref != 0) {+ FAIL_IF(emit_vex_instruction(compiler, pref, vreg, 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, vreg, 0, vreg, 0);++ src = vreg;+ }++ FAIL_IF(emit_vex_instruction(compiler, VPERMQ_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, vreg, 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, vreg, 0, src, 0));+ else+ FAIL_IF(emit_groupf(compiler, PSHUFLW_x_xm | pref | EX86_SSE2, vreg, 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, vreg, 0, vreg, 0);++ src = vreg;+ SLJIT_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, vreg, 0, src, 0));+ else+ FAIL_IF(emit_groupf(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, vreg, 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 vreg,+ 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, vreg, 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, vreg, 0, src, srcw);+ return emit_groupf(compiler, CVTPS2PD_x_xm | EX86_SSE2, vreg, 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, vreg, 0, src, srcw);+ return emit_groupf_ext(compiler, opcode | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, src, srcw);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 vreg,+ 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, vreg, 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, vreg, vreg, 0));+ else+ FAIL_IF(emit_groupf(compiler, PACKSSWB_x_xm | EX86_PREF_66 | EX86_SSE2, TMP_FREG, vreg, 0));+ vreg = 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, vreg, 0));+ else+ FAIL_IF(emit_groupf(compiler, op, dst_r, vreg, 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, vreg, 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, vreg, 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, vreg, 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_vreg, sljit_s32 src_vreg)+{+ 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_vreg, src_vreg, 0);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,+ sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w)+{+ 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 op = 0;+ sljit_uw mov_op = 0;++ CHECK_ERROR();+ CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w));+ ADJUST_LOCAL_OFFSET(src2, src2w);++#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;++ case SLJIT_SIMD_OP2_SHUFFLE:+ if (reg_size != 4)+ return SLJIT_ERR_UNSUPPORTED;++ op = PSHUFB_x_xm | EX86_PREF_66 | VEX_OP_0F38;+ break;+ }++ if (type & SLJIT_SIMD_TEST)+ return SLJIT_SUCCESS;++ if ((src2 & SLJIT_MEM) && SLJIT_SIMD_GET_ELEM2_SIZE(type) < reg_size) {+ mov_op = ((type & SLJIT_SIMD_FLOAT) ? (MOVUPS_x_xm | (elem_size == 3 ? EX86_PREF_66 : 0)) : (MOVDQU_x_xm | EX86_PREF_F3)) | EX86_SSE2;+ if (use_vex)+ FAIL_IF(emit_vex_instruction(compiler, mov_op, TMP_FREG, 0, src2, src2w));+ else+ FAIL_IF(emit_groupf(compiler, mov_op, TMP_FREG, src2, src2w));++ src2 = TMP_FREG;+ src2w = 0;+ }++ if (reg_size == 5 || use_vex) {+ if (reg_size == 5)+ op |= VEX_256;++ return emit_vex_instruction(compiler, op | EX86_SSE2 | VEX_SSE2_OPV, dst_vreg, src1_vreg, src2, src2w);+ }++ if (dst_vreg != src1_vreg) {+ if (dst_vreg == src2) {+ if (SLJIT_SIMD_GET_OPCODE(type) == SLJIT_SIMD_OP2_SHUFFLE) {+ FAIL_IF(emit_simd_mov(compiler, type, TMP_FREG, src2));+ FAIL_IF(emit_simd_mov(compiler, type, dst_vreg, src1_vreg));+ src2 = TMP_FREG;+ src2w = 0;+ } else+ src2 = src1_vreg;+ } else+ FAIL_IF(emit_simd_mov(compiler, type, dst_vreg, src1_vreg));+ }++ if (op & (VEX_OP_0F38 | VEX_OP_0F3A))+ return emit_groupf_ext(compiler, op | EX86_SSE2, dst_vreg, src2, src2w);+ return emit_groupf(compiler, op | EX86_SSE2, dst_vreg, src2, src2w);+}++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));++ if ((op & SLJIT_ATOMIC_USE_LS) || GET_OPCODE(op) == SLJIT_MOV_S8 || GET_OPCODE(op) == SLJIT_MOV_S16 || GET_OPCODE(op) == SLJIT_MOV_S32)+ return SLJIT_ERR_UNSUPPORTED;++ if (op & SLJIT_ATOMIC_TEST)+ return SLJIT_SUCCESS;++ SLJIT_SKIP_CHECKS(compiler);+ return sljit_emit_op1(compiler, op & ~SLJIT_ATOMIC_USE_CAS, 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;+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ sljit_s32 saved_reg = TMP_REG1;+ sljit_s32 swap_tmp = 0;+ 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));++ if ((op & SLJIT_ATOMIC_USE_LS) || GET_OPCODE(op) == SLJIT_MOV_S8 || GET_OPCODE(op) == SLJIT_MOV_S16 || GET_OPCODE(op) == SLJIT_MOV_S32)+ return SLJIT_ERR_UNSUPPORTED;++ if (op & SLJIT_ATOMIC_TEST)+ return SLJIT_SUCCESS;++ op = GET_OPCODE(op);++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if (temp_reg == SLJIT_TMP_DEST_REG) {+ FAIL_IF(emit_byte(compiler, XCHG_EAX_r | reg_map[TMP_REG1]));++ if (src_reg == SLJIT_R0)+ src_reg = TMP_REG1;+ if (mem_reg == SLJIT_R0)+ mem_reg = TMP_REG1;++ temp_reg = SLJIT_R0;+ swap_tmp = 1;+ }++ /* Src is virtual register or its low byte is not accessible. */+ if ((src_reg & SLJIT_MEM) || (op == SLJIT_MOV_U8 && reg_map[src_reg] >= 4)) {+ SLJIT_ASSERT(src_reg != SLJIT_R1 && temp_reg != SLJIT_TMP_DEST_REG);++ if (swap_tmp) {+ saved_reg = (mem_reg != SLJIT_R1) ? SLJIT_R1 : SLJIT_R2;++ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, saved_reg, 0);+ EMIT_MOV(compiler, saved_reg, 0, src_reg, srcw);+ } else+ EMIT_MOV(compiler, TMP_REG1, 0, src_reg, srcw);++ src_reg = saved_reg;++ if (mem_reg == src_reg)+ mem_reg = saved_reg;+ }+#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, TMP_REG2, 0, SLJIT_R0, 0);+ EMIT_MOV(compiler, SLJIT_R0, 0, temp_reg, 0);++ if (src_reg == SLJIT_R0)+ src_reg = TMP_REG2;+ if (mem_reg == SLJIT_R0)+ mem_reg = TMP_REG2;+#else /* !SLJIT_CONFIG_X86_64 */+ SLJIT_ASSERT(!swap_tmp);++ if (src_reg == TMP_REG1) {+ if (mem_reg == SLJIT_R0) {+ 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;+ saved_reg = SLJIT_R1;+ } else {+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R0, 0);+ EMIT_MOV(compiler, SLJIT_R0, 0, temp_reg, tempw);+ saved_reg = SLJIT_R0;+ }+ } else {+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R0, 0);+ EMIT_MOV(compiler, SLJIT_R0, 0, temp_reg, tempw);++ if (src_reg == SLJIT_R0)+ src_reg = TMP_REG1;+ if (mem_reg == SLJIT_R0)+ mem_reg = TMP_REG1;+ }+#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 (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if (swap_tmp) {+ SLJIT_ASSERT(temp_reg == SLJIT_R0);+ FAIL_IF(emit_byte(compiler, XCHG_EAX_r | reg_map[TMP_REG1]));++ if (saved_reg != TMP_REG1)+ return emit_mov(compiler, saved_reg, 0, SLJIT_MEM1(SLJIT_SP), 0);+ return SLJIT_SUCCESS;+ }+#endif /* SLJIT_CONFIG_X86_32 */++ 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_REG2, 0);+#else /* !SLJIT_CONFIG_X86_64 */+ EMIT_MOV(compiler, SLJIT_R0, 0, (saved_reg == SLJIT_R0) ? SLJIT_MEM1(SLJIT_SP) : saved_reg, 0);+ if (saved_reg == SLJIT_R1)+ return emit_mov(compiler, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_SP), 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);+ ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);++ CHECK_EXTRA_REGS(dst, dstw, (void)0);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = 0;+#endif++#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 op,+ sljit_s32 dst, sljit_sw dstw,+ sljit_sw init_value)+{+ sljit_u8 *inst;+ struct sljit_const *const_;+ sljit_s32 reg;+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ sljit_s32 dst_is_ereg = 0;+#endif /* !SLJIT_CONFIG_X86_32 */++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_const(compiler, op, dst, dstw, init_value));+ ADJUST_LOCAL_OFFSET(dst, dstw);++ CHECK_EXTRA_REGS(dst, dstw, dst_is_ereg = 1);++ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));+ PTR_FAIL_IF(!const_);+ set_const(const_, compiler);++ switch (GET_OPCODE(op)) {+ case SLJIT_MOV_U8:+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = (op & SLJIT_32);+#endif /* SLJIT_CONFIG_X86_64 */++ if ((init_value & 0x100) != 0)+ init_value = init_value | -(sljit_sw)0x100;+ else+ init_value = (sljit_u8)init_value;++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if (dst_is_ereg) {+ if (emit_mov(compiler, dst, dstw, SLJIT_IMM, (sljit_s32)init_value))+ return NULL;+ dst = 0;+ break;+ }+#endif /* !SLJIT_CONFIG_X86_32 */++ reg = FAST_IS_REG(dst) ? dst : TMP_REG1;++ if (emit_mov(compiler, reg, 0, SLJIT_IMM, init_value))+ return NULL;+ break;+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ case SLJIT_MOV:+ compiler->mode32 = 0;+ reg = FAST_IS_REG(dst) ? dst : TMP_REG1;++ if (emit_load_imm64(compiler, reg, init_value))+ return NULL;+ break;+#endif /* SLJIT_CONFIG_X86_64 */+ default:+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ compiler->mode32 = (op == SLJIT_MOV32);+#endif /* SLJIT_CONFIG_X86_64 */++ if (emit_mov(compiler, dst, dstw, SLJIT_IMM, (sljit_s32)init_value))+ return NULL;+ dst = 0;+ break;+ }++ inst = (sljit_u8*)ensure_buf(compiler, 1);+ PTR_FAIL_IF(!inst);++ inst[0] = SLJIT_INST_CONST;++ if (dst & SLJIT_MEM) {+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (op == SLJIT_MOV) {+ if (emit_mov(compiler, dst, dstw, TMP_REG1, 0))+ return NULL;+ return const_;+ }+#endif++ if (emit_mov_byte(compiler, 0, dst, dstw, TMP_REG1, 0))+ return NULL;+ }++ return const_;+}++SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,+ 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 */+ SLJIT_UNUSED_ARG(op);++ CHECK_ERROR_PTR();+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, 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;+ if (dst & SLJIT_MEM)+ reg = TMP_REG1;+ else+ reg = (op != SLJIT_ADD_ABS_ADDR) ? dst : TMP_REG2;++ 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 */+ if (op == SLJIT_ADD_ABS_ADDR) {+ if (dst != SLJIT_R0) {+ /* Must not be a signed byte argument. */+ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 0x100, dst, dstw);+ PTR_FAIL_IF(!inst);+ *(inst + 1) |= ADD;+ } else+ PTR_FAIL_IF(emit_do_imm(compiler, ADD_EAX_i32, 0));+ } else {+ 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 (op == SLJIT_ADD_ABS_ADDR) {+ inst = emit_x86_instruction(compiler, 1, reg, 0, dst, dstw);+ PTR_FAIL_IF(!inst);+ *inst = ADD_rm_r;+ } else 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)+{+ SLJIT_UNUSED_ARG(executable_offset);++ SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + sizeof(sljit_uw)), 0);+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ sljit_unaligned_store_sw((void*)addr, (sljit_sw)(new_target - (addr + 4) - (sljit_uw)executable_offset));+#else+ sljit_unaligned_store_sw((void*)addr, (sljit_sw)new_target);+#endif+ SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + sizeof(sljit_uw)), 1);+}++SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)+{+ void *start_addr;+ SLJIT_UNUSED_ARG(executable_offset);++#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ if (op == SLJIT_MOV) {+ start_addr = (void*)(addr - sizeof(sljit_sw));+ SLJIT_UPDATE_WX_FLAGS(start_addr, (void*)addr, 0);+ sljit_unaligned_store_sw(start_addr, new_constant);+ SLJIT_UPDATE_WX_FLAGS(start_addr, (void*)addr, 1);+ return;+ }+#endif++ start_addr = (void*)(addr - sizeof(sljit_s32));++ if ((op | SLJIT_32) == SLJIT_MOV32_U8) {+ if ((new_constant & 0x100) != 0)+ new_constant = new_constant | -(sljit_sw)0x100;+ else+ new_constant = (sljit_u8)new_constant;+ }++ SLJIT_UPDATE_WX_FLAGS(start_addr, (void*)addr, 0);+ sljit_unaligned_store_s32(start_addr, (sljit_s32)new_constant);+ SLJIT_UPDATE_WX_FLAGS(start_addr, (void*)addr, 1);+}
+ src/c/pcre2/deps/sljit/sljit_src/sljitSerialize.c view
@@ -0,0 +1,585 @@+/*+ * 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_GET_LABEL_INDEX(label) \+ ((label)->u.index < SLJIT_LABEL_ALIGNED ? (label)->u.index : ((struct sljit_extended_label*)(label))->index)++SLJIT_API_FUNC_ATTRIBUTE sljit_uw sljit_get_label_index(struct sljit_label *label)+{+ return SLJIT_GET_LABEL_INDEX(label);+}++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 aligned_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_aligned_label {+ sljit_uw size;+ sljit_uw data;+};++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_aligned_label *serialized_aligned_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;+ }++ label = compiler->labels;+ while (label != NULL) {+ used_size = sizeof(struct sljit_serialized_label);++ if (label->u.index >= SLJIT_LABEL_ALIGNED)+ used_size += sizeof(struct sljit_serialized_aligned_label);++ serialized_size += used_size;+ label = label->next;+ }++ 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;+ counter = 0;+ while (label != NULL) {+ serialized_label = (struct sljit_serialized_label*)ptr;+ serialized_label->size = (label->u.index < SLJIT_LABEL_ALIGNED) ? label->size : label->u.index;+ ptr += sizeof(struct sljit_serialized_label);++ if (label->u.index >= SLJIT_LABEL_ALIGNED) {+ serialized_aligned_label = (struct sljit_serialized_aligned_label*)ptr;+ serialized_aligned_label->size = label->size;+ serialized_aligned_label->data = ((struct sljit_extended_label*)label)->data;+ ptr += sizeof(struct sljit_serialized_aligned_label);+ counter++;+ }++ label = label->next;+ }+ serialized_compiler->aligned_label_count = counter;++ 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 = SLJIT_GET_LABEL_INDEX(jump->u.label);+ 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_aligned_label *serialized_aligned_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_label **label_list_ptr = 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, type, used_size, aligned_size;+ sljit_uw label_count, aligned_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;+ aligned_label_count = serialized_compiler->aligned_label_count;+ i = (label_count * sizeof(struct sljit_serialized_label)) + (aligned_label_count * sizeof(struct sljit_serialized_aligned_label));++ if ((sljit_uw)(end - ptr) < i)+ goto error;++ label_list = (struct sljit_label **)SLJIT_MALLOC(label_count * sizeof(struct sljit_label*), allocator_data);+ if (label_list == NULL)+ goto error;++ label_list_ptr = label_list;+ for (i = 0; i < label_count; i++) {+ serialized_label = (struct sljit_serialized_label*)ptr;+ type = serialized_label->size;++ if (type < SLJIT_LABEL_ALIGNED) {+ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));+ } else {+ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));+ }++ if (label == NULL)+ goto error;++ label->next = NULL;++ if (last_label != NULL)+ last_label->next = label;+ else+ compiler->labels = label;+ last_label = label;++ *label_list_ptr++ = label;++ ptr += sizeof(struct sljit_serialized_label);++ if (type < SLJIT_LABEL_ALIGNED) {+ label->u.index = i;+ label->size = type;+ } else {+ if (aligned_label_count == 0)+ goto error;++ aligned_label_count--;++ serialized_aligned_label = (struct sljit_serialized_aligned_label*)ptr;+ label->u.index = type;+ label->size = serialized_aligned_label->size;++ ((struct sljit_extended_label*)label)->index = i;+ ((struct sljit_extended_label*)label)->data = serialized_aligned_label->data;+ ptr += sizeof(struct sljit_serialized_aligned_label);+ }+ }+ compiler->last_label = last_label;++ if (aligned_label_count != 0)+ goto error;++ 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/deps/sljit/sljit_src/sljitUtils.c view
@@ -0,0 +1,344 @@+/*+ * 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.+ */++/* ------------------------------------------------------------------------ */+/* Locks */+/* ------------------------------------------------------------------------ */++/* Executable Allocator */++#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) \+ && !(defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR)+#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)+#define SLJIT_ALLOCATOR_LOCK()+#define SLJIT_ALLOCATOR_UNLOCK()+#elif !(defined _WIN32)+#include <pthread.h>++static pthread_mutex_t allocator_lock = PTHREAD_MUTEX_INITIALIZER;++#define SLJIT_ALLOCATOR_LOCK() pthread_mutex_lock(&allocator_lock)+#define SLJIT_ALLOCATOR_UNLOCK() pthread_mutex_unlock(&allocator_lock)+#else /* windows */+static HANDLE allocator_lock;++static SLJIT_INLINE void allocator_grab_lock(void)+{+ HANDLE lock;+ if (SLJIT_UNLIKELY(!InterlockedCompareExchangePointer(&allocator_lock, NULL, NULL))) {+ lock = CreateMutex(NULL, FALSE, NULL);+ if (InterlockedCompareExchangePointer(&allocator_lock, lock, NULL))+ CloseHandle(lock);+ }+ WaitForSingleObject(allocator_lock, INFINITE);+}++#define SLJIT_ALLOCATOR_LOCK() allocator_grab_lock()+#define SLJIT_ALLOCATOR_UNLOCK() ReleaseMutex(allocator_lock)+#endif /* thread implementation */+#endif /* SLJIT_EXECUTABLE_ALLOCATOR && !SLJIT_WX_EXECUTABLE_ALLOCATOR */++/* ------------------------------------------------------------------------ */+/* Stack */+/* ------------------------------------------------------------------------ */++#if ((defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) \+ && !(defined SLJIT_UTIL_SIMPLE_STACK_ALLOCATION && SLJIT_UTIL_SIMPLE_STACK_ALLOCATION)) \+ || ((defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) \+ && !((defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR) \+ || (defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR)))++#ifndef _WIN32+/* Provides mmap function. */+#include <sys/types.h>+#include <sys/mman.h>++#ifndef MAP_ANON+#ifdef MAP_ANONYMOUS+#define MAP_ANON MAP_ANONYMOUS+#endif /* MAP_ANONYMOUS */+#endif /* !MAP_ANON */++#ifndef MAP_ANON++#include <fcntl.h>++#ifdef O_CLOEXEC+#define SLJIT_CLOEXEC O_CLOEXEC+#else /* !O_CLOEXEC */+#define SLJIT_CLOEXEC 0+#endif /* O_CLOEXEC */++/* Some old systems do not have MAP_ANON. */+static int dev_zero = -1;++#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)++static SLJIT_INLINE int open_dev_zero(void)+{+ dev_zero = open("/dev/zero", O_RDWR | SLJIT_CLOEXEC);++ return dev_zero < 0;+}++#else /* !SLJIT_SINGLE_THREADED */++#include <pthread.h>++static pthread_mutex_t dev_zero_mutex = PTHREAD_MUTEX_INITIALIZER;++static SLJIT_INLINE int open_dev_zero(void)+{+ pthread_mutex_lock(&dev_zero_mutex);+ if (SLJIT_UNLIKELY(dev_zero < 0))+ dev_zero = open("/dev/zero", O_RDWR | SLJIT_CLOEXEC);++ pthread_mutex_unlock(&dev_zero_mutex);+ return dev_zero < 0;+}++#endif /* SLJIT_SINGLE_THREADED */+#undef SLJIT_CLOEXEC+#endif /* !MAP_ANON */+#endif /* !_WIN32 */+#endif /* open_dev_zero */++#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) \+ || (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)++#ifdef _WIN32++static SLJIT_INLINE sljit_uw get_page_alignment(void) {+ SYSTEM_INFO si;+ static sljit_uw sljit_page_align = 0;+ if (!sljit_page_align) {+ GetSystemInfo(&si);+ sljit_page_align = (sljit_uw)si.dwPageSize - 1;+ }+ return sljit_page_align;+}++#else++#include <unistd.h>++static SLJIT_INLINE sljit_uw get_page_alignment(void) {+ static sljit_uw sljit_page_align = 0;++ sljit_sw align;++ if (!sljit_page_align) {+#ifdef _SC_PAGESIZE+ align = sysconf(_SC_PAGESIZE);+#else+ align = getpagesize();+#endif+ /* Should never happen. */+ if (align < 0)+ align = 4096;+ sljit_page_align = (sljit_uw)align - 1;+ }+ return sljit_page_align;+}++#endif /* _WIN32 */++#endif /* get_page_alignment() */++#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)++#if (defined SLJIT_UTIL_SIMPLE_STACK_ALLOCATION && SLJIT_UTIL_SIMPLE_STACK_ALLOCATION)++SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data)+{+ struct sljit_stack *stack;+ void *ptr;++ SLJIT_UNUSED_ARG(allocator_data);++ if (start_size > max_size || start_size < 1)+ return NULL;++ stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data);+ if (stack == NULL)+ return NULL;++ ptr = SLJIT_MALLOC(max_size, allocator_data);+ if (ptr == NULL) {+ SLJIT_FREE(stack, allocator_data);+ return NULL;+ }++ stack->min_start = (sljit_u8 *)ptr;+ stack->end = stack->min_start + max_size;+ stack->start = stack->end - start_size;+ stack->top = stack->end;+ return stack;+}++SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)+{+ SLJIT_UNUSED_ARG(allocator_data);+ SLJIT_FREE((void*)stack->min_start, allocator_data);+ SLJIT_FREE(stack, allocator_data);+}++SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start)+{+ if ((new_start < stack->min_start) || (new_start >= stack->end))+ return NULL;+ stack->start = new_start;+ return new_start;+}++#else /* !SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */++#ifdef _WIN32++SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)+{+ SLJIT_UNUSED_ARG(allocator_data);+ VirtualFree((void*)stack->min_start, 0, MEM_RELEASE);+ SLJIT_FREE(stack, allocator_data);+}++#else /* !_WIN32 */++SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)+{+ SLJIT_UNUSED_ARG(allocator_data);+ munmap((void*)stack->min_start, (size_t)(stack->end - stack->min_start));+ SLJIT_FREE(stack, allocator_data);+}++#endif /* _WIN32 */++SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data)+{+ struct sljit_stack *stack;+ void *ptr;+ sljit_uw page_align;++ SLJIT_UNUSED_ARG(allocator_data);++ if (start_size > max_size || start_size < 1)+ return NULL;++ stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data);+ if (stack == NULL)+ return NULL;++ /* Align max_size. */+ page_align = get_page_alignment();+ max_size = (max_size + page_align) & ~page_align;++#ifdef _WIN32+ ptr = VirtualAlloc(NULL, max_size, MEM_RESERVE, PAGE_READWRITE);+ if (!ptr) {+ SLJIT_FREE(stack, allocator_data);+ return NULL;+ }++ stack->min_start = (sljit_u8 *)ptr;+ stack->end = stack->min_start + max_size;+ stack->start = stack->end;++ if (sljit_stack_resize(stack, stack->end - start_size) == NULL) {+ sljit_free_stack(stack, allocator_data);+ return NULL;+ }+#else /* !_WIN32 */+#ifdef MAP_ANON+ ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);+#else /* !MAP_ANON */+ if (SLJIT_UNLIKELY((dev_zero < 0) && open_dev_zero())) {+ SLJIT_FREE(stack, allocator_data);+ return NULL;+ }+ ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0);+#endif /* MAP_ANON */+ if (ptr == MAP_FAILED) {+ SLJIT_FREE(stack, allocator_data);+ return NULL;+ }+ stack->min_start = (sljit_u8 *)ptr;+ stack->end = stack->min_start + max_size;+ stack->start = stack->end - start_size;+#endif /* _WIN32 */++ stack->top = stack->end;+ return stack;+}++SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start)+{+#if defined _WIN32 || defined(POSIX_MADV_DONTNEED)+ sljit_uw aligned_old_start;+ sljit_uw aligned_new_start;+ sljit_uw page_align;+#endif++ if ((new_start < stack->min_start) || (new_start >= stack->end))+ return NULL;++#ifdef _WIN32+ page_align = get_page_alignment();++ aligned_new_start = (sljit_uw)new_start & ~page_align;+ aligned_old_start = ((sljit_uw)stack->start) & ~page_align;+ if (aligned_new_start != aligned_old_start) {+ if (aligned_new_start < aligned_old_start) {+ if (!VirtualAlloc((void*)aligned_new_start, aligned_old_start - aligned_new_start, MEM_COMMIT, PAGE_READWRITE))+ return NULL;+ }+ else {+ if (!VirtualFree((void*)aligned_old_start, aligned_new_start - aligned_old_start, MEM_DECOMMIT))+ return NULL;+ }+ }+#elif defined(POSIX_MADV_DONTNEED)+ if (stack->start < new_start) {+ page_align = get_page_alignment();++ aligned_new_start = (sljit_uw)new_start & ~page_align;+ aligned_old_start = ((sljit_uw)stack->start) & ~page_align;++ if (aligned_new_start > aligned_old_start) {+ posix_madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, POSIX_MADV_DONTNEED);+#ifdef MADV_FREE+ madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, MADV_FREE);+#endif /* MADV_FREE */+ }+ }+#endif /* _WIN32 */++ stack->start = new_start;+ return new_start;+}++#endif /* SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */++#endif /* SLJIT_UTIL_STACK */
+ src/c/pcre2/deps/sljit/test_src/sljitConfigPost.h view
@@ -0,0 +1,33 @@+/*+ * 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_POST_H_+#define SLJIT_CONFIG_POST_H_++void *sljit_test_malloc_exec(sljit_uw size, void *exec_allocator_data);+void sljit_test_free_code(void* code, void *exec_allocator_data);++#endif /* SLJIT_CONFIG_POST_H_ */
+ src/c/pcre2/deps/sljit/test_src/sljitConfigPre.h view
@@ -0,0 +1,35 @@+/*+ * 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_PRE_H_+#define SLJIT_CONFIG_PRE_H_++#define SLJIT_HAVE_CONFIG_POST 1++#define SLJIT_MALLOC_EXEC(size, exec_allocator_data) sljit_test_malloc_exec((size), (exec_allocator_data))+#define SLJIT_FREE_EXEC(ptr, exec_allocator_data) sljit_test_free_code((ptr), (exec_allocator_data))++#endif /* SLJIT_CONFIG_PRE_H_ */
+ src/c/pcre2/deps/sljit/test_src/sljitMain.c view
@@ -0,0 +1,84 @@+/*+ * Stack-less Just-In-Time compiler+ *+ * Copyright 2009-2010 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 "sljitLir.h"++#include <stdio.h>+#include <stdlib.h>++int sljit_test(int argc, char* argv[]);++union executable_code {+ void* code;+ sljit_sw (SLJIT_FUNC *func)(sljit_sw* a);+};+typedef union executable_code executable_code;++static void error(const char* str)+{+ printf("An error occured: %s\n", str);+ exit(-1);+}++void devel(void)+{+ executable_code code;++ struct sljit_compiler *compiler = sljit_create_compiler(NULL);+ sljit_sw buf[4];++ if (!compiler)+ error("Not enough of memory");+ buf[0] = 5;+ buf[1] = 12;+ buf[2] = 0;+ buf[3] = 0;++#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)+ sljit_compiler_verbose(compiler, stdout);+#endif+ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 4 | SLJIT_ENTER_FLOAT(4), 5, 2 * sizeof(sljit_sw));++ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ sljit_free_compiler(compiler);++ printf("Code at: %p\n", (void*)SLJIT_FUNC_ADDR(code.code));++ printf("Function returned with %ld\n", (long)code.func((sljit_sw*)buf));+ printf("buf[0] = %ld\n", (long)buf[0]);+ printf("buf[1] = %ld\n", (long)buf[1]);+ printf("buf[2] = %ld\n", (long)buf[2]);+ printf("buf[3] = %ld\n", (long)buf[3]);+ sljit_free_code(code.code, NULL);+}++int main(int argc, char* argv[])+{+ /* devel(); */+ return sljit_test(argc, argv);+}
+ src/c/pcre2/deps/sljit/test_src/sljitTest.c view
@@ -0,0 +1,10396 @@+/*+ * 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.+ */++/* Must be the first one. Must not depend on any other include. */+#include "sljitLir.h"++#include <stdio.h>+#include <stdlib.h>+#include <string.h>++#ifdef _MSC_VER+#pragma warning(push)+#pragma warning(disable: 4127) /* conditional expression is constant */+#endif /* _MSC_VER */++#if defined _WIN32 || defined _WIN64+#define COLOR_RED+#define COLOR_GREEN+#define COLOR_ARCH+#define COLOR_DEFAULT+#else /* !_WIN32 && !_WIN64 */+#define COLOR_RED "\33[31m"+#define COLOR_GREEN "\33[32m"+#define COLOR_ARCH "\33[33m"+#define COLOR_DEFAULT "\33[0m"+#endif /* _WIN32 || _WIN64 */++union executable_code {+ void* code;+ sljit_sw (SLJIT_FUNC *func0)(void);+ sljit_sw (SLJIT_FUNC *func1)(sljit_sw a);+ sljit_sw (SLJIT_FUNC *func2)(sljit_sw a, sljit_sw b);+ sljit_sw (SLJIT_FUNC *func3)(sljit_sw a, sljit_sw b, sljit_sw c);++ void (SLJIT_FUNC *test57_f1)(sljit_s32 a, sljit_uw b, sljit_u32 c, sljit_sw d);+ void (SLJIT_FUNC *test57_f2)(sljit_s32 a, sljit_u32 b, sljit_sw c, sljit_sw d);++ void (SLJIT_FUNC *test58_f1)(sljit_s32 a, sljit_sw b, sljit_sw c, sljit_s32 d);+ void (SLJIT_FUNC *test58_f2)(sljit_sw a, sljit_sw b, sljit_s32 c, sljit_s32 d);++ void (SLJIT_FUNC *test_float12_f1)(sljit_s32 a, sljit_f32 b, sljit_uw c, sljit_f64 d);+ void (SLJIT_FUNC *test_float12_f2)(sljit_f32 a, sljit_f64 b, sljit_f32 c, sljit_s32 d);+ void (SLJIT_FUNC *test_float12_f3)(sljit_f64 a, sljit_f32 b, sljit_u32 c, sljit_f32 d);+ void (SLJIT_FUNC *test_float12_f4)(sljit_f64 a, sljit_s32 b, sljit_f32 c, sljit_f64 d);+ void (SLJIT_FUNC *test_float12_f5)(sljit_f32 a, sljit_s32 b, sljit_uw c, sljit_u32 d);+ void (SLJIT_FUNC *test_float12_f6)(sljit_f64 a, sljit_f64 b, sljit_uw c, sljit_sw d);+ void (SLJIT_FUNC *test_float12_f7)(sljit_f64 a, sljit_f64 b, sljit_uw c, sljit_f64 d);+ void (SLJIT_FUNC *test_float12_f8)(sljit_f64 a, sljit_f64 b, sljit_f64 c, sljit_s32 d);++ void (SLJIT_FUNC *test_float14_f1)(sljit_f64 a, sljit_f64 b, sljit_f64 c, sljit_sw d);+ void (SLJIT_FUNC *test_float14_f2)(sljit_f64 a, sljit_f64 b, sljit_sw c, sljit_sw d);++ sljit_sw (SLJIT_FUNC *test_call6_f1)(sljit_f32 a, sljit_f64 b);+ sljit_sw (SLJIT_FUNC *test_call6_f2)(sljit_f64 a, sljit_f64 b, sljit_f64 c, sljit_f64 d);+ sljit_sw (SLJIT_FUNC *test_call6_f3)(sljit_f64 a, sljit_f64 b, sljit_f64 c);++ sljit_f32 (SLJIT_FUNC *test_call10_f1)(sljit_sw a);+ sljit_f64 (SLJIT_FUNC *test_call10_f2)(sljit_sw a);+};+typedef union executable_code executable_code;++static sljit_s32 successful_tests = 0;+static sljit_s32 verbose = 0;+static sljit_s32 silent = 0;++#define FAILED(cond, text) \+ if (SLJIT_UNLIKELY(cond)) { \+ printf(text); \+ return; \+ }++#define CHECK(compiler) \+ if (sljit_get_compiler_error(compiler) != SLJIT_ERR_COMPILED) { \+ printf("Compiler error: %d\n", sljit_get_compiler_error(compiler)); \+ sljit_free_compiler(compiler); \+ return; \+ }++#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)+#define IS_32BIT 0+#define IS_64BIT 1+#define WCONST(const64, const32) ((sljit_sw)SLJIT_W(const64))+#else /* !SLJIT_64BIT_ARCHITECTURE */+#define IS_32BIT 1+#define IS_64BIT 0+#define WCONST(const64, const32) ((sljit_sw)const32)+#endif /* SLJIT_64BIT_ARCHITECTURE */++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)+#define IS_X86 1+#else /* !SLJIT_CONFIG_X86 */+#define IS_X86 0+#endif /* SLJIT_CONFIG_X86 */++#if (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM)+#define IS_ARM 1+#else /* !SLJIT_CONFIG_ARM */+#define IS_ARM 0+#endif /* SLJIT_CONFIG_ARM */++#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+#define LITTLE_BIG(a, b) (a)+#else /* !SLJIT_LITTLE_ENDIAN */+#define LITTLE_BIG(a, b) (b)+#endif /* SLJIT_LITTLE_ENDIAN */++static void cond_set(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_s32 type)+{+ /* Testing both sljit_emit_op_flags and sljit_emit_jump. */+ struct sljit_jump* jump;+ struct sljit_label* label;++ sljit_emit_op_flags(compiler, SLJIT_MOV, dst, dstw, type);+ jump = sljit_emit_jump(compiler, type);+ sljit_emit_op2(compiler, SLJIT_ADD, dst, dstw, dst, dstw, SLJIT_IMM, 2);+ label = sljit_emit_label(compiler);+ sljit_set_label(jump, label);+}++#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)++/* For interface testing and for test51. */+void *sljit_test_malloc_exec(sljit_uw size, void *exec_allocator_data)+{+ if (exec_allocator_data)+ return exec_allocator_data;++ return SLJIT_BUILTIN_MALLOC_EXEC(size, exec_allocator_data);+}++/* For interface testing. */+void sljit_test_free_code(void* code, void *exec_allocator_data)+{+ SLJIT_UNUSED_ARG(exec_allocator_data);+ SLJIT_BUILTIN_FREE_EXEC(code, exec_allocator_data);+}++#define MALLOC_EXEC(result, size) \+ result = SLJIT_MALLOC_EXEC(size, NULL); \+ if (!result) { \+ printf("Cannot allocate executable memory\n"); \+ return; \+ } \+ memset(result, 255, size);++#define FREE_EXEC(ptr) \+ SLJIT_FREE_EXEC(((sljit_u8*)(ptr)) + SLJIT_EXEC_OFFSET(ptr), NULL);++static void test_exec_allocator(void)+{+ /* This is not an sljit test. */+ void *ptr1;+ void *ptr2;+ void *ptr3;++ if (verbose)+ printf("Run executable allocator test\n");++ MALLOC_EXEC(ptr1, 32);+ MALLOC_EXEC(ptr2, 512);+ MALLOC_EXEC(ptr3, 512);+ FREE_EXEC(ptr2);+ FREE_EXEC(ptr3);+ FREE_EXEC(ptr1);+ MALLOC_EXEC(ptr1, 262104);+ MALLOC_EXEC(ptr2, 32000);+ FREE_EXEC(ptr1);+ MALLOC_EXEC(ptr1, 262104);+ FREE_EXEC(ptr1);+ FREE_EXEC(ptr2);+ MALLOC_EXEC(ptr1, 512);+ MALLOC_EXEC(ptr2, 512);+ MALLOC_EXEC(ptr3, 512);+ FREE_EXEC(ptr2);+ MALLOC_EXEC(ptr2, 512);+#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)+ sljit_free_unused_memory_exec();+#endif /* SLJIT_EXECUTABLE_ALLOCATOR */+ FREE_EXEC(ptr3);+ FREE_EXEC(ptr1);+ FREE_EXEC(ptr2);++#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)+ sljit_free_unused_memory_exec();+#endif /* SLJIT_EXECUTABLE_ALLOCATOR */+}++#undef MALLOC_EXEC++#endif /* !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) */++static void test_macros(void)+{+ SLJIT_ASSERT(SLJIT_IS_MEM(SLJIT_MEM0()));+ SLJIT_ASSERT(SLJIT_IS_MEM(SLJIT_MEM1(SLJIT_S0)));+ SLJIT_ASSERT(SLJIT_IS_MEM(SLJIT_MEM2(SLJIT_R0, SLJIT_S0)));+ SLJIT_ASSERT(SLJIT_IS_MEM0(SLJIT_MEM0()));+ SLJIT_ASSERT(!SLJIT_IS_MEM0(SLJIT_MEM1(SLJIT_S0)));+ SLJIT_ASSERT(!SLJIT_IS_MEM0(SLJIT_MEM2(SLJIT_R0, SLJIT_S0)));+ SLJIT_ASSERT(!SLJIT_IS_MEM1(SLJIT_MEM0()));+ SLJIT_ASSERT(SLJIT_IS_MEM1(SLJIT_MEM1(SLJIT_S0)));+ SLJIT_ASSERT(!SLJIT_IS_MEM1(SLJIT_MEM2(SLJIT_R0, SLJIT_S0)));+ SLJIT_ASSERT(!SLJIT_IS_MEM2(SLJIT_MEM0()));+ SLJIT_ASSERT(!SLJIT_IS_MEM2(SLJIT_MEM1(SLJIT_R0)));+ SLJIT_ASSERT(SLJIT_IS_MEM2(SLJIT_MEM2(SLJIT_R0, SLJIT_R1)));++ SLJIT_ASSERT(!SLJIT_IS_REG(SLJIT_IMM));+ SLJIT_ASSERT(!SLJIT_IS_MEM(SLJIT_IMM));+ SLJIT_ASSERT(SLJIT_IS_IMM(SLJIT_IMM));+ SLJIT_ASSERT(!SLJIT_IS_REG_PAIR(SLJIT_IMM));+ SLJIT_ASSERT(SLJIT_IS_REG(SLJIT_S0));+ SLJIT_ASSERT(!SLJIT_IS_MEM(SLJIT_S0));+ SLJIT_ASSERT(!SLJIT_IS_IMM(SLJIT_S0));+ SLJIT_ASSERT(!SLJIT_IS_REG_PAIR(SLJIT_S0));+ SLJIT_ASSERT(!SLJIT_IS_REG(SLJIT_REG_PAIR(SLJIT_R0, SLJIT_S0)));+ SLJIT_ASSERT(!SLJIT_IS_MEM(SLJIT_REG_PAIR(SLJIT_R0, SLJIT_S0)));+ SLJIT_ASSERT(!SLJIT_IS_IMM(SLJIT_REG_PAIR(SLJIT_R0, SLJIT_S0)));+ SLJIT_ASSERT(SLJIT_IS_REG_PAIR(SLJIT_REG_PAIR(SLJIT_R0, SLJIT_S0)));++ SLJIT_ASSERT(SLJIT_EXTRACT_REG(SLJIT_R2) == SLJIT_R2);+ SLJIT_ASSERT(SLJIT_EXTRACT_REG(SLJIT_FR1) == SLJIT_FR1);+ SLJIT_ASSERT(SLJIT_EXTRACT_REG(SLJIT_MEM1(SLJIT_S2)) == SLJIT_S2);+ SLJIT_ASSERT(SLJIT_EXTRACT_REG(SLJIT_MEM2(SLJIT_S1, SLJIT_S2)) == SLJIT_S1);+ SLJIT_ASSERT(SLJIT_EXTRACT_REG(SLJIT_REG_PAIR(SLJIT_R3, SLJIT_S3)) == SLJIT_R3);+ SLJIT_ASSERT(SLJIT_EXTRACT_REG(SLJIT_REG_PAIR(SLJIT_FR2, SLJIT_FR4)) == SLJIT_FR2);+ SLJIT_ASSERT(SLJIT_EXTRACT_SECOND_REG(SLJIT_MEM2(SLJIT_S1, SLJIT_S2)) == SLJIT_S2);+ SLJIT_ASSERT(SLJIT_EXTRACT_SECOND_REG(SLJIT_REG_PAIR(SLJIT_R3, SLJIT_S3)) == SLJIT_S3);+ SLJIT_ASSERT(SLJIT_EXTRACT_SECOND_REG(SLJIT_REG_PAIR(SLJIT_FR2, SLJIT_FR4)) == SLJIT_FR4);+}++static void test1(void)+{+ /* Enter and return from an sljit function. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);++ if (verbose)+ printf("Run test1\n");++ FAILED(!compiler, "cannot create compiler\n");++ /* 3 arguments passed, 3 arguments used. */+ sljit_emit_enter(compiler, 0, SLJIT_ARGS3(W, W, W, W), 3, 3, 0);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_S1, 0);++ SLJIT_ASSERT(sljit_get_generated_code_size(compiler) == 0);+ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ SLJIT_ASSERT(compiler->error == SLJIT_ERR_COMPILED);+ SLJIT_ASSERT(sljit_get_generated_code_size(compiler) > 0);+ sljit_free_compiler(compiler);++ FAILED(code.func3(3, -21, 86) != -21, "test1 case 1 failed\n");+ FAILED(code.func3(4789, 47890, 997) != 47890, "test1 case 2 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test2(void)+{+ /* Test mov. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[12];+ sljit_s32 i;+ static sljit_sw data[2] = { 0, -9876 };++ if (verbose)+ printf("Run test2\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 12; i++)+ buf[i] = 0;+ buf[0] = 5678;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 9999);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_S0, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM2(SLJIT_S1, SLJIT_R1), 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 2);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_S1, SLJIT_S0), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_S1, SLJIT_R1), 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 3);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_S1, SLJIT_S0), SLJIT_WORD_SHIFT, SLJIT_MEM0(), (sljit_sw)&buf);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), (sljit_sw)&data);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf - 0x12345678);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), 0x12345678);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 3456);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf - 0xff890 + 6 * (sljit_sw)sizeof(sljit_sw));+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0xff890, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf + 0xff890 + 7 * (sljit_sw)sizeof(sljit_sw));+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), -0xff890, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf - 0xfff0ff + 8 * (sljit_sw)sizeof(sljit_sw));+ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0xfff0ff, SLJIT_IMM, 7896);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf + 0xfff100 + 9 * (sljit_sw)sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -2450);+ /* buf[9] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), -0xfff100, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)&buf - 0xffef01 + 10 * (sljit_sw)sizeof(sljit_sw));+ /* buf[10] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 0xffef01, SLJIT_IMM, 8796);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)&buf + 0xffef01 + 11 * (sljit_sw)sizeof(sljit_sw));+ /* buf[11] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), -0xffef01, SLJIT_IMM, 5704);++ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R2, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ FAILED(code.func1((sljit_sw)&buf) != 9999, "test2 case 1 failed\n");+ FAILED(buf[1] != 9999, "test2 case 2 failed\n");+ FAILED(buf[2] != 9999, "test2 case 3 failed\n");+ FAILED(buf[3] != 5678, "test2 case 4 failed\n");+ FAILED(buf[4] != -9876, "test2 case 5 failed\n");+ FAILED(buf[5] != 5678, "test2 case 6 failed\n");+ FAILED(buf[6] != 3456, "test2 case 7 failed\n");+ FAILED(buf[7] != 3456, "test2 case 8 failed\n");+ FAILED(buf[8] != 7896, "test2 case 9 failed\n");+ FAILED(buf[9] != -2450, "test2 case 10 failed\n");+ FAILED(buf[10] != 8796, "test2 case 11 failed\n");+ FAILED(buf[11] != 5704, "test2 case 12 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test3(void)+{+ /* Test not. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[5];++ if (verbose)+ printf("Run test3\n");++ FAILED(!compiler, "cannot create compiler\n");+ buf[0] = 1234;+ buf[1] = 0;+ buf[2] = 9876;+ buf[3] = 0;+ buf[4] = 0x12345678;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 1, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_MEM0(), (sljit_sw)&buf[1], SLJIT_MEM0(), (sljit_sw)&buf[1], SLJIT_IMM, -1);+ /* buf[3] */+ sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_RETURN_REG, 0, SLJIT_IMM, -1, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_IMM, -1);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf[4] - 0xff0000 - 0x20);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)&buf[4] - 0xff0000);+ sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_MEM1(SLJIT_R1), 0xff0000 + 0x20, SLJIT_IMM, -1, SLJIT_MEM1(SLJIT_R2), 0xff0000);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ FAILED(code.func1((sljit_sw)&buf) != ~1234, "test3 case 1 failed\n");+ FAILED(buf[1] != ~1234, "test3 case 2 failed\n");+ FAILED(buf[3] != ~9876, "test3 case 3 failed\n");+ FAILED(buf[4] != ~0x12345678, "test3 case 4 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test4(void)+{+ /* Test negate. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[4];++ if (verbose)+ printf("Run test4\n");++ FAILED(!compiler, "cannot create compiler\n");+ buf[0] = 0;+ buf[1] = 1234;+ buf[2] = 0;+ buf[3] = 0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2(W, P, W), 3, 2, 0);+ /* buf[0] */+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM0(), (sljit_sw)&buf[0], SLJIT_IMM, 0, SLJIT_MEM0(), (sljit_sw)&buf[1]);+ /* buf[2] */+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_IMM, 0, SLJIT_S1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 299);+ /* buf[3] */+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_IMM, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ FAILED(code.func2((sljit_sw)&buf, 4567) != -4567, "test4 case 1 failed\n");+ FAILED(buf[0] != -1234, "test4 case 2 failed\n");+ FAILED(buf[2] != -4567, "test4 case 3 failed\n");+ FAILED(buf[3] != -299, "test4 case 4 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test5(void)+{+ /* Test add. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_s32 i;+ sljit_sw buf[10];++ if (verbose)+ printf("Run test5\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 10; i++)+ buf[i] = 0;++ buf[0] = 100;+ buf[1] = 200;+ buf[2] = 300;+ buf[8] = 313;+ buf[9] = 856;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 50);+ /* buf[2] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 1, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 1, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 0);+ /* buf[0] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_sw) + 2);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 50);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);+ /* buf[5] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_IMM, 4, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_IMM, 50, SLJIT_R1, 0);+ /* buf[4] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_IMM, 50, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw));+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R1, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw));+ /* buf[5] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw));+ /* buf[3] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x1e7d39f2);+ /* buf[6] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R1, 0, SLJIT_IMM, 0x23de7c06);+ /* buf[7] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_IMM, 0x3d72e452, SLJIT_R1, 0);+ /* buf[8] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_IMM, -43, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)(buf + 9) >> 1);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R1), (sljit_sw)(buf + 1), SLJIT_MEM1(SLJIT_R2), (sljit_sw)(buf + 9) >> 1);+ /* buf[9] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R1, 0);++ /* Return value */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_IMM, 1000, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1430);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_IMM, -99, SLJIT_R0, 0);++ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ FAILED(code.func1((sljit_sw)&buf) != 2437 + 2 * sizeof(sljit_sw), "test5 case 1 failed\n");+ FAILED(buf[0] != 202 + 2 * sizeof(sljit_sw), "test5 case 2 failed\n");+ FAILED(buf[2] != 500, "test5 case 3 failed\n");+ FAILED(buf[3] != 400, "test5 case 4 failed\n");+ FAILED(buf[4] != 200, "test5 case 5 failed\n");+ FAILED(buf[5] != 250, "test5 case 6 failed\n");+ FAILED(buf[6] != 0x425bb5f8, "test5 case 7 failed\n");+ FAILED(buf[7] != 0x5bf01e44, "test5 case 8 failed\n");+ FAILED(buf[8] != 270, "test5 case 9 failed\n");+ FAILED(buf[9] != 1056, "test5 case 10 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test6(void)+{+ /* Test addc, sub, subc. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[23];+ sljit_s32 i;++ if (verbose)+ printf("Run test6\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 23; i++)+ buf[i] = 0;+ buf[10] = 4000;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1);+ sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -1);+ /* buf[0] */+ sljit_emit_op2(compiler, SLJIT_ADDC, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 0, SLJIT_IMM, 0);+ sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R0, 0);+ /* buf[1] */+ sljit_emit_op2(compiler, SLJIT_ADDC, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, 4);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 100);+ /* buf[2] */+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_R0, 0, SLJIT_IMM, 50);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 6000);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_IMM, 10);+ sljit_emit_op2(compiler, SLJIT_SUBC, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_IMM, 5);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 100);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 5000);+ sljit_emit_op2(compiler, SLJIT_SUBC, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 5000);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_IMM, 6000, SLJIT_R0, 0);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 100);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 32768);+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7, SLJIT_R1, 0);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -32767);+ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 8, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x52cd3bf4);+ /* buf[9] */+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 9, SLJIT_R0, 0, SLJIT_IMM, 0x3da297c6);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 6000);+ /* buf[10] */+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 10, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 10, SLJIT_R1, 0);+ /* buf[11] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -1);+ sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);+ sljit_emit_op2(compiler, SLJIT_ADDC, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 11, SLJIT_IMM, 0xff00ff, SLJIT_R1, 0);+ /* buf[12] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);+ sljit_emit_op2(compiler, SLJIT_SUBC, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 12, SLJIT_R1, 0, SLJIT_IMM, 0xff00ff);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 5);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 4);+ /* buf[13] */+ sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 13, SLJIT_R0, 0, SLJIT_IMM, -2);+ /* buf[14] */+ sljit_emit_op2(compiler, SLJIT_ADDC, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 14, SLJIT_R1, 0, SLJIT_IMM, -2);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -5);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -4);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -2);+ sljit_emit_op2(compiler, SLJIT_SUBC, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, -2);+ /* buf[15] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 15, SLJIT_R0, 0);+ /* buf[16] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 16, SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 3);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 4);+ sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, -4);+ sljit_emit_op2(compiler, SLJIT_ADDC, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, -4);+ /* buf[17] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 17, SLJIT_R1, 0);+ /* buf[18] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 18, SLJIT_R2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -3);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -4);+ /* buf[19] */+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 19, SLJIT_R1, 0, SLJIT_IMM, -4);+ /* buf[20] */+ sljit_emit_op2(compiler, SLJIT_SUBC, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 20, SLJIT_R2, 0, SLJIT_IMM, -4);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -100);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -200);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R0, 0);+ /* buf[21] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 21, SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op2(compiler, SLJIT_SUBC, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ /* buf[22] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 22, SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 10);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 5);+ sljit_emit_op2(compiler, SLJIT_SUBC, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 2);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, -2220);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ FAILED(code.func1((sljit_sw)&buf) != 2223, "test6 case 1 failed\n");+ FAILED(buf[0] != 1, "test6 case 2 failed\n");+ FAILED(buf[1] != 5, "test6 case 3 failed\n");+ FAILED(buf[2] != 50, "test6 case 4 failed\n");+ FAILED(buf[3] != 4, "test6 case 5 failed\n");+ FAILED(buf[4] != 50, "test6 case 6 failed\n");+ FAILED(buf[5] != 50, "test6 case 7 failed\n");+ FAILED(buf[6] != 1000, "test6 case 8 failed\n");+ FAILED(buf[7] != 100 - 32768, "test6 case 9 failed\n");+ FAILED(buf[8] != 100 + 32767, "test6 case 10 failed\n");+ FAILED(buf[9] != 0x152aa42e, "test6 case 11 failed\n");+ FAILED(buf[10] != -2000, "test6 case 12 failed\n");+ FAILED(buf[11] != 0xff0100, "test6 case 13 failed\n");+ FAILED(buf[12] != -0xff0101, "test6 case 14 failed\n");+ FAILED(buf[13] != 3, "test6 case 15 failed\n");+ FAILED(buf[14] != 3, "test6 case 16 failed\n");+ FAILED(buf[15] != -3, "test6 case 17 failed\n");+ FAILED(buf[16] != -3, "test6 case 18 failed\n");+ FAILED(buf[17] != -1, "test6 case 19 failed\n");+ FAILED(buf[18] != 0, "test6 case 20 failed\n");+ FAILED(buf[19] != 1, "test6 case 21 failed\n");+ FAILED(buf[20] != 0, "test6 case 22 failed\n");+ FAILED(buf[21] != 100, "test6 case 23 failed\n");+ FAILED(buf[22] != -3, "test6 case 24 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test7(void)+{+ /* Test logical operators. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_s32 i;+ sljit_sw buf[9];++ if (verbose)+ printf("Run test7\n");++ FAILED(!compiler, "cannot create compiler\n");+ for (i = 0; i < 9; i++)+ buf[i] = 0;++ buf[0] = 0xff80;+ buf[1] = 0x0f808080;+ buf[3] = 0xaaaaaa;+ buf[5] = 0x4040;+ buf[7] = (sljit_sw)0xc43a7f95;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0xf0C000);+ /* buf[2] */+ sljit_emit_op2(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_R0, 0, SLJIT_IMM, 0x308f);+ /* buf[0] */+ sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw));+ /* buf[3] */+ sljit_emit_op2(compiler, SLJIT_AND, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_IMM, 0xf0f0f0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0xC0F0);+ sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5);+ sljit_emit_op2(compiler, SLJIT_OR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0xff0000);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_R0, 0);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0xC0F0);+ sljit_emit_op2(compiler, SLJIT_AND, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5);+ sljit_emit_op2(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, SLJIT_R2, 0, SLJIT_IMM, 0xff0000);+ /* buf[1] */+ sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, 0xFFFFFF, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw));+ /* buf[6] */+ sljit_emit_op2(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6, SLJIT_IMM, (sljit_sw)0xa56c82c0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6);+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7);+ sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7, SLJIT_IMM, (sljit_sw)0xff00ff00, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x76);+ sljit_emit_op2(compiler, SLJIT_AND, SLJIT_R1, 0, SLJIT_IMM, 0x1c, SLJIT_R1, 0);+ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 8, SLJIT_R1, 0);+ /* Return value */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0xff00ff00);+ sljit_emit_op2(compiler, SLJIT_OR, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 0x0f);+ sljit_emit_op2(compiler, SLJIT_AND, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0x888888, SLJIT_R1, 0);++ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ FAILED(code.func1((sljit_sw)&buf) != 0x8808, "test7 case 1 failed\n");+ FAILED(buf[0] != 0x0F807F00, "test7 case 2 failed\n");+ FAILED(buf[1] != 0x0F7F7F7F, "test7 case 3 failed\n");+ FAILED(buf[2] != 0x00F0F08F, "test7 case 4 failed\n");+ FAILED(buf[3] != 0x00A0A0A0, "test7 case 5 failed\n");+ FAILED(buf[4] != 0x00FF80B0, "test7 case 6 failed\n");+ FAILED(buf[5] != 0x00FF4040, "test7 case 7 failed\n");+ FAILED(buf[6] != (sljit_sw)0xa56c82c0, "test7 case 8 failed\n");+ FAILED(buf[7] != 0x3b3a8095, "test7 case 9 failed\n");+ FAILED(buf[8] != 0x14, "test7 case 10 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test8(void)+{+ /* Test flags (neg, cmp, test). */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[27];+ sljit_s32 i;++ if (verbose)+ printf("Run test8\n");++ FAILED(!compiler, "cannot create compiler\n");+ buf[0] = 100;+ for (i = 1; i < 27; i++)+ buf[i] = 3;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 3, 2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 20);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 10);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_IMM, 6, SLJIT_IMM, 5);+ /* buf[1] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_NOT_EQUAL);+ /* buf[2] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_EQUAL);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R0, 0, SLJIT_IMM, 3000);+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_GREATER);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 3000);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_S1, 0);+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_LESS);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_R2, 0);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R0, 0, SLJIT_IMM, -15);+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_SIG_GREATER);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, SLJIT_R2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -(sljit_sw)(~(sljit_uw)0 >> 1) - 1);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_OVERFLOW, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_IMM, 0, SLJIT_R0, 0);+ /* buf[6] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6, SLJIT_OVERFLOW);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1);+ sljit_emit_op2(compiler, SLJIT_XOR | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -1);+ /* buf[7] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7, SLJIT_ZERO);+ sljit_emit_op2(compiler, SLJIT_XOR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, -1, SLJIT_R1, 0);+ /* buf[8] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 8, SLJIT_ZERO);+ sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_IMM, 0xffff, SLJIT_R0, 0);+ sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 0xffff);+ /* buf[9] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 9, SLJIT_NOT_ZERO);+ sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_IMM, 0xffff, SLJIT_R1, 0);+ sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_IMM, 0xffff);+ sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R1, 0);+ sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 0x1);+ /* buf[10] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 10, SLJIT_NOT_ZERO);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -(sljit_sw)(~(sljit_uw)0 >> 1) - 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R0, 0);+ /* buf[11] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 11, SLJIT_OVERFLOW);+ sljit_emit_op2u(compiler, SLJIT_ADD | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R0, 0);+ /* buf[12] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 12, SLJIT_OVERFLOW);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 9);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 0, SLJIT_R0, 0);+ /* buf[13] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 13, SLJIT_LESS);+ /* buf[14] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 14, SLJIT_ZERO);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 0, SLJIT_R0, 0);+ /* buf[15] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 15, SLJIT_LESS);+ /* buf[16] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 16, SLJIT_ZERO);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -9);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R0, 0, SLJIT_IMM, 0, SLJIT_R0, 0);+ /* buf[17] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 17, SLJIT_SIG_LESS);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -9);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R0, 0, SLJIT_IMM, 0, SLJIT_R0, 0);+ /* buf[18] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 18, SLJIT_SIG_GREATER);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op2(compiler, SLJIT_OR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0);+ /* buf[19] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 19, SLJIT_ZERO);+ /* buf[20] */+ sljit_emit_op2u(compiler, SLJIT_OR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 20, SLJIT_ZERO);+ sljit_emit_op2(compiler, SLJIT_XOR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0);+ /* buf[21] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 21, SLJIT_ZERO);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)(~(sljit_uw)0 >> 1));+ sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_OVERFLOW, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, 1);+ /* buf[22] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 22, SLJIT_OVERFLOW);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)((~(sljit_uw)0 >> 1) - 500));+ sljit_emit_op2u(compiler, SLJIT_ADD | SLJIT_SET_OVERFLOW, SLJIT_R2, 0, SLJIT_IMM, 500);+ /* buf[23] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 23, SLJIT_OVERFLOW);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(~(~(sljit_uw)0 >> 1)));+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_IMM, 1);+ /* buf[24] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 24, SLJIT_OVERFLOW);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 3);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, 10);+ /* buf[25] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 25, SLJIT_LESS);+ /* buf[26] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 26, SLJIT_S1, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ FAILED(buf[1] != 1, "test8 case 1 failed\n");+ FAILED(buf[2] != 0, "test8 case 2 failed\n");+ FAILED(buf[3] != 0, "test8 case 3 failed\n");+ FAILED(buf[4] != 1, "test8 case 4 failed\n");+ FAILED(buf[5] != 1, "test8 case 5 failed\n");+ FAILED(buf[6] != 1, "test8 case 6 failed\n");+ FAILED(buf[7] != 1, "test8 case 7 failed\n");+ FAILED(buf[8] != 0, "test8 case 8 failed\n");+ FAILED(buf[9] != 1, "test8 case 9 failed\n");+ FAILED(buf[10] != 0, "test8 case 10 failed\n");+ FAILED(buf[11] != 1, "test8 case 11 failed\n");+ FAILED(buf[12] != 0, "test8 case 12 failed\n");+ FAILED(buf[13] != 1, "test8 case 13 failed\n");+ FAILED(buf[14] != 0, "test8 case 14 failed\n");+ FAILED(buf[15] != 0, "test8 case 15 failed\n");+ FAILED(buf[16] != 1, "test8 case 16 failed\n");+ FAILED(buf[17] != 0, "test8 case 17 failed\n");+ FAILED(buf[18] != 1, "test8 case 18 failed\n");+ FAILED(buf[19] != 1, "test8 case 19 failed\n");+ FAILED(buf[20] != 0, "test8 case 20 failed\n");+ FAILED(buf[21] != 1, "test8 case 21 failed\n");+ FAILED(buf[22] != 1, "test8 case 22 failed\n");+ FAILED(buf[23] != 0, "test8 case 23 failed\n");+ FAILED(buf[24] != 1, "test8 case 24 failed\n");+ FAILED(buf[25] != 1, "test8 case 25 failed\n");+ FAILED(buf[26] != -7, "test8 case 26 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test9(void)+{+ /* Test shift. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[18];+ sljit_s32 i;+#ifdef SLJIT_PREF_SHIFT_REG+ sljit_s32 shift_reg = SLJIT_PREF_SHIFT_REG;+#else /* !SLJIT_PREF_SHIFT_REG */+ sljit_s32 shift_reg = SLJIT_R2;+#endif /* SLJIT_PREF_SHIFT_REG */++ SLJIT_ASSERT(shift_reg >= SLJIT_R2 && shift_reg <= SLJIT_R3);++ if (verbose)+ printf("Run test9\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 18; i++)+ buf[i] = -1;++ buf[4] = 1 << 10;+ buf[9] = 3;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 4, 2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0xf);+ sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 3);+ sljit_emit_op2(compiler, SLJIT_LSHR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 1);+ /* buf[1] */+ sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R1, 0, SLJIT_IMM, 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -64);+ sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 2);+ /* buf[2] */+ sljit_emit_op2(compiler, SLJIT_ASHR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_R0, 0, shift_reg, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 0xff);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 4);+ sljit_emit_op2(compiler, SLJIT_SHL, shift_reg, 0, shift_reg, 0, SLJIT_R0, 0);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, shift_reg, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 0xff);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8);+ /* buf[4] */+ sljit_emit_op2(compiler, SLJIT_LSHR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_R0, 0);+ /* buf[5] */+ sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, shift_reg, 0, SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 0xf);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2);+ sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_R0, 0);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6, SLJIT_S1, 0);+ sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_R0, 0);+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0xf00);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 4);+ sljit_emit_op2(compiler, SLJIT_LSHR, SLJIT_R1, 0, SLJIT_R2, 0, SLJIT_R0, 0);+ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 8, SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)buf);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 9);+ /* buf[9] */+ sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), SLJIT_WORD_SHIFT);++ sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 4);+ sljit_emit_op2(compiler, SLJIT_SHL, shift_reg, 0, SLJIT_IMM, 2, shift_reg, 0);+ /* buf[10] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 10, shift_reg, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0xa9);+ sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0x7d00);+ sljit_emit_op2(compiler, SLJIT_LSHR32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 32);+#if IS_64BIT+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, SLJIT_R0, 0);+#endif /* IS_64BIT */+ sljit_emit_op2(compiler, SLJIT_OR, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0xe30000);+#if IS_64BIT+ sljit_emit_op2(compiler, SLJIT_ASHR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0xffc0);+#else /* !IS_64BIT */+ sljit_emit_op2(compiler, SLJIT_ASHR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0xffe0);+#endif /* IS_64BIT */+ sljit_emit_op2(compiler, SLJIT_OR, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0x25000000);+ sljit_emit_op2(compiler, SLJIT_SHL32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0xfffe1);+#if IS_64BIT+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, SLJIT_R0, 0);+#endif /* IS_64BIT */+ /* buf[11] */+ sljit_emit_op2(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 11, SLJIT_R1, 0, SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x5c);+ sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R1, 0, SLJIT_R0, 0, shift_reg, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0xf600);+ sljit_emit_op2(compiler, SLJIT_LSHR32, SLJIT_R0, 0, SLJIT_R0, 0, shift_reg, 0);+#if IS_64BIT+ /* Alternative form of uint32 type cast. */+ sljit_emit_op2(compiler, SLJIT_AND, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0xffffffff);+#endif /* IS_64BIT */+ sljit_emit_op2(compiler, SLJIT_OR, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x630000);+ sljit_emit_op2(compiler, SLJIT_ASHR, SLJIT_R0, 0, SLJIT_R0, 0, shift_reg, 0);+ /* buf[12] */+ sljit_emit_op2(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 12, SLJIT_R1, 0, SLJIT_R0, 0);++ /* Test shift_reg keeps 64 bit value after 32 bit operation. */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -3062);+ sljit_emit_op2(compiler, SLJIT_ASHR32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ /* buf[13] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 13, shift_reg, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -4691);+ sljit_emit_op2(compiler, SLJIT_LSHR32, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_R0, 0);+ /* buf[14] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 14, shift_reg, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -0x3b7a81);+ sljit_emit_op2(compiler, SLJIT_ASHR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2);+ /* buf[15] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 15, SLJIT_R0, 0);++#if IS_64BIT && (defined SLJIT_UPPER_BITS_IGNORED && SLJIT_UPPER_BITS_IGNORED)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0xf7c8e5aef));+ sljit_emit_op2(compiler, SLJIT_LSHR32, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 4);+ /* buf[16] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 16, SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, SLJIT_W(0xff7e824baf));+ sljit_emit_op2(compiler, SLJIT_ASHR32, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, 8);+ /* buf[17] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 17, SLJIT_S1, 0);+#endif /* IS_64BIT && SLJIT_UPPER_BITS_IGNORED */++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ FAILED(buf[0] != 0x3c, "test9 case 1 failed\n");+ FAILED(buf[1] != 0xf0, "test9 case 2 failed\n");+ FAILED(buf[2] != -16, "test9 case 3 failed\n");+ FAILED(buf[3] != 0xff0, "test9 case 4 failed\n");+ FAILED(buf[4] != 4, "test9 case 5 failed\n");+ FAILED(buf[5] != 0xff00, "test9 case 6 failed\n");+ FAILED(buf[6] != 0x3c, "test9 case 7 failed\n");+ FAILED(buf[7] != 0xf0, "test9 case 8 failed\n");+ FAILED(buf[8] != 0xf0, "test9 case 9 failed\n");+ FAILED(buf[9] != 0x18, "test9 case 10 failed\n");+ FAILED(buf[10] != 32, "test9 case 11 failed\n");+ FAILED(buf[11] != 0x4ae37da9, "test9 case 12 failed\n");+ FAILED(buf[12] != 0x63f65c, "test9 case 13 failed\n");+ FAILED(buf[13] != -3062, "test9 case 14 failed\n");+ FAILED(buf[14] != -4691, "test9 case 15 failed\n");+ FAILED(buf[15] != -0xedea1, "test9 case 16 failed\n");+#if IS_64BIT && (defined SLJIT_UPPER_BITS_IGNORED && SLJIT_UPPER_BITS_IGNORED)+ FAILED(*(sljit_s32*)(buf + 16) != 0x7c8e5ae, "test9 case 17 failed\n");+ FAILED(*(sljit_s32*)(buf + 17) != 0x7e824b, "test9 case 18 failed\n");+#endif /* IS_64BIT && SLJIT_UPPER_BITS_IGNORED */++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test10(void)+{+ /* Test multiplications. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[7];++ if (verbose)+ printf("Run test10\n");++ FAILED(!compiler, "cannot create compiler\n");+ buf[0] = 3;+ buf[1] = 0;+ buf[2] = 0;+ buf[3] = 6;+ buf[4] = -10;+ buf[5] = 0;+ buf[6] = 0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 5);+ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 7);+ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_R0, 0, SLJIT_R2, 0, SLJIT_IMM, 8);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_R0, 0, SLJIT_IMM, -3, SLJIT_IMM, -4);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -2);+ /* buf[3] */+ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_sw) / 2);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf[3]);+ /* buf[4] */+ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 1, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 1, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 9);+ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R0, 0);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, SLJIT_R0, 0);+#if IS_64BIT+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 3);+ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x123456789));+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6, SLJIT_R0, 0);+#endif /* IS_64BIT */+ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 11, SLJIT_IMM, 10);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ FAILED(code.func1((sljit_sw)&buf) != 110, "test10 case 1 failed\n");+ FAILED(buf[0] != 15, "test10 case 2 failed\n");+ FAILED(buf[1] != 56, "test10 case 3 failed\n");+ FAILED(buf[2] != 12, "test10 case 4 failed\n");+ FAILED(buf[3] != -12, "test10 case 5 failed\n");+ FAILED(buf[4] != 100, "test10 case 6 failed\n");+ FAILED(buf[5] != 81, "test10 case 7 failed\n");+#if IS_64BIT+ FAILED(buf[6] != SLJIT_W(0x123456789) * 3, "test10 case 8 failed\n");+#endif /* IS_64BIT */++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test11(void)+{+ /* Test rewritable constants. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_const* const1;+ struct sljit_const* const2;+ struct sljit_const* const3;+ struct sljit_const* const4;+ void* value;+ sljit_sw executable_offset;+ sljit_uw const1_addr;+ sljit_uw const2_addr;+ sljit_uw const3_addr;+ sljit_uw const4_addr;+ sljit_sw word_value1 = WCONST(0xaaaaaaaaaaaaaaaa, 0xaaaaaaaa);+ sljit_sw word_value2 = WCONST(0xfee1deadfbadf00d, 0xfbadf00d);+ sljit_sw buf[3];++ if (verbose)+ printf("Run test11\n");++ FAILED(!compiler, "cannot create compiler\n");+ buf[0] = 0;+ buf[1] = 0;+ buf[2] = 0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 1, 0);++ SLJIT_ASSERT(!sljit_alloc_memory(compiler, 0));+ SLJIT_ASSERT(!sljit_alloc_memory(compiler, 16 * sizeof(sljit_sw) + 1));++ /* buf[0] */+ const1 = sljit_emit_const(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)&buf[0], -0x81b9);++ value = sljit_alloc_memory(compiler, 16 * sizeof(sljit_sw));+ if (value != NULL)+ {+ SLJIT_ASSERT(!((sljit_sw)value & ((sljit_sw)sizeof(sljit_sw) - 1)));+ memset(value, 255, 16 * sizeof(sljit_sw));+ }++ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2);+ const2 = sljit_emit_const(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT - 1, -65535);+ /* buf[2] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf[0] + 2 * (sljit_sw)sizeof(sljit_sw) - 2);+ const3 = sljit_emit_const(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, word_value1);++ value = sljit_alloc_memory(compiler, 17);+ if (value != NULL)+ {+ SLJIT_ASSERT(!((sljit_sw)value & ((sljit_sw)sizeof(sljit_sw) - 1)));+ memset(value, 255, 16);+ }++ /* Return value */+ const4 = sljit_emit_const(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, (sljit_sw)0xf7afcdb7);++ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ executable_offset = sljit_get_executable_offset(compiler);+ const1_addr = sljit_get_const_addr(const1);+ const2_addr = sljit_get_const_addr(const2);+ const3_addr = sljit_get_const_addr(const3);+ const4_addr = sljit_get_const_addr(const4);+ sljit_free_compiler(compiler);++ FAILED(code.func1((sljit_sw)&buf) != (sljit_sw)0xf7afcdb7, "test11 case 1 failed\n");+ FAILED(buf[0] != -0x81b9, "test11 case 2 failed\n");+ FAILED(buf[1] != -65535, "test11 case 3 failed\n");+ FAILED(buf[2] != word_value1, "test11 case 4 failed\n");++ /* buf[0] */+ sljit_set_const(const1_addr, SLJIT_MOV, -1, executable_offset);+ /* buf[1] */+ sljit_set_const(const2_addr, SLJIT_MOV, word_value2, executable_offset);+ /* buf[2] */+ sljit_set_const(const3_addr, SLJIT_MOV, (sljit_sw)0xbab0fea1, executable_offset);+ /* Return vaue */+ sljit_set_const(const4_addr, SLJIT_MOV, -60089, executable_offset);++ FAILED(code.func1((sljit_sw)&buf) != -60089, "test11 case 5 failed\n");+ FAILED(buf[0] != -1, "test11 case 6 failed\n");+ FAILED(buf[1] != word_value2, "test11 case 7 failed\n");+ FAILED(buf[2] != (sljit_sw)0xbab0fea1, "test11 case 8 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test12(void)+{+ /* Test rewriteable jumps. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_label *label1;+ struct sljit_label *label2;+ struct sljit_label *label3;+ struct sljit_jump *jump1;+ struct sljit_jump *jump2;+ struct sljit_jump *jump3;+ sljit_sw executable_offset;+ void* value;+ sljit_uw jump1_addr;+ sljit_uw label1_addr;+ sljit_uw label2_addr;+ sljit_sw buf[1];++ if (verbose)+ printf("Run test12\n");++ FAILED(!compiler, "cannot create compiler\n");+ buf[0] = 0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(P, W), 3, 2, 0);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_S1, 0, SLJIT_IMM, 10);+ jump1 = sljit_emit_jump(compiler, SLJIT_REWRITABLE_JUMP | SLJIT_SIG_GREATER);+ /* Default handler. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 5);+ jump2 = sljit_emit_jump(compiler, SLJIT_JUMP);++ value = sljit_alloc_memory(compiler, 15);+ if (value != NULL)+ {+ SLJIT_ASSERT(!((sljit_sw)value & ((sljit_sw)sizeof(sljit_sw) - 1)));+ memset(value, 255, 15);+ }++ /* Handler 1. */+ label1 = sljit_emit_label(compiler);+ sljit_emit_op0(compiler, SLJIT_ENDBR);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 6);+ jump3 = sljit_emit_jump(compiler, SLJIT_JUMP);+ /* Handler 2. */+ label2 = sljit_emit_label(compiler);+ sljit_emit_op0(compiler, SLJIT_ENDBR);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 7);+ /* Exit. */+ label3 = sljit_emit_label(compiler);+ sljit_emit_op0(compiler, SLJIT_ENDBR);+ sljit_set_label(jump2, label3);+ sljit_set_label(jump3, label3);+ /* By default, set to handler 1. */+ sljit_set_label(jump1, label1);+ sljit_emit_return_void(compiler);++ value = sljit_alloc_memory(compiler, 8);+ if (value != NULL)+ {+ SLJIT_ASSERT(!((sljit_sw)value & ((sljit_sw)sizeof(sljit_sw) - 1)));+ memset(value, 255, 8);+ }++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ executable_offset = sljit_get_executable_offset(compiler);+ jump1_addr = sljit_get_jump_addr(jump1);+ label1_addr = sljit_get_label_addr(label1);+ label2_addr = sljit_get_label_addr(label2);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)&buf, 4);+ FAILED(buf[0] != 5, "test12 case 1 failed\n");++ code.func2((sljit_sw)&buf, 11);+ FAILED(buf[0] != 6, "test12 case 2 failed\n");++ sljit_set_jump_addr(jump1_addr, label2_addr, executable_offset);+ code.func2((sljit_sw)&buf, 12);+ FAILED(buf[0] != 7, "test12 case 3 failed\n");++ sljit_set_jump_addr(jump1_addr, label1_addr, executable_offset);+ code.func2((sljit_sw)&buf, 13);+ FAILED(buf[0] != 6, "test12 case 4 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test13(void)+{+ /* Test emit const and jumps. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_label *label;+ struct sljit_jump *jump1;+ struct sljit_jump *jump2;+ struct sljit_const* const1;+ struct sljit_jump *mov_addr;+ sljit_sw executable_offset;+ sljit_uw const_addr;+ sljit_uw jump_addr;+ sljit_uw label_addr;+ sljit_sw buf[4];++ if (verbose)+ printf("Run test13\n");++ FAILED(!compiler, "cannot create compiler\n");+ buf[0] = 0;+ buf[1] = 0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 3, 2, 0);++ jump1 = sljit_emit_jump(compiler, SLJIT_JUMP);+ label = sljit_emit_label(compiler);+ jump2 = sljit_emit_jump(compiler, SLJIT_JUMP);+ sljit_set_label(jump2, label);+ label = sljit_emit_label(compiler);+ sljit_set_label(jump1, label);++ mov_addr = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_R2, 0);+ /* buf[0] */+ const1 = sljit_emit_const(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, -1234);++ sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_R2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, -1234);++ label = sljit_emit_label(compiler);+ sljit_set_label(mov_addr, label);++ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, -56789);+ jump1 = sljit_emit_jump(compiler, SLJIT_JUMP | SLJIT_REWRITABLE_JUMP);+ label = sljit_emit_label(compiler);+ sljit_set_label(jump1, label);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, 0);+ label = sljit_emit_label(compiler);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ executable_offset = sljit_get_executable_offset(compiler);+ const_addr = sljit_get_const_addr(const1);+ jump_addr = sljit_get_jump_addr(jump1);+ label_addr = sljit_get_label_addr(label);+ sljit_free_compiler(compiler);++ sljit_set_const(const_addr, SLJIT_MOV, 87654, executable_offset);+ sljit_set_jump_addr(jump_addr, label_addr, executable_offset);++ code.func1((sljit_sw)&buf);+ FAILED(buf[0] != 87654, "test13 case 1 failed\n");+ FAILED(buf[1] != -56789, "test13 case 2 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test14(void)+{+ /* Test arm constant pool. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_s32 i;+ sljit_sw buf[5];++ if (verbose)+ printf("Run test14\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 5; i++)+ buf[i] = 0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 3, 1, 0);+ for (i = 0; i <= 0xfff; i++) {+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0x81818000 | i);+ if ((i & 0x3ff) == 0)+ /* buf[0-3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), (i >> 10) * (sljit_sw)sizeof(sljit_sw), SLJIT_R0, 0);+ }+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ FAILED((sljit_uw)buf[0] != 0x81818000, "test14 case 1 failed\n");+ FAILED((sljit_uw)buf[1] != 0x81818400, "test14 case 2 failed\n");+ FAILED((sljit_uw)buf[2] != 0x81818800, "test14 case 3 failed\n");+ FAILED((sljit_uw)buf[3] != 0x81818c00, "test14 case 4 failed\n");+ FAILED((sljit_uw)buf[4] != 0x81818fff, "test14 case 5 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test15(void)+{+ /* Test 64 bit. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_s32 i;+ sljit_sw buf[13];++ if (verbose)+ printf("Run test15\n");++ FAILED(!compiler, "cannot create compiler\n");+ for (i = 0; i < 13; i++)+ buf[i] = 0;++ buf[5] = 100;+ buf[6] = 100;+ buf[7] = 100;+ buf[8] = 100;+#if IS_64BIT && (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN)+ buf[10] = SLJIT_W(1) << 32;+#else /* !IS_64BIT || !SLJIT_BIG_ENDIAN */+ buf[10] = 1;+#endif /* IS_64BIT && SLJIT_BIG_ENDIAN */++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 3, 2, 0);++#if IS_64BIT+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, SLJIT_W(0x1122334455667788));+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, SLJIT_W(0x1122334455667788));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(1000000000000));+ /* buf[2] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(1000000000000));+ /* buf[3] */+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_IMM, SLJIT_W(5000000000000), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x1108080808));+ /* buf[4] */+ sljit_emit_op2(compiler, SLJIT_ADD32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x1120202020));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x1108080808));+ sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x1120202020));+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_ZERO);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, SLJIT_S1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_R0, 0);+ sljit_emit_op2u(compiler, SLJIT_AND32 | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x1120202020));+ /* buf[6] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6, SLJIT_ZERO);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x1108080808));+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x2208080808));+ /* buf[7] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7, SLJIT_LESS);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_R0, 0);+ sljit_emit_op2u(compiler, SLJIT_AND32 | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x1104040404));+ /* buf[8] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 8, SLJIT_NOT_ZERO);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 4);+ /* buf[9] */+ sljit_emit_op2(compiler, SLJIT_SHL32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 9, SLJIT_IMM, SLJIT_W(0xffff0000), SLJIT_R0, 0);+ /* buf[10] */+ sljit_emit_op2(compiler, SLJIT_MUL32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 10, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 10, SLJIT_IMM, -1);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, -11);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 20);+ sljit_emit_op2(compiler, SLJIT_ADD32 | SLJIT_SET_CARRY, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R0, 0);+ /* buf[11] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 11, SLJIT_R1, 0);+ sljit_emit_op2(compiler, SLJIT_ADDC32, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_R0, 0);+ /* buf[12] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 12, SLJIT_R0, 0);+#else /* !IS_64BIT */+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 0x11223344);+ /* buf[1] */+ sljit_emit_op2(compiler, SLJIT_ADD32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, 0x44332211);+#endif /* IS_64BIT */++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+#if IS_64BIT+ FAILED(buf[0] != SLJIT_W(0x1122334455667788), "test15 case 1 failed\n");+#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+ FAILED(buf[1] != 0x55667788, "test15 case 2 failed\n");+#else /* !SLJIT_LITTLE_ENDIAN */+ FAILED(buf[1] != SLJIT_W(0x5566778800000000), "test15 case 2 failed\n");+#endif /* SLJIT_LITTLE_ENDIAN */+ FAILED(buf[2] != SLJIT_W(2000000000000), "test15 case 3 failed\n");+ FAILED(buf[3] != SLJIT_W(4000000000000), "test15 case 4 failed\n");+#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+ FAILED(buf[4] != 0x28282828, "test15 case 5 failed\n");+#else /* !SLJIT_LITTLE_ENDIAN */+ FAILED(buf[4] != SLJIT_W(0x2828282800000000), "test15 case 5 failed\n");+#endif /* SLJIT_LITTLE_ENDIAN */+ FAILED(buf[5] != 0, "test15 case 6 failed\n");+ FAILED(buf[6] != 1, "test15 case 7 failed\n");+ FAILED(buf[7] != 1, "test15 case 8 failed\n");+ FAILED(buf[8] != 0, "test15 case 9 failed\n");+#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+ FAILED(buf[9] != (sljit_sw)0xfff00000, "test15 case 10 failed\n");+ FAILED(buf[10] != (sljit_sw)0xffffffff, "test15 case 11 failed\n");+#else /* !SLJIT_LITTLE_ENDIAN */+ FAILED(buf[9] != (sljit_sw)SLJIT_W(0xfff0000000000000), "test15 case 10 failed\n");+ FAILED(buf[10] != (sljit_sw)SLJIT_W(0xffffffff00000000), "test15 case 11 failed\n");+#endif /* SLJIT_LITTLE_ENDIAN */+ FAILED(*(sljit_s32*)(buf + 11) != 9, "test15 case 12 failed\n");+ FAILED(*(sljit_s32*)(buf + 12) != 30, "test15 case 13 failed\n");+#else /* !IS_64BIT */+ FAILED(buf[0] != 0x11223344, "test15 case 1 failed\n");+ FAILED(buf[1] != 0x44332211, "test15 case 2 failed\n");+#endif /* IS_64BIT */++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test16(void)+{+ /* Test arm partial instruction caching. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[10];++ if (verbose)+ printf("Run test16\n");++ FAILED(!compiler, "cannot create compiler\n");+ buf[0] = 6;+ buf[1] = 4;+ buf[2] = 0;+ buf[3] = 0;+ buf[4] = 0;+ buf[5] = 0;+ buf[6] = 2;+ buf[7] = 0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 3, 1, 0);+ /* buf[0] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw));+ /* buf[2] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM0(), (sljit_sw)&buf[2], SLJIT_MEM0(), (sljit_sw)&buf[1], SLJIT_MEM0(), (sljit_sw)&buf[0]);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw));+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_MEM1(SLJIT_R0), (sljit_sw)&buf[0], SLJIT_MEM1(SLJIT_R1), (sljit_sw)&buf[0]);+ /* buf[4] */+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_MEM0(), (sljit_sw)&buf[0], SLJIT_IMM, 2);+ /* buf[5] */+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_R0), (sljit_sw)&buf[0] + 4 * (sljit_sw)sizeof(sljit_sw));+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7, SLJIT_IMM, 10);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 7);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_R1), (sljit_sw)&buf[5], SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM1(SLJIT_R1), (sljit_sw)&buf[5]);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ FAILED(buf[0] != 10, "test16 case 1 failed\n");+ FAILED(buf[1] != 4, "test16 case 2 failed\n");+ FAILED(buf[2] != 14, "test16 case 3 failed\n");+ FAILED(buf[3] != 14, "test16 case 4 failed\n");+ FAILED(buf[4] != 8, "test16 case 5 failed\n");+ FAILED(buf[5] != 6, "test16 case 6 failed\n");+ FAILED(buf[6] != 12, "test16 case 7 failed\n");+ FAILED(buf[7] != 10, "test16 case 8 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test17(void)+{+ /* Test stack. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_jump* jump;+ struct sljit_label* label;+ sljit_sw buf[7];+ sljit_sw offset_value = WCONST(0x1234567812345678, 0x12345678);++ if (verbose)+ printf("Run test17\n");++ FAILED(!compiler, "cannot create compiler\n");+ buf[0] = 5;+ buf[1] = 12;+ buf[2] = 0;+ buf[3] = 0;+ buf[4] = 111;+ buf[6] = -12345;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 5, 5, 4 * sizeof(sljit_sw));+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_uw), SLJIT_MEM1(SLJIT_S0), 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_uw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_IMM, -1);+ /* buf[2] */+ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_uw), SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_uw));+ /* buf[3] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_uw), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_uw), SLJIT_MEM1(SLJIT_SP), 0);+ sljit_get_local_base(compiler, SLJIT_R0, 0, -offset_value);+ sljit_get_local_base(compiler, SLJIT_MEM1(SLJIT_S0), 0, -0x1234);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), 0);+ /* buf[4] */+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_uw), SLJIT_MEM1(SLJIT_R0), offset_value, SLJIT_MEM1(SLJIT_R1), 0x1234 + sizeof(sljit_sw));+ sljit_get_local_base(compiler, SLJIT_MEM1(SLJIT_SP), 0, 8);+ sljit_get_local_base(compiler, SLJIT_R0, 0, 4);+ /* buf[5] */+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_uw), SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R0, 0);+ /* buf[6] */+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_uw));+ /* Dummy last instructions. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 23);+ sljit_emit_label(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ FAILED(code.func1((sljit_sw)&buf) != -12345, "test17 case 1 failed\n");++ FAILED(buf[2] != 60, "test17 case 2 failed\n");+ FAILED(buf[3] != 17, "test17 case 3 failed\n");+ FAILED(buf[4] != 7, "test17 case 4 failed\n");+ FAILED(buf[5] != 4, "test17 case 5 failed\n");++ sljit_free_code(code.code, NULL);++ compiler = sljit_create_compiler(NULL);+ sljit_emit_enter(compiler, 0, SLJIT_ARGS3(W, W, W, W), 3, 3, SLJIT_MAX_LOCAL_SIZE);++ sljit_get_local_base(compiler, SLJIT_R0, 0, SLJIT_MAX_LOCAL_SIZE - sizeof(sljit_sw));+ sljit_get_local_base(compiler, SLJIT_R1, 0, -(sljit_sw)sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -1);+ label = sljit_emit_label(compiler);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R2, 0);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R0, 0);+ jump = sljit_emit_jump(compiler, SLJIT_NOT_EQUAL);+ sljit_set_label(jump, label);++ /* Saved registers should keep their value. */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_S1, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_S2, 0);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ FAILED(code.func3(1234, 5678, 9012) != 15924, "test17 case 5 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test18(void)+{+ /* Test set context. The parts of the jit code can be separated in the memory. */+ executable_code code1;+ executable_code code2;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_jump* jump = NULL;+ sljit_uw addr;+ sljit_sw executable_offset;+ sljit_sw buf[4];++ if (verbose)+ printf("Run test18\n");++ FAILED(!compiler, "cannot create compiler\n");+ buf[0] = 9;+ buf[1] = -6;+ buf[2] = 0;+ buf[3] = 0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 2, 2 * sizeof(sljit_sw));++ /* Return value */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 10);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_SP), 0);++ jump = sljit_emit_jump(compiler, SLJIT_JUMP | SLJIT_REWRITABLE_JUMP);+ sljit_set_target(jump, 0);++ code1.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ executable_offset = sljit_get_executable_offset(compiler);+ addr = sljit_get_jump_addr(jump);++ sljit_free_compiler(compiler);++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ /* Other part of the jit code. */+ sljit_set_context(compiler, 0, 1, 3, 2, 2 * sizeof(sljit_sw));++ sljit_emit_op0(compiler, SLJIT_ENDBR);+ /* buf[2] */+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), 0);+ /* buf[3] */+ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw));++ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);++ code2.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ sljit_set_jump_addr(addr, SLJIT_FUNC_UADDR(code2.code), executable_offset);++ FAILED(code1.func1((sljit_sw)&buf) != 19, "test18 case 1 failed\n");+ FAILED(buf[2] != -16, "test18 case 2 failed\n");+ FAILED(buf[3] != 100, "test18 case 3 failed\n");++ sljit_free_code(code1.code, NULL);+ sljit_free_code(code2.code, NULL);+ successful_tests++;+}++static void test19(void)+{+ /* Test simple byte and half-int data transfers. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[4];+ sljit_s16 sbuf[9];+ sljit_s8 bbuf[5];++ if (verbose)+ printf("Run test19\n");++ FAILED(!compiler, "cannot create compiler\n");+ buf[0] = 0;+ buf[1] = 0;+ buf[2] = -1;+ buf[3] = -1;++ sbuf[0] = 0;+ sbuf[1] = 0;+ sbuf[2] = -9;+ sbuf[3] = 0;+ sbuf[4] = 0;+ sbuf[5] = 0;+ sbuf[6] = 0;++ bbuf[0] = 0;+ bbuf[1] = 0;+ bbuf[2] = -56;+ bbuf[3] = 0;+ bbuf[4] = 0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS3V(P, P, P), 3, 3, 0);++ /* sbuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_IMM, -13);+ /* sbuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s16), SLJIT_IMM, 0x1234);+ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s16));+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, 2 * sizeof(sljit_s16));+ /* sbuf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s16), SLJIT_MEM1(SLJIT_S1), -(sljit_sw)sizeof(sljit_s16));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0xff0000 + 8000);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 2);+ /* sbuf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM2(SLJIT_S1, SLJIT_R1), 1, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R2, 0, SLJIT_S1, 0, SLJIT_IMM, 0x1234 - 3 * sizeof(sljit_s16));+ /* sbuf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM1(SLJIT_R2), 0x1234, SLJIT_IMM, -9317);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S1, 0, SLJIT_IMM, 0x1234 + 4 * sizeof(sljit_s16));+ /* sbuf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM1(SLJIT_R2), -0x1234, SLJIT_IMM, -9317);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R2, 0, SLJIT_S1, 0, SLJIT_IMM, 0x12348 - 5 * sizeof(sljit_s16));+ /* sbuf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM1(SLJIT_R2), 0x12348, SLJIT_IMM, -8888);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S1, 0, SLJIT_IMM, 0x12348 + 6 * sizeof(sljit_s16));+ /* sbuf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM1(SLJIT_R2), -0x12348, SLJIT_IMM, -8888);++ /* bbuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_MEM1(SLJIT_S2), 0, SLJIT_IMM, -45);+ /* sbuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_s8), SLJIT_IMM, 0x12);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 4 * sizeof(sljit_s8));+ sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S2), 2 * sizeof(sljit_s8));+ sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_S1, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_S1, 0, SLJIT_S1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_R2, 0, SLJIT_S1, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R2, 0);+ /* bbuf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S2), 3 * sizeof(sljit_s8), SLJIT_S1, 0);+ /* bbuf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM2(SLJIT_S2, SLJIT_R0), 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_R0, 0, SLJIT_IMM, 0);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func3((sljit_sw)&buf, (sljit_sw)&sbuf, (sljit_sw)&bbuf);+ FAILED(buf[0] != -9, "test19 case 1 failed\n");+ FAILED(buf[1] != -56, "test19 case 2 failed\n");+ FAILED(buf[2] != 0, "test19 case 3 failed\n");+ FAILED(buf[3] != 0, "test19 case 4 failed\n");++ FAILED(sbuf[0] != -13, "test19 case 5 failed\n");+ FAILED(sbuf[1] != 0x1234, "test19 case 6 failed\n");+ FAILED(sbuf[3] != 0x1234, "test19 case 7 failed\n");+ FAILED(sbuf[4] != 8000, "test19 case 8 failed\n");+ FAILED(sbuf[5] != -9317, "test19 case 9 failed\n");+ FAILED(sbuf[6] != -9317, "test19 case 10 failed\n");+ FAILED(sbuf[7] != -8888, "test19 case 11 failed\n");+ FAILED(sbuf[8] != -8888, "test19 case 12 failed\n");++ FAILED(bbuf[0] != -45, "test19 case 13 failed\n");+ FAILED(bbuf[1] != 0x12, "test19 case 14 failed\n");+ FAILED(bbuf[3] != -56, "test19 case 15 failed\n");+ FAILED(bbuf[4] != 4, "test19 case 16 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test20(void)+{+ /* Test 32 bit / 64 bit signed / unsigned int transfer and conversion.+ This test has do real things on 64 bit systems, but works on 32 bit systems as well. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[9];+ sljit_s32 ibuf[5];+ union {+ sljit_s32 asint;+ sljit_u8 asbytes[4];+ } u;+ sljit_sw garbage = WCONST(0x1234567812345678, 0x12345678);++ if (verbose)+ printf("Run test20\n");++ FAILED(!compiler, "cannot create compiler\n");+ buf[0] = 0;+ buf[1] = 0;+ buf[2] = 0;+ buf[3] = 0;+ buf[4] = 0;+ buf[5] = 0;+ buf[6] = 0;+ buf[7] = 0;+ buf[8] = 0;++ ibuf[0] = 0;+ ibuf[1] = 0;+ ibuf[2] = -5791;+ ibuf[3] = 43579;+ ibuf[4] = 658923;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2(W, P, P), 3, 3, 0);+ /* ibuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_IMM, 34567);+ /* ibuf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 4);+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), 0, SLJIT_IMM, -7654);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, garbage);+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, garbage);+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, garbage);+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_s32));+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x0f00f00);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 0x7777);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0x7777 + 3 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[4] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 0x7777);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), -0x7777 + 4 * (sljit_sw)sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[5] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 5 * sizeof(sljit_sw));+ sljit_emit_op2(compiler, SLJIT_LSHR, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_R1, SLJIT_R1), 0, SLJIT_IMM, 16);+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op2(compiler, SLJIT_OR, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 1, SLJIT_IMM, 64, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)&buf[7], SLJIT_IMM, 0x123456);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), (sljit_sw)&buf[6], SLJIT_MEM0(), (sljit_sw)&buf[7]);+ /* buf[7] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 5 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_R1, 0);+ /* buf[8] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S0, 0, SLJIT_IMM, 7 * sizeof(sljit_sw));+ sljit_emit_op2(compiler, SLJIT_LSHR, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM2(SLJIT_R2, SLJIT_R2), 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf[8] - 0x12340);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0x12340, SLJIT_R2, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_R0), 0x12340, SLJIT_MEM1(SLJIT_R2), 3 * sizeof(sljit_sw), SLJIT_IMM, 6);+ /* ibuf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_s32), SLJIT_IMM, 0x12345678);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x2bd700 | 243);+ sljit_emit_return(compiler, SLJIT_MOV_S8, SLJIT_R1, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ FAILED(code.func2((sljit_sw)&buf, (sljit_sw)&ibuf) != -13, "test20 case 1 failed\n");+ FAILED(buf[0] != -5791, "test20 case 2 failed\n");+ FAILED(buf[1] != 43579, "test20 case 3 failed\n");+ FAILED(buf[2] != 658923, "test20 case 4 failed\n");+ FAILED(buf[3] != 0x0f00f00, "test20 case 5 failed\n");+ FAILED(buf[4] != 0x0f00f00, "test20 case 6 failed\n");+ FAILED(buf[5] != 80, "test20 case 7 failed\n");+ FAILED(buf[6] != 0x123456, "test20 case 8 failed\n");+ FAILED(buf[7] != (sljit_sw)&buf[5], "test20 case 9 failed\n");+ FAILED(buf[8] != (sljit_sw)&buf[5] + 6, "test20 case 10 failed\n");++ FAILED(ibuf[0] != 34567, "test20 case 11 failed\n");+ FAILED(ibuf[1] != -7654, "test20 case 12 failed\n");+ u.asint = ibuf[4];+#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+ FAILED(u.asbytes[0] != 0x78, "test20 case 13 failed\n");+ FAILED(u.asbytes[1] != 0x56, "test20 case 14 failed\n");+ FAILED(u.asbytes[2] != 0x34, "test20 case 15 failed\n");+ FAILED(u.asbytes[3] != 0x12, "test20 case 16 failed\n");+#else /* !SLJIT_LITTLE_ENDIAN */+ FAILED(u.asbytes[0] != 0x12, "test20 case 13 failed\n");+ FAILED(u.asbytes[1] != 0x34, "test20 case 14 failed\n");+ FAILED(u.asbytes[2] != 0x56, "test20 case 15 failed\n");+ FAILED(u.asbytes[3] != 0x78, "test20 case 16 failed\n");+#endif /* SLJIT_LITTLE_ENDIAN */++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test21(void)+{+ /* Some complicated addressing modes. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[9];+ sljit_s16 sbuf[5];+ sljit_s8 bbuf[7];++ if (verbose)+ printf("Run test21\n");++ FAILED(!compiler, "cannot create compiler\n");++ buf[0] = 100567;+ buf[1] = 75799;+ buf[2] = 0;+ buf[3] = -8;+ buf[4] = -50;+ buf[5] = 0;+ buf[6] = 0;+ buf[7] = 0;+ buf[8] = 0;++ sbuf[0] = 30000;+ sbuf[1] = 0;+ sbuf[2] = 0;+ sbuf[3] = -12345;+ sbuf[4] = 0;++ bbuf[0] = -128;+ bbuf[1] = 0;+ bbuf[2] = 0;+ bbuf[3] = 99;+ bbuf[4] = 0;+ bbuf[5] = 0;+ bbuf[6] = 0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS3V(P, P, P), 3, 3, 0);++ /* Nothing should be updated. */+ /* sbuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM0(), (sljit_sw)&sbuf[1], SLJIT_MEM0(), (sljit_sw)&sbuf[0]);+ /* bbuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_MEM0(), (sljit_sw)&bbuf[1], SLJIT_MEM0(), (sljit_sw)&bbuf[0]);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2);+ /* sbuf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), 1, SLJIT_MEM0(), (sljit_sw)&sbuf[3]);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf[0]);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 2);+ /* buf[2] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM2(SLJIT_R0, SLJIT_R2), SLJIT_WORD_SHIFT, SLJIT_MEM0(), (sljit_sw)&buf[0], SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_s8));+ /* bbuf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_R0), (sljit_sw)&bbuf[1], SLJIT_MEM1(SLJIT_R0), (sljit_sw)&bbuf[2]);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_s16));+ /* sbuf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM1(SLJIT_R1), (sljit_sw)&sbuf[3], SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 3);+ /* buf[3] */+ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 4);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_S0, 0);+ /* buf[4] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 9 * sizeof(sljit_sw));+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 4 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -(4 << SLJIT_WORD_SHIFT));+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_R0, SLJIT_R2), 0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf - 0x7fff8000 + 6 * (sljit_sw)sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 952467);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0x7fff8000, SLJIT_R1, 0);+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0x7fff8000 + sizeof(sljit_sw), SLJIT_MEM1(SLJIT_R0), 0x7fff8000);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf + 0x7fff7fff + 6 * (sljit_sw)sizeof(sljit_sw));+ /* buf[8] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_R0), -0x7fff7fff + 2 * (sljit_sw)sizeof(sljit_sw), SLJIT_MEM1(SLJIT_R0), -0x7fff7fff + (sljit_sw)sizeof(sljit_sw), SLJIT_MEM1(SLJIT_R0), -0x7fff7fff);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&bbuf - 0x7fff7ffe + 3 * (sljit_sw)sizeof(sljit_s8));+ /* bbuf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_MEM1(SLJIT_R0), 0x7fff7fff, SLJIT_MEM1(SLJIT_R0), 0x7fff7ffe);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&bbuf + 0x7fff7fff + 5 * (sljit_sw)sizeof(sljit_s8));+ /* bbuf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_MEM1(SLJIT_R0), -0x7fff7fff, SLJIT_MEM1(SLJIT_R0), -0x7fff8000);+#if IS_64BIT+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&bbuf - SLJIT_W(0x123456123456));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&bbuf - SLJIT_W(0x123456123456));+ /* bbuf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_MEM1(SLJIT_R0), SLJIT_W(0x123456123456) + 6 * sizeof(sljit_s8), SLJIT_MEM1(SLJIT_R1), SLJIT_W(0x123456123456));+#endif /* IS_64BIT */++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func3((sljit_sw)&buf, (sljit_sw)&sbuf, (sljit_sw)&bbuf);+ FAILED(buf[2] != 176366, "test21 case 1 failed\n");+ FAILED(buf[3] != 64, "test21 case 2 failed\n");+ FAILED(buf[4] != -100, "test21 case 3 failed\n");+ FAILED(buf[5] != 100567, "test21 case 4 failed\n");+ FAILED(buf[6] != 952467, "test21 case 5 failed\n");+ FAILED(buf[7] != 952467, "test21 case 6 failed\n");+ FAILED(buf[8] != 952467 * 2, "test21 case 7 failed\n");++ FAILED(sbuf[1] != 30000, "test21 case 8 failed\n");+ FAILED(sbuf[2] != -12345, "test21 case 9 failed\n");+ FAILED(sbuf[4] != sizeof(sljit_s16), "test21 case 10 failed\n");++ FAILED(bbuf[1] != -128, "test21 case 11 failed\n");+ FAILED(bbuf[2] != 99, "test21 case 12 failed\n");+ FAILED(bbuf[4] != 99, "test21 case 13 failed\n");+ FAILED(bbuf[5] != 99, "test21 case 14 failed\n");+#if IS_64BIT+ FAILED(bbuf[6] != -128, "test21 case 15 failed\n");+#endif /* IS_64BIT */++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test22(void)+{+#if IS_64BIT+ /* 64 bit loads. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_s32 i;+ sljit_sw buf[16];++ if (verbose)+ printf("Run test22\n");++ FAILED(!compiler, "cannot create compiler\n");+ for (i = 0; i < 15; i++)+ buf[i] = SLJIT_W(0x1aaaaaaaaaaaaaaa);++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 3, 1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 1 * sizeof(sljit_sw), SLJIT_IMM, 0x7fff);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_IMM, -0x8000);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_IMM, 0x7fffffff);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_IMM, SLJIT_W(-0x80000000));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_IMM, SLJIT_W(0x1234567887654321));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_IMM, SLJIT_W(0xff80000000));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_IMM, SLJIT_W(0x3ff0000000));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_IMM, (sljit_sw)SLJIT_W(0xfffffff800100000));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_IMM, (sljit_sw)SLJIT_W(0xfffffff80010f000));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_IMM, SLJIT_W(0x07fff00000008001));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_IMM, SLJIT_W(0x07fff00080010000));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_IMM, SLJIT_W(0x07fff00080018001));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_IMM, SLJIT_W(0x07fff00ffff00000));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_IMM, 0x1f8ff);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_IMM, SLJIT_W(0xde12347ffffabc));++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ FAILED(buf[0] != 0, "test22 case 1 failed\n");+ FAILED(buf[1] != 0x7fff, "test22 case 2 failed\n");+ FAILED(buf[2] != -0x8000, "test22 case 3 failed\n");+ FAILED(buf[3] != 0x7fffffff, "test22 case 4 failed\n");+ FAILED(buf[4] != SLJIT_W(-0x80000000), "test22 case 5 failed\n");+ FAILED(buf[5] != SLJIT_W(0x1234567887654321), "test22 case 6 failed\n");+ FAILED(buf[6] != SLJIT_W(0xff80000000), "test22 case 7 failed\n");+ FAILED(buf[7] != SLJIT_W(0x3ff0000000), "test22 case 8 failed\n");+ FAILED((sljit_uw)buf[8] != SLJIT_W(0xfffffff800100000), "test22 case 9 failed\n");+ FAILED((sljit_uw)buf[9] != SLJIT_W(0xfffffff80010f000), "test22 case 10 failed\n");+ FAILED(buf[10] != SLJIT_W(0x07fff00000008001), "test22 case 11 failed\n");+ FAILED(buf[11] != SLJIT_W(0x07fff00080010000), "test22 case 12 failed\n");+ FAILED(buf[12] != SLJIT_W(0x07fff00080018001), "test22 case 13 failed\n");+ FAILED(buf[13] != SLJIT_W(0x07fff00ffff00000), "test22 case 14 failed\n");+ FAILED(buf[14] != 0x1f8ff, "test22 case 15 failed\n");+ FAILED(buf[15] != SLJIT_W(0xde12347ffffabc), "test22 case 16 failed\n");++ sljit_free_code(code.code, NULL);+#endif /* IS_64BIT */+ successful_tests++;+}++static void test23(void)+{+ /* Aligned access without aligned offsets. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[4];+ sljit_s32 ibuf[4];+ sljit_f64 dbuf[4];++ if (verbose)+ printf("Run test23\n");++ FAILED(!compiler, "cannot create compiler\n");++ buf[0] = -2789;+ buf[1] = 0;+ buf[2] = 4;+ buf[3] = -4;++ ibuf[0] = -689;+ ibuf[1] = 0;+ ibuf[2] = -6;+ ibuf[3] = 3;++ dbuf[0] = 5.75;+ dbuf[1] = 0.0;+ dbuf[2] = 0.0;+ dbuf[3] = -4.0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS3V(P, P, P), 3, 3, 0);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 3);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), -3);+ /* ibuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32) - 1, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), -1);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) - 3, SLJIT_R0, 0);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 100);+ /* buf[2] */+ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_MEM1(SLJIT_R0), (sljit_sw)sizeof(sljit_sw) * 2 - 103, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2 - 3, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3 - 3);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_IMM, 100);+ /* ibuf[2] */+ sljit_emit_op2(compiler, SLJIT_MUL32, SLJIT_MEM1(SLJIT_R0), (sljit_sw)sizeof(sljit_s32) * 2 - 101, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32) * 2 - 1, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32) * 3 - 1);++ if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S2, 0, SLJIT_S2, 0, SLJIT_IMM, 3);+ /* dbuf[1] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f64) - 3, SLJIT_MEM1(SLJIT_S2), -3);+ /* dbuf[2] */+ sljit_emit_fop2(compiler, SLJIT_ADD_F64, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f64) * 2 - 3, SLJIT_MEM1(SLJIT_S2), -3, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f64) - 3);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S2, 0, SLJIT_IMM, 2);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sizeof(sljit_f64) * 3 - 4) >> 1);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S2, 0, SLJIT_IMM, 1);+ /* dbuf[3] */+ sljit_emit_fop2(compiler, SLJIT_DIV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64) * 3 - 5, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f64) * 2 - 3, SLJIT_MEM2(SLJIT_R2, SLJIT_R1), 1);+ }++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func3((sljit_sw)&buf, (sljit_sw)&ibuf, (sljit_sw)&dbuf);++ FAILED(buf[1] != -689, "test23 case 1 failed\n");+ FAILED(buf[2] != -16, "test23 case 2 failed\n");+ FAILED(ibuf[1] != -2789, "test23 case 3 failed\n");+ FAILED(ibuf[2] != -18, "test23 case 4 failed\n");++ if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) {+ FAILED(dbuf[1] != 5.75, "test23 case 5 failed\n");+ FAILED(dbuf[2] != 11.5, "test23 case 6 failed\n");+ FAILED(dbuf[3] != -2.875, "test23 case 7 failed\n");+ }++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test24(void)+{+#define SET_NEXT_BYTE(type) \+ cond_set(compiler, SLJIT_R2, 0, type); \+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S0), 1, SLJIT_R2, 0); \+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 1);+#if IS_64BIT+#define RESULT(i) i+#else /* !IS_64BIT */+#define RESULT(i) (3 - i)+#endif /* IS_64BIT */++ /* Playing with conditional flags. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_u8 buf[45];+ sljit_u32 i;+#ifdef SLJIT_PREF_SHIFT_REG+ sljit_s32 shift_reg = SLJIT_PREF_SHIFT_REG;+#else /* !SLJIT_PREF_SHIFT_REG */+ sljit_s32 shift_reg = SLJIT_R2;+#endif /* SLJIT_PREF_SHIFT_REG */++ SLJIT_ASSERT(shift_reg >= SLJIT_R2 && shift_reg <= SLJIT_R3);++ if (verbose)+ printf("Run test24\n");++ for (i = 0; i < sizeof(buf); ++i)+ buf[i] = 0xaa;++ FAILED(!compiler, "cannot create compiler\n");++ /* 3 arguments passed, 3 arguments used. */+ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 4, 3, 0);++ /* buf[0] */+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 1);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x1001);+ sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 20);+ /* 0x100100000 on 64 bit machines, 0x100000 on 32 bit machines. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x800000);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op0(compiler, SLJIT_ENDBR); /* ENDBR should keep the flags. */+ sljit_emit_op0(compiler, SLJIT_NOP); /* Nop should keep the flags. */+ SET_NEXT_BYTE(SLJIT_GREATER);+ /* buf[2] */+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_R1, 0);+ SET_NEXT_BYTE(SLJIT_LESS);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_R1, 0);+ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_GREATER, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op0(compiler, SLJIT_ENDBR); /* ENDBR should keep the flags. */+ sljit_emit_op0(compiler, SLJIT_NOP); /* Nop should keep the flags. */+ SET_NEXT_BYTE(SLJIT_GREATER);+ /* buf[4] */+ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_R1, 0);+ SET_NEXT_BYTE(SLJIT_LESS);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x1000);+ sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 20);+ sljit_emit_op2(compiler, SLJIT_OR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0x10);+ /* 0x100000010 on 64 bit machines, 0x10 on 32 bit machines. */+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R0, 0, SLJIT_IMM, 0x80);+ SET_NEXT_BYTE(SLJIT_GREATER);+ /* buf[6] */+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 0x80);+ SET_NEXT_BYTE(SLJIT_LESS);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_R0, 0);+ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_GREATER, SLJIT_R0, 0, SLJIT_IMM, 0x80);+ SET_NEXT_BYTE(SLJIT_GREATER);+ /* buf[7] */+ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 0x80);+ SET_NEXT_BYTE(SLJIT_LESS);++ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1);+ /* 0xff..ff on all machines. */+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 1);+ SET_NEXT_BYTE(SLJIT_LESS_EQUAL);+ /* buf[9] */+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 1);+ SET_NEXT_BYTE(SLJIT_GREATER_EQUAL);+ /* buf[10] */+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R2, 0, SLJIT_R1, 0, SLJIT_IMM, -1);+ SET_NEXT_BYTE(SLJIT_SIG_GREATER);+ /* buf[12] */+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, -1);+ SET_NEXT_BYTE(SLJIT_SIG_LESS);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R1, 0, SLJIT_R0, 0);+ SET_NEXT_BYTE(SLJIT_EQUAL);+ /* buf[14] */+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_R0, 0);+ SET_NEXT_BYTE(SLJIT_NOT_EQUAL);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, -2);+ SET_NEXT_BYTE(SLJIT_OVERFLOW);+ /* buf[16] */+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, -2);+ SET_NEXT_BYTE(SLJIT_NOT_OVERFLOW);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, -2);+ SET_NEXT_BYTE(SLJIT_GREATER_EQUAL);+ /* buf[17] */+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, -2);+ SET_NEXT_BYTE(SLJIT_LESS_EQUAL);+ /* buf[20] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)((sljit_uw)1 << ((8 * sizeof(sljit_uw)) - 1)));+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, 1);+ SET_NEXT_BYTE(SLJIT_SIG_LESS);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -1);+ SET_NEXT_BYTE(SLJIT_SIG_GREATER);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, 1);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER_EQUAL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -2);+ SET_NEXT_BYTE(SLJIT_SIG_GREATER_EQUAL);+ /* buf[21] */+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2);+ SET_NEXT_BYTE(SLJIT_SIG_GREATER);++ /* buf[22] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0x80000000);+ sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 16);+ sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 16);+ /* 0x80..0 on 64 bit machines, 0 on 32 bit machines. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)0xffffffff);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R1, 0);+ SET_NEXT_BYTE(SLJIT_OVERFLOW);+ /* buf[24] */+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R1, 0);+ SET_NEXT_BYTE(SLJIT_NOT_OVERFLOW);+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_R1, 0);+ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R1, 0);+ SET_NEXT_BYTE(SLJIT_OVERFLOW);+ /* buf[25] */+ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R1, 0);+ SET_NEXT_BYTE(SLJIT_NOT_OVERFLOW);++ /* buf[26] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op2u(compiler, SLJIT_SUBC | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op2(compiler, SLJIT_SUBC, SLJIT_R0, 0, SLJIT_IMM, 6, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S0), 1, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 1);++ /* buf[27] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1);+ sljit_emit_op2u(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op2u(compiler, SLJIT_ADDC | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op2(compiler, SLJIT_ADDC, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 9);+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S0), 1, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 1);++ /* buf[28] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, (8 * sizeof(sljit_sw)) - 1);+ sljit_emit_op2u(compiler, SLJIT_ADD | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 0);+ SET_NEXT_BYTE(SLJIT_EQUAL);+ /* buf[29] */+ sljit_emit_op2u(compiler, SLJIT_ADD | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R0, 0);+ SET_NEXT_BYTE(SLJIT_EQUAL);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op2(compiler, SLJIT_ASHR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0);+ /* buf[30] */+ SET_NEXT_BYTE(SLJIT_EQUAL);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op2(compiler, SLJIT_LSHR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0xffffc0);+ /* buf[31] */+ SET_NEXT_BYTE(SLJIT_NOT_EQUAL);+ sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op2(compiler, SLJIT_ASHR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R0, 0, shift_reg, 0);+ /* buf[32] */+ SET_NEXT_BYTE(SLJIT_EQUAL);+ sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op2(compiler, SLJIT_LSHR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R0, 0, shift_reg, 0);+ /* buf[33] */+ SET_NEXT_BYTE(SLJIT_NOT_EQUAL);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_SUBC | SLJIT_SET_CARRY, SLJIT_R2, 0, SLJIT_IMM, 1, SLJIT_R0, 0);+ /* buf[34] */+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S0), 1, SLJIT_R2, 0);+ sljit_emit_op2u(compiler, SLJIT_SUBC | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op2(compiler, SLJIT_SUBC, SLJIT_R2, 0, SLJIT_IMM, 1, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S0), 2, SLJIT_R2, 0);+ /* buf[35] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 2);++ /* buf[36] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -34);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 0x1234);+ SET_NEXT_BYTE(SLJIT_LESS);+ /* buf[37] */+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R0, 0, SLJIT_IMM, 0x1234);+ SET_NEXT_BYTE(SLJIT_SIG_LESS);+#if IS_64BIT+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x12300000000) - 43);+#else /* !IS_64BIT */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, -43);+#endif /* IS_64BIT */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, -96);+ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_R1, 0);+ /* buf[38] */+ SET_NEXT_BYTE(SLJIT_LESS);+ /* buf[39] */+ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_SIG_GREATER, SLJIT_R0, 0, SLJIT_R1, 0);+ SET_NEXT_BYTE(SLJIT_SIG_GREATER);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 3);+ sljit_emit_op2(compiler, SLJIT_SUB32 | SLJIT_SET_SIG_LESS, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, -7);+ /* buf[40] */+ SET_NEXT_BYTE(SLJIT_SIG_LESS);+ sljit_emit_op2(compiler, SLJIT_SUB32 | SLJIT_SET_SIG_LESS, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 7);+ /* buf[41] */+ SET_NEXT_BYTE(SLJIT_SIG_LESS);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R1, 0, SLJIT_IMM, -1);+ /* buf[42] */+ SET_NEXT_BYTE(SLJIT_LESS);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R1, 0, SLJIT_IMM, -1);+ /* buf[43] */+ SET_NEXT_BYTE(SLJIT_GREATER);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);++ FAILED(buf[0] != RESULT(1), "test24 case 1 failed\n");+ FAILED(buf[1] != RESULT(2), "test24 case 2 failed\n");+ FAILED(buf[2] != 2, "test24 case 3 failed\n");+ FAILED(buf[3] != 1, "test24 case 4 failed\n");+ FAILED(buf[4] != RESULT(1), "test24 case 5 failed\n");+ FAILED(buf[5] != RESULT(2), "test24 case 6 failed\n");+ FAILED(buf[6] != 2, "test24 case 7 failed\n");+ FAILED(buf[7] != 1, "test24 case 8 failed\n");++ FAILED(buf[8] != 2, "test24 case 9 failed\n");+ FAILED(buf[9] != 1, "test24 case 10 failed\n");+ FAILED(buf[10] != 2, "test24 case 11 failed\n");+ FAILED(buf[11] != 1, "test24 case 12 failed\n");+ FAILED(buf[12] != 1, "test24 case 13 failed\n");+ FAILED(buf[13] != 2, "test24 case 14 failed\n");+ FAILED(buf[14] != 2, "test24 case 15 failed\n");+ FAILED(buf[15] != 1, "test24 case 16 failed\n");+ FAILED(buf[16] != 1, "test24 case 17 failed\n");+ FAILED(buf[17] != 2, "test24 case 18 failed\n");+ FAILED(buf[18] != 1, "test24 case 19 failed\n");+ FAILED(buf[19] != 1, "test24 case 20 failed\n");+ FAILED(buf[20] != 1, "test24 case 21 failed\n");+ FAILED(buf[21] != 2, "test24 case 22 failed\n");++ FAILED(buf[22] != RESULT(1), "test24 case 23 failed\n");+ FAILED(buf[23] != RESULT(2), "test24 case 24 failed\n");+ FAILED(buf[24] != 2, "test24 case 25 failed\n");+ FAILED(buf[25] != 1, "test24 case 26 failed\n");++ FAILED(buf[26] != 5, "test24 case 27 failed\n");+ FAILED(buf[27] != 9, "test24 case 28 failed\n");++ FAILED(buf[28] != 2, "test24 case 29 failed\n");+ FAILED(buf[29] != 1, "test24 case 30 failed\n");++ FAILED(buf[30] != 1, "test24 case 31 failed\n");+ FAILED(buf[31] != 1, "test24 case 32 failed\n");+ FAILED(buf[32] != 1, "test24 case 33 failed\n");+ FAILED(buf[33] != 1, "test24 case 34 failed\n");++ FAILED(buf[34] != 1, "test24 case 35 failed\n");+ FAILED(buf[35] != 0, "test24 case 36 failed\n");++ FAILED(buf[36] != 2, "test24 case 37 failed\n");+ FAILED(buf[37] != 1, "test24 case 38 failed\n");+ FAILED(buf[38] != 2, "test24 case 39 failed\n");+ FAILED(buf[39] != 1, "test24 case 40 failed\n");++ FAILED(buf[40] != 2, "test24 case 42 failed\n");+ FAILED(buf[41] != 1, "test24 case 43 failed\n");+ FAILED(buf[42] != 1, "test24 case 44 failed\n");+ FAILED(buf[43] != 2, "test24 case 45 failed\n");+ FAILED(buf[44] != 0xaa, "test24 case 46 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+#undef SET_NEXT_BYTE+#undef RESULT+}++static void test25(void)+{+ /* Test mov. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_const* const1 = NULL;+ struct sljit_label* label = NULL;+ sljit_uw label_addr = 0;+ sljit_sw buf[5];++ if (verbose)+ printf("Run test25\n");++ FAILED(!compiler, "cannot create compiler\n");++ buf[0] = -36;+ buf[1] = 8;+ buf[2] = 0;+ buf[3] = 10;+ buf[4] = 0;++ FAILED(!compiler, "cannot create compiler\n");+ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 5, 5, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -234);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw));+ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_S3, 0, SLJIT_R3, 0, SLJIT_R4, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_S3, 0);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_S3, 0, SLJIT_IMM, 0);+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_NOT_ZERO);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_S3, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw));+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_S4, 0, SLJIT_S4, 0, SLJIT_R4, 0);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_S4, 0);++ if (sljit_has_cpu_feature(SLJIT_HAS_MEMORY_BARRIER) != 0)+ SLJIT_ASSERT(sljit_emit_op0(compiler, SLJIT_MEMORY_BARRIER) != SLJIT_ERR_UNSUPPORTED);++ const1 = sljit_emit_const(compiler, SLJIT_MOV, SLJIT_S3, 0, 0);+ sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_S3, 0);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_S3, 0, SLJIT_S3, 0, SLJIT_IMM, 100);+ label = sljit_emit_label(compiler);+ sljit_emit_op0(compiler, SLJIT_ENDBR);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_S3, 0);++ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R4, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ label_addr = sljit_get_label_addr(label);+ sljit_set_const(sljit_get_const_addr(const1), SLJIT_MOV, (sljit_sw)label_addr, sljit_get_executable_offset(compiler));++ sljit_free_compiler(compiler);++ FAILED(code.func1((sljit_sw)&buf) != 8, "test25 case 1 failed\n");+ FAILED(buf[1] != -1872, "test25 case 2 failed\n");+ FAILED(buf[2] != 1, "test25 case 3 failed\n");+ FAILED(buf[3] != 2, "test25 case 4 failed\n");+ FAILED(buf[4] != (sljit_sw)label_addr, "test25 case 5 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test26(void)+{+ /* Test signed/unsigned bytes and halfs. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[25];+ sljit_s32 i;++ if (verbose)+ printf("Run test26\n");++ for (i = 0; i < 25; i++)+ buf[i] = 0;++ FAILED(!compiler, "cannot create compiler\n");+ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 5, 5, 0);++ sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_R0, 0, SLJIT_IMM, -187);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_R0, 0, SLJIT_IMM, -605);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_uw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_R0, 0, SLJIT_IMM, -56);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_uw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_R4, 0, SLJIT_IMM, 0xcde5);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_uw), SLJIT_R4, 0);++ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_R0, 0, SLJIT_IMM, -45896);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_uw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_R0, 0, SLJIT_IMM, -1472797);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_uw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_R0, 0, SLJIT_IMM, -12890);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_uw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_R4, 0, SLJIT_IMM, 0x9cb0a6);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_uw), SLJIT_R4, 0);++#if IS_64BIT+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(-3580429715));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_uw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(-100722768662));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_uw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(-1457052677972));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_uw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R4, 0, SLJIT_IMM, SLJIT_W(0xcef97a70b5));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_uw), SLJIT_R4, 0);+#endif /* IS_64BIT */++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -187);+ sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_uw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -605);+ sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_R0, 0, SLJIT_S2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_uw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -56);+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_R0, 0, SLJIT_R2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_uw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 0xcde5);+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_R4, 0, SLJIT_R3, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_uw), SLJIT_R4, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -45896);+ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_uw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -1472797);+ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_R0, 0, SLJIT_S2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_uw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -12890);+ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_R0, 0, SLJIT_R2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_uw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 0x9cb0a6);+ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_R4, 0, SLJIT_R3, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 19 * sizeof(sljit_uw), SLJIT_R4, 0);++#if IS_64BIT+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(-3580429715));+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 20 * sizeof(sljit_uw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, SLJIT_W(-100722768662));+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_S2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 21 * sizeof(sljit_uw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, SLJIT_W(-1457052677972));+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, SLJIT_R2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 22 * sizeof(sljit_uw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, SLJIT_W(0xcef97a70b5));+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R4, 0, SLJIT_R3, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 23 * sizeof(sljit_uw), SLJIT_R4, 0);+#endif /* IS_64BIT */++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 0x9faa5);+ sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_S2, 0, SLJIT_S2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 24 * sizeof(sljit_uw), SLJIT_S2, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ FAILED(buf[0] != 69, "test26 case 1 failed\n");+ FAILED(buf[1] != -93, "test26 case 2 failed\n");+ FAILED(buf[2] != 200, "test26 case 3 failed\n");+ FAILED(buf[3] != 0xe5, "test26 case 4 failed\n");+ FAILED(buf[4] != 19640, "test26 case 5 failed\n");+ FAILED(buf[5] != -31005, "test26 case 6 failed\n");+ FAILED(buf[6] != 52646, "test26 case 7 failed\n");+ FAILED(buf[7] != 0xb0a6, "test26 case 8 failed\n");++#if IS_64BIT+ FAILED(buf[8] != SLJIT_W(714537581), "test26 case 9 failed\n");+ FAILED(buf[9] != SLJIT_W(-1938520854), "test26 case 10 failed\n");+ FAILED(buf[10] != SLJIT_W(3236202668), "test26 case 11 failed\n");+ FAILED(buf[11] != SLJIT_W(0xf97a70b5), "test26 case 12 failed\n");+#endif /* IS_64BIT */++ FAILED(buf[12] != 69, "test26 case 13 failed\n");+ FAILED(buf[13] != -93, "test26 case 14 failed\n");+ FAILED(buf[14] != 200, "test26 case 15 failed\n");+ FAILED(buf[15] != 0xe5, "test26 case 16 failed\n");+ FAILED(buf[16] != 19640, "test26 case 17 failed\n");+ FAILED(buf[17] != -31005, "test26 case 18 failed\n");+ FAILED(buf[18] != 52646, "test26 case 19 failed\n");+ FAILED(buf[19] != 0xb0a6, "test26 case 20 failed\n");++#if IS_64BIT+ FAILED(buf[20] != SLJIT_W(714537581), "test26 case 21 failed\n");+ FAILED(buf[21] != SLJIT_W(-1938520854), "test26 case 22 failed\n");+ FAILED(buf[22] != SLJIT_W(3236202668), "test26 case 23 failed\n");+ FAILED(buf[23] != SLJIT_W(0xf97a70b5), "test26 case 24 failed\n");+#endif /* IS_64BIT */++ FAILED(buf[24] != -91, "test26 case 25 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test27(void)+{+ /* Test unused results. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[1];++ if (verbose)+ printf("Run test27\n");++ FAILED(!compiler, "cannot create compiler\n");+ buf[0] = 0;+ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 5, 5, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, 1);+#if IS_64BIT+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_S1, 0, SLJIT_IMM, SLJIT_W(-0x123ffffffff));+#else /* !IS_64BIT */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_S1, 0, SLJIT_IMM, 1);+#endif /* IS_64BIT */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_IMM, 1);++ /* Some calculations with unused results. */+ sljit_emit_op2u(compiler, SLJIT_ADD | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_GREATER_EQUAL, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op2u(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op2u(compiler, SLJIT_SHL | SLJIT_SET_Z, SLJIT_S3, 0, SLJIT_R2, 0);+ sljit_emit_op2u(compiler, SLJIT_LSHR | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 5);+ sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 0xff);++ /* Testing that any change happens. */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R2, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R3, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R4, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_S1, 0, SLJIT_S1, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S1, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S2, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S3, 0);+ /* buf[0] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0, SLJIT_S4, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ FAILED(buf[0] != 9, "test27 case 1 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test28(void)+{+ /* Integer mul and set flags. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[12];+ sljit_s32 i;+ sljit_sw big_word = WCONST(0x7fffffff00000000, 0x7fffffff);+ sljit_sw big_word2 = WCONST(0x7fffffff00000012, 0x00000012);++ if (verbose)+ printf("Run test28\n");++ for (i = 0; i < 12; i++)+ buf[i] = 3;++ FAILED(!compiler, "cannot create compiler\n");++ /* buf[0] */+ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 3, 5, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0);+ sljit_emit_op2u(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_IMM, -45);+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_NOT_OVERFLOW);+ /* buf[1] */+ sljit_emit_op2u(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_IMM, -45);+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_OVERFLOW);++ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, big_word);+ sljit_emit_op2(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R2, 0, SLJIT_S2, 0, SLJIT_IMM, -2);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 33); /* Should not change flags. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0); /* Should not change flags. */+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_OVERFLOW);+ /* buf[3] */+ sljit_emit_op2(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R2, 0, SLJIT_S2, 0, SLJIT_IMM, -2);+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_NOT_OVERFLOW);++ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_S3, 0, SLJIT_IMM, 0x3f6b0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_S4, 0, SLJIT_IMM, 0x2a783);+ sljit_emit_op2(compiler, SLJIT_MUL32 | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_S3, 0, SLJIT_S4, 0);+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_OVERFLOW);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R1, 0);++ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, big_word2);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_R1, 0);+ sljit_emit_op2(compiler, SLJIT_MUL32 | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 23);+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_OVERFLOW);++ /* buf[7] */+ sljit_emit_op2u(compiler, SLJIT_MUL32 | SLJIT_SET_OVERFLOW, SLJIT_R2, 0, SLJIT_IMM, -23);+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_NOT_OVERFLOW);+ /* buf[8] */+ sljit_emit_op2u(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R2, 0, SLJIT_IMM, -23);+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_NOT_OVERFLOW);++ /* buf[9] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 67);+ sljit_emit_op2(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, -23);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);++ FAILED(buf[0] != 1, "test28 case 1 failed\n");+ FAILED(buf[1] != 2, "test28 case 2 failed\n");+ FAILED(buf[2] != 1, "test28 case 3 failed\n");+ FAILED(buf[3] != 2, "test28 case 4 failed\n");+ FAILED(buf[4] != 1, "test28 case 5 failed\n");+ FAILED((buf[5] & (sljit_sw)0xffffffff) != (sljit_sw)0x85540c10, "test28 case 6 failed\n");+ FAILED(buf[6] != 2, "test28 case 7 failed\n");+ FAILED(buf[7] != 1, "test28 case 8 failed\n");+ FAILED(buf[8] != 1, "test28 case 9 failed\n");+ FAILED(buf[9] != -1541, "test28 case 10 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test29(void)+{+ /* Test setting multiple flags. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_jump* jump;+ sljit_sw buf[10];++ if (verbose)+ printf("Run test29\n");++ buf[0] = 3;+ buf[1] = 3;+ buf[2] = 3;+ buf[3] = 3;+ buf[4] = 3;+ buf[5] = 3;+ buf[6] = 3;+ buf[7] = 3;+ buf[8] = 3;+ buf[9] = 3;++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 3, 3, 0);++ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 20);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 10);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_R2, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_ZERO);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -10);+ jump = sljit_emit_jump(compiler, SLJIT_LESS);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, 11);+ sljit_set_label(jump, sljit_emit_label(compiler));++ /* buf[2] */+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_SIG_GREATER, SLJIT_R2, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_SIG_GREATER);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_IMM, 45);+ jump = sljit_emit_jump(compiler, SLJIT_NOT_EQUAL);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_IMM, 55);+ sljit_set_label(jump, sljit_emit_label(compiler));++ /* buf[4-5] */+#if IS_64BIT+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)SLJIT_W(0x8000000000000000));+#else /* !IS_64BIT */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)SLJIT_W(0x80000000));+#endif /* IS_64BIT */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_OVERFLOW, SLJIT_R2, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_IMM, 33);+ jump = sljit_emit_jump(compiler, SLJIT_NOT_OVERFLOW);+ /* buf[5] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_ZERO);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_IMM, 13);+ sljit_set_label(jump, sljit_emit_label(compiler));++ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0x80000000);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_SUB32 | SLJIT_SET_Z | SLJIT_SET_OVERFLOW, SLJIT_R2, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0);+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_NOT_ZERO);+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_IMM, 78);+ jump = sljit_emit_jump(compiler, SLJIT_OVERFLOW);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_IMM, 48);+ sljit_set_label(jump, sljit_emit_label(compiler));++ /* buf[8] */+#if IS_64BIT+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)SLJIT_W(0x8000000000000000));+#else /* !IS_64BIT */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)SLJIT_W(0x80000000));+#endif /* IS_64BIT */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_Z | SLJIT_SET_OVERFLOW, SLJIT_R2, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_IMM, 30);+ jump = sljit_emit_jump(compiler, SLJIT_NOT_OVERFLOW);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_IMM, 50);+ /* buf[9] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_ZERO);+ sljit_set_label(jump, sljit_emit_label(compiler));++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);++ FAILED(buf[0] != 0, "test29 case 1 failed\n");+ FAILED(buf[1] != 11, "test29 case 2 failed\n");+ FAILED(buf[2] != 1, "test29 case 3 failed\n");+ FAILED(buf[3] != 45, "test29 case 4 failed\n");+ FAILED(buf[4] != 13, "test29 case 5 failed\n");+ FAILED(buf[5] != 0, "test29 case 6 failed\n");+ FAILED(buf[6] != 0, "test29 case 7 failed\n");+ FAILED(buf[7] != 48, "test29 case 8 failed\n");+ FAILED(buf[8] != 50, "test29 case 9 failed\n");+ FAILED(buf[9] != 1, "test29 case 10 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test30(void)+{+ /* Test fast calls. */+ executable_code codeA;+ executable_code codeB;+ executable_code codeC;+ executable_code codeD;+ executable_code codeE;+ executable_code codeF;+ struct sljit_compiler* compiler;+ struct sljit_jump *jump;+ struct sljit_label* label;+ sljit_uw addr;+ sljit_up buf[2];++ if (verbose)+ printf("Run test30\n");++ buf[0] = 0;+ buf[1] = 0;++ /* A */+ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");+ sljit_set_context(compiler, 0, 1, 5, 5, 2 * sizeof(sljit_up));++ sljit_emit_op0(compiler, SLJIT_ENDBR);+ sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_R1, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 4);+ sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_R1, 0);++ codeA.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ /* B */+ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");+ sljit_set_context(compiler, 0, 1, 5, 5, 2 * sizeof(sljit_up));++ sljit_emit_op0(compiler, SLJIT_ENDBR);+ sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_R4, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 6);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(codeA.code));+ sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_R1, 0);+ sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_R4, 0);++ codeB.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ /* C */+ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");+ sljit_set_context(compiler, 0, 1, 5, 5, 2 * sizeof(sljit_up));++ sljit_emit_op0(compiler, SLJIT_ENDBR);+ sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_up));+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 8);+ jump = sljit_emit_jump(compiler, SLJIT_FAST_CALL | SLJIT_REWRITABLE_JUMP);+ sljit_set_target(jump, SLJIT_FUNC_UADDR(codeB.code));+ sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_up));++ codeC.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ /* D */+ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");+ sljit_set_context(compiler, 0, 1, 5, 5, 2 * sizeof(sljit_up));++ label = sljit_emit_label(compiler);+ jump = sljit_emit_jump(compiler, SLJIT_JUMP | SLJIT_REWRITABLE_JUMP);+ sljit_set_label(jump, label);+ label = sljit_emit_label(compiler);+ sljit_emit_op0(compiler, SLJIT_ENDBR);+ sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 10);+ sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, SLJIT_FUNC_ADDR(codeC.code));+ sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_MEM1(SLJIT_SP), 0);++ codeD.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ addr = sljit_get_label_addr(label);+ sljit_free_compiler(compiler);++ /* E */+ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");+ sljit_set_context(compiler, 0, 1, 5, 5, 2 * sizeof(sljit_up));++ sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 12);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_up), SLJIT_IMM, (sljit_sp)addr);+ sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_up));+ sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_MEM1(SLJIT_S0), 0);++ codeE.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ /* F */+ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 5, 5, 2 * sizeof(sljit_up));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, SLJIT_FUNC_ADDR(codeE.code));+ label = sljit_emit_label(compiler);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0);++ codeF.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ addr = sljit_get_label_addr(label);+ sljit_free_compiler(compiler);++ FAILED(codeF.func1((sljit_sw)&buf) != 40, "test30 case 1 failed\n");+ FAILED(buf[0] != addr - SLJIT_RETURN_ADDRESS_OFFSET, "test30 case 2 failed\n");++ sljit_free_code(codeA.code, NULL);+ sljit_free_code(codeB.code, NULL);+ sljit_free_code(codeC.code, NULL);+ sljit_free_code(codeD.code, NULL);+ sljit_free_code(codeE.code, NULL);+ sljit_free_code(codeF.code, NULL);+ successful_tests++;+}++static void test31(void)+{+ /* More complicated tests for fast calls. */+ executable_code codeA;+ executable_code codeB;+ executable_code codeC;+ struct sljit_compiler* compiler;+ struct sljit_jump *jump = NULL;+ struct sljit_label* label;+ sljit_sw executable_offset;+ sljit_uw return_addr;+ sljit_uw jump_addr = 0;+ sljit_up buf[1];++ if (verbose)+ printf("Run test31\n");++ buf[0] = 0;++ /* A */+ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");+ sljit_set_context(compiler, 0, 0, 2, 2, 0);++ sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM0(), (sljit_sw)&buf[0]);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 5);++ jump = sljit_emit_jump(compiler, SLJIT_FAST_CALL | SLJIT_REWRITABLE_JUMP);+ sljit_set_target(jump, 0);++ label = sljit_emit_label(compiler);+ sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_MEM0(), (sljit_sw)&buf[0]);++ codeA.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ executable_offset = sljit_get_executable_offset(compiler);+ jump_addr = sljit_get_jump_addr(jump);+ sljit_free_compiler(compiler);++ /* B */+ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");+ sljit_set_context(compiler, 0, 0, 2, 2, 0);++ sljit_emit_op0(compiler, SLJIT_ENDBR);+ sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_R1, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 7);+ sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_R1, 0);++ codeB.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ sljit_set_jump_addr(jump_addr, SLJIT_FUNC_UADDR(codeB.code), executable_offset);++ /* C */+ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 2, 2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, SLJIT_FUNC_ADDR(codeA.code));+ label = sljit_emit_label(compiler);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0);++ codeC.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ return_addr = sljit_get_label_addr(label);+ sljit_free_compiler(compiler);++ FAILED(codeC.func0() != 12, "test31 case 1 failed\n");+ FAILED(buf[0] != return_addr - SLJIT_RETURN_ADDRESS_OFFSET, "test31 case 2 failed\n");++ sljit_free_code(codeA.code, NULL);+ sljit_free_code(codeB.code, NULL);+ sljit_free_code(codeC.code, NULL);+ successful_tests++;+}++static void cmp_test(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w)+{+ /* 2 = true, 1 = false */+ struct sljit_jump* jump;+ struct sljit_label* label;++ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S0), 1, SLJIT_IMM, 2);+ jump = sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w);+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S0), 1, SLJIT_IMM, 1);+ label = sljit_emit_label(compiler);+ sljit_emit_op0(compiler, SLJIT_ENDBR);+ sljit_set_label(jump, label);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 1);+}++#define TEST_CASES (7 + 10 + 12 + 11 + 4)+static void test32(void)+{+ /* Compare instruction. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);++ sljit_s8 buf[TEST_CASES];+ sljit_s8 compare_buf[TEST_CASES] = {+ 1, 1, 2, 2, 1, 2, 2,+ 1, 1, 2, 2, 2, 1, 2, 2, 1, 1,+ 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 2, 2,+ 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2,+ 2, 1, 1, 2+ };+ sljit_sw data[4];+ sljit_s32 i;++ if (verbose)+ printf("Run test32\n");++ FAILED(!compiler, "cannot create compiler\n");+ for (i = 0; i < TEST_CASES; ++i)+ buf[i] = 100;+ data[0] = 32;+ data[1] = -9;+ data[2] = 43;+ data[3] = -13;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(P, P), 3, 2, 0);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 1);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 13);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 15);+ /* buf[0], compare_buf[0-6] */+ cmp_test(compiler, SLJIT_EQUAL, SLJIT_IMM, 9, SLJIT_R0, 0);+ /* buf[1] */+ cmp_test(compiler, SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 3);+ /* buf[2] */+ cmp_test(compiler, SLJIT_EQUAL, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_IMM, -13);+ /* buf[3] */+ cmp_test(compiler, SLJIT_NOT_EQUAL, SLJIT_IMM, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ /* buf[4] */+ cmp_test(compiler, SLJIT_NOT_EQUAL | SLJIT_REWRITABLE_JUMP, SLJIT_IMM, 0, SLJIT_R0, 0);+ /* buf[5] */+ cmp_test(compiler, SLJIT_EQUAL, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_WORD_SHIFT);+ /* buf[6] */+ cmp_test(compiler, SLJIT_EQUAL | SLJIT_REWRITABLE_JUMP, SLJIT_R0, 0, SLJIT_IMM, 0);++ /* buf[7-16], compare_buf[7-16] */+ cmp_test(compiler, SLJIT_SIG_LESS, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -8);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0);+ cmp_test(compiler, SLJIT_SIG_GREATER, SLJIT_R0, 0, SLJIT_IMM, 0);+ cmp_test(compiler, SLJIT_SIG_LESS_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0);+ cmp_test(compiler, SLJIT_SIG_LESS | SLJIT_REWRITABLE_JUMP, SLJIT_R0, 0, SLJIT_IMM, 0);+ cmp_test(compiler, SLJIT_SIG_GREATER_EQUAL, SLJIT_R1, 0, SLJIT_IMM, 0);+ cmp_test(compiler, SLJIT_SIG_GREATER, SLJIT_IMM, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_sw));+ cmp_test(compiler, SLJIT_SIG_LESS_EQUAL, SLJIT_IMM, 0, SLJIT_R1, 0);+ cmp_test(compiler, SLJIT_SIG_LESS, SLJIT_IMM, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_sw));+ cmp_test(compiler, SLJIT_SIG_LESS, SLJIT_IMM, 0, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_sw));+ cmp_test(compiler, SLJIT_SIG_LESS | SLJIT_REWRITABLE_JUMP, SLJIT_IMM, 0, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_sw));++ /* buf[17-28], compare_buf[17-28] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0);+ cmp_test(compiler, SLJIT_LESS, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_sw));+ cmp_test(compiler, SLJIT_GREATER_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 8);+ cmp_test(compiler, SLJIT_LESS, SLJIT_R0, 0, SLJIT_IMM, -10);+ cmp_test(compiler, SLJIT_LESS, SLJIT_R0, 0, SLJIT_IMM, 8);+ cmp_test(compiler, SLJIT_GREATER_EQUAL, SLJIT_IMM, 8, SLJIT_R1, 0);+ cmp_test(compiler, SLJIT_GREATER_EQUAL | SLJIT_REWRITABLE_JUMP, SLJIT_IMM, 8, SLJIT_R1, 0);+ cmp_test(compiler, SLJIT_GREATER, SLJIT_IMM, 8, SLJIT_R1, 0);+ cmp_test(compiler, SLJIT_LESS_EQUAL, SLJIT_IMM, 7, SLJIT_R0, 0);+ cmp_test(compiler, SLJIT_GREATER, SLJIT_IMM, 1, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_sw));+ cmp_test(compiler, SLJIT_LESS_EQUAL, SLJIT_R0, 0, SLJIT_R1, 0);+ cmp_test(compiler, SLJIT_GREATER, SLJIT_R0, 0, SLJIT_R1, 0);+ cmp_test(compiler, SLJIT_GREATER | SLJIT_REWRITABLE_JUMP, SLJIT_R0, 0, SLJIT_R1, 0);++ /* buf[29-39], compare_buf[29-39] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -3);+ cmp_test(compiler, SLJIT_SIG_LESS, SLJIT_R0, 0, SLJIT_R1, 0);+ cmp_test(compiler, SLJIT_SIG_GREATER_EQUAL, SLJIT_R0, 0, SLJIT_R1, 0);+ cmp_test(compiler, SLJIT_SIG_LESS, SLJIT_R0, 0, SLJIT_IMM, -1);+ cmp_test(compiler, SLJIT_SIG_GREATER_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 1);+ cmp_test(compiler, SLJIT_SIG_LESS, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_IMM, -1);+ cmp_test(compiler, SLJIT_SIG_LESS | SLJIT_REWRITABLE_JUMP, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_IMM, -1);+ cmp_test(compiler, SLJIT_SIG_LESS_EQUAL, SLJIT_R0, 0, SLJIT_R1, 0);+ cmp_test(compiler, SLJIT_SIG_GREATER, SLJIT_R0, 0, SLJIT_R1, 0);+ cmp_test(compiler, SLJIT_SIG_LESS_EQUAL, SLJIT_IMM, -4, SLJIT_R0, 0);+ cmp_test(compiler, SLJIT_SIG_GREATER, SLJIT_IMM, -1, SLJIT_R1, 0);+ cmp_test(compiler, SLJIT_SIG_GREATER | SLJIT_REWRITABLE_JUMP, SLJIT_R1, 0, SLJIT_IMM, -1);++#if IS_64BIT+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0xf00000004));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_R1, 0);+ /* buf[40-43] */+ cmp_test(compiler, SLJIT_LESS | SLJIT_32, SLJIT_R1, 0, SLJIT_IMM, 5);+ cmp_test(compiler, SLJIT_LESS, SLJIT_R0, 0, SLJIT_IMM, 5);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0xff0000004));+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_R0, 0);+ cmp_test(compiler, SLJIT_SIG_GREATER | SLJIT_32, SLJIT_R1, 0, SLJIT_IMM, 5);+ cmp_test(compiler, SLJIT_SIG_GREATER, SLJIT_R0, 0, SLJIT_IMM, 5);+#else /* !IS_64BIT */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 4);+ /* buf[40-43] */+ cmp_test(compiler, SLJIT_LESS | SLJIT_32, SLJIT_R0, 0, SLJIT_IMM, 5);+ cmp_test(compiler, SLJIT_GREATER | SLJIT_32, SLJIT_R0, 0, SLJIT_IMM, 5);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0xf0000004);+ cmp_test(compiler, SLJIT_SIG_GREATER | SLJIT_32, SLJIT_R0, 0, SLJIT_IMM, 5);+ cmp_test(compiler, SLJIT_SIG_LESS | SLJIT_32, SLJIT_R0, 0, SLJIT_IMM, 5);+#endif /* IS_64BIT */++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)&buf, (sljit_sw)&data);++ for (i = 0; i < TEST_CASES; ++i)+ if (SLJIT_UNLIKELY(buf[i] != compare_buf[i])) {+ printf("test32 case %d failed\n", i + 1);+ return;+ }++ sljit_free_code(code.code, NULL);+ successful_tests++;+}+#undef TEST_CASES++#if IS_64BIT+#define BITN(n) (SLJIT_W(1) << (63 - (n)))+#else /* !IS_64BIT */+#define BITN(n) (1 << (31 - ((n) & 0x1f)))+#endif /* IS_64BIT */++static void test33(void)+{+ /* Test count leading zeroes. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[9];+ sljit_s32 ibuf[3];+ sljit_s32 i;++ if (verbose)+ printf("Run test33\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 9; i++)+ buf[i] = -1;+ for (i = 0; i < 3; i++)+ ibuf[i] = -1;+ buf[2] = 0;+ buf[4] = BITN(13);++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(P, P), 2, 3, 0);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, BITN(27));+ sljit_emit_op1(compiler, SLJIT_CLZ, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, BITN(47));+ sljit_emit_op1(compiler, SLJIT_CLZ, SLJIT_R0, 0, SLJIT_S2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_CLZ, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw));+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_CLZ, SLJIT_R0, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* ibuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_CLZ32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R0, 0);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_CLZ, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, BITN(58));+ sljit_emit_op1(compiler, SLJIT_CLZ, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_CLZ, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* ibuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xff08a00000, 0x08a00000));+ sljit_emit_op1(compiler, SLJIT_CLZ32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_R0, 0);+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_CLZ32, SLJIT_R0, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xffc8a00000, 0xc8a00000));+ sljit_emit_op1(compiler, SLJIT_CLZ32, SLJIT_R0, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0xa00a);+ sljit_emit_op2(compiler, SLJIT_SHL32, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, 8);+ /* ibuf[2] */+ sljit_emit_op1(compiler, SLJIT_CLZ32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32), SLJIT_R0, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)&buf, (sljit_sw)&ibuf);+ FAILED(buf[0] != 27, "test33 case 1 failed\n");+ FAILED(buf[1] != WCONST(47, 15), "test33 case 2 failed\n");+ FAILED(buf[2] != WCONST(64, 32), "test33 case 3 failed\n");+ FAILED(buf[3] != 0, "test33 case 4 failed\n");+ FAILED(ibuf[0] != 32, "test33 case 5 failed\n");+ FAILED(buf[4] != 13, "test33 case 6 failed\n");+ FAILED(buf[5] != WCONST(58, 26), "test33 case 7 failed\n");+ FAILED(buf[6] != WCONST(64, 32), "test33 case 8 failed\n");+ FAILED(ibuf[1] != 4, "test33 case 9 failed\n");+ FAILED((buf[7] & (sljit_sw)0xffffffff) != 4, "test33 case 10 failed\n");+ FAILED((buf[8] & (sljit_sw)0xffffffff) != 0, "test33 case 11 failed\n");+ FAILED(ibuf[2] != 8, "test33 case 12 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++#undef BITN++static void test34(void)+{+#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)+ /* Test stack utility. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_jump* alloc1_fail;+ struct sljit_jump* alloc2_fail;+ struct sljit_jump* alloc3_fail;+ struct sljit_jump* sanity1_fail;+ struct sljit_jump* sanity2_fail;+ struct sljit_jump* sanity3_fail;+ struct sljit_jump* sanity4_fail;+ struct sljit_jump* jump;+ struct sljit_label* label;++ if (verbose)+ printf("Run test34\n");++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 3, 1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8192);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 65536);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0);+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(P, W, W, P), SLJIT_IMM, SLJIT_FUNC_ADDR(sljit_allocate_stack));+ alloc1_fail = sljit_emit_cmp(compiler, SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_RETURN_REG, 0);++ /* Write 8k data. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct sljit_stack, start));+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 8192);+ label = sljit_emit_label(compiler);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_IMM, -1);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_sw));+ jump = sljit_emit_cmp(compiler, SLJIT_LESS, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_set_label(jump, label);++ /* Grow stack. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct sljit_stack, end), SLJIT_IMM, 65536);+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(P, P, P), SLJIT_IMM, SLJIT_FUNC_ADDR(sljit_stack_resize));+ alloc2_fail = sljit_emit_cmp(compiler, SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);+ sanity1_fail = sljit_emit_cmp(compiler, SLJIT_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct sljit_stack, start));++ /* Write 64k data. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct sljit_stack, start));+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 65536);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct sljit_stack, min_start));+ sanity2_fail = sljit_emit_cmp(compiler, SLJIT_NOT_EQUAL, SLJIT_R0, 0, SLJIT_R2, 0);+ label = sljit_emit_label(compiler);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_IMM, -1);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_sw));+ jump = sljit_emit_cmp(compiler, SLJIT_LESS, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_set_label(jump, label);++ /* Shrink stack. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct sljit_stack, end), SLJIT_IMM, 32768);+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(P, P, P), SLJIT_IMM, SLJIT_FUNC_ADDR(sljit_stack_resize));+ alloc3_fail = sljit_emit_cmp(compiler, SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);+ sanity3_fail = sljit_emit_cmp(compiler, SLJIT_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct sljit_stack, start));++ /* Write 32k data. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct sljit_stack, start));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct sljit_stack, end));+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R2, 0, SLJIT_R1, 0, SLJIT_IMM, 32768);+ sanity4_fail = sljit_emit_cmp(compiler, SLJIT_NOT_EQUAL, SLJIT_R0, 0, SLJIT_R2, 0);+ label = sljit_emit_label(compiler);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_IMM, -1);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_sw));+ jump = sljit_emit_cmp(compiler, SLJIT_LESS, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_set_label(jump, label);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0);+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2V(P, P), SLJIT_IMM, SLJIT_FUNC_ADDR(sljit_free_stack));++ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_IMM, 4567);++ label = sljit_emit_label(compiler);+ sljit_set_label(alloc1_fail, label);+ sljit_set_label(alloc2_fail, label);+ sljit_set_label(alloc3_fail, label);+ sljit_set_label(sanity1_fail, label);+ sljit_set_label(sanity2_fail, label);+ sljit_set_label(sanity3_fail, label);+ sljit_set_label(sanity4_fail, label);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_IMM, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ /* Just survive this. */+ FAILED(code.func0() != 4567, "test34 case 1 failed\n");++ sljit_free_code(code.code, NULL);+#endif /* SLJIT_UTIL_STACK */+ successful_tests++;+}++static void test35(void)+{+ /* Test error handling. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_jump* jump;++ if (verbose)+ printf("Run test35\n");++ FAILED(!compiler, "cannot create compiler\n");++ /* Such assignment should never happen in a regular program. */+ compiler->error = -3967;++ SLJIT_ASSERT(sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(W, W), 5 | SLJIT_ENTER_FLOAT(6), 5, 32) == -3967);+ SLJIT_ASSERT(sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R1, 0) == -3967);+ SLJIT_ASSERT(sljit_emit_op0(compiler, SLJIT_NOP) == -3967);+ SLJIT_ASSERT(sljit_emit_op0(compiler, SLJIT_ENDBR) == -3967);+ SLJIT_ASSERT(sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 1) == -3967);+ SLJIT_ASSERT(sljit_emit_op2(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), 64, SLJIT_MEM1(SLJIT_S0), -64) == -3967);+ SLJIT_ASSERT(sljit_emit_fop1(compiler, SLJIT_ABS_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_R1), 0) == -3967);+ SLJIT_ASSERT(sljit_emit_fop2(compiler, SLJIT_DIV_F64, SLJIT_FR2, 0, SLJIT_MEM2(SLJIT_R0, SLJIT_S0), 0, SLJIT_FR2, 0) == -3967);+ SLJIT_ASSERT(!sljit_emit_label(compiler));+ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS4(W, 32, P, F32, F64));+ SLJIT_ASSERT(!jump);+ sljit_set_label(jump, (struct sljit_label*)0x123450);+ sljit_set_target(jump, 0x123450);+ jump = sljit_emit_cmp(compiler, SLJIT_SIG_LESS_EQUAL, SLJIT_R0, 0, SLJIT_R1, 0);+ SLJIT_ASSERT(!jump);+ SLJIT_ASSERT(sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM1(SLJIT_R0), 8) == -3967);+ SLJIT_ASSERT(sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_OVERFLOW) == -3967);+ SLJIT_ASSERT(!sljit_emit_const(compiler, SLJIT_MOV, SLJIT_R0, 0, 99));++ SLJIT_ASSERT(!compiler->labels && !compiler->jumps && !compiler->consts);+ SLJIT_ASSERT(!compiler->last_label && !compiler->last_jump && !compiler->last_const);+ SLJIT_ASSERT(!compiler->buf->next && !compiler->buf->used_size);+ SLJIT_ASSERT(!compiler->abuf->next && !compiler->abuf->used_size);++ sljit_set_compiler_memory_error(compiler);+ FAILED(sljit_get_compiler_error(compiler) != -3967, "test35 case 1 failed\n");++ code.code = sljit_generate_code(compiler, 0, NULL);+ FAILED(sljit_get_compiler_error(compiler) != -3967, "test35 case 2 failed\n");+ FAILED(!!code.code, "test35 case 3 failed\n");+ sljit_free_compiler(compiler);++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ FAILED(sljit_get_compiler_error(compiler) != SLJIT_SUCCESS, "test35 case 4 failed\n");+ sljit_set_compiler_memory_error(compiler);+ FAILED(sljit_get_compiler_error(compiler) != SLJIT_ERR_ALLOC_FAILED, "test35 case 5 failed\n");+ sljit_free_compiler(compiler);++ successful_tests++;+}++static void test36(void)+{+ /* Test emit_op_flags. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[10];++ if (verbose)+ printf("Run test36\n");++ FAILED(!compiler, "cannot create compiler\n");+ buf[0] = -100;+ buf[1] = -100;+ buf[2] = -100;+ buf[3] = -8;+ buf[4] = -100;+ buf[5] = -100;+ buf[6] = 0;+ buf[7] = 0;+ buf[8] = -100;+ buf[9] = -100;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 4, sizeof(sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -5);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_IMM, -6, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x123456);+ sljit_emit_op_flags(compiler, SLJIT_OR, SLJIT_R1, 0, SLJIT_SIG_LESS);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -13);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_IMM, -13, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 0);+ sljit_emit_op_flags(compiler, SLJIT_OR | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_EQUAL);+ /* buf[1] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_NOT_EQUAL);+ sljit_emit_op2(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), 0);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_IMM, -13, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0);+ sljit_emit_op_flags(compiler, SLJIT_OR | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_EQUAL);+ /* buf[2] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_EQUAL);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -13);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 3);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ /* buf[3] */+ sljit_emit_op_flags(compiler, SLJIT_OR, SLJIT_MEM2(SLJIT_S0, SLJIT_R1), SLJIT_WORD_SHIFT, SLJIT_SIG_LESS);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -8);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 33);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 0);+ sljit_emit_op_flags(compiler, SLJIT_OR | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_GREATER);+ sljit_emit_op_flags(compiler, SLJIT_OR, SLJIT_S1, 0, SLJIT_EQUAL);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, 0x88);+ sljit_emit_op_flags(compiler, SLJIT_OR, SLJIT_S3, 0, SLJIT_NOT_EQUAL);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_S1, 0);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, SLJIT_S3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x84);+ sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_IMM, 0x180, SLJIT_R0, 0);+ /* buf[6] */+ sljit_emit_op_flags(compiler, SLJIT_OR | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6, SLJIT_EQUAL);+ /* buf[7] */+ sljit_emit_op_flags(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7, SLJIT_EQUAL);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op_flags(compiler, SLJIT_OR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_NOT_EQUAL);+ /* buf[8] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 8, SLJIT_NOT_EQUAL);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x123456);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op_flags(compiler, SLJIT_OR, SLJIT_R0, 0, SLJIT_GREATER);+ /* buf[9] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 9, SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 0xbaddead);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ FAILED(code.func1((sljit_sw)&buf) != 0xbaddead, "test36 case 1 failed\n");+ FAILED(buf[0] != 0x123457, "test36 case 2 failed\n");+ FAILED(buf[1] != 1, "test36 case 3 failed\n");+ FAILED(buf[2] != 0, "test36 case 4 failed\n");+ FAILED(buf[3] != -7, "test36 case 5 failed\n");+ FAILED(buf[4] != 0, "test36 case 6 failed\n");+ FAILED(buf[5] != 0x89, "test36 case 7 failed\n");+ FAILED(buf[6] != 0, "test36 case 8 failed\n");+ FAILED(buf[7] != 1, "test36 case 9 failed\n");+ FAILED(buf[8] != 1, "test36 case 10 failed\n");+ FAILED(buf[9] != 0x123457, "test36 case 11 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test37(void)+{+ /* Test inline assembly. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_s32 i;+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ sljit_u8 inst[16];+#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ sljit_u8 inst[16];+ sljit_s32 reg;+#else /* !SLJIT_CONFIG_X86_32 && !SLJIT_CONFIG_X86_64 */+ sljit_u32 inst;+#endif /* SLJIT_CONFIG_X86_32 */++ if (verbose)+ printf("Run test37\n");++#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ SLJIT_ASSERT(sljit_has_cpu_feature(SLJIT_HAS_VIRTUAL_REGISTERS) == 0);+#endif /* !SLJIT_CONFIG_X86_32 */++ for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS; i++) {+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ if (SLJIT_R(i) >= SLJIT_R3 && SLJIT_R(i) <= SLJIT_R8) {+ SLJIT_ASSERT(sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_R(i)) == -1);+ continue;+ }+#endif /* SLJIT_CONFIG_X86_32 */+ SLJIT_ASSERT(sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_R(i)) >= 0+ && sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_R(i)) < 64);+ }++ FAILED(!compiler, "cannot create compiler\n");+ sljit_emit_enter(compiler, 0, SLJIT_ARGS2(W, W, W), 3, 3, 0);++ /* Returns with the sum of SLJIT_S0 and SLJIT_S1. */+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ /* lea SLJIT_RETURN_REG, [SLJIT_S0, SLJIT_S1] */+ inst[0] = 0x48;+ inst[1] = 0x8d;+ inst[2] = (sljit_u8)(0x04 | ((sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_RETURN_REG) & 0x7) << 3));+ inst[3] = (sljit_u8)((sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S0) & 0x7)+ | ((sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S1) & 0x7) << 3));+ sljit_emit_op_custom(compiler, inst, 4);+#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ /* lea SLJIT_RETURN_REG, [SLJIT_S0, SLJIT_S1] */+ inst[0] = 0x48; /* REX_W */+ inst[1] = 0x8d;+ reg = sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_RETURN_REG);+ inst[2] = (sljit_u8)(0x04 | ((reg & 0x7) << 3));+ if (reg > 7)+ inst[0] |= 0x04; /* REX_R */+ reg = sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S0);+ inst[3] = (sljit_u8)(reg & 0x7);+ if (reg > 7)+ inst[0] |= 0x01; /* REX_B */+ reg = sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S1);+ inst[3] = (sljit_u8)(inst[3] | ((reg & 0x7) << 3));+ if (reg > 7)+ inst[0] |= 0x02; /* REX_X */+ sljit_emit_op_custom(compiler, inst, 4);+#elif (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)+ /* add rd, rn, rm */+ inst = 0xe0800000 | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_RETURN_REG) << 12)+ | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S0) << 16)+ | (sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S1);+ sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32));+#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)+ /* add rd, rn, rm */+ inst = 0xeb000000 | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_RETURN_REG) << 8)+ | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S0) << 16)+ | (sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S1);+ sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32));+#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)+ /* add rd, rn, rm */+ inst = 0x8b000000 | (sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_RETURN_REG)+ | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S0) << 5)+ | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S1) << 16);+ sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32));+#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)+ /* add rD, rA, rB */+ inst = (31 << 26) | (266 << 1) | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_RETURN_REG) << 21)+ | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S0) << 16)+ | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S1) << 11);+ sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32));+#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)+ /* addu rd, rs, rt */+ inst = 33 | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_RETURN_REG) << 11)+ | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S0) << 21)+ | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S1) << 16);+ sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32));+#elif (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)+ /* daddu rd, rs, rt */+ inst = 45 | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_RETURN_REG) << 11)+ | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S0) << 21)+ | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S1) << 16);+ sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32));+#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)+ /* add rd, rs1, rs2 */+ inst = 0x33 | (0 << 12) | (0 << 25) | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_RETURN_REG) << 7)+ | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S0) << 15)+ | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S1) << 20);+ sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32));+#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)+ /* agrk rd, rs1, rs2 */+ inst = (0xb9e8u << 16)+ | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_RETURN_REG) << 4)+ | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S0) << 12)+ | (sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S1);+ sljit_emit_op_custom(compiler, &inst, sizeof(inst));+#elif (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)+ /* add.d rd, rs1, rs2 */+ inst = (0x21u << 15) | (sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_RETURN_REG)+ | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S0) << 5)+ | ((sljit_u32)sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_S1) << 10);+ sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32));+#else+ inst = 0;+ sljit_emit_op_custom(compiler, &inst, 0);+#endif++ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ FAILED(code.func2(32, -11) != 21, "test37 case 1 failed\n");+ FAILED(code.func2(1000, 234) != 1234, "test37 case 2 failed\n");+#if IS_64BIT+ FAILED(code.func2(SLJIT_W(0x20f0a04090c06070), SLJIT_W(0x020f0a04090c0607)) != SLJIT_W(0x22ffaa4499cc6677), "test37 case 3 failed\n");+#endif /* IS_64BIT */++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test38(void)+{+ /* Test long multiply and division. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_s32 i;+ sljit_sw buf[7 + 4 + 8 + 8 + 2];++ if (verbose)+ printf("Run test38\n");++ FAILED(!compiler, "cannot create compiler\n");+ for (i = 0; i < 7 + 4 + 8 + 8; i++)+ buf[i] = -1;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 5, 5, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -0x1fb308a);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 0xf50c873);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, 0x8a0475b);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 0x9dc849b);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -0x7c69a35);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, 0x5a4d0c4);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_IMM, 0x9a3b06d);++#if IS_64BIT+ /* buf[7-26] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(-0x5dc4f897b8cd67f5));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x3f8b5c026cb088df));+ sljit_emit_op0(compiler, SLJIT_LMUL_UW);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(-0x5dc4f897b8cd67f5));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x3f8b5c026cb088df));+ sljit_emit_op0(compiler, SLJIT_LMUL_SW);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(-0x5dc4f897b8cd67f5));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x3f8b5c026cb088df));+ sljit_emit_op0(compiler, SLJIT_DIVMOD_UW);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(-0x5dc4f897b8cd67f5));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x3f8b5c026cb088df));+ sljit_emit_op0(compiler, SLJIT_DIVMOD_SW);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x5cf783d3cf0a74b0));+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x3d5df42d03a28fc7));+ sljit_emit_op0(compiler, SLJIT_DIVMOD_U32);+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x371df5197ba26a28));+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x46c78a5cfd6a420c));+ sljit_emit_op0(compiler, SLJIT_DIVMOD_S32);+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R1, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)SLJIT_W(0xc456f048c28a611b));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x3d4af2c543));+ sljit_emit_op0(compiler, SLJIT_DIV_UW);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 19 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 20 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(-0x720fa4b74c329b14));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0xa64ae42b7d6));+ sljit_emit_op0(compiler, SLJIT_DIV_SW);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 21 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 22 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x4af51c027b34));+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x9ba4ff2906b14));+ sljit_emit_op0(compiler, SLJIT_DIV_U32);+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 23 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 24 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0xc40b58a3f20d));+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(-0xa63c923));+ sljit_emit_op0(compiler, SLJIT_DIV_S32);+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R1, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 25 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 26 * sizeof(sljit_sw), SLJIT_R1, 0);++#else /* !IS_64BIT */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -0x58cd67f5);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x3cb088df);+ sljit_emit_op0(compiler, SLJIT_LMUL_UW);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -0x58cd67f5);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x3cb088df);+ sljit_emit_op0(compiler, SLJIT_LMUL_SW);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -0x58cd67f5);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x3cb088df);+ sljit_emit_op0(compiler, SLJIT_DIVMOD_UW);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -0x58cd67f5);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x3cb088df);+ sljit_emit_op0(compiler, SLJIT_DIVMOD_SW);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0xcf0a74b0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0x03a28fc7);+ sljit_emit_op0(compiler, SLJIT_DIVMOD_U32);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0x7ba26a28);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)0xfd6a420c);+ sljit_emit_op0(compiler, SLJIT_DIVMOD_S32);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0x9d4b7036);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0xb86d0);+ sljit_emit_op0(compiler, SLJIT_DIV_UW);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 19 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 20 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -0x58b0692c);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0xd357);+ sljit_emit_op0(compiler, SLJIT_DIV_SW);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 21 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 22 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0x1c027b34);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)0xf2906b14);+ sljit_emit_op0(compiler, SLJIT_DIV_U32);+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 23 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 24 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0x58a3f20d);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, -0xa63c923);+ sljit_emit_op0(compiler, SLJIT_DIV_S32);+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R1, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 25 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 26 * sizeof(sljit_sw), SLJIT_R1, 0);+#endif /* IS_64BIT */++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, -1000123);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 1000);+ sljit_emit_op0(compiler, SLJIT_DIVMOD_S32);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 27 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 28 * sizeof(sljit_sw), SLJIT_R1, 0);++ /* buf[0-6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R3, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R4, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_S1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_S2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_S3, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_S4, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);++ FAILED(buf[0] != -0x1fb308a, "test38 case 1 failed\n");+ FAILED(buf[1] != 0xf50c873, "test38 case 2 failed\n");+ FAILED(buf[2] != 0x8a0475b, "test38 case 3 failed\n");+ FAILED(buf[3] != 0x9dc849b, "test38 case 4 failed\n");+ FAILED(buf[4] != -0x7c69a35, "test38 case 5 failed\n");+ FAILED(buf[5] != 0x5a4d0c4, "test38 case 6 failed\n");+ FAILED(buf[6] != 0x9a3b06d, "test38 case 7 failed\n");++ FAILED(buf[7] != WCONST(-4388959407985636971, -1587000939), "test38 case 8 failed\n");+ FAILED(buf[8] != WCONST(2901680654366567099, 665003983), "test38 case 9 failed\n");+ FAILED(buf[9] != WCONST(-4388959407985636971, -1587000939), "test38 case 10 failed\n");+ FAILED(buf[10] != WCONST(-1677173957268872740, -353198352), "test38 case 11 failed\n");+ FAILED(buf[11] != 2, "test38 case 12 failed\n");+ FAILED(buf[12] != WCONST(2532236178951865933, 768706125), "test38 case 13 failed\n");+ FAILED(buf[13] != -1, "test38 case 14 failed\n");+ FAILED(buf[14] != WCONST(-2177944059851366166, -471654166), "test38 case 15 failed\n");++ FAILED(buf[15] != 56, "test38 case 16 failed\n");+ FAILED(buf[16] != 58392872, "test38 case 17 failed\n");+ FAILED(buf[17] != -47, "test38 case 18 failed\n");+ FAILED(buf[18] != 35949148, "test38 case 19 failed\n");++ FAILED(buf[19] != WCONST(0x3340bfc, 0xda5), "test38 case 20 failed\n");+ FAILED(buf[20] != WCONST(0x3d4af2c543, 0xb86d0), "test38 case 21 failed\n");+ FAILED(buf[21] != WCONST(-0xaf978, -0x6b6e), "test38 case 22 failed\n");+ FAILED(buf[22] != WCONST(0xa64ae42b7d6, 0xd357), "test38 case 23 failed\n");++ FAILED(buf[23] != 0x0, "test38 case 24 failed\n");+ FAILED(buf[24] != (sljit_sw)0xf2906b14, "test38 case 25 failed\n");+ FAILED(buf[25] != -0x8, "test38 case 26 failed\n");+ FAILED(buf[26] != -0xa63c923, "test38 case 27 failed\n");++ FAILED(*(sljit_s32*)(buf + 27) != -1000, "test38 case 28 failed\n");+ FAILED(*(sljit_s32*)(buf + 28) != -123, "test38 case 29 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test39(void)+{+ /* Test mov. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ void *buf[5];++ if (verbose)+ printf("Run test39\n");++ FAILED(!compiler, "cannot create compiler\n");++ buf[0] = buf + 2;+ buf[1] = NULL;+ buf[2] = NULL;+ buf[3] = NULL;+ buf[4] = NULL;+ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(P, P), 3, 2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_up), SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_up));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 2);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_MEM2(SLJIT_S0, SLJIT_R1), SLJIT_POINTER_SHIFT, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_up));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 3 << SLJIT_POINTER_SHIFT);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_S0, 0);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_MEM2(SLJIT_R2, SLJIT_R1), 0, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2 * sizeof(sljit_up));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1 << SLJIT_POINTER_SHIFT);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_MEM2(SLJIT_R2, SLJIT_R1), 2, SLJIT_R0, 0);++ sljit_emit_return(compiler, SLJIT_MOV_P, SLJIT_R0, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ FAILED(code.func1((sljit_sw)&buf) != (sljit_sw)(buf + 2), "test39 case 1 failed\n");+ FAILED(buf[1] != buf + 2, "test39 case 2 failed\n");+ FAILED(buf[2] != buf + 3, "test39 case 3 failed\n");+ FAILED(buf[3] != buf + 4, "test39 case 4 failed\n");+ FAILED(buf[4] != buf + 2, "test39 case 5 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test40(void)+{+ /* Test sljit_emit_op_flags with 32 bit operations. */++ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_s32 buf[24];+ sljit_sw buf2[6];+ sljit_s32 i;++ if (verbose)+ printf("Run test40\n");++ for (i = 0; i < 24; ++i)+ buf[i] = -17;+ buf[16] = 0;+ for (i = 0; i < 6; ++i)+ buf2[i] = -13;+ buf2[4] = -124;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(P, P), 3, 3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -7);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_R2, 0, SLJIT_IMM, 13);+ /* buf[0] */+ sljit_emit_op_flags(compiler, SLJIT_MOV32, SLJIT_MEM0(), (sljit_sw)&buf, SLJIT_LESS);+ /* buf[2] */+ sljit_emit_op_flags(compiler, SLJIT_AND32, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_s32), SLJIT_NOT_ZERO);++ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_IMM, -7);+ /* buf[4] */+ sljit_emit_op_flags(compiler, SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_s32), SLJIT_EQUAL);+ /* buf[6] */+ sljit_emit_op_flags(compiler, SLJIT_AND32, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_s32), SLJIT_NOT_EQUAL);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x1235);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 0x1235);+ sljit_emit_op_flags(compiler, SLJIT_AND32 | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_ZERO);+ /* buf[8] */+ sljit_emit_op_flags(compiler, SLJIT_AND32, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_s32), SLJIT_ZERO);+ /* buf[10] */+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_s32), SLJIT_R0, 0);++ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_IMM, -7);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 12);+ /* buf[12] */+ sljit_emit_op_flags(compiler, SLJIT_MOV32, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 2, SLJIT_EQUAL);+ sljit_emit_op_flags(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_EQUAL);+ /* buf[14] */+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_s32), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 16);+ /* buf[16] */+ sljit_emit_op_flags(compiler, SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 2, SLJIT_EQUAL);+ /* buf[18] */+ sljit_emit_op_flags(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_s32), SLJIT_NOT_EQUAL);++ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_IMM, -7);+ /* buf[20] */+ sljit_emit_op_flags(compiler, SLJIT_XOR32 | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S0), 20 * sizeof(sljit_s32), SLJIT_ZERO);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 39);+ sljit_emit_op_flags(compiler, SLJIT_XOR32, SLJIT_R0, 0, SLJIT_NOT_ZERO);+ /* buf[22] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 22 * sizeof(sljit_s32), SLJIT_R0, 0);++ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R2, 0, SLJIT_IMM, -7);+ /* buf2[0] */+ sljit_emit_op_flags(compiler, SLJIT_AND, SLJIT_MEM0(), (sljit_sw)&buf2, SLJIT_GREATER);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R2, 0, SLJIT_IMM, 5);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1);+ /* buf2[1] */+ sljit_emit_op_flags(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_SIG_LESS);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_R2, 0, SLJIT_IMM, 5);+ /* buf2[2] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_LESS);+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_NOT_EQUAL);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R2, 0, SLJIT_IMM, 5);+ /* buf2[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_sw), SLJIT_S2, 0);+ sljit_emit_op_flags(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_SIG_LESS);+ /* buf2[4] */+ sljit_emit_op_flags(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_sw), SLJIT_ZERO);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R2, 0, SLJIT_IMM, 0);+ /* buf2[5] */+ sljit_emit_op_flags(compiler, SLJIT_XOR, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_sw), SLJIT_GREATER);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)&buf, (sljit_sw)&buf2);+ FAILED(buf[0] != 0, "test40 case 1 failed\n");+ FAILED(buf[1] != -17, "test40 case 2 failed\n");+ FAILED(buf[2] != 1, "test40 case 3 failed\n");+ FAILED(buf[3] != -17, "test40 case 4 failed\n");+ FAILED(buf[4] != 1, "test40 case 5 failed\n");+ FAILED(buf[5] != -17, "test40 case 6 failed\n");+ FAILED(buf[6] != 1, "test40 case 7 failed\n");+ FAILED(buf[7] != -17, "test40 case 8 failed\n");+ FAILED(buf[8] != 0, "test40 case 9 failed\n");+ FAILED(buf[9] != -17, "test40 case 10 failed\n");+ FAILED(buf[10] != 1, "test40 case 11 failed\n");+ FAILED(buf[11] != -17, "test40 case 12 failed\n");+ FAILED(buf[12] != 1, "test40 case 13 failed\n");+ FAILED(buf[13] != -17, "test40 case 14 failed\n");+ FAILED(buf[14] != 1, "test40 case 15 failed\n");+ FAILED(buf[15] != -17, "test40 case 16 failed\n");+ FAILED(buf[16] != 0, "test40 case 17 failed\n");+ FAILED(buf[17] != -17, "test40 case 18 failed\n");+ FAILED(buf[18] != 0, "test40 case 19 failed\n");+ FAILED(buf[19] != -17, "test40 case 20 failed\n");+ FAILED(buf[20] != -18, "test40 case 21 failed\n");+ FAILED(buf[21] != -17, "test40 case 22 failed\n");+ FAILED(buf[22] != 38, "test40 case 23 failed\n");+ FAILED(buf[23] != -17, "test40 case 24 failed\n");++ FAILED(buf2[0] != 0, "test40 case 25 failed\n");+ FAILED(buf2[1] != 1, "test40 case 26 failed\n");+ FAILED(buf2[2] != 0, "test40 case 27 failed\n");+ FAILED(buf2[3] != 1, "test40 case 28 failed\n");+ FAILED(buf2[4] != -123, "test40 case 29 failed\n");+ FAILED(buf2[5] != -14, "test40 case 30 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test41(void)+{+ /* Test jump optimizations. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_s32 i;+ sljit_sw buf[15];+ struct sljit_jump *jump;++ if (verbose)+ printf("Run test41\n");++ FAILED(!compiler, "cannot create compiler\n");+ for (i = 0; i < 15; i++)+ buf[i] = -1;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 3, 2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x3a5c6f);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 3);+ sljit_set_target(sljit_emit_jump(compiler, SLJIT_LESS), 0x11223344);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0xd37c10);+#if IS_64BIT+ sljit_set_target(sljit_emit_jump(compiler, SLJIT_LESS), SLJIT_W(0x1122334455));+#endif /* IS_64BIT */+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x670b15);+#if IS_64BIT+ sljit_set_target(sljit_emit_jump(compiler, SLJIT_LESS), SLJIT_W(0x112233445566));+#endif /* IS_64BIT */+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 0x59b48e);+#if IS_64BIT+ sljit_set_target(sljit_emit_jump(compiler, SLJIT_LESS), SLJIT_W(0x1122334455667788));+#endif /* IS_64BIT */+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_S1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -0x58b026);+ sljit_set_target(sljit_emit_cmp(compiler, SLJIT_EQUAL, SLJIT_R1, 0, SLJIT_IMM, 0), 0x11223344);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 0);+#if IS_64BIT+ sljit_set_target(sljit_emit_cmp(compiler, SLJIT_NOT_EQUAL, SLJIT_IMM, 0, SLJIT_S1, 0), SLJIT_W(0x1122334455));+#endif /* IS_64BIT */+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_S1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0xcb69a1);+#if IS_64BIT+ sljit_set_target(sljit_emit_cmp(compiler, SLJIT_EQUAL, SLJIT_R1, 0, SLJIT_IMM, 0), SLJIT_W(0x112233445566));+#endif /* IS_64BIT */+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0);+#if IS_64BIT+ sljit_set_target(sljit_emit_cmp(compiler, SLJIT_NOT_EQUAL, SLJIT_IMM, 0, SLJIT_R1, 0), SLJIT_W(0x1122334455667788));+#endif /* IS_64BIT */+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0xf698c1);+ sljit_set_target(sljit_emit_cmp(compiler, SLJIT_SIG_LESS, SLJIT_R1, 0, SLJIT_IMM, 0), 0x11223344);+ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 0x3ba046);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0);+#if IS_64BIT+ sljit_set_target(sljit_emit_cmp(compiler, SLJIT_GREATER, SLJIT_R1, 0, SLJIT_S1, 0), SLJIT_W(0x1122334455));+#endif /* IS_64BIT */+ /* buf[9] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_S1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -0x62b193);+#if IS_64BIT+ sljit_set_target(sljit_emit_cmp(compiler, SLJIT_SIG_GREATER, SLJIT_R0, 0, SLJIT_R1, 0), SLJIT_W(0x112233445566));+#endif /* IS_64BIT */+ /* buf[10] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x5ed062);+#if IS_64BIT+ sljit_set_target(sljit_emit_cmp(compiler, SLJIT_GREATER, SLJIT_IMM, 1000, SLJIT_R1, 0), SLJIT_W(0x1122334455667788));+#endif /* IS_64BIT */+ /* buf[11] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -0xb2091c);+ jump = sljit_emit_cmp(compiler, SLJIT_NOT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0);+ for (i = 0; i < 1000; i++)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_set_label(jump, sljit_emit_label(compiler));+ /* buf[12] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 0x684b1c);+ jump = sljit_emit_cmp(compiler, SLJIT_NOT_EQUAL, SLJIT_IMM, 0, SLJIT_S1, 0);+ for (i = 0; i < 100000; i++)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 2);+ sljit_set_label(jump, sljit_emit_label(compiler));+ /* buf[13] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_S1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -0xe49051);+ /* Unsigned compare. */+ jump = sljit_emit_cmp(compiler, SLJIT_GREATER, SLJIT_R1, 0, SLJIT_IMM, 100);+ for (i = 0; i < 100000; i++)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 3);+ sljit_set_label(jump, sljit_emit_label(compiler));+ /* buf[14] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ FAILED(buf[0] != 0x3a5c6f, "test41 case 1 failed\n");+ FAILED(buf[1] != 0xd37c10, "test41 case 2 failed\n");+ FAILED(buf[2] != 0x670b15, "test41 case 3 failed\n");+ FAILED(buf[3] != 0x59b48e, "test41 case 4 failed\n");+ FAILED(buf[4] != -0x58b026, "test41 case 5 failed\n");+ FAILED(buf[5] != 0, "test41 case 6 failed\n");+ FAILED(buf[6] != 0xcb69a1, "test41 case 7 failed\n");+ FAILED(buf[7] != 0, "test41 case 8 failed\n");+ FAILED(buf[8] != 0xf698c1, "test41 case 9 failed\n");+ FAILED(buf[9] != 0x3ba046, "test41 case 10 failed\n");+ FAILED(buf[10] != -0x62b193, "test41 case 11 failed\n");+ FAILED(buf[11] != 0x5ed062, "test41 case 12 failed\n");+ FAILED(buf[12] != -0xb2091c, "test41 case 13 failed\n");+ FAILED(buf[13] != 0x684b1c, "test41 case 14 failed\n");+ FAILED(buf[14] != -0xe49051, "test41 case 15 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test42(void)+{+ /* Test all registers provided by the CPU. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_jump* jump;+ sljit_sw buf[2];+ sljit_s32 i;++ if (verbose)+ printf("Run test42\n");++ FAILED(!compiler, "cannot create compiler\n");++ buf[0] = 39;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), SLJIT_NUMBER_OF_REGISTERS, 0, 0);++ for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS; i++)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, 32);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)buf);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0);++ for (i = 2; i < SLJIT_NUMBER_OF_REGISTERS; i++) {+ if (sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_R(i)) >= 0) {+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R(i)), 0);+ } else+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, buf[0]);+ }++ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 32);+ for (i = 2; i < SLJIT_NUMBER_OF_REGISTERS; i++) {+ if (sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_R(i)) >= 0) {+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R(i)), 32);+ } else+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, buf[0]);+ }++ for (i = 2; i < SLJIT_NUMBER_OF_REGISTERS; i++) {+ if (sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_R(i)) >= 0) {+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, 32);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_MEM2(SLJIT_R(i), SLJIT_R0), 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_MEM2(SLJIT_R0, SLJIT_R(i)), 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, 8);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_MEM2(SLJIT_R0, SLJIT_R(i)), 2);+ } else+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 3 * buf[0]);+ }++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 32 + sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func0();++ FAILED(buf[1] != (39 * 5 * (SLJIT_NUMBER_OF_REGISTERS - 2)), "test42 case 1 failed\n");++ sljit_free_code(code.code, NULL);++ /* Next test. */++ compiler = sljit_create_compiler(NULL);++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), SLJIT_NUMBER_OF_SCRATCH_REGISTERS, SLJIT_NUMBER_OF_SAVED_REGISTERS, 0);++ for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS; i++)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, 17);++ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS0(W));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ for (i = 0; i < SLJIT_NUMBER_OF_SAVED_REGISTERS; i++)+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S(i), 0);++ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), SLJIT_NUMBER_OF_REGISTERS, 0, 0);+ for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS; i++)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, 35);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ FAILED(code.func0() != (SLJIT_NUMBER_OF_SAVED_REGISTERS * 17), "test42 case 2 failed\n");++ sljit_free_code(code.code, NULL);++ /* Next test. */++ compiler = sljit_create_compiler(NULL);++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), SLJIT_NUMBER_OF_SCRATCH_REGISTERS, SLJIT_NUMBER_OF_SAVED_REGISTERS, 0);++ for (i = 0; i < SLJIT_NUMBER_OF_SAVED_REGISTERS; i++)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S(i), 0, SLJIT_IMM, 68);+ for (i = 0; i < SLJIT_NUMBER_OF_SCRATCH_REGISTERS; i++)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, 0);++ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS0(W));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ for (i = 0; i < SLJIT_NUMBER_OF_SAVED_REGISTERS; i++)+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S(i), 0);++ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), SLJIT_NUMBER_OF_REGISTERS, 0, 0);+ for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS; i++)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, 43);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ FAILED(code.func0() != (SLJIT_NUMBER_OF_SAVED_REGISTERS * 68), "test42 case 3 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test43(void)+{+ /* Test addressing modes. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_u8 buf[3 + SLJIT_NUMBER_OF_REGISTERS * 3];+ sljit_u8 *buf_start;+ sljit_uw addr = (sljit_uw)&buf;+ sljit_s32 i;++ addr = addr + 3 - (addr % 3);+ buf_start = (sljit_u8*)addr;++ SLJIT_ASSERT((addr % 3) == 0);++ for (i = 0; i < (sljit_s32)sizeof(buf); i++)+ buf[i] = 0;++ if (verbose)+ printf("Run test43\n");++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), SLJIT_NUMBER_OF_REGISTERS, 0, 0);++ addr /= 3;+ for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS; i++, addr++) {+ if (sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_R(i)) == -1)+ continue;+ /* buf_start[i * 3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, (sljit_sw)addr);+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM2(SLJIT_R(i), SLJIT_R(i)), 1, SLJIT_IMM, 88 + i);+ /* buf_start[i * 3 + 1] */+ if (i != 0) {+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)(addr * 2 + 1));+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM2(SLJIT_R(i), SLJIT_R0), 0, SLJIT_IMM, 147 + i);+ }+ /* buf_start[i * 3 + 2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, (sljit_sw)(addr * 3 + 2));+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_R(i)), 0, SLJIT_IMM, 191 + i);+ }++ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R2, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func0();++ for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS; i++) {+ if (sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_R(i)) == -1)+ continue;++ FAILED(buf_start[i * 3] != 88 + i, "test43 case 1 failed\n");+ if (i != 0) {+ FAILED(buf_start[i * 3 + 1] != 147 + i, "test43 case 2 failed\n");+ }+ FAILED(buf_start[i * 3 + 2] != 191 + i, "test43 case 3 failed\n");+ }++ sljit_free_code(code.code, NULL);++ successful_tests++;+}++static void test44(void)+{+ /* Test select operation. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ int i;+ sljit_sw buf[25];+ sljit_s32 ibuf[9];++ union {+ sljit_f32 value;+ sljit_s32 s32_value;+ } sbuf[3];++ sbuf[0].s32_value = 0x7fffffff;+ sbuf[1].value = 7.5;+ sbuf[2].value = -14.75;++ if (verbose)+ printf("Run test44\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 25; i++)+ buf[i] = 0;+ for (i = 0; i < 9; i++)+ ibuf[i] = 0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS3V(P, P, P), 5 | SLJIT_ENTER_FLOAT(3), 3, 2 * sizeof(sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 17);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 34);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R0, 0, SLJIT_IMM, -10);+ sljit_emit_select(compiler, SLJIT_SIG_LESS, SLJIT_R0, SLJIT_R1, 0, SLJIT_R0);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R0, 0, SLJIT_IMM, -10);+ sljit_emit_select(compiler, SLJIT_SIG_GREATER, SLJIT_R0, SLJIT_R1, 0, SLJIT_R0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -67);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 81);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R0, 0, SLJIT_IMM, -10);+ sljit_emit_select(compiler, SLJIT_SIG_LESS_EQUAL, SLJIT_R0, SLJIT_R0, 0, SLJIT_R1);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R0, 0, SLJIT_IMM, -66);+ sljit_emit_select(compiler, SLJIT_SIG_GREATER, SLJIT_R0, SLJIT_R0, 0, SLJIT_R1);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 24);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 23);+ sljit_emit_select(compiler, SLJIT_EQUAL, SLJIT_R0, SLJIT_IMM, 66, SLJIT_R0);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_IMM, 78);+ sljit_emit_select(compiler, SLJIT_NOT_EQUAL, SLJIT_R0, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R0);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_select(compiler, SLJIT_NOT_EQUAL, SLJIT_R0, SLJIT_IMM, WCONST(0x1234567812345678, 0x12345678), SLJIT_R0);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R0, 0);++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ SLJIT_ASSERT(sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_R3) == -1 && sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_R4) == -1);+#endif /* SLJIT_CONFIG_X86_32 */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 7);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -45);+ sljit_emit_op2(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 8);+ sljit_emit_select(compiler, SLJIT_OVERFLOW, SLJIT_R3, SLJIT_IMM, 35, SLJIT_R3);+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R3, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0x1010000000, 0x100000));+ sljit_emit_op2u(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_IMM, WCONST(0x1010000000, 0x100000));+ sljit_emit_select(compiler, SLJIT_OVERFLOW, SLJIT_R3, SLJIT_IMM, 35, SLJIT_R3);+ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 71);+ sljit_emit_op2(compiler, SLJIT_LSHR | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 8);+ sljit_emit_select(compiler, SLJIT_NOT_ZERO, SLJIT_R3, SLJIT_IMM, 13, SLJIT_R0);+ /* buf[9] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 12);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -29);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 8);+ sljit_emit_select(compiler, SLJIT_OVERFLOW, SLJIT_R0, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R3);+ /* buf[10] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 16);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_IMM, -12);+ sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_IMM, 8);+ sljit_emit_select(compiler, SLJIT_NOT_EQUAL, SLJIT_R0, SLJIT_MEM1(SLJIT_R0), 11 * sizeof(sljit_sw), SLJIT_R1);+ /* buf[11] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 99);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_IMM, -21);+ sljit_emit_select(compiler, SLJIT_EQUAL, SLJIT_R0, SLJIT_MEM1(SLJIT_R0), 12 * sizeof(sljit_sw), SLJIT_R1);+ /* buf[12] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 43);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 90);+ sljit_emit_op2u(compiler, SLJIT_XOR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 2);+ sljit_emit_select(compiler, SLJIT_ZERO, SLJIT_R1, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R1);+ /* buf[13] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, -62);+ sljit_emit_select(compiler, SLJIT_NOT_ZERO, SLJIT_R2, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_R1);+ /* buf[14] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_R2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 15);+ sljit_emit_op2u(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_IMM, 38);+ sljit_emit_select(compiler, SLJIT_CARRY, SLJIT_R0, SLJIT_MEM2(SLJIT_S0, SLJIT_R1), SLJIT_WORD_SHIFT, SLJIT_R0);+ /* buf[15] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, WCONST(0x8800000000, 0x8800000) + 16 * sizeof(sljit_sw));+ sljit_emit_op2u(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_IMM, 77);+ sljit_emit_select(compiler, SLJIT_CARRY, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), WCONST(-0x8800000000, -0x8800000), SLJIT_R0);+ /* buf[16] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_R0, 0);++ if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) {+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S2), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S2), 2 * sizeof(sljit_f32));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 16);+ sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0);+ sljit_emit_select(compiler, SLJIT_F_EQUAL, SLJIT_R0, SLJIT_IMM, -45, SLJIT_R0);+ /* buf[17] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_GREATER, SLJIT_FR1, 0, SLJIT_FR2, 0);+ sljit_emit_select(compiler, SLJIT_F_GREATER, SLJIT_R0, SLJIT_IMM, -45, SLJIT_R0);+ /* buf[18] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_GREATER_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0);+ sljit_emit_select(compiler, SLJIT_F_GREATER_EQUAL, SLJIT_R0, SLJIT_IMM, 33, SLJIT_R0);+ /* buf[19] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 19 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -70);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 8);+ sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_LESS, SLJIT_FR1, 0, SLJIT_FR2, 0);+ sljit_emit_select(compiler, SLJIT_F_LESS, SLJIT_R0, SLJIT_R0, 0, SLJIT_R1);+ /* buf[20] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 20 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_LESS_EQUAL, SLJIT_FR2, 0, SLJIT_FR1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -60);+ sljit_emit_select(compiler, SLJIT_F_GREATER, SLJIT_R0, SLJIT_IMM, 8, SLJIT_R0);+ /* buf[21] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 21 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_NOT_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0);+ sljit_emit_select(compiler, SLJIT_F_NOT_EQUAL, SLJIT_R0, SLJIT_IMM, 31, SLJIT_R0);+ /* buf[22] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 22 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 23 * sizeof(sljit_sw), SLJIT_IMM, 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 53);+ sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_ORDERED, SLJIT_FR1, 0, SLJIT_FR0, 0);+ sljit_emit_select(compiler, SLJIT_ORDERED, SLJIT_R0, SLJIT_MEM1(SLJIT_S0), 23 * sizeof(sljit_sw), SLJIT_R1);+ /* buf[23] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 23 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 24 * sizeof(sljit_sw), SLJIT_IMM, 59);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1);+ sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_UNORDERED, SLJIT_FR0, 0, SLJIT_FR1, 0);+ sljit_emit_select(compiler, SLJIT_UNORDERED, SLJIT_R0, SLJIT_MEM1(SLJIT_R0), 24 * sizeof(sljit_sw), SLJIT_R1);+ /* buf[24] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 24 * sizeof(sljit_sw), SLJIT_R0, 0);+ }++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 177);+ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 178);+ sljit_emit_select(compiler, SLJIT_LESS | SLJIT_32, SLJIT_R0, SLJIT_IMM, 200, SLJIT_R0);+ /* ibuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_s32) >> 1);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_IMM, 177);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 95);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_s32));+ sljit_emit_select(compiler, SLJIT_LESS_EQUAL | SLJIT_32, SLJIT_R0, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), 1, SLJIT_R1);+ /* ibuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R3, 0, SLJIT_IMM, 56);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, -63);+ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_SIG_LESS, SLJIT_R3, 0, SLJIT_R4, 0);+ sljit_emit_select(compiler, SLJIT_SIG_LESS | SLJIT_32, SLJIT_R3, SLJIT_R4, 0, SLJIT_R3);+ /* ibuf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32), SLJIT_R3, 0);+ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_SIG_LESS, SLJIT_R3, 0, SLJIT_R4, 0);+ sljit_emit_select(compiler, SLJIT_SIG_GREATER_EQUAL | SLJIT_32, SLJIT_R3, SLJIT_R4, 0, SLJIT_R3);+ /* ibuf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_R3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_s32), SLJIT_IMM, 467);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 10);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R2, 0, SLJIT_IMM, 20);+ sljit_emit_select(compiler, SLJIT_SIG_LESS | SLJIT_32, SLJIT_R2, SLJIT_MEM0(), (sljit_sw)(ibuf + 4), SLJIT_R2);+ /* ibuf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_s32), SLJIT_R2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 5 * sizeof(sljit_s32));+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_s32), SLJIT_IMM, -29);+ sljit_emit_op2u(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, -1);+ sljit_emit_select(compiler, SLJIT_CARRY | SLJIT_32, SLJIT_R2, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), 0, SLJIT_R2);+ /* ibuf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_s32), SLJIT_R2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 689);+ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 800);+ sljit_emit_select(compiler, SLJIT_LESS | SLJIT_32, SLJIT_R1, SLJIT_IMM, 0, SLJIT_R0);+ /* ibuf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_s32), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, -510);+ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_SIG_GREATER_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 800);+ sljit_emit_select(compiler, SLJIT_SIG_GREATER_EQUAL | SLJIT_32, SLJIT_R0, SLJIT_IMM, 0, SLJIT_R0);+ /* ibuf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 7 * sizeof(sljit_s32), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 649);+ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 400);+ sljit_emit_select(compiler, SLJIT_NOT_EQUAL | SLJIT_32, SLJIT_R0, SLJIT_R1, 0, SLJIT_R1);+ sljit_emit_select(compiler, SLJIT_NOT_EQUAL | SLJIT_32, SLJIT_R0, SLJIT_R0, 0, SLJIT_R0);+ /* ibuf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 8 * sizeof(sljit_s32), SLJIT_R0, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func3((sljit_sw)&buf, (sljit_sw)&ibuf, (sljit_sw)&sbuf);++ FAILED(buf[0] != 17, "test44 case 1 failed\n");+ FAILED(buf[1] != 34, "test44 case 2 failed\n");+ FAILED(buf[2] != -67, "test44 case 3 failed\n");+ FAILED(buf[3] != 81, "test44 case 4 failed\n");+ FAILED(buf[4] != 24, "test44 case 5 failed\n");+ FAILED(buf[5] != 78, "test44 case 6 failed\n");+ FAILED(buf[6] != WCONST(0x1234567812345678, 0x12345678), "test44 case 7 failed\n");+ FAILED(buf[7] != -45, "test44 case 8 failed\n");+ FAILED(buf[8] != 35, "test44 case 9 failed\n");+ FAILED(buf[9] != 71, "test44 case 10 failed\n");+ FAILED(buf[10] != -29, "test44 case 11 failed\n");+ FAILED(buf[11] != 16, "test44 case 12 failed\n");+ FAILED(buf[12] != -21, "test44 case 13 failed\n");+ FAILED(buf[13] != 90, "test44 case 14 failed\n");+ FAILED(buf[14] != -62, "test44 case 15 failed\n");+ FAILED(buf[15] != 38, "test44 case 16 failed\n");+ FAILED(buf[16] != 77, "test44 case 17 failed\n");++ if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) {+ FAILED(buf[17] != 16, "test44 case 18 failed\n");+ FAILED(buf[18] != -45, "test44 case 19 failed\n");+ FAILED(buf[19] != 33, "test44 case 20 failed\n");+ FAILED(buf[20] != 8, "test44 case 21 failed\n");+ FAILED(buf[21] != -60, "test44 case 22 failed\n");+ FAILED(buf[22] != 31, "test44 case 23 failed\n");+ FAILED(buf[23] != 53, "test44 case 24 failed\n");+ FAILED(buf[24] != 59, "test44 case 25 failed\n");+ }++ FAILED(ibuf[0] != 200, "test44 case 26 failed\n");+ FAILED(ibuf[1] != 177, "test44 case 27 failed\n");+ FAILED(ibuf[2] != 56, "test44 case 28 failed\n");+ FAILED(ibuf[3] != -63, "test44 case 29 failed\n");+ FAILED(ibuf[4] != 467, "test44 case 30 failed\n");+ FAILED(ibuf[5] != -29, "test44 case 31 failed\n");+ FAILED(ibuf[6] != 0, "test44 case 32 failed\n");+ FAILED(ibuf[7] != -510, "test44 case 33 failed\n");+ FAILED(ibuf[8] != 649, "test44 case 34 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test45(void)+{+ /* Check value preservation. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[2];+ sljit_s32 i;++ if (verbose)+ printf("Run test45\n");++ FAILED(!compiler, "cannot create compiler\n");+ buf[0] = 0;+ buf[1] = 0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), SLJIT_NUMBER_OF_REGISTERS, 0, sizeof (sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 217);++ /* Check 1 */+ for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS; i++)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, 118);++ sljit_emit_op0(compiler, SLJIT_DIVMOD_SW);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);++ for (i = 2; i < SLJIT_NUMBER_OF_REGISTERS; i++)+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R(i), 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)(buf + 0), SLJIT_R0, 0);++ /* Check 2 */+ for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS; i++)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, 146);++ sljit_emit_op0(compiler, SLJIT_DIV_SW);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);++ for (i = 1; i < SLJIT_NUMBER_OF_REGISTERS; i++)+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R(i), 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)(buf + 1), SLJIT_R0, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func0();++ FAILED(buf[0] != (SLJIT_NUMBER_OF_REGISTERS - 2) * 118 + 217, "test45 case 1 failed\n");+ FAILED(buf[1] != (SLJIT_NUMBER_OF_REGISTERS - 1) * 146 + 217, "test45 case 2 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test46(void)+{+ /* Check integer subtraction with negative immediate. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[13];+ sljit_s32 i;++ if (verbose)+ printf("Run test46\n");++ for (i = 0; i < 13; i++)+ buf[i] = 77;++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 3, 1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 90 << 12);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -(91 << 12));+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R1, 0);+ /* buf[1] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_SIG_GREATER);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -(91 << 12));+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R1, 0);+ /* buf[3] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_LESS);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER_EQUAL, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -(91 << 12));+ /* buf[4] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_SIG_GREATER_EQUAL);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -(91 << 12));+ /* buf[5] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_LESS_EQUAL);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -(91 << 12));+ /* buf[6] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_GREATER);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -(91 << 12));+ /* buf[7] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_SIG_LESS);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 90);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -91);+ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[9] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_SIG_GREATER);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 90);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -91);+ /* buf[10] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_LESS_EQUAL);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, -0x7fffffff);+ sljit_emit_op2(compiler, SLJIT_ADD32 | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -(91 << 12));+ /* buf[11] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_OVERFLOW);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, -0x7fffffff-1);+ sljit_emit_op2(compiler, SLJIT_SUB32 | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_IMM, 0, SLJIT_R0, 0);+ /* buf[12] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_OVERFLOW);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);++ FAILED(buf[0] != (181 << 12), "test46 case 1 failed\n");+ FAILED(buf[1] != 1, "test46 case 2 failed\n");+ FAILED(buf[2] != (181 << 12), "test46 case 3 failed\n");+ FAILED(buf[3] != 1, "test46 case 4 failed\n");+ FAILED(buf[4] != 1, "test46 case 5 failed\n");+ FAILED(buf[5] != 1, "test46 case 6 failed\n");+ FAILED(buf[6] != 0, "test46 case 7 failed\n");+ FAILED(buf[7] != 0, "test46 case 8 failed\n");+ FAILED(buf[8] != 181, "test46 case 9 failed\n");+ FAILED(buf[9] != 1, "test46 case 10 failed\n");+ FAILED(buf[10] != 1, "test46 case 11 failed\n");+ FAILED(buf[11] != 1, "test46 case 12 failed\n");+ FAILED(buf[12] != 1, "test46 case 13 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test47(void)+{+ /* Check prefetch instructions. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_label* labels[5];+ sljit_up addr[5];+ int i;++ if (verbose)+ printf("Run test47\n");++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), 3, 1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ labels[0] = sljit_emit_label(compiler);+ /* Should never crash. */+ sljit_emit_op_src(compiler, SLJIT_PREFETCH_L1, SLJIT_MEM2(SLJIT_R0, SLJIT_R0), 2);+ labels[1] = sljit_emit_label(compiler);+ sljit_emit_op_src(compiler, SLJIT_PREFETCH_L2, SLJIT_MEM0(), 0);+ labels[2] = sljit_emit_label(compiler);+#if IS_64BIT+ sljit_emit_op_src(compiler, SLJIT_PREFETCH_L3, SLJIT_MEM1(SLJIT_R0), SLJIT_W(0x1122334455667788));+#else /* !IS_64BIT */+ sljit_emit_op_src(compiler, SLJIT_PREFETCH_L3, SLJIT_MEM1(SLJIT_R0), 0x11223344);+#endif /* IS_64BIT */+ labels[3] = sljit_emit_label(compiler);+ sljit_emit_op_src(compiler, SLJIT_PREFETCH_ONCE, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw));+ labels[4] = sljit_emit_label(compiler);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ for (i = 0; i < 5; i++)+ addr[i] = sljit_get_label_addr(labels[i]);++ sljit_free_compiler(compiler);++ code.func0();++ if (sljit_has_cpu_feature(SLJIT_HAS_PREFETCH)) {+ FAILED(addr[0] == addr[1], "test47 case 1 failed\n");+ FAILED(addr[1] == addr[2], "test47 case 2 failed\n");+ FAILED(addr[2] == addr[3], "test47 case 3 failed\n");+ FAILED(addr[3] == addr[4], "test47 case 4 failed\n");+ } else {+ FAILED(addr[0] != addr[1], "test47 case 1 failed\n");+ FAILED(addr[1] != addr[2], "test47 case 2 failed\n");+ FAILED(addr[2] != addr[3], "test47 case 3 failed\n");+ FAILED(addr[3] != addr[4], "test47 case 4 failed\n");+ }++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test48(void)+{+ /* Test memory accesses with pre/post updates. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_u32 i;+ sljit_s32 supported[10];+ sljit_sw wbuf[18];+ sljit_s8 bbuf[4];+ sljit_s32 ibuf[4];++#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)+ static sljit_u8 expected[10] = { 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 };+#elif (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32)+ static sljit_u8 expected[10] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };+#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)+ static sljit_u8 expected[10] = { 1, 0, 1, 1, 0, 1, 1, 1, 0, 0 };+#elif (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)+ static sljit_u8 expected[10] = { 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 };+#else+ static sljit_u8 expected[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };+#endif++ if (verbose)+ printf("Run test48\n");++ for (i = 0; i < 18; i++)+ wbuf[i] = 0;+ wbuf[2] = -887766;++ bbuf[0] = 0;+ bbuf[1] = 0;+ bbuf[2] = -13;++ ibuf[0] = -5678;+ ibuf[1] = 0;+ ibuf[2] = 0;++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS3V(P, P, P), 4 | SLJIT_ENTER_FLOAT(4), 3, sizeof(sljit_sw));++ supported[0] = sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_sw));+ if (supported[0] == SLJIT_SUCCESS) {+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0);+ sljit_emit_mem_update(compiler, SLJIT_MOV, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_sw));+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R1, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0);+ }++ supported[1] = sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM1(SLJIT_R2), -2 * (sljit_sw)sizeof(sljit_s8));+ if (supported[1] == SLJIT_SUCCESS) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S1, 0, SLJIT_IMM, 2 * sizeof(sljit_s8));+ sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM1(SLJIT_R2), -2 * (sljit_sw)sizeof(sljit_s8));+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R2, 0);+ }++ supported[2] = sljit_emit_mem_update(compiler, SLJIT_MOV_S32 | SLJIT_MEM_SUPP, SLJIT_R2, SLJIT_MEM1(SLJIT_R1), -2 * (sljit_sw)sizeof(sljit_s32));+ if (supported[2] == SLJIT_SUCCESS) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S2, 0, SLJIT_IMM, 2 * sizeof(sljit_s32));+ sljit_emit_mem_update(compiler, SLJIT_MOV_S32, SLJIT_R2, SLJIT_MEM1(SLJIT_R1), -2 * (sljit_sw)sizeof(sljit_s32));+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R2, 0);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R1, 0);+ }++ supported[3] = sljit_emit_mem_update(compiler, SLJIT_MOV32 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE, SLJIT_R1, SLJIT_MEM1(SLJIT_R2), 2 * sizeof(sljit_s32));+ if (supported[3] == SLJIT_SUCCESS) {+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, -8765);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R2, 0, SLJIT_S2, 0, SLJIT_IMM, sizeof(sljit_s32));+ sljit_emit_mem_update(compiler, SLJIT_MOV32 | SLJIT_MEM_STORE, SLJIT_R1, SLJIT_MEM1(SLJIT_R2), 2 * sizeof(sljit_s32));+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R2, 0);+ }++ supported[4] = sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_POST, SLJIT_R1, SLJIT_MEM1(SLJIT_R2), -128 * (sljit_sw)sizeof(sljit_s8));+ if (supported[4] == SLJIT_SUCCESS) {+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -121);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_S1, 0);+ sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_STORE | SLJIT_MEM_POST, SLJIT_R1, SLJIT_MEM1(SLJIT_R2), -128 * (sljit_sw)sizeof(sljit_s8));+ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R2, 0);+ }++ supported[5] = sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), 1);+ if (supported[5] == SLJIT_SUCCESS) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 9 * sizeof(sljit_sw) - 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -881199);+ sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_STORE, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), 1);+ /* buf[10] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R0, 0);+ }++ supported[6] = sljit_emit_mem_update(compiler, SLJIT_MOV_S32 | SLJIT_MEM_SUPP, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0);+ if (supported[6] == SLJIT_SUCCESS) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S2, 0, SLJIT_IMM, 213);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -213);+ sljit_emit_mem_update(compiler, SLJIT_MOV_S32, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0);+ /* buf[11] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[12] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_R1, 0);+ }++ supported[7] = sljit_emit_mem_update(compiler, SLJIT_MOV_S32 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0);+ if (supported[7] == SLJIT_SUCCESS) {+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_S2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 2 * sizeof(sljit_s32));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -7890);+ sljit_emit_mem_update(compiler, SLJIT_MOV_S32 | SLJIT_MEM_STORE, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0);+ /* buf[13] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_R1, 0);+ }++ supported[8] = sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 2);+ if (supported[8] == SLJIT_SUCCESS) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 2 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 2 * sizeof(sljit_sw));+ sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 2);+ /* buf[14] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[15] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_R1, 0);+ }++ supported[9] = sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0);+ if (supported[9] == SLJIT_SUCCESS) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 2 * sizeof(sljit_s8));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -2 * (sljit_sw)sizeof(sljit_s8));+ sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0);+ /* buf[16] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[17] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_sw), SLJIT_R1, 0);+ }++ SLJIT_ASSERT(sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_SUPP, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 1) == SLJIT_ERR_UNSUPPORTED);+ SLJIT_ASSERT(sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_SUPP, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 1) == SLJIT_ERR_UNSUPPORTED);++#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)+ /* TODO: at least for ARM (both V5 and V7) the range below needs further fixing */+ SLJIT_ASSERT(sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), 256) == SLJIT_ERR_UNSUPPORTED);+ SLJIT_ASSERT(sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), -257) == SLJIT_ERR_UNSUPPORTED);+#endif /* SLJIT_CONFIG_ARM_THUMB2 || SLJIT_CONFIG_ARM_64 */++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func3((sljit_sw)&wbuf, (sljit_sw)&bbuf, (sljit_sw)&ibuf);++ FAILED(sizeof(expected) != sizeof(supported) / sizeof(sljit_s32), "test48 case 1 failed\n");++ for (i = 0; i < sizeof(expected); i++) {+ if (expected[i]) {+ if (supported[i] != SLJIT_SUCCESS) {+ printf("tast60 case %d should be supported\n", i + 1);+ return;+ }+ } else {+ if (supported[i] == SLJIT_SUCCESS) {+ printf("test48 case %d should not be supported\n", i + 1);+ return;+ }+ }+ }++ FAILED(supported[0] == SLJIT_SUCCESS && wbuf[0] != -887766, "test48 case 2 failed\n");+ FAILED(supported[0] == SLJIT_SUCCESS && wbuf[1] != (sljit_sw)(wbuf + 2), "test48 case 3 failed\n");+ FAILED(supported[1] == SLJIT_SUCCESS && wbuf[3] != -13, "test48 case 4 failed\n");+ FAILED(supported[1] == SLJIT_SUCCESS && wbuf[4] != (sljit_sw)(bbuf), "test48 case 5 failed\n");+ FAILED(supported[2] == SLJIT_SUCCESS && wbuf[5] != -5678, "test48 case 6 failed\n");+ FAILED(supported[2] == SLJIT_SUCCESS && wbuf[6] != (sljit_sw)(ibuf), "test48 case 7 failed\n");+ FAILED(supported[3] == SLJIT_SUCCESS && ibuf[1] != -8765, "test48 case 8 failed\n");+ FAILED(supported[3] == SLJIT_SUCCESS && wbuf[7] != (sljit_sw)(ibuf + 1), "test48 case 9 failed\n");+ FAILED(supported[4] == SLJIT_SUCCESS && bbuf[0] != -121, "test48 case 10 failed\n");+ FAILED(supported[4] == SLJIT_SUCCESS && wbuf[8] != (sljit_sw)(bbuf) - 128 * (sljit_sw)sizeof(sljit_s8), "test48 case 11 failed\n");+ FAILED(supported[5] == SLJIT_SUCCESS && wbuf[9] != -881199, "test48 case 12 failed\n");+ FAILED(supported[5] == SLJIT_SUCCESS && wbuf[10] != (sljit_sw)(wbuf + 9), "test48 case 13 failed\n");+ FAILED(supported[6] == SLJIT_SUCCESS && wbuf[11] != -5678, "test48 case 14 failed\n");+ FAILED(supported[6] == SLJIT_SUCCESS && wbuf[12] != (sljit_sw)(ibuf), "test48 case 15 failed\n");+ FAILED(supported[7] == SLJIT_SUCCESS && ibuf[2] != -7890, "test48 case 16 failed\n");+ FAILED(supported[7] == SLJIT_SUCCESS && wbuf[13] != (sljit_sw)(ibuf + 2), "test48 case 17 failed\n");+ FAILED(supported[8] == SLJIT_SUCCESS && wbuf[14] != -887766, "test48 case 18 failed\n");+ FAILED(supported[8] == SLJIT_SUCCESS && wbuf[15] != (sljit_sw)(wbuf + 10), "test48 case 19 failed\n");+ FAILED(supported[9] == SLJIT_SUCCESS && wbuf[16] != -13, "test48 case 20 failed\n");+ FAILED(supported[9] == SLJIT_SUCCESS && wbuf[17] != (sljit_sw)(bbuf), "test48 case 21 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test49(void)+{+ /* Test fast calls flag preservation. */+ executable_code code1;+ executable_code code2;+ struct sljit_compiler* compiler;++ if (verbose)+ printf("Run test49\n");++ /* A */+ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");+ sljit_set_context(compiler, 0, SLJIT_ARGS1(W, W), 1, 1, 0);++ sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_R0, 0);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_S0, 0, SLJIT_IMM, 42);+ sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_R0, 0);++ code1.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ /* B */+ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, W), 1, 1, 0);+ sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, SLJIT_FUNC_ADDR(code1.code));+ sljit_set_current_flags(compiler, SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_COMPARE | SLJIT_SET_Z | SLJIT_SET_LESS);+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_ZERO);+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_LESS);+ sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 1);+ sljit_emit_op2(compiler, SLJIT_OR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S0, 0);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0);++ code2.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ FAILED(code2.func1(88) != 0, "test49 case 1 failed\n");+ FAILED(code2.func1(42) != 1, "test49 case 2 failed\n");+ FAILED(code2.func1(0) != 2, "test49 case 3 failed\n");++ sljit_free_code(code1.code, NULL);+ sljit_free_code(code2.code, NULL);+ successful_tests++;+}++static void test50(void)+{+ /* Test mov addr. */+ executable_code code;+ struct sljit_label *label[2];+ struct sljit_jump *mov_addr[5];+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_uw addr[2];+ sljit_uw buf[4];+ sljit_sw offs = WCONST(0x123456789012, 0x12345678);++ if (verbose)+ printf("Run test50\n");++ FAILED(!compiler, "cannot create compiler\n");+ buf[0] = 0;+ buf[1] = 0;+ buf[2] = 0;+ buf[3] = 0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 1, 2 * sizeof(sljit_sw));++ /* buf[0-1] */+ mov_addr[0] = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);++ mov_addr[1] = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_uw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_uw), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_uw));++ label[0] = sljit_emit_label(compiler);+ sljit_set_label(mov_addr[0], label[0]);+ sljit_set_label(mov_addr[1], label[0]);++ /* buf[2-3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)(buf + 2) - offs);+ mov_addr[2] = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_MEM1(SLJIT_R0), offs);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (offs + (sljit_sw)sizeof(sljit_uw)) >> 1);+ mov_addr[3] = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 1);++ label[1] = sljit_emit_label(compiler);+ sljit_set_label(mov_addr[2], label[1]);+ sljit_set_label(mov_addr[3], label[1]);++ /* Return value */+ mov_addr[4] = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_RETURN_REG, 0);+ sljit_set_label(mov_addr[4], label[0]);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ addr[0] = sljit_get_label_addr(label[0]);+ addr[1] = sljit_get_label_addr(label[1]);++ sljit_free_compiler(compiler);++ FAILED(code.func1((sljit_sw)&buf) != (sljit_sw)addr[0], "test50 case 1 failed\n");+ FAILED(buf[0] != addr[0], "test50 case 2 failed\n");+ FAILED(buf[1] != addr[0], "test50 case 3 failed\n");+ FAILED(buf[2] != addr[1], "test50 case 4 failed\n");+ FAILED(buf[3] != addr[1], "test50 case 5 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test51(void)+{+ /* Test mov addr with absolute label addresses */+ executable_code code;+ sljit_uw malloc_addr;+ struct sljit_jump *mov_addr[2];+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_generate_code_buffer code_buffer;+ sljit_uw buf[9];+ sljit_s32 i;+ /* Must be even because it is also used for addressing. */+ sljit_uw offs1 = 0x7f1f;+ sljit_uw offs2 = 0x7f1f2f3f;+ sljit_uw offs3 = (sljit_uw)WCONST(0xfedcba9876, 0x80000000);+ sljit_uw offs4 = (sljit_uw)WCONST(0x789abcdeff12, 0xefdfcfbf);+ sljit_uw offs5 = (sljit_uw)WCONST(0x7fffffff7ff, 0x87654321);+ sljit_uw offs6 = (sljit_uw)WCONST(0xfedcba9811223344, 0xffffffff);++ if (verbose)+ printf("Run test51\n");++ FAILED(!compiler, "cannot create compiler\n");++ code_buffer.size = 2048;+ malloc_addr = (sljit_uw)SLJIT_MALLOC_EXEC(code_buffer.size, NULL);++ if (!malloc_addr) {+ printf("Cannot allocate executable memory\n");+ return;+ }++ code_buffer.buffer = (void*)malloc_addr;+ code_buffer.executable_offset = SLJIT_EXEC_OFFSET((void*)malloc_addr);+ malloc_addr += (sljit_uw)code_buffer.executable_offset;++ for (i = 0; i < 9; i++)+ buf[i] = 0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 3, 2 * sizeof(sljit_sw));++ /* buf[0] */+ mov_addr[0] = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);++ /* buf[1] */+ mov_addr[1] = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_uw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_uw), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_uw));++ sljit_set_target(mov_addr[0], malloc_addr);+ sljit_set_target(mov_addr[1], malloc_addr + 1);++ /* buf[2] */+ mov_addr[0] = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_S2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_uw), SLJIT_S2, 0);++ /* buf[3] */+ mov_addr[1] = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_MEM1(SLJIT_SP), 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_uw), SLJIT_MEM1(SLJIT_SP), 0);++ sljit_set_target(mov_addr[0], offs1);+ sljit_set_target(mov_addr[1], offs1);++ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)(buf + 4) - (sljit_sw)offs1);+ mov_addr[0] = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_MEM1(SLJIT_R0), (sljit_sw)offs1);++ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)(buf + 5) - 0x1234);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)0x1234 >> 1);+ mov_addr[1] = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 1);++ sljit_set_target(mov_addr[0], offs2);+ sljit_set_target(mov_addr[1], offs2);++ /* buf[6] */+ mov_addr[0] = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_R1, 0);+ sljit_set_target(mov_addr[0], offs3);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_uw), SLJIT_R1, 0);++ /* buf[7] */+ mov_addr[0] = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_R2, 0);+ sljit_set_target(mov_addr[0], offs4);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_uw), SLJIT_R2, 0);++ /* buf[8] */+ mov_addr[0] = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_S1, 0);+ sljit_set_target(mov_addr[0], offs5);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_uw), SLJIT_S1, 0);++ mov_addr[0] = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_RETURN_REG, 0);+ sljit_set_target(mov_addr[0], offs6);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);++ code.code = sljit_generate_code(compiler, SLJIT_GENERATE_CODE_BUFFER, &code_buffer);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ FAILED(code.func1((sljit_sw)&buf) != (sljit_sw)offs6, "test51 case 1 failed\n");+ FAILED(buf[0] != malloc_addr, "test51 case 2 failed\n");+ FAILED(buf[1] != malloc_addr + 1, "test51 case 3 failed\n");+ FAILED(buf[2] != offs1, "test51 case 4 failed\n");+ FAILED(buf[3] != offs1, "test51 case 5 failed\n");+ FAILED(buf[4] != offs2, "test51 case 6 failed\n");+ FAILED(buf[5] != offs2, "test51 case 7 failed\n");+ FAILED(buf[6] != offs3, "test51 case 8 failed\n");+ FAILED(buf[7] != offs4, "test51 case 9 failed\n");+ FAILED(buf[8] != offs5, "test51 case 10 failed\n");++ sljit_free_code(code.code, NULL);++ successful_tests++;+}++static void test52(void)+{+ /* Test jump tables. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_s32 i;+ /* Normally this table is allocated on the heap. */+ sljit_uw addr[64];+ struct sljit_label *labels[64];+ struct sljit_jump *jump;++ if (verbose)+ printf("Run test52\n");++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2(W, W, W), 1, 2, 0);++ jump = sljit_emit_cmp(compiler, SLJIT_GREATER_EQUAL, SLJIT_S0, 0, SLJIT_IMM, 64);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)addr);+ sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM2(SLJIT_R0, SLJIT_S0), SLJIT_WORD_SHIFT);++ for (i = 0; i < 64; i++) {+ labels[i] = sljit_emit_label(compiler);+ sljit_emit_op0(compiler, SLJIT_ENDBR);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_IMM, i * 2);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);+ }++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_IMM, -1);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ for (i = 0; i < 64; i++) {+ addr[i] = sljit_get_label_addr(labels[i]);+ }++ sljit_free_compiler(compiler);++ FAILED(code.func2(64, 0) != -1, "test52 case 1 failed\n");++ for (i = 0; i < 64; i++) {+ FAILED(code.func2(i, i * 2) != i * 4, "test52 case 2 failed\n");+ }++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test53(void)+{+ /* Test direct jumps (computed goto). */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_s32 i;+ sljit_uw addr[64];+ struct sljit_label *labels[64];++ if (verbose)+ printf("Run test53\n");++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2(W, W, W), 1, 2, 0);+ sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_S0, 0);++ for (i = 0; i < 64; i++) {+ labels[i] = sljit_emit_label(compiler);+ sljit_emit_op0(compiler, SLJIT_ENDBR);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_IMM, i * 2);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);+ }++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ for (i = 0; i < 64; i++) {+ addr[i] = sljit_get_label_addr(labels[i]);+ }++ sljit_free_compiler(compiler);++ for (i = 0; i < 64; i++) {+ FAILED(code.func2((sljit_sw)addr[i], i) != i * 3, "test53 case 1 failed\n");+ }++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test54(void)+{+ /* Test skipping returns from fast calls (return type is fast). */+ executable_code code;+ struct sljit_compiler *compiler = sljit_create_compiler(NULL);+ struct sljit_jump *call, *jump;+ struct sljit_label *label;++ if (verbose)+ printf("Run test54\n");++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 3, 1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ call = sljit_emit_jump(compiler, SLJIT_FAST_CALL);++ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0);++ /* First function, never returns. */+ label = sljit_emit_label(compiler);+ sljit_set_label(call, label);+ sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_R1, 0);++ call = sljit_emit_jump(compiler, SLJIT_FAST_CALL);++ /* Should never return here, marked by a segmentation fault if it does. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);++ /* Second function, skips the first function. */+ sljit_set_label(call, sljit_emit_label(compiler));+ sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_R2, 0);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1);++ jump = sljit_emit_cmp(compiler, SLJIT_NOT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 1);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_R1, 0);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_FAST_CALL), label);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op_src(compiler, SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN, SLJIT_S0, 0);+ sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_S0, 0);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_op_src(compiler, SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN, SLJIT_R1, 0);+ sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_R1, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ sljit_free_compiler(compiler);++ FAILED(code.func0() != 3, "test54 case 1 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test55(void)+{+ /* Test skipping returns from fast calls (return type is normal). */+ executable_code code;+ struct sljit_compiler *compiler;+ struct sljit_jump *call, *jump;+ struct sljit_label *label;+ int i;++ if (verbose)+ printf("Run test55\n");++ for (i = 0; i < 6; i++) {+ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 2 + (i % 6), (i % 6), 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ call = sljit_emit_jump(compiler, SLJIT_FAST_CALL);++ /* Should never return here, marked by a segmentation fault if it does. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);++ /* Recursive fast call. */+ label = sljit_emit_label(compiler);+ sljit_set_label(call, label);+ sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_R1, 0);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1);++ jump = sljit_emit_cmp(compiler, SLJIT_GREATER_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 4);++ sljit_set_label(sljit_emit_jump(compiler, SLJIT_FAST_CALL), label);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ sljit_free_compiler(compiler);++ if (SLJIT_UNLIKELY(code.func0() != 4)) {+ printf("test55 case %d failed\n", i + 1);+ return;+ }+ sljit_free_code(code.code, NULL);+ }++ successful_tests++;+}++static void test56(void)+{+ /* Test sljit_set_current_flags. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[8];+ sljit_s32 i;++ if (verbose)+ printf("Run test56\n");++ for (i = 0; i < 8; i++)+ buf[i] = 4;++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 3, 1, 0);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)1 << ((sizeof (sljit_sw) * 8) - 2));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_label(compiler);+ sljit_set_current_flags(compiler, SLJIT_SET_OVERFLOW | SLJIT_CURRENT_FLAGS_ADD);+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_OVERFLOW);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 5);+ sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_label(compiler);+ sljit_set_current_flags(compiler, SLJIT_SET_OVERFLOW | SLJIT_CURRENT_FLAGS_ADD);+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_OVERFLOW);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_label(compiler);+ sljit_set_current_flags(compiler, SLJIT_SET_OVERFLOW);+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_OVERFLOW);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 5);+ sljit_emit_op2(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R1, 0);+ sljit_emit_label(compiler);+ sljit_set_current_flags(compiler, SLJIT_SET_OVERFLOW);+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_OVERFLOW);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 6);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 5);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R1, 0, SLJIT_R2, 0);+ sljit_emit_label(compiler);+ sljit_set_current_flags(compiler, SLJIT_SET_GREATER | SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_COMPARE);+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_GREATER);+ /* buf[5] */+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R2, 0);+ sljit_emit_label(compiler);+ sljit_set_current_flags(compiler, SLJIT_SET_Z | SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_COMPARE);+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_ZERO);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(1u << 31));+ sljit_emit_op2u(compiler, SLJIT_ADD32 | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R1, 0);+ sljit_emit_label(compiler);+ sljit_set_current_flags(compiler, SLJIT_SET_Z | SLJIT_CURRENT_FLAGS_32 | SLJIT_CURRENT_FLAGS_ADD);+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_ZERO);+ /* buf[7] */+ sljit_emit_op2u(compiler, SLJIT_SHL32 | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_IMM, 1);+ sljit_emit_label(compiler);+ sljit_set_current_flags(compiler, SLJIT_SET_Z | SLJIT_CURRENT_FLAGS_32);+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_NOT_ZERO);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);++ FAILED(buf[0] != 1, "test56 case 1 failed\n");+ FAILED(buf[1] != 2, "test56 case 2 failed\n");+ FAILED(buf[2] != 1, "test56 case 3 failed\n");+ FAILED(buf[3] != 2, "test56 case 4 failed\n");+ FAILED(buf[4] != 1, "test56 case 5 failed\n");+ FAILED(buf[5] != 2, "test56 case 6 failed\n");+ FAILED(buf[6] != 1, "test56 case 7 failed\n");+ FAILED(buf[7] != 2, "test56 case 8 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test57(void)+{+ /* Test argument passing to sljit_emit_enter. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw wbuf[2];+ sljit_s32 ibuf[2];++ if (verbose)+ printf("Run test57\n");++ wbuf[0] = 0;+ wbuf[1] = 0;+ ibuf[0] = 0;+ ibuf[1] = 0;++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS4V(32, W, 32, W), 1, 4, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&wbuf);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_S3, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&ibuf);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_s32), SLJIT_S2, 0);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.test57_f1(-1478, 9476, 4928, -6832);++ FAILED(wbuf[0] != 9476, "test57 case 1 failed\n");+ FAILED(wbuf[1] != -6832, "test57 case 2 failed\n");+ FAILED(ibuf[0] != -1478, "test57 case 3 failed\n");+ FAILED(ibuf[1] != 4928, "test57 case 4 failed\n");++ sljit_free_code(code.code, NULL);++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS4V(32, 32, W, W), 1, 4, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&wbuf);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_S1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&ibuf);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_s32), SLJIT_S3, 0);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.test57_f2(4721, 7892, -3579, -4830);++ FAILED(wbuf[0] != 4721, "test57 case 5 failed\n");+ FAILED(wbuf[1] != 7892, "test57 case 6 failed\n");+ FAILED(ibuf[0] != -3579, "test57 case 7 failed\n");+ FAILED(ibuf[1] != -4830, "test57 case 8 failed\n");++ sljit_free_code(code.code, NULL);++ successful_tests++;+}++static void test58(void)+{+ /* Test passing arguments in registers. */+ executable_code code;+ struct sljit_compiler* compiler;+ sljit_sw wbuf[2];+ sljit_s32 ibuf[2];++ if (verbose)+ printf("Run test58\n");++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS4V(32_R, W, W_R, 32), 3, 2, 0);+ /* wbuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&wbuf);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_S0, 0);+ /* wbuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_R2, 0);+ /* ibuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&ibuf);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0);+ /* ibuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_s32), SLJIT_S1, 0);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.test58_f1(3467, -6781, 5038, 6310);++ FAILED(wbuf[0] != -6781, "test58 case 1 failed\n");+ FAILED(wbuf[1] != 5038, "test58 case 2 failed\n");+ FAILED(ibuf[0] != 3467, "test58 case 3 failed\n");+ FAILED(ibuf[1] != 6310, "test58 case 4 failed\n");+ sljit_free_code(code.code, NULL);++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS4V(32, W_R, W, 32_R), 4, 2, 8192);+ /* wbuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&wbuf);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_R1, 0);+ /* wbuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_S1, 0);+ /* ibuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&ibuf);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S0, 0);+ /* ibuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_s32), SLJIT_R3, 0);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.test58_f1(-9723, 5208, 4761, 5084);++ FAILED(wbuf[0] != 5208, "test58 case 5 failed\n");+ FAILED(wbuf[1] != 4761, "test58 case 6 failed\n");+ FAILED(ibuf[0] != -9723, "test58 case 7 failed\n");+ FAILED(ibuf[1] != 5084, "test58 case 8 failed\n");+ sljit_free_code(code.code, NULL);++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS4V(32_R, W_R, W_R, 32_R), 4, 1, SLJIT_MAX_LOCAL_SIZE);+ /* wbuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&wbuf);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R1, 0);+ /* wbuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R2, 0);+ /* ibuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&ibuf);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);+ /* ibuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_s32), SLJIT_R3, 0);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.test58_f1(5934, 6043, -8572, -3861);++ FAILED(wbuf[0] != 6043, "test58 case 9 failed\n");+ FAILED(wbuf[1] != -8572, "test58 case 10 failed\n");+ FAILED(ibuf[0] != 5934, "test58 case 11 failed\n");+ FAILED(ibuf[1] != -3861, "test58 case 12 failed\n");+ sljit_free_code(code.code, NULL);++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS4V(W_R, W_R, 32_R, 32_R), 4, 1, SLJIT_MAX_LOCAL_SIZE);+ sljit_set_context(compiler, 0, SLJIT_ARGS4V(W_R, W_R, 32_R, 32_R), 4, 1, SLJIT_MAX_LOCAL_SIZE);+ /* wbuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&wbuf);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);+ /* wbuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R1, 0);+ /* ibuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&ibuf);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R2, 0);+ /* ibuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_s32), SLJIT_R3, 0);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.test58_f2(6732, -5916, 2740, -3621);++ FAILED(wbuf[0] != 6732, "test58 case 13 failed\n");+ FAILED(wbuf[1] != -5916, "test58 case 14 failed\n");+ FAILED(ibuf[0] != 2740, "test58 case 15 failed\n");+ FAILED(ibuf[1] != -3621, "test58 case 16 failed\n");+ sljit_free_code(code.code, NULL);++ successful_tests++;+}++static void test59(void)+{+ /* Test carry flag. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw wbuf[15];+ sljit_s32 i;++ if (verbose)+ printf("Run test59\n");++ for (i = 0; i < 15; i++)+ wbuf[i] = -1;++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(W), 3, 2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1);+ sljit_emit_op2u(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_CARRY);+ /* wbuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R1, 0);+ cond_set(compiler, SLJIT_R1, 0, SLJIT_CARRY);+ /* wbuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2);+ sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -1);+ sljit_set_current_flags(compiler, SLJIT_SET_CARRY | SLJIT_CURRENT_FLAGS_ADD);+ /* wbuf[2] */+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_NOT_CARRY);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op2(compiler, SLJIT_SHL32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 31);+ sljit_emit_op2u(compiler, SLJIT_ADD32 | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0);+ cond_set(compiler, SLJIT_R1, 0, SLJIT_CARRY);+ /* wbuf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 5);+ sljit_emit_op2(compiler, SLJIT_ADD32 | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 5);+ cond_set(compiler, SLJIT_R1, 0, SLJIT_CARRY);+ /* wbuf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 1);+ cond_set(compiler, SLJIT_R1, 0, SLJIT_CARRY);+ /* wbuf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 1);+ cond_set(compiler, SLJIT_R1, 0, SLJIT_NOT_CARRY);+ /* wbuf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 1);+ /* wbuf[7] */+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_CARRY);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_set_current_flags(compiler, SLJIT_SET_CARRY | SLJIT_CURRENT_FLAGS_32 | SLJIT_CURRENT_FLAGS_SUB);+ cond_set(compiler, SLJIT_R1, 0, SLJIT_NOT_CARRY);+ /* wbuf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op2(compiler, SLJIT_SHL32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 31);+ sljit_emit_op2(compiler, SLJIT_SUB32, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op2(compiler, SLJIT_SUB32 | SLJIT_SET_CARRY, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R0, 0);+ cond_set(compiler, SLJIT_R1, 0, SLJIT_NOT_CARRY);+ /* wbuf[9] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -2);+ cond_set(compiler, SLJIT_R1, 0, SLJIT_NOT_CARRY);+ /* wbuf[10] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op2(compiler, SLJIT_ADDC | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R0, 0);+ cond_set(compiler, SLJIT_R1, 0, SLJIT_CARRY);+ /* wbuf[11] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op2(compiler, SLJIT_SHL32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 31);+ sljit_emit_op2(compiler, SLJIT_ADD32 | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op2(compiler, SLJIT_ADDC32 | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R0, 0);+ cond_set(compiler, SLJIT_R1, 0, SLJIT_CARRY);+ /* wbuf[12] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op2(compiler, SLJIT_SUBC | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1);+ cond_set(compiler, SLJIT_R1, 0, SLJIT_CARRY);+ /* wbuf[13] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op2(compiler, SLJIT_SUB32 | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op2(compiler, SLJIT_SUBC32 | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1);+ cond_set(compiler, SLJIT_R1, 0, SLJIT_NOT_CARRY);+ /* wbuf[14] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&wbuf);++ FAILED(wbuf[0] != 1, "test59 case 1 failed\n");+ FAILED(wbuf[1] != 1, "test59 case 2 failed\n");+ FAILED(wbuf[2] != 2, "test59 case 3 failed\n");+ FAILED(wbuf[3] != 1, "test59 case 4 failed\n");+ FAILED(wbuf[4] != 2, "test59 case 5 failed\n");+ FAILED(wbuf[5] != 1, "test59 case 6 failed\n");+ FAILED(wbuf[6] != 1, "test59 case 7 failed\n");+ FAILED(wbuf[7] != 1, "test59 case 8 failed\n");+ FAILED(wbuf[8] != 2, "test59 case 9 failed\n");+ FAILED(wbuf[9] != 2, "test59 case 10 failed\n");+ FAILED(wbuf[10] != 1, "test59 case 11 failed\n");+ FAILED(wbuf[11] != 2, "test59 case 12 failed\n");+ FAILED(wbuf[12] != 1, "test59 case 13 failed\n");+ FAILED(wbuf[13] != 1, "test59 case 14 failed\n");+ FAILED(wbuf[14] != 1, "test59 case 15 failed\n");+ sljit_free_code(code.code, NULL);++ successful_tests++;+}++static void copy_u8(void *dst, sljit_sw offset, const void *src, sljit_uw length)+{+ sljit_u8 *dst_p = (sljit_u8 *)dst + offset;+ const sljit_u8 *src_p = (sljit_u8 *)src;++ while (length-- != 0)+ *dst_p++ = *src_p++;+}++static int cmp_u8(const void *src1, sljit_sw offset, const void *src2, sljit_uw length)+{+ const sljit_u8 *src1_p = (sljit_u8 *)src1 + offset;+ const sljit_u8 *src2_p = (sljit_u8 *)src2;++ while (--length != 0) {+ if (*src1_p != *src2_p)+ return 0;+ src1_p++;+ src2_p++;+ }+ return 1;+}++static void test60(void)+{+ /* Test unaligned accesses. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw i;+ sljit_sw wbuf[13];+ sljit_s32 ibuf[1];+ sljit_s16 hbuf[1];+ sljit_f64 dbuf[5];+ sljit_f32 sbuf[3];+ sljit_s8 bbuf_start[40 + 8 /* for alignment */];+ sljit_s8 *bbuf = (sljit_s8 *)(((sljit_uw)bbuf_start + 7) & ~(sljit_uw)7);++ SLJIT_ASSERT(((sljit_uw)bbuf & 0x7) == 0);++ if (verbose)+ printf("Run test60\n");++ for (i = 0; i < 13; i++)+ wbuf[i] = -3;++ for (i = 0; i < 40; i++)+ bbuf[i] = -3;++ wbuf[0] = -46870;+ ibuf[0] = -38512;+ hbuf[0] = -28531;+ copy_u8(bbuf, 3, hbuf, sizeof(sljit_s16));+ copy_u8(bbuf, 5, ibuf, sizeof(sljit_s32));+ copy_u8(bbuf, 9, wbuf, sizeof(sljit_sw));+ copy_u8(bbuf, 18, ibuf, sizeof(sljit_s32));+ copy_u8(bbuf, 22, wbuf, sizeof(sljit_sw));+ copy_u8(bbuf, 32, wbuf, sizeof(sljit_sw));++ wbuf[0] = -62945;+ ibuf[0] = -90678;+ hbuf[0] = -17249;+ bbuf[0] = -73;++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(P, P), 2, 2, 0);++ sljit_emit_mem(compiler, SLJIT_MOV_S8 | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM0(), (sljit_sw)bbuf);+ /* wbuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_mem(compiler, SLJIT_MOV_U8 | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), 0);+ /* wbuf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 0);+ /* bbuf[1] */+ sljit_emit_mem(compiler, SLJIT_MOV_U8 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s8));++ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 100000);+ sljit_emit_mem(compiler, SLJIT_MOV_S16 | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), 100000 + 3);+ /* wbuf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 1000);+ sljit_emit_mem(compiler, SLJIT_MOV_U16 | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), -1000 + 3);+ /* wbuf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_R0, 0, SLJIT_MEM0(), (sljit_sw)&hbuf);+ /* bbuf[3] */+ sljit_emit_mem(compiler, SLJIT_MOV_S16 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM1(SLJIT_S1), 3);++ sljit_emit_mem(compiler, SLJIT_MOV_S32 | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM1(SLJIT_S1), 5);+ /* wbuf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 5);+ sljit_emit_mem(compiler, SLJIT_MOV_U32 | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM2(SLJIT_R0, SLJIT_S1), 0);+ /* wbuf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 100000);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_MEM0(), (sljit_sw)&ibuf);+ /* bbuf[5] */+ sljit_emit_mem(compiler, SLJIT_MOV32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), 100000 + 5);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 100000);+#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R1), -100000 + 9);+#else /* !SLJIT_UNALIGNED */+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), -100000 + 9);+#endif /* SLJIT_UNALIGNED */+ /* wbuf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 0);+ /* bbuf[9] */+#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), -100000 + 9, SLJIT_R0, 0);+#else /* !SLJIT_UNALIGNED */+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), -100000 + 9);+#endif /* SLJIT_UNALIGNED */++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 18 >> 1);+ sljit_emit_mem(compiler, SLJIT_MOV_S32 | SLJIT_MEM_ALIGNED_16, SLJIT_R0, SLJIT_MEM2(SLJIT_S1, SLJIT_R1), 1);+ /* wbuf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_MEM0(), (sljit_sw)&ibuf);+ /* bbuf[18] */+ sljit_emit_mem(compiler, SLJIT_MOV_S32 | SLJIT_MEM_STORE | SLJIT_MEM_ALIGNED_16, SLJIT_R0, SLJIT_MEM2(SLJIT_S1, SLJIT_R1), 1);++ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_ALIGNED_16, SLJIT_R0, SLJIT_MEM0(), (sljit_sw)bbuf + 22);+ /* wbuf[9] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 0);+ /* bbuf[22] */+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_ALIGNED_16, SLJIT_R0, SLJIT_MEM0(), (sljit_sw)bbuf + 22);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_IMM, 128);+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_ALIGNED_32, SLJIT_R0, SLJIT_MEM1(SLJIT_R0), -128 + 32);+ /* wbuf[10] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 128);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 0);+ /* bbuf[32] */+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_ALIGNED_32, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), -128 + 32);++ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM1(SLJIT_S0), 0);+ /* wbuf[11] */+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw));+ /* wbuf[12] */+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED, SLJIT_S0, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw));++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)&wbuf, (sljit_sw)bbuf);++ FAILED(wbuf[1] != -73, "test60 case 1 failed\n");+ FAILED(wbuf[2] != (sljit_u8)-73, "test60 case 2 failed\n");+ FAILED(bbuf[1] != -73, "test60 case 3 failed\n");+ FAILED(wbuf[3] != -28531, "test60 case 4 failed\n");+ FAILED(wbuf[4] != (sljit_u16)-28531, "test60 case 5 failed\n");+ FAILED(cmp_u8(bbuf, 3, hbuf, sizeof(sljit_s16)) != 1, "test60 case 6 failed\n");+ FAILED(wbuf[5] != -38512, "test60 case 7 failed\n");+ FAILED(wbuf[6] != WCONST((sljit_u32)-38512, -38512), "test60 case 8 failed\n");+ FAILED(cmp_u8(bbuf, 5, ibuf, sizeof(sljit_s32)) != 1, "test60 case 9 failed\n");+ FAILED(wbuf[7] != -46870, "test60 case 10 failed\n");+ FAILED(cmp_u8(bbuf, 9, wbuf, sizeof(sljit_sw)) != 1, "test60 case 11 failed\n");+ FAILED(wbuf[8] != -38512, "test60 case 12 failed\n");+ FAILED(cmp_u8(bbuf, 18, ibuf, sizeof(sljit_s32)) != 1, "test60 case 13 failed\n");+ FAILED(wbuf[9] != -46870, "test60 case 14 failed\n");+ FAILED(cmp_u8(bbuf, 22, wbuf, sizeof(sljit_sw)) != 1, "test60 case 15 failed\n");+ FAILED(wbuf[10] != -46870, "test60 case 16 failed\n");+ FAILED(cmp_u8(bbuf, 32, wbuf, sizeof(sljit_sw)) != 1, "test60 case 17 failed\n");+ FAILED(wbuf[11] != -62945, "test60 case 18 failed\n");+ FAILED(wbuf[12] != (sljit_sw)&wbuf, "test60 case 19 failed\n");++ sljit_free_code(code.code, NULL);++ if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) {+ for (i = 0; i < 40; i++)+ bbuf[i] = -3;++ for (i = 0; i < 5; i++)+ dbuf[i] = 0;++ dbuf[0] = 6897.75;+ sbuf[0] = -8812.25;+ copy_u8(bbuf, 1, sbuf, sizeof(sljit_f32));+ copy_u8(bbuf, 5, dbuf, sizeof(sljit_f64));+ copy_u8(bbuf, 14, sbuf, sizeof(sljit_f32));+ copy_u8(bbuf, 18, dbuf, sizeof(sljit_f64));+ copy_u8(bbuf, 28, dbuf, sizeof(sljit_f64));++ dbuf[0] = -18046.5;+ sbuf[0] = 3751.75;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS3V(P, P, P), 1 | SLJIT_ENTER_FLOAT(1), 3, 0);++ sljit_emit_fmem(compiler, SLJIT_MOV_F32 | SLJIT_MEM_UNALIGNED, SLJIT_FR0, SLJIT_MEM0(), (sljit_sw)bbuf + 1);+ /* sbuf[1] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f32), SLJIT_FR0, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), 0);+ /* bbuf[1] */+ sljit_emit_fmem(compiler, SLJIT_MOV_F32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED, SLJIT_FR0, SLJIT_MEM0(), (sljit_sw)bbuf + 1);++ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S2, 0, SLJIT_IMM, 100000);+#if (defined SLJIT_FPU_UNALIGNED && SLJIT_FPU_UNALIGNED)+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_R0), 100000 + 5);+#else /* !SLJIT_FPU_UNALIGNED */+ sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_UNALIGNED, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), 100000 + 5);+#endif /* SLJIT_FPU_UNALIGNED */+ /* dbuf[1] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64), SLJIT_FR0, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0);+ /* bbuf[5] */+#if (defined SLJIT_FPU_UNALIGNED && SLJIT_FPU_UNALIGNED)+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 100000 + 5, SLJIT_FR0, 0);+#else /* !SLJIT_FPU_UNALIGNED */+ sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), 100000 + 5);+#endif /* SLJIT_FPU_UNALIGNED */++ sljit_emit_fmem(compiler, SLJIT_MOV_F32 | SLJIT_MEM_ALIGNED_16, SLJIT_FR0, SLJIT_MEM1(SLJIT_S2), 14);+ /* sbuf[2] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f32), SLJIT_FR0, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), 0);+ /* bbuf[14] */+ sljit_emit_fmem(compiler, SLJIT_MOV_F32 | SLJIT_MEM_STORE | SLJIT_MEM_ALIGNED_16, SLJIT_FR0, SLJIT_MEM1(SLJIT_S2), 14);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 18 >> 1);+ sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_ALIGNED_16, SLJIT_FR0, SLJIT_MEM2(SLJIT_S2, SLJIT_R0), 1);+ /* dbuf[2] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64), SLJIT_FR0, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0);+ /* bbuf[18] */+ sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_STORE | SLJIT_MEM_ALIGNED_16, SLJIT_FR0, SLJIT_MEM2(SLJIT_S2, SLJIT_R0), 1);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S2, 0, SLJIT_IMM, 128);+ sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_ALIGNED_32, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), -128 + 28);+ /* dbuf[3] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f64), SLJIT_FR0, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0);+ /* bbuf[28] */+ sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_STORE | SLJIT_MEM_ALIGNED_32, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), -128 + 28);++ sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_ALIGNED_32, SLJIT_FR0, SLJIT_MEM1(SLJIT_S0), 0);+ /* dbuf[4] */+ sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_STORE | SLJIT_MEM_ALIGNED_32, SLJIT_FR0, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_f64));++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func3((sljit_sw)&dbuf, (sljit_sw)&sbuf, (sljit_sw)bbuf);++ FAILED(sbuf[1] != -8812.25, "test60 case 20 failed\n");+ FAILED(cmp_u8(bbuf, 1, sbuf, sizeof(sljit_f32)) != 1, "test60 case 21 failed\n");+ FAILED(dbuf[1] != 6897.75, "test60 case 22 failed\n");+ FAILED(cmp_u8(bbuf, 5, dbuf, sizeof(sljit_f64)) != 1, "test60 case 23 failed\n");+ FAILED(sbuf[2] != -8812.25, "test60 case 24 failed\n");+ FAILED(cmp_u8(bbuf, 14, sbuf, sizeof(sljit_f32)) != 1, "test60 case 25 failed\n");+ FAILED(dbuf[2] != 6897.75, "test60 case 26 failed\n");+ FAILED(cmp_u8(bbuf, 18, dbuf, sizeof(sljit_f64)) != 1, "test60 case 27 failed\n");+ FAILED(dbuf[3] != 6897.75, "test60 case 28 failed\n");+ FAILED(cmp_u8(bbuf, 28, dbuf, sizeof(sljit_f64)) != 1, "test60 case 29 failed\n");+ FAILED(dbuf[4] != -18046.5, "test60 case 30 failed\n");++ sljit_free_code(code.code, NULL);+ }++ successful_tests++;+}++static void test61(void)+{+ /* Test register pair movement. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[33];+ sljit_s8 bbuf_start[66 + 8 /* for alignment */];+ sljit_s8 *bbuf = (sljit_s8 *)(((sljit_uw)bbuf_start + 7) & ~(sljit_uw)7);+ sljit_s32 i;++ if (verbose)+ printf("Run test61\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 33; i++)+ buf[i] = -1;+ for (i = 0; i < 66 + 8; i++)+ bbuf_start[i] = -1;++ buf[0] = -5836;+ buf[1] = 3724;+ buf[2] = -9035;+ buf[3] = (sljit_sw)bbuf + 50 + 0xfff;++ copy_u8(bbuf, 1, buf, sizeof(sljit_sw));+ copy_u8(bbuf, 1 + sizeof(sljit_sw), buf + 1, sizeof(sljit_sw));+ copy_u8(bbuf, 34, buf + 2, sizeof(sljit_sw));+ copy_u8(bbuf, 34 + sizeof(sljit_sw), buf + 3, sizeof(sljit_sw));++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(W), 5, 5, 3 * sizeof(sljit_sw));++ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R1), SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw));+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 5814);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 7201);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S0, 0, SLJIT_IMM, 6 * sizeof(sljit_sw) + 77);+ /* buf[6-7] */+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R1), SLJIT_MEM1(SLJIT_R2), -77);++ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 36);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 9);+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R1), SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 2);+ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[9] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw));+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD, SLJIT_REG_PAIR(SLJIT_R1, SLJIT_R0), SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 1);+ /* buf[10] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R1, 0);+ /* buf[11] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -8402);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 6257);+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE, SLJIT_REG_PAIR(SLJIT_R2, SLJIT_R3), SLJIT_MEM1(SLJIT_SP), 0);+ /* buf[12] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), 0);+ /* buf[13] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, 6139);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_sw), SLJIT_IMM, -7049);+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD, SLJIT_REG_PAIR(SLJIT_R4, SLJIT_S4), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw));+ /* buf[14] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_R4, 0);+ /* buf[15] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_S4, 0);++ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R2, 0, SLJIT_S0, 0, SLJIT_IMM, 0x7f404);+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD, SLJIT_REG_PAIR(SLJIT_R2, SLJIT_S4), SLJIT_MEM1(SLJIT_R2), 0x7f404);+ /* buf[16] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_R2, 0);+ /* buf[17] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_sw), SLJIT_S4, 0);++ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 0x7f400 - sizeof(sljit_sw));+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD, SLJIT_REG_PAIR(SLJIT_S2, SLJIT_S3), SLJIT_MEM1(SLJIT_R1), 0x7f400);+ /* buf[18] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_sw), SLJIT_S2, 0);+ /* buf[19] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 19 * sizeof(sljit_sw), SLJIT_S3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 3065);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, 7481);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S2, 0, SLJIT_S0, 0, SLJIT_IMM, 0x7f7f0 + 20 * sizeof(sljit_sw));+ /* buf[20-21] */+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE, SLJIT_REG_PAIR(SLJIT_R3, SLJIT_R4), SLJIT_MEM1(SLJIT_S2), -0x7f7f0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 3275);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, -8714);+ /* buf[22-23] */+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE, SLJIT_REG_PAIR(SLJIT_S1, SLJIT_S3), SLJIT_MEM0(), (sljit_sw)(buf + 22));++ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD | SLJIT_MEM_UNALIGNED, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R1), SLJIT_MEM0(), (sljit_sw)bbuf + 1);+ /* buf[24] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 24 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[25] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 25 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, 3724);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_IMM, -9035);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)bbuf + 18 - 0x7f0f);+ /* bbuf[18], buf[18] + sizeof(sljit_sw) */+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_ALIGNED_16, SLJIT_REG_PAIR(SLJIT_R4, SLJIT_S4), SLJIT_MEM1(SLJIT_R0), 0x7f0f);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)bbuf + 34 - 0xfff);+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD | SLJIT_MEM_ALIGNED_16, SLJIT_REG_PAIR(SLJIT_S1, SLJIT_R0), SLJIT_MEM1(SLJIT_S1), 0xfff);+ /* buf[26] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 26 * sizeof(sljit_sw), SLJIT_S1, 0);+ /* buf[27] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 27 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)bbuf + 34);+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD | SLJIT_MEM_UNALIGNED, SLJIT_REG_PAIR(SLJIT_S1, SLJIT_R0), SLJIT_MEM1(SLJIT_S1), 0);+ /* buf[28] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 28 * sizeof(sljit_sw), SLJIT_S1, 0);+ /* buf[29] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 29 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)bbuf + 1 + 0x8004);+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD | SLJIT_MEM_UNALIGNED, SLJIT_REG_PAIR(SLJIT_S1, SLJIT_R0), SLJIT_MEM1(SLJIT_R0), -0x8004);+ /* buf[30] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 30 * sizeof(sljit_sw), SLJIT_S1, 0);+ /* buf[31] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 31 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)bbuf + 50 + 0xfff);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -9035);+ /* bbuf[50], buf[50] + sizeof(sljit_sw) */+ sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_ALIGNED_16, SLJIT_REG_PAIR(SLJIT_R2, SLJIT_R3), SLJIT_MEM1(SLJIT_R2), -0xfff);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)buf);++ FAILED(buf[3] != (sljit_sw)bbuf + 50 + 0xfff, "test61 case 1 failed\n");+ FAILED(buf[4] != 3724, "test61 case 2 failed\n");+ FAILED(buf[5] != -9035, "test61 case 3 failed\n");+ FAILED(buf[6] != 5814, "test61 case 4 failed\n");+ FAILED(buf[7] != 7201, "test61 case 5 failed\n");+ FAILED(buf[8] != -5836, "test61 case 6 failed\n");+ FAILED(buf[9] != 3724, "test61 case 7 failed\n");+ FAILED(buf[10] != -9035, "test61 case 8 failed\n");+ FAILED(buf[11] != buf[3], "test61 case 9 failed\n");+ FAILED(buf[12] != -8402, "test61 case 10 failed\n");+ FAILED(buf[13] != 6257, "test61 case 11 failed\n");+ FAILED(buf[14] != 6139, "test61 case 12 failed\n");+ FAILED(buf[15] != -7049, "test61 case 13 failed\n");+ FAILED(buf[16] != -5836, "test61 case 14 failed\n");+ FAILED(buf[17] != 3724, "test61 case 15 failed\n");+ FAILED(buf[18] != 3724, "test61 case 16 failed\n");+ FAILED(buf[19] != -9035, "test61 case 17 failed\n");+ FAILED(buf[20] != 3065, "test61 case 18 failed\n");+ FAILED(buf[21] != 7481, "test61 case 19 failed\n");+ FAILED(buf[22] != 3275, "test61 case 20 failed\n");+ FAILED(buf[23] != -8714, "test61 case 21 failed\n");+ FAILED(buf[24] != -5836, "test61 case 22 failed\n");+ FAILED(buf[25] != 3724, "test61 case 23 failed\n");+ FAILED(cmp_u8(bbuf, 18, buf + 1, sizeof(sljit_sw)) != 1, "test61 case 24 failed\n");+ FAILED(cmp_u8(bbuf, 18 + sizeof(sljit_sw), buf + 2, sizeof(sljit_sw)) != 1, "test61 case 25 failed\n");+ FAILED(buf[26] != -9035, "test61 case 26 failed\n");+ FAILED(buf[27] != buf[3], "test61 case 27 failed\n");+ FAILED(buf[28] != -9035, "test61 case 28 failed\n");+ FAILED(buf[29] != buf[3], "test61 case 29 failed\n");+ FAILED(buf[30] != -5836, "test61 case 30 failed\n");+ FAILED(buf[31] != 3724, "test61 case 31 failed\n");+ FAILED(cmp_u8(bbuf, 50, buf + 3, sizeof(sljit_sw)) != 1, "test61 case 32 failed\n");+ FAILED(cmp_u8(bbuf, 50 + sizeof(sljit_sw), buf + 2, sizeof(sljit_sw)) != 1, "test61 case 33 failed\n");+ FAILED(buf[32] != -1, "test61 case 34 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test62(void)+{+ /* Test masked shift. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[9];+ sljit_s32 ibuf[8];+ sljit_s32 i;++ if (verbose)+ printf("Run test62\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 9; i++)+ buf[i] = -1;+ for (i = 0; i < 8; i++)+ ibuf[i] = -1;++ buf[7] = 3;+ ibuf[6] = 4;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(W, W), 5, 5, 2 * sizeof(sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x1234);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 8 * sizeof(sljit_sw) + 4);+ sljit_emit_op2(compiler, SLJIT_MSHL, SLJIT_R2, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 8 * sizeof(sljit_sw));+ /* buf[1] */+ sljit_emit_op2(compiler, SLJIT_MSHL, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0x5678);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 32 + 8);+ sljit_emit_op2(compiler, SLJIT_MSHL32, SLJIT_R2, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ /* ibuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R3, 0, SLJIT_IMM, 1);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, -2);+ /* ibuf[1] */+ sljit_emit_op2(compiler, SLJIT_MSHL32 | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_R3, 0, SLJIT_R4, 0);+ /* buf[2] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_NOT_ZERO);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 8 * sizeof(sljit_sw) + 4);+ sljit_emit_op2(compiler, SLJIT_MLSHR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_R2, 0);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[4] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_NOT_ZERO);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 0x5678);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_IMM, -32);+ sljit_emit_op2(compiler, SLJIT_MLSHR32, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32));+ /* ibuf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_SP), 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0x345678);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 0x123000 - 3 * sizeof(sljit_s32));+ /* ibuf[3] */+ sljit_emit_op2(compiler, SLJIT_MLSHR32, SLJIT_MEM1(SLJIT_R1), 0x123000, SLJIT_R0, 0, SLJIT_IMM, 32 + 4);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -0x100);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 8 * sizeof(sljit_sw) + 4);+ sljit_emit_op2(compiler, SLJIT_MASHR, SLJIT_R1, 0, SLJIT_R3, 0, SLJIT_R2, 0);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_IMM, -0x100);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_IMM, -32 + 1);+ sljit_emit_op2(compiler, SLJIT_MASHR32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_R2, 0);+ /* ibuf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32));++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_s32), SLJIT_IMM, 0x7fffffff);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, -1);+ /* ibuf[5] */+ sljit_emit_op2(compiler, SLJIT_MLSHR32 | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_s32), SLJIT_R0, 0);+ /* buf[6] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_NOT_ZERO);++ /* buf[7] */+ sljit_emit_op2(compiler, SLJIT_MSHL, SLJIT_MEM0(), (sljit_sw)&buf[7], SLJIT_IMM, 0xa, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw));+ /* ibuf[6] */+ sljit_emit_op2(compiler, SLJIT_MLSHR32, SLJIT_MEM0(), (sljit_sw)&ibuf[6], SLJIT_IMM, 0xa5f, SLJIT_MEM0(), (sljit_sw)&ibuf[6]);++#if (defined SLJIT_MASKED_SHIFT && SLJIT_MASKED_SHIFT)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 12344321);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (8 * sizeof(sljit_sw)) + 1);+ /* buf[8] */+ sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R1, 0, SLJIT_R2, 0);+#endif /* SLJIT_MASKED_SHIFT */+#if (defined SLJIT_MASKED_SHIFT32 && SLJIT_MASKED_SHIFT32)+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 24688643);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_IMM, (8 * sizeof(sljit_s32)) + 1);+ /* ibuf[7] */+ sljit_emit_op2(compiler, SLJIT_LSHR32, SLJIT_MEM1(SLJIT_S1), 7 * sizeof(sljit_s32), SLJIT_R1, 0, SLJIT_R2, 0);+#endif /* SLJIT_MASKED_SHIFT32 */++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)buf, (sljit_sw)ibuf);++ FAILED(buf[0] != 0x12340, "test62 case 1 failed\n");+ FAILED(buf[1] != 0x1234, "test62 case 2 failed\n");+ FAILED(ibuf[0] != 0x567800, "test62 case 3 failed\n");+ FAILED(ibuf[1] != (sljit_sw)1 << 30, "test62 case 4 failed\n");+ FAILED(buf[2] != 1, "test62 case 5 failed\n");+ FAILED(buf[3] != ((sljit_uw)-1 >> 4), "test62 case 6 failed\n");+ FAILED(buf[4] != 1, "test62 case 7 failed\n");+ FAILED(ibuf[2] != 0x5678, "test62 case 8 failed\n");+ FAILED(ibuf[3] != 0x34567, "test62 case 9 failed\n");+ FAILED(buf[5] != -0x10, "test62 case 10 failed\n");+ FAILED(ibuf[4] != -0x80, "test62 case 11 failed\n");+ FAILED(ibuf[5] != 0, "test62 case 12 failed\n");+ FAILED(buf[6] != 0, "test62 case 13 failed\n");+ FAILED(buf[7] != 0x50, "test62 case 14 failed\n");+ FAILED(ibuf[6] != 0xa5, "test62 case 15 failed\n");+#if (defined SLJIT_MASKED_SHIFT && SLJIT_MASKED_SHIFT)+ FAILED(buf[8] != 24688642, "test62 case 16 failed\n");+#endif /* SLJIT_MASKED_SHIFT */+#if (defined SLJIT_MASKED_SHIFT32 && SLJIT_MASKED_SHIFT32)+ FAILED(ibuf[7] != 12344321, "test62 case 17 failed\n");+#endif /* SLJIT_MASKED_SHIFT32 */++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test63(void)+{+ /* Test rotate. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[13];+ sljit_s32 ibuf[8];+ sljit_s32 i;+#ifdef SLJIT_PREF_SHIFT_REG+ sljit_s32 shift_reg = SLJIT_PREF_SHIFT_REG;+#else /* !SLJIT_PREF_SHIFT_REG */+ sljit_s32 shift_reg = SLJIT_R2;+#endif /* SLJIT_PREF_SHIFT_REG */++ if (verbose)+ printf("Run test63\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 13; i++)+ buf[i] = -1;+ for (i = 0; i < 8; i++)+ ibuf[i] = -1;++ ibuf[0] = 8;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(W, W), 5, 5, 2 * sizeof(sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0x1234567812345678, 0x12345678));+ sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 12);+ sljit_emit_op2(compiler, SLJIT_ROTL, SLJIT_R0, 0, SLJIT_R0, 0, shift_reg, 0);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xfedcba0987654321, 0x87654321));+ sljit_emit_op2(compiler, SLJIT_ROTL, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 1);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, WCONST(0xfedcba0987654321, 0x87654321));+ sljit_emit_op2(compiler, SLJIT_ROTL, SLJIT_S2, 0, SLJIT_R4, 0, SLJIT_IMM, 0xffff00);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_S2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -1);+ /* buf[3] */+ sljit_emit_op2(compiler, SLJIT_ROTL, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_IMM, WCONST(0x9876543210abcdef, 0x87654321), shift_reg, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_IMM, WCONST(0x9876543210abcdc0, 0x876543e0));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 4);+ sljit_emit_op2(compiler, SLJIT_ROTL, SLJIT_R0, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw));+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, WCONST(0x1234567812345678, 0x12345678));+ sljit_emit_op2(compiler, SLJIT_ROTR, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, 4);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, WCONST(0x1234567812345678, 0x12345678));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 20);+ sljit_emit_op2(compiler, SLJIT_ROTR, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0x1234567887654341, 0x17654321));+ sljit_emit_op2(compiler, SLJIT_ROTR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R0, 0);+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0xfedcba0987654321, 0x87654321));+ /* buf[8] */+ sljit_emit_op2(compiler, SLJIT_ROTR, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 0, SLJIT_R1, 0, SLJIT_IMM, 0xff00);++ sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 0xffc0);+ sljit_emit_op2(compiler, SLJIT_ROTR, SLJIT_R1, 0, SLJIT_R1, 0, shift_reg, 0);+ /* buf[9] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -7834);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0x87654321);+ sljit_emit_op2(compiler, SLJIT_ROTL32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 0);+ /* ibuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R0, 0);+ /* buf[10] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), shift_reg, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, (sljit_sw)0xabc89def);+ sljit_emit_op2(compiler, SLJIT_ROTL32, SLJIT_S4, 0, SLJIT_R4, 0, SLJIT_IMM, 0xfffe1);+ /* ibuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_S4, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, (sljit_sw)0xabc89def);+ sljit_emit_op2(compiler, SLJIT_ROTL32, SLJIT_S4, 0, SLJIT_R4, 0, SLJIT_IMM, 0xfffe0);+ /* ibuf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32), SLJIT_S4, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -6512);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, 0xfffe0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_IMM, (sljit_sw)0xabc89def);+ /* ibuf[3] */+ sljit_emit_op2(compiler, SLJIT_ROTL32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_R4, 0);+ /* buf[11] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), shift_reg, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 30);+ sljit_emit_op2(compiler, SLJIT_ROTR32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0x87654321, SLJIT_R0, 0);+ /* ibuf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_s32), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_IMM, (sljit_sw)0xfedccdef);+ sljit_emit_op2(compiler, SLJIT_ROTR32, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_IMM, 4);+ /* ibuf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_SP), 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_s32), SLJIT_IMM, (sljit_sw)0x89abcdef);+ sljit_emit_op2(compiler, SLJIT_ROTR32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_s32), SLJIT_IMM, 0xfffe0);+ /* ibuf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_s32), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -2647);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)0x89abcde0);+ /* ibuf[7] */+ sljit_emit_op2(compiler, SLJIT_ROTR32, SLJIT_MEM1(SLJIT_S1), 7 * sizeof(sljit_s32), SLJIT_R1, 0, SLJIT_R1, 0);+ /* buf[12] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), shift_reg, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)buf, (sljit_sw)ibuf);++ FAILED(buf[0] != WCONST(0x4567812345678123, 0x45678123), "test63 case 1 failed\n");+ FAILED(buf[1] != WCONST(0xfdb974130eca8643, 0xeca8643), "test63 case 2 failed\n");+ FAILED(buf[2] != WCONST(0xfedcba0987654321, 0x87654321), "test63 case 3 failed\n");+ FAILED(buf[3] != WCONST(0xcc3b2a190855e6f7, 0xc3b2a190), "test63 case 4 failed\n");+ FAILED(buf[4] != WCONST(0x9876543210abcdc0, 0x876543e0), "test63 case 5 failed\n");+ FAILED(buf[5] != WCONST(0x8123456781234567, 0x81234567), "test63 case 6 failed\n");+ FAILED(buf[6] != WCONST(0x4567812345678123, 0x45678123), "test63 case 7 failed\n");+ FAILED(buf[7] != WCONST(0x891a2b3c43b2a1a0, 0x8bb2a190), "test63 case 8 failed\n");+ FAILED(buf[8] != WCONST(0xfedcba0987654321, 0x87654321), "test63 case 9 failed\n");+ FAILED(buf[9] != WCONST(0xfedcba0987654321, 0x87654321), "test63 case 10 failed\n");+ FAILED(ibuf[0] != (sljit_s32)0x65432187, "test63 case 11 failed\n");+ FAILED(buf[10] != -7834, "test63 case 12 failed\n");+ FAILED(ibuf[1] != (sljit_s32)0x57913bdf, "test63 case 13 failed\n");+ FAILED(ibuf[2] != (sljit_s32)0xabc89def, "test63 case 14 failed\n");+ FAILED(ibuf[3] != (sljit_s32)0xabc89def, "test63 case 15 failed\n");+ FAILED(buf[11] != -6512, "test63 case 16 failed\n");+ FAILED(ibuf[4] != (sljit_s32)0x1d950c86, "test63 case 17 failed\n");+ FAILED(ibuf[5] != (sljit_s32)0xffedccde, "test63 case 18 failed\n");+ FAILED(ibuf[6] != (sljit_s32)0x89abcdef, "test63 case 19 failed\n");+ FAILED(ibuf[7] != (sljit_s32)0x89abcde0, "test63 case 20 failed\n");+ FAILED(buf[12] != -2647, "test63 case 21 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test64(void)+{+ /* Test "shift into". */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[19];+ sljit_s32 ibuf[10];+ sljit_s32 i;+#ifdef SLJIT_PREF_SHIFT_REG+ sljit_s32 shift_reg = SLJIT_PREF_SHIFT_REG;+#else /* !SLJIT_PREF_SHIFT_REG */+ sljit_s32 shift_reg = SLJIT_R2;+#endif /* SLJIT_PREF_SHIFT_REG */++ if (verbose)+ printf("Run test64\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 19; i++)+ buf[i] = -1;+ for (i = 0; i < 10; i++)+ ibuf[i] = -1;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(W, W), 5, 5, 2 * sizeof(sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0x1234567812345678, 0x12345678));+ sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 12);+ sljit_emit_shift_into(compiler, SLJIT_SHL, SLJIT_R0, SLJIT_R1, SLJIT_R1, shift_reg, 0);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, WCONST(0x1234567812345678, 0x12345678));+ sljit_emit_shift_into(compiler, SLJIT_MLSHR, SLJIT_R4, SLJIT_R3, SLJIT_R3, SLJIT_IMM, 0xffd4 /* 20 */);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R4, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, shift_reg, 0, SLJIT_IMM, (sljit_s32)0x86421357);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 0xffeb /* 11 */);+ sljit_emit_shift_into(compiler, SLJIT_MSHL32, SLJIT_R0, shift_reg, shift_reg, SLJIT_MEM1(SLJIT_SP), 0);+ /* ibuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -8762);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, (sljit_s32)0x89abcdef);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_IMM, 0xffff);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_IMM, 16 * sizeof(sljit_s32));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 17);+ sljit_emit_shift_into(compiler, SLJIT_MLSHR32, SLJIT_S2, SLJIT_R4, SLJIT_R4, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 2);+ /* ibuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_S2, 0);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), shift_reg, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_IMM, WCONST(0x1234567812345678, 0x12345678));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xabcd000000000000, 0xabcd0000));+ sljit_emit_shift_into(compiler, SLJIT_MSHL, SLJIT_S4, SLJIT_S4, SLJIT_R0, SLJIT_IMM, 12);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_S4, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xaabbccddeeff8899, 0xabcdef89));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, 0xfedcba);+ sljit_emit_shift_into(compiler, SLJIT_LSHR, SLJIT_R1, SLJIT_R0, SLJIT_R4, SLJIT_IMM, 19);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0xfedcba0987654321, 0xfedcba09));+ sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, WCONST(0x7fffffffffffffff, 0x7fffffff));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 1);+ sljit_emit_shift_into(compiler, SLJIT_SHL | SLJIT_SHIFT_INTO_NON_ZERO, SLJIT_R4, SLJIT_R1, shift_reg, SLJIT_MEM1(SLJIT_SP), 0);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R4, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)0xdeadbeaf);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, (sljit_sw)0xfedcba09);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, -5);+ sljit_emit_shift_into(compiler, SLJIT_MLSHR32 | SLJIT_SHIFT_INTO_NON_ZERO, shift_reg, SLJIT_R1, SLJIT_R4, SLJIT_R0, 0);+ /* ibuf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32), shift_reg, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R3, 0, SLJIT_IMM, (sljit_sw)0xabcd6543);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, (sljit_s32)0xc9000000);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0xffe8);+ sljit_emit_shift_into(compiler, SLJIT_MSHL32, shift_reg, SLJIT_R3, SLJIT_R4, SLJIT_R0, 0);+ /* ibuf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), shift_reg, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -6032);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, 0x7cadcad7);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_S3, 0, SLJIT_IMM, (sljit_s32)0xfffffff5);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 3);+ sljit_emit_shift_into(compiler, SLJIT_LSHR32, SLJIT_R4, SLJIT_R4, SLJIT_S3, SLJIT_R0, 0);+ /* ibuf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_s32), SLJIT_R4, 0);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), shift_reg, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -9740);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -5182);+ sljit_emit_shift_into(compiler, SLJIT_SHL, SLJIT_R0, SLJIT_R0, SLJIT_R1, SLJIT_IMM, 0);+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, -4072);+ sljit_emit_op1(compiler, SLJIT_MOV32, shift_reg, 0, SLJIT_IMM, -2813);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0);+ sljit_emit_shift_into(compiler, SLJIT_LSHR32, SLJIT_R0, SLJIT_R0, shift_reg, SLJIT_R1, 0);+ /* ibuf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_s32), SLJIT_R0, 0);+ /* ibuf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_s32), shift_reg, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -3278);+ sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 0);+ sljit_emit_shift_into(compiler, SLJIT_LSHR, SLJIT_R1, SLJIT_R0, SLJIT_R0, shift_reg, 0);+ /* buf[9] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, WCONST(0x1234567890abcdef, 0x12345678));+ sljit_emit_shift_into(compiler, SLJIT_LSHR, SLJIT_R0, SLJIT_S3, SLJIT_S3, SLJIT_IMM, 0xfff8 /* 24/56 */);+ /* buf[10] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, WCONST(0x1234567890abcdef, 0x12345678));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_IMM, WCONST(0xba9876fedcba9800, 0xfedcba00));+ sljit_emit_shift_into(compiler, SLJIT_SHL, SLJIT_S3, SLJIT_S3, SLJIT_S4, SLJIT_IMM, 0xfff8 /* 24/56 */);+ /* buf[11] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_S3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0x1234567890abcdef, 0x12345678));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -4986);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, 0);+ sljit_emit_shift_into(compiler, SLJIT_SHL, SLJIT_R0, SLJIT_R0, SLJIT_R1, SLJIT_R4, 0);+ /* buf[12] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[13] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0x12345678fedcba09, 0x12348765));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_IMM, -1);+ sljit_emit_shift_into(compiler, SLJIT_MLSHR, shift_reg, SLJIT_R0, SLJIT_R1, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw));+ /* buf[14] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), shift_reg, 0);+ /* buf[15] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0x8000000000000005, 0x80000005));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_R1, 0);+ sljit_emit_shift_into(compiler, SLJIT_MSHL, SLJIT_R0, SLJIT_R0, SLJIT_R1, SLJIT_MEM0(), (sljit_sw)(buf + 16));+ /* buf[16] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0x2345678923456789, 0x23456789));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -1);+ sljit_emit_shift_into(compiler, SLJIT_SHL, SLJIT_R0, SLJIT_R1, SLJIT_S2, SLJIT_R0, 0);+ /* buf[17] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0xabc23456);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)0xef000000);+ sljit_emit_shift_into(compiler, SLJIT_SHL32, SLJIT_R0, SLJIT_R0, SLJIT_R1, SLJIT_IMM, 4);+ /* ibuf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 7 * sizeof(sljit_s32), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0xabc23456);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)0xfe);+ sljit_emit_shift_into(compiler, SLJIT_LSHR32, SLJIT_S2, SLJIT_R0, SLJIT_R1, SLJIT_IMM, 4);+ /* ibuf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 8 * sizeof(sljit_s32), SLJIT_S2, 0);++#if (defined SLJIT_MASKED_SHIFT && SLJIT_MASKED_SHIFT)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 12344321);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (8 * sizeof(sljit_sw)) + 1);+ sljit_emit_shift_into(compiler, SLJIT_SHL, SLJIT_R0, SLJIT_R0, SLJIT_R1, SLJIT_R2, 0);+ /* buf[18] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_sw), SLJIT_R0, 0);+#endif /* SLJIT_MASKED_SHIFT */+#if (defined SLJIT_MASKED_SHIFT32 && SLJIT_MASKED_SHIFT32)+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 24688642);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 1);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_IMM, (8 * sizeof(sljit_s32)) + 1);+ sljit_emit_shift_into(compiler, SLJIT_LSHR32, SLJIT_R0, SLJIT_R0, SLJIT_R1, SLJIT_R2, 0);+ /* ibuf[9] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 9 * sizeof(sljit_s32), SLJIT_R0, 0);+#endif /* SLJIT_MASKED_SHIFT32 */++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)buf, (sljit_sw)ibuf);++ FAILED(buf[0] != WCONST(0x4567812345678123, 0x45678123), "test64 case 1 failed\n");+ FAILED(buf[1] != WCONST(0x4567812345678123, 0x45678123), "test64 case 2 failed\n");+ FAILED(ibuf[0] != 0x109abc32, "test64 case 3 failed\n");+ FAILED(ibuf[1] != 0x13579bdf, "test64 case 4 failed\n");+ FAILED(buf[2] != -8762, "test64 case 5 failed\n");+ FAILED(buf[3] != WCONST(0x4567812345678abc, 0x45678abc), "test64 case 6 failed\n");+ FAILED(buf[4] != WCONST(0xdb975557799bbddf, 0xdb975579), "test64 case 7 failed\n");+ FAILED(buf[5] != WCONST(0xfdb974130eca8642, 0xfdb97412), "test64 case 8 failed\n");+ FAILED(ibuf[2] != (sljit_s32)0xdb97413b, "test64 case 9 failed\n");+ FAILED(ibuf[3] != (sljit_s32)0xcd6543c9, "test64 case 10 failed\n");+ FAILED(ibuf[4] != (sljit_s32)0xaf95b95a, "test64 case 11 failed\n");+ FAILED(buf[6] != -6032, "test64 case 12 failed\n");+ FAILED(buf[7] != -9740, "test64 case 13 failed\n");+ FAILED(buf[8] != -5182, "test64 case 14 failed\n");+ FAILED(ibuf[5] != -4072, "test64 case 15 failed\n");+ FAILED(ibuf[6] != -2813, "test64 case 16 failed\n");+ FAILED(buf[9] != -3278, "test64 case 17 failed\n");+ FAILED(buf[10] != WCONST(0x34567890abcdef12, 0x34567812), "test64 case 18 failed\n");+ FAILED(buf[11] != WCONST(0xefba9876fedcba98, 0x78fedcba), "test64 case 19 failed\n");+ FAILED(buf[12] != WCONST(0x1234567890abcdef, 0x12345678), "test64 case 20 failed\n");+ FAILED(buf[13] != -4986, "test64 case 21 failed\n");+ FAILED(buf[14] != WCONST(0x2468acf1fdb97413, 0x24690ecb), "test64 case 22 failed\n");+ FAILED(buf[15] != WCONST(0x12345678fedcba09, 0x12348765), "test64 case 23 failed\n");+ FAILED(buf[16] != 0x30, "test64 case 24 failed\n");+ FAILED(buf[17] != WCONST(0x8d159e248d159e27, 0x8d159e27), "test64 case 25 failed\n");+ FAILED(ibuf[7] != (sljit_s32)0xbc23456e, "test64 case 26 failed\n");+ FAILED(ibuf[8] != (sljit_s32)0xeabc2345, "test64 case 27 failed\n");+#if (defined SLJIT_MASKED_SHIFT && SLJIT_MASKED_SHIFT)+ FAILED(buf[18] != 24688643, "test64 case 28 failed\n");+#endif /* SLJIT_MASKED_SHIFT */+#if (defined SLJIT_MASKED_SHIFT32 && SLJIT_MASKED_SHIFT32)+ FAILED(ibuf[9] != (sljit_s32)-2135139327, "test64 case 29 failed\n");+#endif /* SLJIT_MASKED_SHIFT32 */++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test65(void)+{+ /* Test count trailing zeroes. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[5];+ sljit_s32 ibuf[7];+ sljit_s32 i;++ if (verbose)+ printf("Run test65\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 5; i++)+ buf[i] = -1;+ for (i = 0; i < 7; i++)+ ibuf[i] = -1;++ buf[2] = 0;+ ibuf[3] = 1;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(W, W), 5, 5, 2 * sizeof(sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x80);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_CTZ, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 0x654321);+ sljit_emit_op1(compiler, SLJIT_CTZ, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_SP), 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 2);+ sljit_emit_op1(compiler, SLJIT_CTZ, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_MEM2(SLJIT_S0, SLJIT_S2), SLJIT_WORD_SHIFT);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, (sljit_sw)1 << (8 * sizeof(sljit_sw) - 3));+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 0x100000);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_CTZ, SLJIT_MEM1(SLJIT_R1), 0x100000 + 3 * sizeof(sljit_sw), SLJIT_R4, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_IMM, WCONST(0xabcdef800, 0xcdef800));+ sljit_emit_op1(compiler, SLJIT_CTZ, SLJIT_S4, 0, SLJIT_MEM0(), (sljit_sw)(buf + 4));+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_S4, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0xa400);+ sljit_emit_op2(compiler, SLJIT_ASHR32, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, 4);+ sljit_emit_op1(compiler, SLJIT_CTZ32, SLJIT_R1, 0, SLJIT_R0, 0);+ /* ibuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_R0, 0);+ /* ibuf[1] */+ sljit_emit_op1(compiler, SLJIT_CTZ32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_IMM, 0xbcdefe0);+ sljit_emit_op1(compiler, SLJIT_CTZ32, SLJIT_S4, 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32));+ /* ibuf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32), SLJIT_S4, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 3);+ sljit_emit_op1(compiler, SLJIT_CTZ32, SLJIT_R0, 0, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), 2);+ /* ibuf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_R0, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)buf, (sljit_sw)ibuf);++ FAILED(buf[0] != 7, "test65 case 1 failed\n");+ FAILED(buf[1] != 0, "test65 case 2 failed\n");+ FAILED(buf[2] != WCONST(64, 32), "test65 case 3 failed\n");+ FAILED(buf[3] != WCONST(61, 29), "test65 case 4 failed\n");+ FAILED(buf[4] != 11, "test65 case 5 failed\n");+ FAILED(ibuf[0] != 6, "test65 case 6 failed\n");+ FAILED(ibuf[1] != 32, "test65 case 7 failed\n");+ FAILED(ibuf[2] != 5, "test65 case 8 failed\n");+ FAILED(ibuf[3] != 0, "test65 case 9 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test66(void)+{+ /* Test reverse bytes. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[6];+ sljit_s32 ibuf[5];+ sljit_s32 i;++ if (verbose)+ printf("Run test66\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 6; i++)+ buf[i] = -1;+ for (i = 0; i < 5; i++)+ ibuf[i] = -1;++ buf[3] = WCONST(0x8070605040302010, 0x40302010);+ ibuf[1] = (sljit_s32)0xffeeddcc;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(W, W), 5, 5, 2 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xf1e2d3c4b5a69788, 0xf1e2d3c4));+ sljit_emit_op1(compiler, SLJIT_REV, SLJIT_R0, 0, SLJIT_R0, 0);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, WCONST(0xffeeddccbbaa9988, 0xffeeddcc));+ sljit_emit_op1(compiler, SLJIT_REV, SLJIT_R2, 0, SLJIT_R4, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, WCONST(0x0102030405060708, 0x01020304));+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_REV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_S2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 3);+ sljit_emit_op1(compiler, SLJIT_REV, SLJIT_R4, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_REV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R4, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, WCONST(0x1122334455667788, 0x11223344));+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_REV, SLJIT_MEM0(), (sljit_sw)&buf[4], SLJIT_S2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 5 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xaabbccddeeff0011, 0xaabbccdd));+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_REV, SLJIT_MEM2(SLJIT_S0, SLJIT_R2), 0, SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_s32)0xf1e2d3c4);+ sljit_emit_op1(compiler, SLJIT_REV32, SLJIT_R1, 0, SLJIT_R0, 0);+ /* ibuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R1, 0);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S1, 0, SLJIT_IMM, 0x12340 + sizeof(sljit_s32));+ sljit_emit_op1(compiler, SLJIT_REV32, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R2), -0x12340);+ /* ibuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_R2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, (sljit_s32)0x01020304);+ /* ibuf[2] */+ sljit_emit_op1(compiler, SLJIT_REV32, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), 2, SLJIT_R4, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, (sljit_s32)0x11223344);+ sljit_emit_op1(compiler, SLJIT_REV32, SLJIT_R4, 0, SLJIT_R4, 0);+ /* ibuf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_R4, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, (sljit_s32)0xfeeddccb);+ /* ibuf[4] */+ sljit_emit_op1(compiler, SLJIT_REV32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_SP), 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)buf, (sljit_sw)ibuf);++ FAILED(buf[0] != WCONST(0x8897a6b5c4d3e2f1, 0xc4d3e2f1), "test66 case 1 failed\n");+ FAILED(buf[1] != WCONST(0x8899aabbccddeeff, 0xccddeeff), "test66 case 2 failed\n");+ FAILED(buf[2] != WCONST(0x0807060504030201, 0x04030201), "test66 case 3 failed\n");+ FAILED(buf[3] != WCONST(0x8070605040302010, 0x40302010), "test66 case 4 failed\n");+ FAILED(buf[4] != WCONST(0x8877665544332211, 0x44332211), "test66 case 5 failed\n");+ FAILED(buf[5] != WCONST(0x1100ffeeddccbbaa, 0xddccbbaa), "test66 case 6 failed\n");+ FAILED(ibuf[0] != (sljit_s32)0xc4d3e2f1, "test66 case 7 failed\n");+ FAILED(ibuf[1] != (sljit_s32)0xccddeeff, "test66 case 8 failed\n");+ FAILED(ibuf[2] != (sljit_s32)0x04030201, "test66 case 9 failed\n");+ FAILED(ibuf[3] != (sljit_s32)0x44332211, "test66 case 10 failed\n");+ FAILED(ibuf[4] != (sljit_s32)0xcbdcedfe, "test66 case 11 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test67(void)+{+ /* Test reverse two bytes. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[7];+ sljit_s32 ibuf[4];+ sljit_s16 hbuf[11];+ sljit_s32 i;++ if (verbose)+ printf("Run test67\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 7; i++)+ buf[i] = -1;+ for (i = 0; i < 4; i++)+ ibuf[i] = -1;+ for (i = 0; i < 11; i++)+ hbuf[i] = -1;++ hbuf[0] = (sljit_s16)0x8c9d;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS3V(W, W, W), 5, 5, 2 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0xeeabcd);+ sljit_emit_op1(compiler, SLJIT_REV_U16, SLJIT_R0, 0, SLJIT_R0, 0);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0xeeabcd);+ sljit_emit_op1(compiler, SLJIT_REV_S16, SLJIT_R1, 0, SLJIT_R2, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 0xeeedcb);+ sljit_emit_op1(compiler, SLJIT_REV_U16, SLJIT_R4, 0, SLJIT_R3, 0);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R4, 0);++ /* hbuf[1] */+ sljit_emit_op1(compiler, SLJIT_REV_U16, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_s16), SLJIT_MEM1(SLJIT_S2), 0);+ /* hbuf[2] */+ sljit_emit_op1(compiler, SLJIT_REV_S16, SLJIT_MEM1(SLJIT_S2), 2 * sizeof(sljit_s16), SLJIT_MEM1(SLJIT_S2), 0);++ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, 0xedcb);+ sljit_emit_op1(compiler, SLJIT_REV_U16, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw));+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM1(SLJIT_S2), 3 * sizeof(sljit_s16), SLJIT_IMM, 0xedcb);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 3);+ sljit_emit_op1(compiler, SLJIT_REV_S16, SLJIT_R1, 0, SLJIT_MEM2(SLJIT_S2, SLJIT_R1), 1);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_R2, 0, SLJIT_IMM, 0xd9c8);+ /* hbuf[3] */+ sljit_emit_op1(compiler, SLJIT_REV_S16, SLJIT_MEM1(SLJIT_S2), 3 * sizeof(sljit_s16), SLJIT_R2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_R4, 0, SLJIT_R2, 0);+ sljit_emit_op1(compiler, SLJIT_REV_S16, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s16), SLJIT_R4, 0);+ /* hbuf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_MEM1(SLJIT_S2), 4 * sizeof(sljit_s16), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s16));++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0xeeb1c2);+ sljit_emit_op1(compiler, SLJIT_REV32_U16, SLJIT_R0, 0, SLJIT_R0, 0);+ /* ibuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_IMM, 0xeeb1c2);+ sljit_emit_op1(compiler, SLJIT_REV32_S16, SLJIT_R1, 0, SLJIT_R2, 0);+ /* ibuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R3, 0, SLJIT_IMM, 0xddbfae);+ sljit_emit_op1(compiler, SLJIT_REV32_S16, SLJIT_R4, 0, SLJIT_R3, 0);+ /* ibuf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32), SLJIT_R4, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32_U16, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_IMM, 0xbfae);+ sljit_emit_op1(compiler, SLJIT_REV32_U16, SLJIT_R1, 0, SLJIT_MEM0(), (sljit_sw)(ibuf + 3));+ /* ibuf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0x880102);+ sljit_emit_op1(compiler, SLJIT_REV32_U16, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_R1, 0);+ /* hbuf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_MEM1(SLJIT_S2), 5 * sizeof(sljit_s16), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32));++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R3, 0, SLJIT_IMM, 0x880102);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 6 * sizeof(sljit_s16));+ /* hbuf[6] */+ sljit_emit_op1(compiler, SLJIT_REV32_S16, SLJIT_MEM2(SLJIT_S2, SLJIT_R1), 0, SLJIT_R3, 0);+ /* hbuf[7] */+ hbuf[7] = -367;++#if IS_64BIT+ /* SLJIT_REV truncates memory store, source not sign extended 64bit */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0xdeadbeef4444aa55);+ sljit_emit_op1(compiler, SLJIT_REV_U16, SLJIT_R1, 0, SLJIT_R0, 0);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R1, 0);+ /* hbuf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_MEM1(SLJIT_S2), 8 * sizeof(sljit_u16), SLJIT_R1, 0);+ /* hbuf[9] */+ sljit_emit_op1(compiler, SLJIT_REV_S16, SLJIT_MEM1(SLJIT_S2), 9 * sizeof(sljit_u16), SLJIT_R0, 0);+ /* hbuf[10] */+ hbuf[10] = -42;+ sljit_emit_op1(compiler, SLJIT_REV_S16, SLJIT_R0, 0, SLJIT_R0, 0);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R0, 0);+#endif /* IS_64BIT */++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func3((sljit_sw)buf, (sljit_sw)ibuf, (sljit_sw)hbuf);++ FAILED(buf[0] != 0xcdab, "test67 case 1 failed\n");+ FAILED(buf[1] != -0x3255, "test67 case 2 failed\n");+ FAILED(buf[2] != 0xcbed, "test67 case 3 failed\n");+ FAILED(hbuf[1] != (sljit_s16)0x9d8c, "test67 case 4 failed\n");+ FAILED(hbuf[2] != (sljit_s16)0x9d8c, "test67 case 5 failed\n");+ FAILED(buf[3] != 0xcbed, "test67 case 6 failed\n");+ FAILED(buf[4] != -0x3413, "test67 case 7 failed\n");+ FAILED(hbuf[3] != (sljit_s16)0xc8d9, "test67 case 8 failed\n");+ FAILED(hbuf[4] != (sljit_s16)0xc8d9, "test67 case 9 failed\n");+ FAILED(ibuf[0] != 0xc2b1, "test67 case 10 failed\n");+ FAILED(ibuf[1] != -0x3d4f, "test67 case 11 failed\n");+ FAILED(ibuf[2] != -0x5141, "test67 case 12 failed\n");+ FAILED(ibuf[3] != 0xaebf, "test67 case 13 failed\n");+ FAILED(hbuf[5] != (sljit_s16)0x0201, "test67 case 14 failed\n");+ FAILED(hbuf[6] != (sljit_s16)0x0201, "test67 case 15 failed\n");+ FAILED(hbuf[7] != -367, "test67 case 16 failed\n");+#if IS_64BIT+ FAILED(hbuf[8] != 0x55aa, "test67 case 17 failed\n");+ FAILED(buf[5] != hbuf[8], "test67 case 18 failed\n");+ FAILED(hbuf[9] != hbuf[8], "test67 case 19 failed\n");+ FAILED(hbuf[10] != -42, "test67 case 20 failed\n");+ FAILED(buf[6] != hbuf[9], "test67 case 21 failed\n");+#endif /* IS_64BIT */++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test68(void)+{+ /* Test reverse four bytes. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[7];+ sljit_s32 ibuf[6];+ sljit_s32 i;++ if (verbose)+ printf("Run test68\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 7; i++)+ buf[i] = -1;+ for (i = 0; i < 6; i++)+ ibuf[i] = -1;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(W, W), 5, 5, 2 * sizeof(sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xffffa1b2c3d4, 0xa1b2c3d4));+ sljit_emit_op1(compiler, SLJIT_REV_U32, SLJIT_R0, 0, SLJIT_R0, 0);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);++ /* Sign extend negative integer. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, WCONST(0xffffa1b2c3d4, 0xa1b2c3d4));+ sljit_emit_op1(compiler, SLJIT_REV_S32, SLJIT_R1, 0, SLJIT_R2, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R1, 0);++ /* Sign extend positive integer. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, WCONST(0xffff1a2b3c4d,0x1a2b3c4d));+ sljit_emit_op1(compiler, SLJIT_REV_S32, SLJIT_R1, 0, SLJIT_R2, 0);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_IMM, (sljit_s32)0xf9e8d7c6);+ sljit_emit_op1(compiler, SLJIT_REV_U32, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32));+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_s32));+ sljit_emit_op1(compiler, SLJIT_REV_S32, SLJIT_S2, 0, SLJIT_MEM2(SLJIT_S1, SLJIT_R1), 0);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_S2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, (sljit_s32)0xaabbccdd);+ sljit_emit_op1(compiler, SLJIT_REV_U32, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw));+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, (sljit_s32)0xaabbccdd);+ sljit_emit_op1(compiler, SLJIT_REV_S32, SLJIT_R4, 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw));+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R4, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0xffff01020304, 0x01020304));+ /* ibuf[0] */+ sljit_emit_op1(compiler, SLJIT_REV_U32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 1);+ /* ibuf[1] */+ sljit_emit_op1(compiler, SLJIT_REV_S32, SLJIT_MEM2(SLJIT_S1, SLJIT_S2), 2, SLJIT_S4, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_IMM, (sljit_s32)0xf0e0d0c0);+ /* ibuf[2] */+ sljit_emit_op1(compiler, SLJIT_REV_U32, SLJIT_MEM0(), (sljit_sw)(ibuf + 2), SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32));++ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_S2, 0, SLJIT_S1, 0, SLJIT_IMM, WCONST(0x1234567890ab, 0x12345678) - 3 * sizeof(sljit_s32));+ sljit_emit_op1(compiler, SLJIT_REV_U32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_MEM1(SLJIT_S2), WCONST(0x1234567890ab, 0x12345678));+ /* ibuf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32));++ /* SLJIT_REV memory store truncates and does not overflow */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, WCONST(0xffff8192a3b4, 0x8192a3b4));+ /* ibuf[4] */+ sljit_emit_op1(compiler, SLJIT_REV_S32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_s32), SLJIT_R4, 0);+ /* ibuf[5] */+ ibuf[5] = 0x55555555;++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)buf, (sljit_sw)ibuf);++ FAILED(buf[0] != WCONST(0xd4c3b2a1, 0xd4c3b2a1), "test68 case 1 failed\n");+ FAILED(buf[1] != WCONST(-0x2b3c4d5f, 0xd4c3b2a1), "test68 case 2 failed\n");+ FAILED(buf[2] != 0x4d3c2b1a, "test68 case 3 failed\n");+ FAILED(buf[3] != WCONST(0xc6d7e8f9, 0xc6d7e8f9), "test68 case 4 failed\n");+ FAILED(buf[4] != WCONST(-0x39281707, 0xc6d7e8f9), "test68 case 5 failed\n");+ FAILED(buf[5] != WCONST(0xddccbbaa, 0xddccbbaa), "test68 case 6 failed\n");+ FAILED(buf[6] != WCONST(-0x22334456, 0xddccbbaa), "test68 case 7 failed\n");+ FAILED(ibuf[0] != 0x04030201, "test68 case 8 failed\n");+ FAILED(ibuf[1] != 0x04030201, "test68 case 9 failed\n");+ FAILED(ibuf[2] != (sljit_s32)0xc0d0e0f0, "test68 case 10 failed\n");+ FAILED(ibuf[3] != (sljit_s32)0xc0d0e0f0, "test68 case 11 failed\n");+ FAILED(ibuf[4] != (sljit_s32)0xb4a39281, "test68 case 12 failed\n");+ FAILED(ibuf[5] != 0x55555555, "test68 case 13 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test69(void)+{+ /* Test atomic load and store. */+ executable_code code;+ struct sljit_compiler *compiler;+ struct sljit_label *label;+ struct sljit_jump *jump;+ sljit_u8 supported[11];+ sljit_sw buf[52];+ sljit_s32 i;++ if (verbose)+ printf("Run test69\n");++ if (!sljit_has_cpu_feature(SLJIT_HAS_ATOMIC)) {+ if (verbose)+ printf("no fine-grained atomic available, test69 skipped\n");+ successful_tests++;+ return;+ }++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ for (i = 1; i < 52; i++)+ buf[i] = WCONST(0x5555555555555555, 0x55555555);++ buf[0] = 4678;+ *(sljit_u8*)(buf + 2) = 78;+ *(sljit_u8*)(buf + 5) = 211;+ *(sljit_u16*)(buf + 9) = 17897;+ *(sljit_u16*)(buf + 12) = 57812;+ *(sljit_u32*)(buf + 15) = 1234567890;+ *(sljit_u32*)(buf + 17) = 987609876;+ buf[20] = (sljit_sw)buf;+ *(sljit_u8*)(buf + 22) = 192;+ *(sljit_u16*)(buf + 25) = 6359;+ ((sljit_u8*)(buf + 28))[1] = 105;+ ((sljit_u8*)(buf + 30))[2] = 13;+ ((sljit_u16*)(buf + 33))[1] = 14876;+#if IS_64BIT+ ((sljit_u8*)(buf + 35))[7] = 0x88;+ ((sljit_u16*)(buf + 37))[3] = 0x1337;+ ((sljit_s32*)(buf + 39))[1] = -1;+#endif /* IS_64BIT */+ buf[41] = WCONST(0x37b57b57b57b57b5, 0x37b57b57);+ ((sljit_s32*)(buf + 46))[0] = -8241;+ buf[48] = 98765;+ buf[50] = 87654;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 5, 5, 2 * sizeof(sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0);+ supported[0] = sljit_emit_atomic_load(compiler, SLJIT_MOV | SLJIT_ATOMIC_TEST, SLJIT_R0, SLJIT_R1) != SLJIT_ERR_UNSUPPORTED;+ SLJIT_ASSERT(supported[0] == (sljit_emit_atomic_store(compiler, SLJIT_MOV | SLJIT_ATOMIC_TEST, SLJIT_R0, SLJIT_R1, SLJIT_R2) != SLJIT_ERR_UNSUPPORTED));+ supported[1] = sljit_emit_atomic_load(compiler, SLJIT_MOV_U8 | SLJIT_ATOMIC_TEST, SLJIT_R2, SLJIT_R1) != SLJIT_ERR_UNSUPPORTED;+ SLJIT_ASSERT(supported[1] == (sljit_emit_atomic_store(compiler, SLJIT_MOV_U8 | SLJIT_ATOMIC_TEST, SLJIT_R2, SLJIT_R1, SLJIT_R0) != SLJIT_ERR_UNSUPPORTED));+ supported[2] = sljit_emit_atomic_load(compiler, SLJIT_MOV32_U8 | SLJIT_ATOMIC_TEST, SLJIT_R0, SLJIT_R0) != SLJIT_ERR_UNSUPPORTED;+ SLJIT_ASSERT(supported[2] == (sljit_emit_atomic_store(compiler, SLJIT_MOV32_U8 | SLJIT_ATOMIC_TEST, SLJIT_R0, SLJIT_R0, SLJIT_R1) != SLJIT_ERR_UNSUPPORTED));+ supported[3] = sljit_emit_atomic_load(compiler, SLJIT_MOV_U16 | SLJIT_ATOMIC_TEST, SLJIT_R1, SLJIT_R2) != SLJIT_ERR_UNSUPPORTED;+ SLJIT_ASSERT(supported[3] == (sljit_emit_atomic_store(compiler, SLJIT_MOV_U16 | SLJIT_ATOMIC_TEST, SLJIT_R1, SLJIT_R2, SLJIT_R0) != SLJIT_ERR_UNSUPPORTED));+ supported[4] = sljit_emit_atomic_load(compiler, SLJIT_MOV32_U16 | SLJIT_ATOMIC_TEST, SLJIT_R1, SLJIT_R0) != SLJIT_ERR_UNSUPPORTED;+ SLJIT_ASSERT(supported[4] == (sljit_emit_atomic_store(compiler, SLJIT_MOV32_U16 | SLJIT_ATOMIC_TEST, SLJIT_R1, SLJIT_R0, SLJIT_R2) != SLJIT_ERR_UNSUPPORTED));+ supported[5] = sljit_emit_atomic_load(compiler, SLJIT_MOV_U32 | SLJIT_ATOMIC_TEST, SLJIT_R2, SLJIT_R0) != SLJIT_ERR_UNSUPPORTED;+ SLJIT_ASSERT(supported[5] == (sljit_emit_atomic_store(compiler, SLJIT_MOV_U32 | SLJIT_ATOMIC_TEST, SLJIT_R2, SLJIT_R0, SLJIT_R1) != SLJIT_ERR_UNSUPPORTED));+ supported[6] = sljit_emit_atomic_load(compiler, SLJIT_MOV_S32 | SLJIT_ATOMIC_TEST, SLJIT_R2, SLJIT_R0) != SLJIT_ERR_UNSUPPORTED;+ SLJIT_ASSERT(supported[6] == (sljit_emit_atomic_store(compiler, SLJIT_MOV_S32 | SLJIT_ATOMIC_TEST, SLJIT_R2, SLJIT_R0, SLJIT_R1) != SLJIT_ERR_UNSUPPORTED));+ supported[7] = sljit_emit_atomic_load(compiler, SLJIT_MOV32 | SLJIT_ATOMIC_TEST, SLJIT_R0, SLJIT_R1) != SLJIT_ERR_UNSUPPORTED;+ SLJIT_ASSERT(supported[7] == (sljit_emit_atomic_store(compiler, SLJIT_MOV32 | SLJIT_ATOMIC_TEST, SLJIT_R0, SLJIT_R1, SLJIT_R2) != SLJIT_ERR_UNSUPPORTED));+ supported[8] = sljit_emit_atomic_load(compiler, SLJIT_MOV_P | SLJIT_ATOMIC_TEST, SLJIT_R0, SLJIT_R2) != SLJIT_ERR_UNSUPPORTED;+ SLJIT_ASSERT(supported[8] == (sljit_emit_atomic_store(compiler, SLJIT_MOV_P | SLJIT_ATOMIC_TEST, SLJIT_R0, SLJIT_R2, SLJIT_R1) != SLJIT_ERR_UNSUPPORTED));+ supported[9] = sljit_emit_atomic_load(compiler, SLJIT_MOV | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_TEST, SLJIT_R0, SLJIT_R1) != SLJIT_ERR_UNSUPPORTED;+ SLJIT_ASSERT(supported[9] == (sljit_emit_atomic_store(compiler, SLJIT_MOV | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_TEST, SLJIT_R0, SLJIT_R1, SLJIT_R2) != SLJIT_ERR_UNSUPPORTED));+ supported[10] = sljit_emit_atomic_load(compiler, SLJIT_MOV | SLJIT_ATOMIC_USE_LS | SLJIT_ATOMIC_TEST, SLJIT_R0, SLJIT_R1) != SLJIT_ERR_UNSUPPORTED;+ SLJIT_ASSERT(supported[10] == (sljit_emit_atomic_store(compiler, SLJIT_MOV | SLJIT_ATOMIC_USE_LS | SLJIT_ATOMIC_TEST, SLJIT_R0, SLJIT_R1, SLJIT_R2) != SLJIT_ERR_UNSUPPORTED));+ SLJIT_ASSERT(supported[0] != 0 && supported[7] != 0);++ if (supported[0]) {+ label = sljit_emit_label(compiler);+ sljit_emit_atomic_load(compiler, SLJIT_MOV, SLJIT_R1, SLJIT_S0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -9856);+ /* buf[0] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV | SLJIT_SET_ATOMIC_STORED, SLJIT_R1, SLJIT_S0, SLJIT_R0);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R2, 0);+ }++ if (supported[1]) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 2 * sizeof(sljit_sw));+ label = sljit_emit_label(compiler);+ sljit_emit_atomic_load(compiler, SLJIT_MOV_U8, SLJIT_R2, SLJIT_R1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_R2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 203);+ /* buf[2] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV_U8 | SLJIT_SET_ATOMIC_STORED, SLJIT_R0, SLJIT_R1, SLJIT_R2);+ jump = sljit_emit_jump(compiler, SLJIT_ATOMIC_STORED);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_JUMP), label);+ sljit_set_label(jump, sljit_emit_label(compiler));+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_S2, 0);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0);+ }++ if (supported[2]) {+ label = sljit_emit_label(compiler);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 5 * sizeof(sljit_sw));+ sljit_emit_atomic_load(compiler, SLJIT_MOV32_U8, SLJIT_R0, SLJIT_R0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 5 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 97);+ /* buf[5] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV32_U8 | SLJIT_SET_ATOMIC_STORED, SLJIT_S1, SLJIT_R0, SLJIT_S2);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R1, 0);+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_S1, 0);+ }++ if (supported[3]) {+ label = sljit_emit_label(compiler);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 9 * sizeof(sljit_sw));+ sljit_emit_atomic_load(compiler, SLJIT_MOV_U16, SLJIT_S2, SLJIT_R1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_S2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_S2, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 9 * sizeof(sljit_sw));+ /* buf[9] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV_U16 | SLJIT_SET_ATOMIC_STORED, SLJIT_R0, SLJIT_R0, SLJIT_R1);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[10] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R2, 0);+ /* buf[11] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_R0, 0);+ }++ if (supported[4]) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 12 * sizeof(sljit_sw));+ label = sljit_emit_label(compiler);+ sljit_emit_atomic_load(compiler, SLJIT_MOV32_U16, SLJIT_R0, SLJIT_R1);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 41306);+ /* buf[12] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV32_U16 | SLJIT_SET_ATOMIC_STORED, SLJIT_R0, SLJIT_R1, SLJIT_R3);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[13] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_R2, 0);+ /* buf[14] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_R0, 0);+ }++ if (supported[5]) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S2, 0, SLJIT_S0, 0, SLJIT_IMM, 15 * sizeof(sljit_sw));+ label = sljit_emit_label(compiler);+ sljit_emit_atomic_load(compiler, SLJIT_MOV_U32, SLJIT_R2, SLJIT_S2);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_R2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_R2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 987654321);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S1, 0, SLJIT_S0, 0, SLJIT_IMM, 15 * sizeof(sljit_sw));+ /* buf[15] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV_U32 | SLJIT_SET_ATOMIC_STORED, SLJIT_R1, SLJIT_S1, SLJIT_S3);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[16] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_R0, 0);+ }++ if (supported[7]) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S0, 0, SLJIT_IMM, 17 * sizeof(sljit_sw));+ label = sljit_emit_label(compiler);+ sljit_emit_atomic_load(compiler, SLJIT_MOV32, SLJIT_R0, SLJIT_R2);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_S1, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -573621);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 678906789);+ /* buf[17] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV32 | SLJIT_SET_ATOMIC_STORED, SLJIT_R1, SLJIT_R2, SLJIT_S2);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[18] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_sw), SLJIT_S1, 0);+ /* buf[19] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 19 * sizeof(sljit_sw), SLJIT_R0, 0);+ }++ if (supported[8]) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S0, 0, SLJIT_IMM, 20 * sizeof(sljit_sw));+ label = sljit_emit_label(compiler);+ sljit_emit_atomic_load(compiler, SLJIT_MOV_P, SLJIT_R0, SLJIT_R2);+ sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_S1, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_R1, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_R0, 0, SLJIT_R2, 0);+ /* buf[20] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV_P | SLJIT_SET_ATOMIC_STORED, SLJIT_R0, SLJIT_R2, SLJIT_R1);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[21] */+ sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_MEM1(SLJIT_S0), 21 * sizeof(sljit_sw), SLJIT_S1, 0);+ }++ if (supported[1]) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 22 * sizeof(sljit_sw));+ label = sljit_emit_label(compiler);+ sljit_emit_atomic_load(compiler, SLJIT_MOV_U8, SLJIT_R3, SLJIT_R1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_R3, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_R3, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 240);+ /* buf[22] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV_U8 | SLJIT_SET_ATOMIC_STORED, SLJIT_R3, SLJIT_R1, SLJIT_R4);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[23] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 23 * sizeof(sljit_sw), SLJIT_R2, 0);+ /* buf[24] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 24 * sizeof(sljit_sw), SLJIT_R3, 0);+ }++ if (supported[0]) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 25 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 25 * sizeof(sljit_sw), SLJIT_IMM, 6359);+ label = sljit_emit_label(compiler);+ sljit_emit_atomic_load(compiler, SLJIT_MOV, SLJIT_S3, SLJIT_R0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_S3, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_S3, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, 4059);+ /* buf[25] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV | SLJIT_SET_ATOMIC_STORED, SLJIT_S3, SLJIT_R0, SLJIT_S4);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[26] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 26 * sizeof(sljit_sw), SLJIT_R1, 0);+ /* buf[27] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 27 * sizeof(sljit_sw), SLJIT_R0, 0);+ }++ if (supported[1]) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 28 * sizeof(sljit_sw) + 1);+ label = sljit_emit_label(compiler);+ sljit_emit_atomic_load(compiler, SLJIT_MOV_U8, SLJIT_R0, SLJIT_R1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 204);+ /* buf[28] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV_U8 | SLJIT_SET_ATOMIC_STORED, SLJIT_R2, SLJIT_R1, SLJIT_R0);+ jump = sljit_emit_jump(compiler, SLJIT_ATOMIC_STORED);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_JUMP), label);+ sljit_set_label(jump, sljit_emit_label(compiler));+ /* buf[29] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 29 * sizeof(sljit_sw), SLJIT_S2, 0);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 30 * sizeof(sljit_sw) + 2);+ label = sljit_emit_label(compiler);+ sljit_emit_atomic_load(compiler, SLJIT_MOV_U8, SLJIT_R0, SLJIT_R1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 240);+ /* buf[30] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV_U8 | SLJIT_SET_ATOMIC_STORED, SLJIT_R2, SLJIT_R1, SLJIT_R0);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[31] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 31 * sizeof(sljit_sw), SLJIT_S1, 0);+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_ATOMIC_NOT_STORED);+ /* buf[32] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 32 * sizeof(sljit_sw), SLJIT_R0, 0);+ }++ if (supported[3]) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 33 * sizeof(sljit_sw) + 2);+ label = sljit_emit_label(compiler);+ sljit_emit_atomic_load(compiler, SLJIT_MOV_U16, SLJIT_R0, SLJIT_R1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 51403);+ /* buf[33] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV_U16 | SLJIT_SET_ATOMIC_STORED, SLJIT_R2, SLJIT_R1, SLJIT_R0);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[34] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 34 * sizeof(sljit_sw), SLJIT_S1, 0);+ }++#if IS_64BIT+ if (supported[1]) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 35 * sizeof(sljit_sw) + 7 * sizeof(sljit_u8));+ label = sljit_emit_label(compiler);+ sljit_emit_atomic_load(compiler, SLJIT_MOV_U8, SLJIT_R0, SLJIT_R1);+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_S1, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0xffa5a5a542);+ /* buf[35] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV_U8 | SLJIT_SET_ATOMIC_STORED, SLJIT_R2, SLJIT_R1, SLJIT_R0);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[36] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 36 * sizeof(sljit_sw), SLJIT_S1, 0);+ }++ if (supported[3]) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 37 * sizeof(sljit_sw) + 3 * sizeof(sljit_u16));+ label = sljit_emit_label(compiler);+ sljit_emit_atomic_load(compiler, SLJIT_MOV_U16, SLJIT_R0, SLJIT_R1);+ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_S1, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0xffa5a56942);+ /* buf[37] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV_U16 | SLJIT_SET_ATOMIC_STORED, SLJIT_R2, SLJIT_R1, SLJIT_R0);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[38] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 38 * sizeof(sljit_sw), SLJIT_S1, 0);+ }++ if (supported[5]) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 39 * sizeof(sljit_sw) + sizeof(sljit_u32));+ label = sljit_emit_label(compiler);+ sljit_emit_atomic_load(compiler, SLJIT_MOV_U32, SLJIT_R0, SLJIT_R1);+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_S1, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0xffffdeadbeef);+ /* buf[39] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV_U32 | SLJIT_SET_ATOMIC_STORED, SLJIT_R2, SLJIT_R1, SLJIT_R0);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[40] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 40 * sizeof(sljit_sw), SLJIT_S1, 0);+ }+#endif /* IS_64BIT */++ if (supported[0]) {+ /* Abandoned atomic load. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 8);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, (41 - 8) * sizeof(sljit_sw));++ label = sljit_emit_label(compiler);+ sljit_emit_atomic_load(compiler, SLJIT_MOV, SLJIT_R0, SLJIT_R1);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw));+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, 1);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_NOT_ZERO), label);++ label = sljit_emit_label(compiler);+ sljit_emit_atomic_load(compiler, SLJIT_MOV, SLJIT_R0, SLJIT_R1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, WCONST(0x670c70c70c70c70c, 0x670c70c7));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_R0, 0);+ /* buf[41] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV | SLJIT_SET_ATOMIC_STORED, SLJIT_S1, SLJIT_R1, SLJIT_R0);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[42] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 42 * sizeof(sljit_sw), SLJIT_R2, 0);+ /* buf[43] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 43 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S1, 0, SLJIT_S0, 0, SLJIT_IMM, 44 * sizeof(sljit_sw));+ label = sljit_emit_label(compiler);+ sljit_emit_atomic_load(compiler, SLJIT_MOV, SLJIT_R1, SLJIT_S1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -9107);+ /* buf[44] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV | SLJIT_SET_ATOMIC_STORED, SLJIT_R2, SLJIT_S1, SLJIT_R1);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[45] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 45 * sizeof(sljit_sw), SLJIT_ATOMIC_STORED);+ }++ if (supported[6]) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 46 * sizeof(sljit_sw));+ label = sljit_emit_label(compiler);+ sljit_emit_atomic_load(compiler, SLJIT_MOV_S32, SLJIT_R1, SLJIT_R0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -3058);+ /* buf[46] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV_S32 | SLJIT_SET_ATOMIC_STORED, SLJIT_R1, SLJIT_R0, SLJIT_R2);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[47] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 47 * sizeof(sljit_sw), SLJIT_S1, 0);+ }++ if (supported[9]) {+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 98765);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 48 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -76543);+ label = sljit_emit_label(compiler);+ /* buf[48] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV | SLJIT_ATOMIC_USE_CAS | SLJIT_SET_ATOMIC_STORED, SLJIT_R2, SLJIT_R1, SLJIT_R0);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[49] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 49 * sizeof(sljit_sw), SLJIT_R0, 0);+ }++ if (supported[10]) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S1, 0, SLJIT_S0, 0, SLJIT_IMM, 50 * sizeof(sljit_sw));+ label = sljit_emit_label(compiler);+ sljit_emit_atomic_load(compiler, SLJIT_MOV | SLJIT_ATOMIC_USE_LS, SLJIT_R2, SLJIT_S1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -65432);+ /* buf[50] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV | SLJIT_ATOMIC_USE_LS | SLJIT_SET_ATOMIC_STORED, SLJIT_R1, SLJIT_S1, SLJIT_R1);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[51] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 51 * sizeof(sljit_sw), SLJIT_R2, 0);+ }++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);++ if (supported[0]) {+ FAILED(buf[0] != -9856, "test69 case 1 failed\n");+ FAILED(buf[1] != 4678, "test69 case 2 failed\n");+ }+ if (supported[1]) {+ FAILED(*(sljit_u8*)(buf + 2) != 203, "test69 case 3 failed\n");+ FAILED(((sljit_u8*)(buf + 2))[1] != 0x55, "test69 case 4 failed\n");+ FAILED(buf[3] != 78, "test69 case 5 failed\n");+ FAILED(buf[4] != 203, "test69 case 6 failed\n");+ }+ if (supported[2]) {+ FAILED(*(sljit_u8*)(buf + 5) != 97, "test69 case 7 failed\n");+ FAILED(((sljit_u8*)(buf + 5))[1] != 0x55, "test69 case 8 failed\n");+ FAILED(*(sljit_u32*)(buf + 6) != 211, "test69 case 9 failed\n");+ FAILED(buf[7] != (sljit_sw)(buf + 5), "test69 case 10 failed\n");+ FAILED(buf[8] != 97, "test69 case 11 failed\n");+ }+ if (supported[3]) {+ FAILED(*(sljit_u16*)(buf + 9) != (sljit_u16)(sljit_sw)(buf + 9), "test69 case 12 failed\n");+ FAILED(((sljit_u8*)(buf + 9))[2] != 0x55, "test69 case 13 failed\n");+ FAILED(buf[10] != 17897, "test69 case 14 failed\n");+ FAILED(buf[11] != (sljit_sw)(buf + 9), "test69 case 15 failed\n");+ }+ if (supported[4]) {+ FAILED(*(sljit_u16*)(buf + 12) != 41306, "test69 case 16 failed\n");+ FAILED(((sljit_u8*)(buf + 12))[2] != 0x55, "test69 case 17 failed\n");+ FAILED(*(sljit_u32*)(buf + 13) != 57812, "test69 case 18 failed\n");+ FAILED(buf[14] != 41306, "test69 case 19 failed\n");+ }+ if (supported[5]) {+ FAILED(*(sljit_u32*)(buf + 15) != 987654321, "test69 case 20 failed\n");+#if IS_64BIT+ FAILED(((sljit_u8*)(buf + 15))[4] != 0x55, "test69 case 21 failed\n");+#endif /* IS_64BIT */+ FAILED(buf[16] != 1234567890, "test69 case 22 failed\n");+ }+ if (supported[7]) {+ FAILED(*(sljit_u32*)(buf + 17) != 678906789, "test69 case 23 failed\n");+#if IS_64BIT+ FAILED(((sljit_u8*)(buf + 17))[4] != 0x55, "test69 case 24 failed\n");+#endif /* IS_64BIT */+ FAILED(*(sljit_u32*)(buf + 18) != 987609876, "test69 case 25 failed\n");+#if IS_64BIT+ FAILED(((sljit_u8*)(buf + 18))[4] != 0x55, "test69 case 26 failed\n");+#endif /* IS_64BIT */+ FAILED(buf[19] != -573621, "test69 case 27 failed\n");+ }+ if (supported[8]) {+ FAILED(buf[20] != (sljit_sw)(buf + 20), "test 92 case 28 failed\n");+ FAILED(buf[21] != (sljit_sw)buf, "test 92 case 29 failed\n");+ }+ if (supported[1]) {+ FAILED(*(sljit_u8*)(buf + 22) != 240, "test69 case 30 failed\n");+ FAILED(((sljit_u8*)(buf + 22))[1] != 0x55, "test69 case 31 failed\n");+ FAILED(buf[23] != 192, "test69 case 32 failed\n");+ FAILED(buf[24] != 240, "test69 case 33 failed\n");+ }+ if (supported[0]) {+ FAILED(buf[25] != 4059, "test69 case 34 failed\n");+ FAILED(buf[26] != 6359, "test69 case 35 failed\n");+ FAILED(buf[27] != (sljit_sw)(buf + 25), "test69 case 36 failed\n");+ }+ if (supported[1]) {+ FAILED(((sljit_u8*)(buf + 28))[0] != 0x55, "test69 case 37 failed\n");+ FAILED(((sljit_u8*)(buf + 28))[1] != 204, "test69 case 38 failed\n");+ FAILED(((sljit_u8*)(buf + 28))[2] != 0x55, "test69 case 39 failed\n");+ FAILED(buf[29] != 105, "test69 case 40 failed\n");+ FAILED(((sljit_u8*)(buf + 30))[1] != 0x55, "test69 case 41 failed\n");+ FAILED(((sljit_u8*)(buf + 30))[2] != 240, "test69 case 42 failed\n");+ FAILED(((sljit_u8*)(buf + 30))[3] != 0x55, "test69 case 43 failed\n");+ FAILED(buf[31] != 13, "test69 case 44 failed\n");+ FAILED(buf[32] != 0, "test69 case 45 failed\n");+ }+ if (supported[3]) {+ FAILED(((sljit_u16*)(buf + 33))[0] != 0x5555, "test69 case 46 failed\n");+ FAILED(((sljit_u16*)(buf + 33))[1] != 51403, "test69 case 47 failed\n");+ FAILED(buf[34] != 14876, "test69 case 48 failed\n");+ }+#if IS_64BIT+ if (supported[1]) {+ FAILED(((sljit_u8*)(buf + 35))[7] != 0x42, "test69 case 49 failed\n");+ FAILED(buf[36] != 0x88, "test69 case 50 failed\n");+ }+ if (supported[3]) {+ FAILED(((sljit_u16*)(buf + 37))[3] != 0x6942, "test69 case 51 failed\n");+ FAILED(buf[38] != 0x1337, "test69 case 52 failed\n");+ }+ if (supported[5]) {+ FAILED(((sljit_u32*)(buf + 39))[0] != 0x55555555, "test69 case 53 failed\n");+ FAILED(((sljit_u32*)(buf + 39))[1] != 0xdeadbeef, "test69 case 54 failed\n");+ FAILED(buf[40] != 0xffffffff, "test69 case 55 failed\n");+ }+#endif /* IS_64BIT */+ if (supported[0]) {+ FAILED(buf[41] != WCONST(0x670c70c70c70c70c, 0x670c70c7), "test69 case 56 failed\n");+ FAILED(buf[42] != WCONST(0x37b57b57b57b57b5, 0x37b57b57), "test69 case 57 failed\n");+ FAILED(buf[43] != (sljit_sw)(buf + 41), "test69 case 58 failed\n");++ FAILED(buf[44] != -9107, "test69 case 59 failed\n");+ FAILED(buf[45] != 1, "test69 case 60 failed\n");+ }+ if (supported[6]) {+ FAILED(((sljit_s32*)(buf + 46))[0] != -3058, "test69 case 61 failed\n");+#if IS_64BIT+ FAILED(((sljit_s32*)(buf + 46))[1] != 0x55555555, "test69 case 62 failed\n");+#endif /* IS_64BIT */+ FAILED(buf[47] != -8241, "test69 case 63 failed\n");+ }+ if (supported[9]) {+ FAILED(buf[48] != -76543, "test69 case 64 failed\n");+ FAILED(buf[49] != 98765, "test69 case 65 failed\n");+ }+ if (supported[10]) {+ FAILED(buf[50] != -65432, "test69 case 66 failed\n");+ FAILED(buf[51] != 87654, "test69 case 67 failed\n");+ }++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test70(void)+{+ /* Test accessing temporary registers. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[SLJIT_NUMBER_OF_TEMPORARY_REGISTERS + SLJIT_NUMBER_OF_REGISTERS - 1];+ sljit_f64 fbuf[2 * (SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS + SLJIT_NUMBER_OF_FLOAT_REGISTERS)];+ sljit_s32 i, ctr;++ if (verbose)+ printf("Run test70\n");++ for (i = 0; i < SLJIT_NUMBER_OF_TEMPORARY_REGISTERS; i++)+ buf[i] = -1;++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), SLJIT_NUMBER_OF_REGISTERS - 1, 1, 0);++ ctr = 123;+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_R0, 0, SLJIT_IMM, ctr);++ /* Set registers, also works for virtual registers. */+ for (i = 1; i < SLJIT_NUMBER_OF_TEMPORARY_REGISTERS; i++) {+ SLJIT_ASSERT(sljit_get_register_index(SLJIT_GP_REGISTER, SLJIT_TMP_R(i)) >= 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_R(i), 0, SLJIT_IMM, ++ctr);+ }++ for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS - 1; i++)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, ++ctr);++ /* Save registers, temporaries first to avoid issues when virtual registers are copied. */+ ctr = 0;+ for (i = 0; i < SLJIT_NUMBER_OF_TEMPORARY_REGISTERS; i++, ctr += (sljit_s32)sizeof(sljit_sw))+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), ctr, SLJIT_TMP_R(i), 0);++ for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS - 1; i++, ctr += (sljit_s32)sizeof(sljit_sw))+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), ctr, SLJIT_R(i), 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)buf);+ sljit_free_code(code.code, NULL);++ for (i = 0; i < (SLJIT_NUMBER_OF_TEMPORARY_REGISTERS + SLJIT_NUMBER_OF_REGISTERS - 1); i++) {+ FAILED(buf[i] != (123 + i), "test70 case 1 failed\n");+ }++ if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) {+ successful_tests++;+ return;+ }++ ctr = SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS + SLJIT_NUMBER_OF_FLOAT_REGISTERS;+ for (i = 0; i < ctr; i++) {+ fbuf[i] = 123.0 + i;+ fbuf[ctr + i] = -1.0;+ }++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 0 | SLJIT_ENTER_FLOAT(SLJIT_NUMBER_OF_FLOAT_REGISTERS), 1, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_TMP_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0);+ ctr = sizeof(sljit_f64);+ for (i = 1; i < SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS; i++, ctr += (sljit_s32)(sizeof(sljit_f64))) {+ SLJIT_ASSERT(sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_TMP_FR(i)) >= 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_TMP_FR(i), 0, SLJIT_MEM1(SLJIT_S0), ctr);+ }++ for (i = 0; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++, ctr += (sljit_s32)(sizeof(sljit_f64)))+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR(i), 0, SLJIT_MEM1(SLJIT_S0), ctr);++ for (i = 0; i < SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS; i++, ctr += (sljit_s32)(sizeof(sljit_f64)))+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), ctr, SLJIT_TMP_FR(i), 0);++ for (i = 0; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++, ctr += (sljit_s32)(sizeof(sljit_f64)))+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), ctr, SLJIT_FR(i), 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)fbuf);+ sljit_free_code(code.code, NULL);++ ctr = SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS + SLJIT_NUMBER_OF_FLOAT_REGISTERS;+ for (i = 0; i < ctr; i++) {+ FAILED(fbuf[ctr + i] != (123.0 + i), "test70 case 2 failed\n");+ }++ if (sljit_has_cpu_feature(SLJIT_HAS_F64_AS_F32_PAIR)) {+ fbuf[0] = 123456789012.0;+ fbuf[1] = -1.0;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 0 | SLJIT_ENTER_FLOAT(SLJIT_NUMBER_OF_FLOAT_REGISTERS), 1, 0);++#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_TMP_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_F64_SECOND(SLJIT_TMP_FR0), 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f32));+#else /* !SLJIT_LITTLE_ENDIAN */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_TMP_FR0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_F64_SECOND(SLJIT_TMP_FR0), 0, SLJIT_MEM1(SLJIT_S0), 0);+#endif /* SLJIT_LITTLE_ENDIAN */++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64), SLJIT_TMP_FR0, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)fbuf);+ sljit_free_code(code.code, NULL);++ FAILED(fbuf[1] != 123456789012.0, "test70 case 3 failed\n");+ }++ if (sljit_has_cpu_feature(SLJIT_HAS_SIMD)) {+ fbuf[0] = 123456789012.0;+ fbuf[1] = 456789012345.0;+ fbuf[2] = -1.0;+ fbuf[3] = -1.0;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 0 | SLJIT_ENTER_FLOAT(SLJIT_NUMBER_OF_FLOAT_REGISTERS), 1, 0);++ i = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_64 | SLJIT_SIMD_FLOAT | SLJIT_SIMD_MEM_ALIGNED_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | i, SLJIT_TMP_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | i, SLJIT_TMP_VR0, SLJIT_MEM1(SLJIT_S0), 16);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)fbuf);+ sljit_free_code(code.code, NULL);++ FAILED(fbuf[2] != 123456789012.0, "test70 case 4 failed\n");+ FAILED(fbuf[3] != 456789012345.0, "test70 case 5 failed\n");+ }++ successful_tests++;+}++static void test71(void)+{+ /* Test accessing named temporary registers. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[64];+ struct sljit_jump *jumps[2];+ struct sljit_label *labels[3];+ sljit_s32 i;++ if (verbose)+ printf("Run test71\n");++ for (i = 0; i < 64; i++)+ buf[i] = -1;++ buf[63] = (sljit_sw)&buf;+ buf[62] = (sljit_sw)&buf + 70 * (sljit_sw)sizeof(sljit_sw);+ buf[61] = WCONST(0x5c78930a47b18f24, 0x5c78930a);+ *(sljit_u16*)(buf + 60) = 0x8c93;+ buf[59] = 0;+ *(sljit_u8*)(buf + 59) = 0xe5;+ *(sljit_u32*)(buf + 58) = 0x2eb09f24;+ buf[57] = -0x6b301e7;+ *(sljit_s32*)(buf + 56) = -0xe0b38cd;+ buf[55] = WCONST(0x73b18cd05fa29bc7, 0x73b18cd0);+ buf[54] = 0;+ *(sljit_u16*)(buf + 54) = 0xa39a;+ buf[53] = (61 * sizeof(sljit_sw)) >> 1;++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 5, 5, 2 * sizeof(sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x7890abcdef123456, 0x7890abcd));+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)(buf + 0), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)(buf + 63) - WCONST(0x7a6b5c4d3e2f10ff, 0x7a6b5cff));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0x6786786786786786, 0x67867867));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_R0), WCONST(0x7a6b5c4d3e2f10ff, 0x7a6b5cff));+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_TMP_DEST_REG), sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)(buf + 63) + WCONST(0x6abcabcabcabcabc, 0x6abcabca));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_S1), -WCONST(0x6abcabcabcabcabc, 0x6abcabca));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_TMP_DEST_REG), 62 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_TMP_DEST_REG), -9 * (sljit_sw)sizeof(sljit_sw));+ sljit_emit_op2(compiler, SLJIT_LSHR, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 4);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(buf + 60) - WCONST(0x374c74c74c74c74c, 0x374c74c7));+ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_R1), WCONST(0x374c74c74c74c74c, 0x374c74c7));+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 15);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_R1), WCONST(0x374c74c74c74c74c, 0x374c74c7) - 56 * (sljit_sw)sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (62 * sizeof(sljit_sw)) >> 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 1);+ sljit_emit_op1(compiler, SLJIT_MOV32_S8, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_TMP_DEST_REG), -11 * (sljit_sw)sizeof(sljit_sw));+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM0(), (sljit_sw)(buf + 5), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, (sljit_sw)buf);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw));+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 58 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_TMP_DEST_REG), 0);+ sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 0xff);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)(buf + 7) + WCONST(0x35d45d45d45d45d4, 0x35d45d45));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 10);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_S1, 0, SLJIT_IMM, -10);+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_SIG_GREATER);+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), -WCONST(0x35d45d45d45d45d4, 0x35d45d45), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0x2eb09f24);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(buf + 8) - WCONST(0x7a31a31a31a31a31, 0x7a31a31a));+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_S0), 58 * sizeof(sljit_sw));+ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_MEM1(SLJIT_R1), WCONST(0x7a31a31a31a31a31, 0x7a31a31a), SLJIT_TMP_DEST_REG, 0);+ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_Z, SLJIT_TMP_DEST_REG, 0, SLJIT_R0, 0);+ /* buf[9] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_EQUAL);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_S0), 61 * sizeof(sljit_sw));+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 43);+ /* buf[10] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);+ sljit_emit_op2(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 0xff);+ /* buf[11] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ /* Limit checks. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_S0), 57 * sizeof(sljit_sw));+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 255);+ /* buf[12] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_S0), 57 * sizeof(sljit_sw));+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 255);+ /* buf[13] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_S0), 57 * sizeof(sljit_sw));+ sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 8 * sizeof(sljit_sw) - 1);+ /* buf[14] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_S0), 56 * sizeof(sljit_sw));+ sljit_emit_op2(compiler, SLJIT_ADD32, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 255);+ /* buf[15] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_S0), 56 * sizeof(sljit_sw));+ sljit_emit_op2(compiler, SLJIT_SUB32, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 255);+ /* buf[16] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_S0), 56 * sizeof(sljit_sw));+ sljit_emit_op2(compiler, SLJIT_ASHR32, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 31);+ /* buf[17] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ /* Register operations. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x1234567);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_S0), 57 * sizeof(sljit_sw));+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_R0, 0);+ /* buf[18] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 400);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 255);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_TMP_DEST_REG, 0, SLJIT_R0, 0);+ sljit_emit_select(compiler, SLJIT_LESS_EQUAL, SLJIT_R0, SLJIT_TMP_DEST_REG, 0, SLJIT_R0);+ /* buf[19] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 19 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 100);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 255);+ sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_LESS_EQUAL, SLJIT_TMP_DEST_REG, 0, SLJIT_R0, 0);+ sljit_emit_select(compiler, SLJIT_LESS_EQUAL | SLJIT_32, SLJIT_R0, SLJIT_TMP_DEST_REG, 0, SLJIT_R0);+ /* buf[20] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 20 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 200);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 600);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 255);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_select(compiler, SLJIT_GREATER, SLJIT_TMP_DEST_REG, SLJIT_R0, 0, SLJIT_R1);+ /* buf[21] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 21 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ /* Register preserving. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0xa8d18d18d18d18d1, 0xa8d18d18));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)(buf + 55) + WCONST(0x360a60a60a60a60a, 0x360a60a6));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(buf + 22) - WCONST(0x53f93f93f93f93f9, 0x53f93f93));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), -WCONST(0x360a60a60a60a60a, 0x360a60a6));+ /* buf[22] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), WCONST(0x53f93f93f93f93f9, 0x53f93f93), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)(buf + 23) - WCONST(0x7c41c41c41c41c41, 0x7c41c41c));+ /* buf[23] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), WCONST(0x7c41c41c41c41c41, 0x7c41c41c), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)(buf + 54) + WCONST(0x45ba5ba5ba5ba5ba, 0x45ba5ba5));+ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_R2), -WCONST(0x45ba5ba5ba5ba5ba, 0x45ba5ba5));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, (sljit_sw)(buf + 55) - WCONST(0x1c05c05c05c05c05, 0x1c05c05c));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_S2), WCONST(0x1c05c05c05c05c05, 0x1c05c05c));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 24 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(buf + 25) + WCONST(0x3b47b47b47b47b47, 0x3b47b47b));+ sljit_emit_op2(compiler, SLJIT_ASHR, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 1);+ /* buf[24] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_R0, SLJIT_S0), 0, SLJIT_S2, 0);+ /* buf[25] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), -WCONST(0x3b47b47b47b47b47, 0x3b47b47b), SLJIT_TMP_DEST_REG, 0);++ /* Test multiply. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)(buf + 61) + WCONST(0x51e91e91e91e91e9, 0x51e91e91));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(buf + 55) - WCONST(0x238d38d38d38d38d, 0x238d38d3));+ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_R0), -WCONST(0x51e91e91e91e91e9, 0x51e91e91), SLJIT_MEM1(SLJIT_R1), WCONST(0x238d38d38d38d38d, 0x238d38d3));+ /* buf[26] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 26 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_R0), -WCONST(0x51e91e91e91e91e9, 0x51e91e91), SLJIT_IMM, WCONST(0x3829829829829829, 0x38298298));+ /* buf[27] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 27 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, -123456);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 3);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 4);+ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_R2, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_R2, 0);+ /* buf[28] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 28 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, (sljit_sw)(buf + 55) + WCONST(0x634c34c34c34c34c, 0x634c34c3));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_TMP_DEST_REG), -WCONST(0x634c34c34c34c34c, 0x634c34c3));+ /* buf[29] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 29 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, (sljit_sw)(buf + 30) - WCONST(0x7cabcabcabcabcab, 0x7cabcabc));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0x4a30a30a30a30a30, 0x4a30a30a));+ /* buf[30] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_TMP_DEST_REG), WCONST(0x7cabcabcabcabcab, 0x7cabcabc), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, (53 * sizeof(sljit_sw)) >> 2);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_TMP_DEST_REG), 2);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_TMP_DEST_REG), 1);+ /* buf[31] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 31 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, (32 * sizeof(sljit_sw)) >> 2);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0x123456);+ /* buf[32] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_S0, SLJIT_TMP_DEST_REG), 2, SLJIT_R2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, (33 * sizeof(sljit_sw)));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x654321);+ /* buf[33] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_S0, SLJIT_TMP_DEST_REG), 0, SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x58b26f7b);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_TMP_DEST_REG, 0);+ /* buf[34] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 34 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x5e7ce7ce7ce7ce7c, 0x5e7ce7ce));+ jumps[0] = sljit_emit_jump(compiler, SLJIT_REWRITABLE_JUMP | SLJIT_JUMP);+ sljit_set_target(jumps[0], 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM0(), 0);+ labels[0] = sljit_emit_label(compiler);+ /* buf[35] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 35 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x3b41b41b41b41b41, 0x3b41b41b));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 99);+ jumps[1] = sljit_emit_cmp(compiler, SLJIT_REWRITABLE_JUMP | SLJIT_GREATER, SLJIT_TMP_DEST_REG, 0, SLJIT_R0, 0);+ sljit_set_target(jumps[1], 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM0(), 0);+ labels[1] = sljit_emit_label(compiler);+ /* buf[36] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 36 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, (sljit_sw)(buf + 63) - WCONST(0x3209209209209209, 0x32092092));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_TMP_DEST_REG), WCONST(0x3209209209209209, 0x32092092));+ /* buf[37] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 37 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[38] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 38 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ /* Select with SLJIT_TMP_DEST_REG as dst_reg. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, WCONST(0x5f9ef9ef9ef9ef9e, 0x5f9ef9ef));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 0);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_TMP_DEST_REG, 0, SLJIT_R0, 0);+ sljit_emit_select(compiler, SLJIT_GREATER_EQUAL, SLJIT_TMP_DEST_REG, SLJIT_IMM, WCONST(0x130b30b30b30b30b, 0x130b30b3), SLJIT_R3);+ /* buf[39] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 39 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 10);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -10);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER_EQUAL, SLJIT_TMP_DEST_REG, 0, SLJIT_R1, 0);+ sljit_emit_select(compiler, SLJIT_SIG_GREATER_EQUAL, SLJIT_TMP_DEST_REG, SLJIT_IMM, WCONST(0x728c28c28c28c28c, 0x728c28c2), SLJIT_TMP_DEST_REG);+ /* buf[40] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 40 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x574d74d74d74d74d, 0x574d74d7));+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 20);+ sljit_emit_select(compiler, SLJIT_LESS_EQUAL, SLJIT_TMP_DEST_REG, SLJIT_IMM, WCONST(0x6b5fb5fb5fb5fb5f, 0x6b5fb5fb), SLJIT_TMP_DEST_REG);+ /* buf[41] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 41 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x46c86c86c86c86c8, 0x46c86c86));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)(buf + 61) - WCONST(0x6e37e37e37e37e37, 0x6e37e37e));+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS_EQUAL, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 20);+ sljit_emit_select(compiler, SLJIT_SIG_LESS_EQUAL, SLJIT_TMP_DEST_REG, SLJIT_MEM1(SLJIT_R0), WCONST(0x6e37e37e37e37e37, 0x6e37e37e), SLJIT_TMP_DEST_REG);+ /* buf[42] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 42 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, (sljit_sw)(buf + 44) - WCONST(0x5c49c49c49c49c49, 0x5c49c49c));+ sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM1(SLJIT_TMP_DEST_REG), WCONST(0x5c49c49c49c49c49, 0x5c49c49c));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);+ labels[2] = sljit_emit_label(compiler);+ /* buf[43] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 43 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ sljit_set_jump_addr(sljit_get_jump_addr(jumps[0]), sljit_get_label_addr(labels[0]), sljit_get_executable_offset(compiler));+ sljit_set_jump_addr(sljit_get_jump_addr(jumps[1]), sljit_get_label_addr(labels[1]), sljit_get_executable_offset(compiler));++ /* The buf[44] can be overwritten later. */+ buf[44] = (sljit_sw)sljit_get_label_addr(labels[2]);++ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ FAILED(buf[0] != WCONST(0x7890abcdef123456, 0x7890abcd), "test71 case 1 failed\n");+ FAILED(buf[1] != WCONST(0x6786786786786786, 0x67867867), "test71 case 2 failed\n");+ FAILED(buf[2] != WCONST(0x5c78930a47b18f2, 0x5c78930), "test71 case 3 failed\n");+ FAILED(buf[3] != 0x8c93, "test71 case 4 failed\n");+ FAILED(*(sljit_u8*)(buf + 4) != 0xa2, "test71 case 5 failed\n");+ FAILED(*(sljit_s32*)(buf + 5) != -0x1b, "test71 case 6 failed\n");+ FAILED(buf[6] != 0x2eb09fdb, "test71 case 7 failed\n");+ FAILED(buf[7] != 1, "test71 case 8 failed\n");+ FAILED(*(sljit_u16*)(buf + 8) != 0x9f24, "test71 case 9 failed\n");+ FAILED(buf[10] != WCONST(0x5c78930a47b18ef9, 0x5c7892df), "test71 case 10 failed\n");+ FAILED(buf[11] != WCONST(0xf9, 0xdf), "test71 case 11 failed\n");+ FAILED(buf[12] != -0x6b300e8, "test71 case 12 failed\n");+ FAILED(buf[13] != -0x6b302e6, "test71 case 13 failed\n");+ FAILED(buf[14] != WCONST(0x8000000000000000, 0x80000000), "test71 case 14 failed\n");+ FAILED(*(sljit_s32*)(buf + 15) != -0xe0b37ce, "test71 case 15 failed\n");+ FAILED(*(sljit_s32*)(buf + 16) != -0xe0b39cc, "test71 case 16 failed\n");+ FAILED(*(sljit_s32*)(buf + 17) != -1, "test71 case 17 failed\n");+ FAILED(buf[18] != -0x58fbc80, "test71 case 18 failed\n");+ FAILED(buf[19] != 255, "test71 case 19 failed\n");+ FAILED(*(sljit_s32*)(buf + 20) != 100, "test71 case 20 failed\n");+ FAILED(buf[21] != 600, "test71 case 21 failed\n");+ FAILED(buf[22] != WCONST(0x73b18cd05fa29bc7, 0x73b18cd0), "test71 case 22 failed\n");+ FAILED(buf[23] != WCONST(0xa8d18d18d18d18d1, 0xa8d18d18), "test71 case 23 failed\n");+ FAILED(buf[24] != WCONST(0x73b18cd05fa29bc7, 0x73b18cd0), "test71 case 24 failed\n");+ FAILED(buf[25] != -0x2e33, "test71 case 25 failed\n");+ FAILED(buf[26] != WCONST(0x3e4dc6212d7910fc, 0x3a4af020), "test71 case 26 failed\n");+ FAILED(buf[27] != WCONST(0x4032c4ae5cb54cc4, 0xdedc61f0), "test71 case 27 failed\n");+ FAILED(buf[28] != -123468, "test71 case 28 failed\n");+ FAILED(buf[29] != WCONST(0x73b18cd05fa29bc7, 0x73b18cd0), "test71 case 29 failed\n");+ FAILED(buf[30] != WCONST(0x4a30a30a30a30a30, 0x4a30a30a), "test71 case 30 failed\n");+ FAILED(buf[31] != WCONST(0x5c78930a47b18f24, 0x5c78930a), "test71 case 31 failed\n");+ FAILED(buf[32] != 0x123456, "test71 case 32 failed\n");+ FAILED(buf[33] != 0x654321, "test71 case 33 failed\n");+ FAILED(buf[34] != 0x58b26f7b, "test71 case 34 failed\n");+ FAILED(buf[35] != WCONST(0x5e7ce7ce7ce7ce7c, 0x5e7ce7ce), "test71 case 35 failed\n");+ FAILED(buf[36] != WCONST(0x3b41b41b41b41b41, 0x3b41b41b), "test71 case 36 failed\n");+ FAILED(buf[37] != (sljit_sw)&buf, "test71 case 37 failed\n");+ FAILED(buf[38] != (sljit_sw)(buf + 63) - WCONST(0x3209209209209209, 0x32092092), "test71 case 38 failed\n");+ FAILED(buf[39] != WCONST(0x5f9ef9ef9ef9ef9e, 0x5f9ef9ef), "test71 case 39 failed\n");+ FAILED(buf[40] != WCONST(0x728c28c28c28c28c, 0x728c28c2), "test71 case 40 failed\n");+ FAILED(buf[41] != WCONST(0x574d74d74d74d74d, 0x574d74d7), "test71 case 41 failed\n");+ FAILED(buf[42] != WCONST(0x46c86c86c86c86c8, 0x46c86c86), "test71 case 42 failed\n");+ FAILED(buf[43] != (sljit_sw)(buf + 44) - WCONST(0x5c49c49c49c49c49, 0x5c49c49c), "test71 case 43 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test72(void)+{+ /* Test accessing named temporary registers. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_label *label;+ sljit_uw addr, prev_addr;+ sljit_uw id;++ if (verbose)+ printf("Run test72\n");++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_label(compiler);+ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 3, 3, 2 * sizeof(sljit_sw));++ sljit_emit_label(compiler);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 76);+ sljit_emit_label(compiler);+ sljit_emit_label(compiler);+ sljit_emit_label(compiler);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S0, 0);+ sljit_emit_label(compiler);++ sljit_emit_return_void(compiler);+ sljit_emit_label(compiler);++ label = sljit_get_first_label(compiler);++ id = 0;+ while (label != NULL) {+ SLJIT_ASSERT(sljit_get_label_index(label) == id++);+ label = sljit_get_next_label(label);+ }+ SLJIT_ASSERT(id == 5);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ label = sljit_get_first_label(compiler);++ id = 0;+ prev_addr = 0;+ while (label != NULL) {+ addr = sljit_get_label_addr(label);+ SLJIT_ASSERT(prev_addr < addr && addr >= 1024);++ prev_addr = addr;+ id++;+ label = sljit_get_next_label(label);+ }+ SLJIT_ASSERT(id == 5);++ sljit_free_compiler(compiler);+ sljit_free_code(code.code, NULL);++ if (id == 5 && prev_addr > 0)+ successful_tests++;+}++static void test73(void)+{+ /* Test muladd fusion. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[12];+ sljit_s32 ibuf[12];+ sljit_s32 i;++ if (verbose)+ printf("Run test73\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 12; i++)+ buf[i] = 0;+ for (i = 0; i < 12; i++)+ ibuf[i] = 0;+ buf[1] = WCONST(0x476c76c76c76c7, 0x476c76);+ buf[2] = 5;+ ibuf[0] = 67433;+ ibuf[1] = 47853;+ ibuf[2] = 0x5a73a73a;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(P, P), 5, 5, 2 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 67);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 3456);+ sljit_emit_op2r(compiler, SLJIT_MULADD, SLJIT_R1, SLJIT_R0, 0, SLJIT_IMM, 53);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, 92456);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, 364034);+ sljit_emit_op2r(compiler, SLJIT_MULADD32, SLJIT_R4, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S1), 0);+ /* ibuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R4, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, WCONST(0x691d91d91d91d9, 0x691d91));+ sljit_emit_op2r(compiler, SLJIT_MULADD, SLJIT_S2, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_S0, SLJIT_R1), 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_S2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 1234);+ sljit_emit_op2r(compiler, SLJIT_MULADD, SLJIT_R3, SLJIT_IMM, WCONST(0x68a78a78a78a78, 0x68a78a), SLJIT_IMM, WCONST(0x5b6cb6cb6cb6cb, 0x5b6cb6));+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R3, 0, SLJIT_IMM, 45671);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 57340);+ sljit_emit_op2r(compiler, SLJIT_MULADD32, SLJIT_R1, SLJIT_R3, 0, SLJIT_MEM0(), (sljit_sw)(ibuf + 1));+ /* ibuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, -907);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -9675);+ sljit_emit_op2r(compiler, SLJIT_MULADD, SLJIT_R2, SLJIT_IMM, 781, SLJIT_MEM1(SLJIT_SP), 0);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)(ibuf + 2) + WCONST(0x685e85e85e85e85e, 0x685e85e8));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, (sljit_sw)(ibuf + 2) - WCONST(0x7f23f23f23f23f23, 0x7f23f23f));+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0x45b30c14);+ sljit_emit_op2r(compiler, SLJIT_MULADD32, SLJIT_R0, SLJIT_MEM1(SLJIT_R2), -WCONST(0x685e85e85e85e85e, 0x685e85e8), SLJIT_MEM1(SLJIT_S2), WCONST(0x7f23f23f23f23f23, 0x7f23f23f));+ /* ibuf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 624);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 912);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 540);+ sljit_emit_op2r(compiler, SLJIT_MULADD, SLJIT_S2, SLJIT_R0, 0, SLJIT_R1, 0);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_S2, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)&buf, (sljit_sw)&ibuf);++ FAILED(buf[0] != 7007, "test73 case 1 failed\n");+ FAILED(ibuf[0] != 1939982186, "test73 case 2 failed\n");+ FAILED(buf[1] != WCONST(0x1ce3be3be3be3bc, 0x1ce3bdf), "test73 case 3 failed\n");+ FAILED(buf[2] != WCONST(0xe4601f605bec21fa, 0xff2358ee), "test73 case 4 failed\n");+ FAILED(ibuf[1] != -2109415593, "test73 case 5 failed\n");+ FAILED(buf[3] != -718042, "test73 case 6 failed\n");+ FAILED(ibuf[2] != (sljit_s32)0xb90bc538, "test73 case 7 failed\n");+ FAILED(buf[4] != 569628, "test73 case 8 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test74(void)+{+ /* Test binary operations with named temporary registers. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[64];+ sljit_s32 i;+ struct sljit_jump* jump;++ if (verbose)+ printf("Run test74\n");++ for (i = 0; i < 64; i++)+ buf[i] = -1;++ buf[63] = WCONST(0xabcdef123456789, 0xabcdef1);+ buf[62] = WCONST(0x5678905678905678, 0x56789056);++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 5, 5, 2 * sizeof(sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x467e67e67e67e67e, 0x467e67e6));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0x1234567812345678, 0x12345678));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0x987654321fedcba, 0x1fedcba));+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_R1, 0, SLJIT_IMM, WCONST(0x1512512512512512, 0x15125125));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(buf + 63) + WCONST(0x4b6ab6ab6ab6ab6a, 0x4b6ab6ab));+ sljit_emit_op2(compiler, SLJIT_AND, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R1), -WCONST(0x4b6ab6ab6ab6ab6a, 0x4b6ab6ab));+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R2, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x3c29c29c29c29c29, 0x3c29c29c));+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x1234561234561234, 0x12345612));+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0xef12345678ef1234, 0xef123456));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(buf + 62) - WCONST(0x760d60d60d60d60d, 0x760d60d6));+ sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_R1), WCONST(0x760d60d60d60d60d, 0x760d60d6));+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);+ /* buf[5] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_CARRY);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x7b52b52b52b52b52, 0x7b52b52b));+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_S2, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x1594594594594594, 0x15945945));+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_S2, 0);+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);+ /* buf[8] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_LESS);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x253a53a53a53a53a, 0x253a53a5));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0xffff);+ /* Only SUB and AND supported for op2u. */+ sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_IMM, WCONST(0x3d4ed4ed4ed4ed4e, 0x3d4ed4ed));+ /* Not all target registers are supported. */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_NOT_ZERO);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R1, 0, SLJIT_IMM, WCONST(0x3d4ed4ed4ed4ed4e, 0x3d4ed4ed));+ /* buf[9] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);+ /* buf[10] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[11] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_SIG_GREATER);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x6b4cb4cb4cb4cb4c, 0x6b4cb4cb));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 13);+ jump = sljit_emit_cmp(compiler, SLJIT_LESS, SLJIT_R0, 0, SLJIT_IMM, WCONST(0x50e80e80e80e80e8, 0x50e80e80));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);+ sljit_set_label(jump, sljit_emit_label(compiler));+ /* buf[12] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x4752752752752752, 0x47527527));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(buf + 63) - WCONST(0x29d19d19d19d19d1, 0x29d19d19));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -13);+ jump = sljit_emit_cmp(compiler, SLJIT_GREATER, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_R1), WCONST(0x29d19d19d19d19d1, 0x29d19d19));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);+ sljit_set_label(jump, sljit_emit_label(compiler));+ /* buf[13] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x53c43c43c43c43c4, 0x53c43c43));+ jump = sljit_emit_cmp(compiler, SLJIT_GREATER, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x26f16f16f16f16f1, 0x26f16f16));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);+ sljit_set_label(jump, sljit_emit_label(compiler));+ /* buf[14] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x5f82f82f82f82f82, 0x5f82f82f));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, (sljit_sw)(buf + 62) + WCONST(0x2b64b64b64b64b64, 0x2b64b64b));+ jump = sljit_emit_cmp(compiler, SLJIT_SIG_GREATER, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_S2), -WCONST(0x2b64b64b64b64b64, 0x2b64b64b));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);+ sljit_set_label(jump, sljit_emit_label(compiler));+ /* buf[15] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x7c29c29c29c29c29, 0x7c29c29c));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0xffff00);+ /* Only SUB and AND supported for op2u. */+ sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_IMM, 12);+ /* Not all target registers are supported. */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_NOT_ZERO);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R1, 0, SLJIT_IMM, 12);+ /* buf[16] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);+ /* buf[17] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[18] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_sw), SLJIT_LESS);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);++ FAILED(buf[0] != WCONST(0x2746a79d24857b8a, 0x2746a79d), "test74 case 1 failed\n");+ FAILED(buf[1] != WCONST(0x884444121444488, 0xbcdcb0), "test74 case 2 failed\n");+ FAILED(buf[2] != WCONST(0x467e67e67e67e67e, 0x467e67e6), "test74 case 3 failed\n");+ FAILED(buf[3] != WCONST(0x29f56c89f56c89f5, 0x29f56c8a), "test74 case 4 failed\n");+ FAILED(buf[4] != WCONST(0x458ac4acf17f68ac, 0x458ac4ac), "test74 case 5 failed\n");+ FAILED(buf[5] != 1, "test74 case 6 failed\n");+ FAILED(buf[6] != WCONST(0x65be5be5be5be5be, 0x65be5be6), "test74 case 7 failed\n");+ FAILED(buf[7] != WCONST(0x7b52b52b52b52b52, 0x7b52b52b), "test74 case 8 failed\n");+ FAILED(buf[8] != 0, "test74 case 9 failed\n");+ FAILED(buf[9] != WCONST(0x253a53a53a53a53a, 0x253a53a5), "test74 case 10 failed\n");+ FAILED(buf[10] != 1, "test74 case 11 failed\n");+ FAILED(buf[11] != 0, "test74 case 12 failed\n");+ FAILED(buf[12] != WCONST(0x6b4cb4cb4cb4cb4c, 0x6b4cb4cb), "test74 case 13 failed\n");+ FAILED(buf[13] != WCONST(0x4752752752752752, 0x47527527), "test74 case 14 failed\n");+ FAILED(buf[14] != WCONST(0x53c43c43c43c43c4, 0x53c43c43), "test74 case 15 failed\n");+ FAILED(buf[15] != WCONST(0x5f82f82f82f82f82, 0x5f82f82f), "test74 case 16 failed\n");+ FAILED(buf[16] != WCONST(0x7c29c29c29c29c29, 0x7c29c29c), "test74 case 17 failed\n");+ FAILED(buf[17] != 0, "test74 case 18 failed\n");+ FAILED(buf[18] != 0, "test74 case 18 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test75(void)+{+ /* Test atomic load and store with SLJIT_TMP_DEST_REG. */+ executable_code code;+ struct sljit_compiler *compiler;+ struct sljit_label *label;+ sljit_u8 supported[2];+ sljit_sw buf[23];+ sljit_s32 i;++ if (verbose)+ printf("Run test75\n");++ if (!sljit_has_cpu_feature(SLJIT_HAS_ATOMIC)) {+ if (verbose)+ printf("no fine-grained atomic available, test75 skipped\n");+ successful_tests++;+ return;+ }++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ for (i = 1; i < 23; i++)+ buf[i] = WCONST(0x5555555555555555, 0x55555555);++ buf[0] = -38967;+ buf[3] = 18076;+ buf[7] = -57392;+ buf[11] = 60197;+ buf[15] = 28516;+ buf[19] = -43752;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 5, 5, 2 * sizeof(sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0);+ supported[0] = sljit_emit_atomic_load(compiler, SLJIT_MOV | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_TEST, SLJIT_R0, SLJIT_R1) != SLJIT_ERR_UNSUPPORTED;+ SLJIT_ASSERT(supported[0] == (sljit_emit_atomic_store(compiler, SLJIT_MOV | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_TEST, SLJIT_R0, SLJIT_R1, SLJIT_R2) != SLJIT_ERR_UNSUPPORTED));+ supported[1] = sljit_emit_atomic_load(compiler, SLJIT_MOV | SLJIT_ATOMIC_USE_LS | SLJIT_ATOMIC_TEST, SLJIT_R0, SLJIT_R1) != SLJIT_ERR_UNSUPPORTED;+ SLJIT_ASSERT(supported[1] == (sljit_emit_atomic_store(compiler, SLJIT_MOV | SLJIT_ATOMIC_USE_LS | SLJIT_ATOMIC_TEST, SLJIT_R0, SLJIT_R1, SLJIT_R2) != SLJIT_ERR_UNSUPPORTED));++ label = sljit_emit_label(compiler);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 11111);+ sljit_emit_atomic_load(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, SLJIT_S0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 56892);+ /* buf[0] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV | SLJIT_SET_ATOMIC_STORED, SLJIT_R1, SLJIT_S0, SLJIT_TMP_DEST_REG);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 22222);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S1, 0, SLJIT_S0, 0, SLJIT_IMM, 3 * sizeof(sljit_sw));+ label = sljit_emit_label(compiler);+ sljit_emit_atomic_load(compiler, SLJIT_MOV, SLJIT_R4, SLJIT_S1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, -33271);+ /* buf[3] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV | SLJIT_SET_ATOMIC_STORED, SLJIT_TMP_DEST_REG, SLJIT_S1, SLJIT_R4);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R4, 0);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 33333);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 7 * sizeof(sljit_sw));+ sljit_emit_atomic_load(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, SLJIT_R1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, 26920);+ /* buf[7] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV | SLJIT_SET_ATOMIC_STORED, SLJIT_S3, SLJIT_R1, SLJIT_TMP_DEST_REG);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);+ /* buf[9] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_S3, 0);+ /* buf[10] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 44444);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S0, 0, SLJIT_IMM, 11 * sizeof(sljit_sw));+ sljit_emit_atomic_load(compiler, SLJIT_MOV, SLJIT_R1, SLJIT_R2);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, -28715);+ /* buf[11] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV | SLJIT_SET_ATOMIC_STORED, SLJIT_TMP_DEST_REG, SLJIT_R2, SLJIT_R1);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[12] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);+ /* buf[13] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_R1, 0);+ /* buf[14] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_R0, 0);++ if (supported[0]) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 15 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 28516);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -40591);+ /* buf[15] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV | SLJIT_ATOMIC_USE_CAS | SLJIT_SET_ATOMIC_STORED, SLJIT_R2, SLJIT_R0, SLJIT_R1);+ /* buf[16] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_R2, 0);+ /* buf[17] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_sw), SLJIT_R1, 0);+ /* buf[18] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_sw), SLJIT_R0, 0);+ }++ if (supported[1]) {+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 19 * sizeof(sljit_sw));+ sljit_emit_atomic_load(compiler, SLJIT_MOV | SLJIT_ATOMIC_USE_LS, SLJIT_S1, SLJIT_R0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 38021);+ /* buf[19] */+ sljit_emit_atomic_store(compiler, SLJIT_MOV | SLJIT_ATOMIC_USE_LS | SLJIT_SET_ATOMIC_STORED, SLJIT_S2, SLJIT_R0, SLJIT_S1);+ sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);+ /* buf[20] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 20 * sizeof(sljit_sw), SLJIT_S2, 0);+ /* buf[21] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 21 * sizeof(sljit_sw), SLJIT_S1, 0);+ /* buf[22] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 22 * sizeof(sljit_sw), SLJIT_R0, 0);+ }++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);++ FAILED(buf[0] != 56892, "test75 case 1 failed\n");+ FAILED(buf[1] != -38967, "test75 case 2 failed\n");+ FAILED(buf[2] != 11111, "test75 case 3 failed\n");+ FAILED(buf[3] != -33271, "test75 case 4 failed\n");+ FAILED(buf[4] != -33271, "test75 case 5 failed\n");+ FAILED(buf[5] != 18076, "test75 case 6 failed\n");+ FAILED(buf[6] != 22222, "test75 case 7 failed\n");+ FAILED(buf[7] != 26920, "test75 case 8 failed\n");+ FAILED(buf[8] != -57392, "test75 case 9 failed\n");+ FAILED(buf[9] != 26920, "test75 case 10 failed\n");+ FAILED(buf[10] != 33333, "test75 case 11 failed\n");+ FAILED(buf[11] != -28715, "test75 case 12 failed\n");+ FAILED(buf[12] != -28715, "test75 case 13 failed\n");+ FAILED(buf[13] != 60197, "test75 case 14 failed\n");+ FAILED(buf[14] != 44444, "test75 case 15 failed\n");++ if (supported[0]) {+ FAILED(buf[15] != -40591, "test75 case 16 failed\n");+ FAILED(buf[16] != -40591, "test75 case 17 failed\n");+ FAILED(buf[17] != 28516, "test75 case 18 failed\n");+ FAILED(buf[18] != (sljit_sw)(buf + 15), "test75 case 19 failed\n");+ }++ if (supported[1]) {+ FAILED(buf[19] != 38021, "test75 case 20 failed\n");+ FAILED(buf[20] != 38021, "test75 case 21 failed\n");+ FAILED(buf[21] != -43752, "test75 case 22 failed\n");+ FAILED(buf[22] != (sljit_sw)(buf + 19), "test75 case 23 failed\n");+ }++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test76(void)+{+ /* Test atomic load and store with SLJIT_TMP_DEST_REG. */+ executable_code code;+ struct sljit_compiler *compiler = sljit_create_compiler(NULL);+ sljit_sw buf[6];++ if (verbose)+ printf("Run test76\n");++ FAILED(!compiler, "cannot create compiler\n");++ buf[0] = 0;+ buf[1] = 0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 3, 3, 0);++#if IS_64BIT+#if (defined SLJIT_UPPER_BITS_IGNORED && SLJIT_UPPER_BITS_IGNORED)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x123456fdf08a71));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x12000003e8));+ sljit_emit_op0(compiler, SLJIT_DIVMOD_SW);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x123456fdf08a71));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x12000003e8));+ sljit_emit_op0(compiler, SLJIT_DIVMOD_S32);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R1, 0);+#endif /* SLJIT_UPPER_BITS_IGNORED */+#if (defined SLJIT_UPPER_BITS_ZERO_EXTENDED && SLJIT_UPPER_BITS_ZERO_EXTENDED)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 123456789);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 234567890);+ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 123456789);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 234567890);+ sljit_emit_op2(compiler, SLJIT_MUL32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R0, 0);+#endif /* SLJIT_UPPER_BITS_ZERO_EXTENDED */+#if (defined SLJIT_UPPER_BITS_SIGN_EXTENDED && SLJIT_UPPER_BITS_SIGN_EXTENDED)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -123456789);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 234567890);+ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, -123456789);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 234567890);+ sljit_emit_op2(compiler, SLJIT_MUL32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R0, 0);+#endif /* SLJIT_UPPER_BITS_SIGN_EXTENDED */+#if (defined SLJIT_UPPER_BITS_PRESERVED && SLJIT_UPPER_BITS_PRESERVED)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x12345678f8a432eb) /* -123456789 */);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 234567890);+ sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x12345678f8a432eb) /* -123456789 */);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 234567890);+ sljit_emit_op2(compiler, SLJIT_MUL32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R0, 0);+#endif /* SLJIT_UPPER_BITS_PRESERVED */+#endif /* IS_64BIT */++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);++#if IS_64BIT+#if (defined SLJIT_UPPER_BITS_IGNORED && SLJIT_UPPER_BITS_IGNORED)+ FAILED(buf[0] != 66280, "test76 case 1 failed\n");+ FAILED(buf[1] != SLJIT_W(29963923505), "test76 case 2 failed\n");+ FAILED(*(sljit_s32*)(buf + 2) != -34567, "test76 case 3 failed\n");+ FAILED(*(sljit_s32*)(buf + 3) != -567, "test76 case 4 failed\n");+#endif /* SLJIT_UPPER_BITS_IGNORED */+#if (defined SLJIT_UPPER_BITS_ZERO_EXTENDED && SLJIT_UPPER_BITS_ZERO_EXTENDED)+ FAILED(buf[4] != SLJIT_W(28958998501905210), "test76 case 5 failed\n");+ FAILED(buf[5] != 1119998778, "test76 case 6 failed\n");+#endif /* SLJIT_UPPER_BITS_ZERO_EXTENDED */+#if (defined SLJIT_UPPER_BITS_SIGN_EXTENDED && SLJIT_UPPER_BITS_SIGN_EXTENDED)+ FAILED(buf[4] != SLJIT_W(-28958998501905210), "test76 case 7 failed\n");+ FAILED(buf[5] != -1119998778, "test76 case 8 failed\n");+#endif /* SLJIT_UPPER_BITS_SIGN_EXTENDED */+#if (defined SLJIT_UPPER_BITS_PRESERVED && SLJIT_UPPER_BITS_PRESERVED)+ FAILED(buf[4] != SLJIT_W(5698607360772025542), "test76 case 9 failed\n");+ FAILED(buf[5] != SLJIT_W(0x12345678bd3e2cc6), "test76 case 10 failed\n");+#endif /* SLJIT_UPPER_BITS_PRESERVED */+#endif /* IS_64BIT */++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test77(void)+{+ /* Test op2cmp operation. */+ executable_code code;+ struct sljit_compiler *compiler = sljit_create_compiler(NULL);+ struct sljit_jump *jump;+ struct sljit_label *label;+ sljit_sw executable_offset;+ sljit_uw jump_addr, label_addr;+ sljit_s32 i;+ sljit_sw buf[28];++ if (verbose)+ printf("Run test77\n");++ for (i = 0; i < 28; i++)+ buf[i] = -1;++ buf[8] = 0xff00ff;++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 5, 5, 2 * sizeof(sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1234);+ jump = sljit_emit_op2cmpz(compiler, SLJIT_SUB | SLJIT_JUMP_IF_ZERO, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 3);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);+ sljit_set_label(jump, sljit_emit_label(compiler));++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 1);+ jump = sljit_emit_op2cmpz(compiler, SLJIT_SUB32 | SLJIT_JUMP_IF_NON_ZERO, SLJIT_S1, 0, SLJIT_R1, 0, SLJIT_IMM, 12345);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);+ sljit_set_label(jump, sljit_emit_label(compiler));+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R1, 0);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_S1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, -100);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_IMM, 100);+ /* buf[3] */+ jump = sljit_emit_op2cmpz(compiler, SLJIT_ADD | SLJIT_JUMP_IF_ZERO, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);+ sljit_set_label(jump, sljit_emit_label(compiler));++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_S4, 0, SLJIT_IMM, 4321);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, -4321);+ /* Default: SLJIT_JUMP_IF_NON_ZERO */+ jump = sljit_emit_op2cmpz(compiler, SLJIT_ADD32, SLJIT_R0, 0, SLJIT_S4, 0, SLJIT_R4, 0);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_S4, 0);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R4, 0);+ sljit_set_label(jump, sljit_emit_label(compiler));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (7 * sizeof(sljit_sw)) >> 2);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (8 * sizeof(sljit_sw)) >> 2);+ /* buf[7] */+ jump = sljit_emit_op2cmpz(compiler, SLJIT_AND | SLJIT_JUMP_IF_ZERO, SLJIT_MEM2(SLJIT_S0, SLJIT_R1), 2, SLJIT_IMM, 0x0f0f0f, SLJIT_MEM2(SLJIT_S0, SLJIT_R2), 2);+ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R1, 0);+ /* buf[9] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R2, 0);+ sljit_set_label(jump, sljit_emit_label(compiler));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (10 * sizeof(sljit_sw)) >> 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, 0x0f0f0f);+ /* buf[11] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_IMM, 0xff00ff);+ /* Default: SLJIT_JUMP_IF_NON_ZERO */+ /* buf[10] */+ jump = sljit_emit_op2cmpz(compiler, SLJIT_OR32, SLJIT_MEM2(SLJIT_R2, SLJIT_S1), 1, SLJIT_MEM1(SLJIT_R2), 11 * sizeof(sljit_sw), SLJIT_R4, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);+ sljit_set_label(jump, sljit_emit_label(compiler));+ /* buf[12] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_R4, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -0x1234);+ jump = sljit_emit_op2cmpz(compiler, SLJIT_SHL | SLJIT_JUMP_IF_ZERO, SLJIT_TMP_DEST_REG, 0, SLJIT_R2, 0, SLJIT_IMM, 4);+ /* buf[13] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);+ /* buf[14] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_R2, 0);+ sljit_set_label(jump, sljit_emit_label(compiler));++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 0x1234);+ jump = sljit_emit_op2cmpz(compiler, SLJIT_ASHR32 | SLJIT_JUMP_IF_NON_ZERO, SLJIT_R1, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 4);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);+ sljit_set_label(jump, sljit_emit_label(compiler));+ /* buf[15] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_R1, 0);+ /* buf[16] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0xff0000);+ /* buf[17] */+ jump = sljit_emit_op2cmpz(compiler, SLJIT_AND | SLJIT_JUMP_IF_ZERO, SLJIT_MEM0(), (sljit_sw)(buf + 17), SLJIT_R1, 0, SLJIT_IMM, 0xffff);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);+ sljit_set_label(jump, sljit_emit_label(compiler));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -10);+ jump = sljit_emit_op2cmpz(compiler, SLJIT_ADD | SLJIT_SET_CARRY | SLJIT_JUMP_IF_ZERO, SLJIT_R1, 0, SLJIT_R2, 0, SLJIT_IMM, 20);+ /* buf[18] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_sw), SLJIT_R1, 0);+ /* buf[19] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 19 * sizeof(sljit_sw), SLJIT_CARRY);+ sljit_set_label(jump, sljit_emit_label(compiler));++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_S3, 0, SLJIT_IMM, 0x7fffffff);+ jump = sljit_emit_op2cmpz(compiler, SLJIT_SUB32 | SLJIT_SET_OVERFLOW | SLJIT_JUMP_IF_NON_ZERO | SLJIT_REWRITABLE_JUMP, SLJIT_S3, 0, SLJIT_S3, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);+ sljit_set_label(jump, sljit_emit_label(compiler));+ /* buf[20] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 20 * sizeof(sljit_sw), SLJIT_S3, 0);+ sljit_set_current_flags(compiler, SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_32 | SLJIT_CURRENT_FLAGS_OP2CMPZ | SLJIT_SET_OVERFLOW);+ /* buf[21] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 21 * sizeof(sljit_sw), SLJIT_OVERFLOW);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 21);+ label = sljit_emit_label(compiler);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1);+ /* Default: SLJIT_JUMP_IF_NON_ZERO */+ sljit_set_label(sljit_emit_op2cmpz(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1), label);+ /* buf[22] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 22 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[23] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 23 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, -(sljit_sw)sizeof(sljit_sw) * 17);+ label = sljit_emit_label(compiler);+ sljit_emit_op2(compiler, SLJIT_ADD32, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);+ /* Default: SLJIT_JUMP_IF_NON_ZERO */+ sljit_set_label(sljit_emit_op2cmpz(compiler, SLJIT_ADD32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_sw)), label);+ /* buf[24] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 24 * sizeof(sljit_sw), SLJIT_R1, 0);+ /* buf[25] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 25 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 12345);+ jump = sljit_emit_op2cmpz(compiler, SLJIT_SUB | SLJIT_SET_LESS | SLJIT_JUMP_IF_NON_ZERO | SLJIT_REWRITABLE_JUMP, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, 2345);+ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);+ label = sljit_emit_label(compiler);+ /* buf[26] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 26 * sizeof(sljit_sw), SLJIT_S1, 0);+ sljit_set_current_flags(compiler, SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_OP2CMPZ | SLJIT_SET_LESS);+ /* buf[27] */+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 27 * sizeof(sljit_sw), SLJIT_LESS);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ executable_offset = sljit_get_executable_offset(compiler);+ jump_addr = sljit_get_jump_addr(jump);+ label_addr = sljit_get_label_addr(label);+ sljit_free_compiler(compiler);++ sljit_set_jump_addr(jump_addr, label_addr, executable_offset);++ code.func1((sljit_sw)&buf);++ FAILED(buf[0] != 1231, "test77 case 1 failed\n");+ FAILED(*(sljit_s32*)(buf + 1) != 1, "test77 case 2 failed\n");+ FAILED(*(sljit_s32*)(buf + 2) != -12344, "test77 case 3 failed\n");+ FAILED(buf[3] != 0, "test77 case 4 failed\n");+ FAILED(*(sljit_s32*)(buf + 4) != 0, "test77 case 5 failed\n");+ FAILED(*(sljit_s32*)(buf + 5) != 4321, "test77 case 6 failed\n");+ FAILED(*(sljit_s32*)(buf + 6) != -4321, "test77 case 7 failed\n");+ FAILED(buf[7] != 0xf000f, "test77 case 8 failed\n");+ FAILED(buf[8] != (7 * sizeof(sljit_sw)) >> 2, "test77 case 9 failed\n");+ FAILED(buf[9] != (8 * sizeof(sljit_sw)) >> 2, "test77 case 10 failed\n");+ FAILED(*(sljit_s32*)(buf + 10) != 0xff0fff, "test77 case 11 failed\n");+ FAILED(*(sljit_s32*)(buf + 11) != 0xff00ff, "test77 case 12 failed\n");+ FAILED(*(sljit_s32*)(buf + 12) != 0x0f0f0f, "test77 case 13 failed\n");+ FAILED(buf[13] != -0x12340, "test77 case 14 failed\n");+ FAILED(buf[14] != -0x1234, "test77 case 15 failed\n");+ FAILED(*(sljit_s32*)(buf + 15) != 0x123, "test77 case 16 failed\n");+ FAILED(*(sljit_s32*)(buf + 16) != 0x1234, "test77 case 17 failed\n");+ FAILED(buf[17] != 0, "test77 case 18 failed\n");+ FAILED(buf[18] != 10, "test77 case 19 failed\n");+ FAILED(buf[19] != 1, "test77 case 20 failed\n");+ FAILED(*(sljit_s32*)(buf + 20) != (sljit_s32)0x80000000, "test77 case 21 failed\n");+ FAILED(buf[21] != 1, "test77 case 22 failed\n");+ FAILED(buf[22] != 21, "test77 case 23 failed\n");+ FAILED(buf[23] != 0, "test77 case 24 failed\n");+ FAILED(*(sljit_s32*)(buf + 24) != 17, "test77 case 25 failed\n");+ FAILED(*(sljit_s32*)(buf + 25) != 0, "test77 case 26 failed\n");+ FAILED(buf[26] != 10000, "test77 case 27 failed\n");+ FAILED(buf[27] != 0, "test77 case 28 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test78(void)+{+ /* Test op2cmp operation. */+ executable_code code;+ struct sljit_compiler *compiler = sljit_create_compiler(NULL);+ sljit_sw executable_offset;+ sljit_s32 i;+ struct sljit_const *consts[11];+ sljit_uw const_addr[11];+ sljit_sw buf[11];++ if (verbose)+ printf("Run test78\n");++ for (i = 0; i < 11; i++)+ buf[i] = -1;++#if IS_64BIT+ buf[10] = (sljit_sw)SLJIT_W(0xaaaaaaaaaaaaaaaa);+#endif /* IS_64BIT */++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 5, 5, 2 * sizeof(sljit_sw));++ consts[0] = sljit_emit_const(compiler, SLJIT_MOV_S32, SLJIT_S1, 0, WCONST(0xffff123456, 0xff123456));+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_S1, 0);++ /* buf[1] */+ consts[1] = sljit_emit_const(compiler, SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), WCONST(0xffabcdef01, 0xabcdef01));++ consts[2] = sljit_emit_const(compiler, SLJIT_MOV32, SLJIT_R1, 0, WCONST(0xff1234567f, 0x1234567f));+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R1, 0);++ consts[3] = sljit_emit_const(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), WCONST(0xffedcba987, 0xedcba987));+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32));++ consts[4] = sljit_emit_const(compiler, SLJIT_MOV_U8, SLJIT_TMP_DEST_REG, 0, 0xaaaafe);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ consts[5] = sljit_emit_const(compiler, SLJIT_MOV32_U8, SLJIT_S4, 0, 0xaaab14);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_S4, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (6 * sizeof(sljit_sw)) >> 1);++ /* buf[6] */+ consts[6] = sljit_emit_const(compiler, SLJIT_MOV_U8, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), (1), 0xaaaac2);++ consts[7] = sljit_emit_const(compiler, SLJIT_MOV_U8, SLJIT_R4, 0, 0xaaaaff);+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R4, 0);++ consts[8] = sljit_emit_const(compiler, SLJIT_MOV32_U8, SLJIT_R0, 0, 0xaaab00);+ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R0, 0);++ /* buf[9] */+ consts[9] = sljit_emit_const(compiler, SLJIT_MOV32_U8, SLJIT_MEM0(), (sljit_sw)(buf + 9), 0xaaaaa0);++ /* buf[10] */+ consts[10] = sljit_emit_const(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), WCONST(0xcc12345678, 0x12345678));++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ executable_offset = sljit_get_executable_offset(compiler);+ for (i = 0; i < 11; i++)+ const_addr[i] = sljit_get_const_addr(consts[i]);++ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);++ FAILED(buf[0] != (sljit_s32)0xff123456, "test78 case 1 failed\n");+ FAILED(buf[1] != (sljit_s32)0xabcdef01, "test78 case 2 failed\n");+ FAILED(*(sljit_s32*)(buf + 2) != (sljit_s32)0x1234567f, "test78 case 3 failed\n");+ FAILED(*(sljit_s32*)(buf + 3) != (sljit_s32)0xedcba987, "test78 case 4 failed\n");+ FAILED(buf[4] != 0xfe, "test78 case 5 failed\n");+ FAILED(*(sljit_s32*)(buf + 5) != -0xec, "test78 case 6 failed\n");+ FAILED(*(sljit_u16*)(buf + 6) != LITTLE_BIG(0xffc2, 0xc2ff), "test78 case 7 failed\n");+ FAILED(buf[7] != 0xff, "test78 case 8 failed\n");+ FAILED(*(sljit_s32*)(buf + 8) != -0x100, "test78 case 9 failed\n");+ FAILED(*(sljit_u16*)(buf + 9) != LITTLE_BIG(0xffa0, 0xa0ff), "test78 case 10 failed\n");+#if IS_64BIT+ FAILED(buf[10] != (sljit_sw)LITTLE_BIG(SLJIT_W(0xaaaaaaaa12345678), SLJIT_W(0x12345678aaaaaaaa)), "test78 case 11 failed\n");+#else /* !IS_64BIT */+ FAILED(buf[10] != (sljit_sw)0x12345678, "test78 case 11 failed\n");+#endif /* IS_64BIT */++ sljit_set_const(const_addr[0], SLJIT_MOV_S32, WCONST(0xffff654321, 0xff654321), executable_offset);+ sljit_set_const(const_addr[1], SLJIT_MOV_S32, WCONST(0xff01fedcba, 0x01fedcba), executable_offset);+ sljit_set_const(const_addr[2], SLJIT_MOV32, WCONST(0xfff7654321, 0xf7654321), executable_offset);+ sljit_set_const(const_addr[3], SLJIT_MOV32, WCONST(0xff789abcde, 0x789abcde), executable_offset);+ sljit_set_const(const_addr[4], SLJIT_MOV_U8, 0xbbbeff, executable_offset);+ sljit_set_const(const_addr[5], SLJIT_MOV32_U8, 0xbbb100, executable_offset);+ sljit_set_const(const_addr[6], SLJIT_MOV_U8, 0xaaaa93, executable_offset);+ sljit_set_const(const_addr[7], SLJIT_MOV_U8, 0xbbbf39, executable_offset);+ sljit_set_const(const_addr[8], SLJIT_MOV32_U8, 0xaaaa6c, executable_offset);+ sljit_set_const(const_addr[9], SLJIT_MOV32_U8, 0xaaaa53, executable_offset);+ sljit_set_const(const_addr[10], SLJIT_MOV32, WCONST(0xee87654321, 0x87654321), executable_offset);++ code.func1((sljit_sw)&buf);++ FAILED(buf[0] != (sljit_s32)0xff654321, "test78 case 12 failed\n");+ FAILED(buf[1] != (sljit_s32)0x01fedcba, "test78 case 13 failed\n");+ FAILED(*(sljit_s32*)(buf + 2) != (sljit_s32)0xf7654321, "test78 case 14 failed\n");+ FAILED(*(sljit_s32*)(buf + 3) != (sljit_s32)0x789abcde, "test78 case 15 failed\n");+ FAILED(buf[4] != 0xff, "test78 case 16 failed\n");+ FAILED(*(sljit_s32*)(buf + 5) != -0x100, "test78 case 17 failed\n");+ FAILED(*(sljit_u16*)(buf + 6) != LITTLE_BIG(0xff93, 0x93ff), "test78 case 18 failed\n");+ FAILED(buf[7] != -0xc7, "test78 case 19 failed\n");+ FAILED(*(sljit_s32*)(buf + 8) != 0x6c, "test78 case 20 failed\n");+ FAILED(*(sljit_u16*)(buf + 9) != LITTLE_BIG(0xff53, 0x53ff), "test78 case 21 failed\n");+#if IS_64BIT+ FAILED(buf[10] != (sljit_sw)LITTLE_BIG(SLJIT_W(0xaaaaaaaa87654321), SLJIT_W(0x87654321aaaaaaaa)), "test78 case 22 failed\n");+#else /* !IS_64BIT */+ FAILED(buf[10] != (sljit_sw)0x87654321, "test78 case 22 failed\n");+#endif /* IS_64BIT */++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+#ifdef SLJIT_TMP_OPT_REG+#error "Opt reg must not be defined"+#endif /* SLJIT_TMP_OPT_REG */+#else /* !SLJIT_CONFIG_X86_32 */+#ifndef SLJIT_TMP_OPT_REG+#error "Opt reg must be defined"+#endif /* !SLJIT_TMP_OPT_REG */+#endif /* SLJIT_CONFIG_X86_32 */++static void test79(void)+{+ /* Test operations with temporary registers. */+ executable_code code;+ struct sljit_compiler *compiler = sljit_create_compiler(NULL);+ sljit_s32 i;+ sljit_sw buf[23];++ if (verbose)+ printf("Run test79\n");++ for (i = 0; i < 23; i++)+ buf[i] = -1;++ buf[20] = WCONST(0xe56c91d40f839ba7, 0xe56c91d4);+ buf[22] = WCONST(0x748bd902ca1f623f, 0x748bd902);++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 5, 5, 2 * sizeof(sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0xab45fc67848b20cd, 0xab45fc67));+ sljit_emit_op2(compiler, SLJIT_ROTL, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 13);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x68dbc5f3082b93bc, 0x68dbc5f3));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xa40cd62f48a5c95f, 0x6b0cd32f));+ sljit_emit_op2(compiler, SLJIT_ROTR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 13);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x5b9ce407a41b283d, 0x5b9ce407));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, 0x7);+ sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_R4, 0, SLJIT_IMM, 0x3);+ sljit_emit_select(compiler, SLJIT_NOT_ZERO, SLJIT_TMP_DEST_REG, SLJIT_IMM, 0, SLJIT_TMP_DEST_REG);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0xe89c406b930d2781, 0xe89c406b));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0x3);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R2, 0, SLJIT_IMM, 0x3);+ sljit_emit_select(compiler, SLJIT_LESS, SLJIT_TMP_DEST_REG, SLJIT_IMM, 0, SLJIT_TMP_DEST_REG);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0xa27d450e183f96b1, 0xa27d450e));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 0x4);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R3, 0, SLJIT_IMM, 0x3);+ sljit_emit_select(compiler, SLJIT_GREATER, SLJIT_TMP_DEST_REG, SLJIT_IMM, 1, SLJIT_TMP_DEST_REG);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x3c0671d85a4c1392, 0x3c0671d8));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x7);+ sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 0x3);+ sljit_emit_select(compiler, SLJIT_ZERO, SLJIT_TMP_DEST_REG, SLJIT_IMM, 1, SLJIT_TMP_DEST_REG);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x4b92f038d7e5b64c, 0x4b92f038));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -0x7);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R3, 0, SLJIT_IMM, 0x3);+ sljit_emit_select(compiler, SLJIT_SIG_LESS, SLJIT_TMP_DEST_REG, SLJIT_IMM, -1, SLJIT_TMP_DEST_REG);+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x1c46e3f720c15b9a, 0x1c46e3f7));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -0x2);+ sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 0x1);+ sljit_emit_select(compiler, SLJIT_CARRY, SLJIT_TMP_DEST_REG, SLJIT_IMM, -1, SLJIT_TMP_DEST_REG);+ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x9b307fe21d5a9821, 0x9b307fe2));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0x1);+ sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R2, 0, SLJIT_IMM, 0x2);+ sljit_emit_select(compiler, SLJIT_EQUAL, SLJIT_TMP_DEST_REG, SLJIT_IMM, 0, SLJIT_TMP_DEST_REG);+ /* buf[9] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++#ifdef SLJIT_TMP_OPT_REG+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 10 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0xa4809b26cdb751f3, 0xa4809b26));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_OPT_REG, 0, SLJIT_IMM, -7);+ /* buf[10] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_TMP_DEST_REG, 0);+ /* buf[11] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_TMP_OPT_REG, 0);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 12 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x157b03de69f20846, 0x157b03de));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_OPT_REG, 0, SLJIT_R0, 0);+ /* buf[12] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_TMP_OPT_REG), 0, SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_OPT_REG, 0, SLJIT_IMM, 5);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_R0, 0);+ /* buf[13] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_TMP_DEST_REG), sizeof(sljit_sw), SLJIT_TMP_OPT_REG, 0);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 15 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x6fe403c1d892adb6, 0x6fe403c1));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_OPT_REG, 0, SLJIT_R0, 0);+ /* buf[14] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_TMP_OPT_REG), -(sljit_sw)sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x5b91308c748b8c14, 0x5b91308c));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_OPT_REG, 0, SLJIT_TMP_DEST_REG, 0);+ sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_OPT_REG, 0, SLJIT_IMM, 17);+ /* buf[15] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x9afc578046ef513d, 0x9afc5780));+ sljit_emit_op2(compiler, SLJIT_ASHR, SLJIT_TMP_OPT_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(47, 15));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_OPT_REG, 0);+ /* buf[16] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ if (sljit_has_cpu_feature(SLJIT_HAS_ROT)) {+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0xbd649c21073e96a7, 0xbd649c21));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_OPT_REG, 0, SLJIT_TMP_DEST_REG, 0);+ sljit_emit_op2(compiler, SLJIT_ROTL, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_OPT_REG, 0, SLJIT_IMM, 18);+ /* buf[17] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0xe8d91a537c04f791, 0xe8d91a53));+ sljit_emit_op2(compiler, SLJIT_ROTR, SLJIT_TMP_OPT_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(47, 17));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_OPT_REG, 0);+ /* buf[18] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);+ }++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S0, 0, SLJIT_IMM, 19 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, (sljit_sw)(buf + 20) - WCONST(0x3f5872cba61409e4, 0x3f5872cb));+ /* Result is SLJIT_TMP_OPT_REG, but the addressing does not use SLJIT_TMP_OPT_REG. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_OPT_REG, 0, SLJIT_MEM1(SLJIT_TMP_DEST_REG), WCONST(0x3f5872cba61409e4, 0x3f5872cb));+ /* buf[19] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R2), 0, SLJIT_TMP_OPT_REG, 0);+ /* buf[20] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R2), sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S1, 0, SLJIT_S0, 0, SLJIT_IMM, 21 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 22);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_OPT_REG, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_TMP_DEST_REG), SLJIT_WORD_SHIFT);+ /* buf[21] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_TMP_OPT_REG, 0);+ /* buf[22] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);+#endif /* SLJIT_TMP_OPT_REG */++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);++ FAILED(buf[0] != WCONST(0xbf8cf0916419b568, 0xbf8cf568), "test79 case 1 failed\n");+ FAILED(buf[1] != WCONST(0x4afd2066b17a452e, 0x997b5866), "test79 case 2 failed\n");+ FAILED(buf[2] != WCONST(0x68dbc5f3082b93bc, 0x68dbc5f3), "test79 case 3 failed\n");+ FAILED(buf[3] != 0, "test79 case 4 failed\n");+ FAILED(buf[4] != WCONST(0xe89c406b930d2781, 0xe89c406b), "test79 case 5 failed\n");+ FAILED(buf[5] != 1, "test79 case 6 failed\n");+ FAILED(buf[6] != WCONST(0x3c0671d85a4c1392, 0x3c0671d8), "test79 case 7 failed\n");+ FAILED(buf[7] != -1, "test79 case 8 failed\n");+ FAILED(buf[8] != WCONST(0x1c46e3f720c15b9a, 0x1c46e3f7), "test79 case 9 failed\n");+ FAILED(buf[9] != WCONST(0x9b307fe21d5a9821, 0x9b307fe2), "test79 case 10 failed\n");+#ifdef SLJIT_TMP_OPT_REG+ FAILED(buf[10] != WCONST(0xa4809b26cdb751f3, 0xa4809b26), "test79 case 11 failed\n");+ FAILED(buf[11] != -7, "test79 case 12 failed\n");+ FAILED(buf[12] != WCONST(0x157b03de69f20846, 0x157b03de), "test79 case 13 failed\n");+ FAILED(buf[13] != 5, "test79 case 14 failed\n");+ FAILED(buf[14] != WCONST(0x6fe403c1d892adb6, 0x6fe403c1), "test79 case 15 failed\n");+ FAILED(buf[15] != WCONST(0x6118e91718280000, 0x61180000), "test79 case 16 failed\n");+ FAILED(buf[16] != WCONST(0xffffffffffff35f8, 0xffff35f8), "test79 case 17 failed\n");+ if (sljit_has_cpu_feature(SLJIT_HAS_ROT)) {+ FAILED(buf[17] != WCONST(0x70841cfa5a9ef592, 0x7086f592), "test79 case 18 failed\n");+ FAILED(buf[18] != WCONST(0x34a6f809ef23d1b2, 0x8d29f46c), "test79 case 19 failed\n");+ }+ FAILED(buf[19] != WCONST(0xe56c91d40f839ba7, 0xe56c91d4), "test79 case 20 failed\n");+ FAILED(buf[20] != (sljit_sw)(buf + 20) - WCONST(0x3f5872cba61409e4, 0x3f5872cb), "test79 case 21 failed\n");+ FAILED(buf[21] != WCONST(0x748bd902ca1f623f, 0x748bd902), "test79 case 22 failed\n");+ FAILED(buf[22] != 22, "test79 case 23 failed\n");+#endif /* SLJIT_TMP_OPT_REG */++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test80(void)+{+ /* Test operations with temporary registers. */+ executable_code code;+ struct sljit_compiler *compiler = sljit_create_compiler(NULL);+ sljit_s32 i;+ sljit_sw buf[23];++ if (verbose)+ printf("Run test80\n");++ for (i = 0; i < 23; i++)+ buf[i] = -1;++ FAILED(!compiler, "cannot create compiler\n");++ buf[2] = WCONST(0x85cc3df2e7498816, 0x85cc3df2);+ buf[3] = WCONST(0x71cab907cf635fbd, 0x71cab907);+ buf[4] = WCONST(0x6b755b3a5d87acf2, 0x6b755b3a);+ buf[11] = WCONST(0xd1f3ee0a7d1ae290, 0xd1f3ee0a);+ buf[12] = WCONST(0xd354694d81091e65, 0xd354694d);++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 5, 5, 2 * sizeof(sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xee8d2ed83b94cd8f, 0xee8d2ed8));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0xa8b2f9100cf290bf, 0xa8b2f910));+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM, SLJIT_S1, 0, SLJIT_R0, 0, SLJIT_R1, 0, 2);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_S1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, WCONST(0xda76115dbd9af63c, 0xda76115d));+ /* buf[1] */+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R2, 0, SLJIT_IMM, WCONST(0x78557b50b25d5f08, 0x78557b50), 64 + 1);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0x28753b0e7cd61227, 0x28753b0e));+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R1, 0, 0);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 3 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (4 * sizeof(sljit_sw)) >> 1);+ /* buf[3] */+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 0, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_MEM2(SLJIT_S0, SLJIT_S1), 1, 9);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xac48ad818df80e85, 0xac48ad81));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0xaa19046e8d660ab2, 0xaa19046e));+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0, 10);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, WCONST(0x7e9b0d6490dbfcc6, 0x7e9b0d64));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, WCONST(0x19ca0db188aeff74, 0x19ca0db1));+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM, SLJIT_S2, 0, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), 11);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_S2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, WCONST(0x605fa96bbdb363dc, 0x605fa96b));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, WCONST(0x99fbcbb5c323e595, 0x99fbcbb5));+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM, SLJIT_S1, 0, SLJIT_R2, 0, SLJIT_S1, 0, 13);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_S1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, WCONST(0x6da5068ebd027176, 0x6da5068e));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0x92f1896d93e139b1, 0x92f1896d));+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R1, 0, 14);+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0x72fddef88fcc49b9, 0x72fddef8));+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM, SLJIT_R0, 0, SLJIT_IMM, WCONST(0x1a9c2dbc1ce76578, 0x1a9c2dbc), SLJIT_R0, 0, 1);+ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, WCONST(0x9d8a20212cc69147, 0x9d8a2021));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, WCONST(0x8f6b0f371ea15727, 0x8f6b0f37));+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM, SLJIT_S2, 0, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), 1);+ /* buf[9] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_S2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, WCONST(0x69d04c189179ecb7, 0x69d04c18));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_IMM, WCONST(0x63a9cef98fca934c, 0x63a9cef9));+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM, SLJIT_R3, 0, SLJIT_R4, 0, SLJIT_S4, 0, -64 + 3);+ /* buf[10] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, WCONST(0x4f1e8c8134c8a4c3, 0x4f1e8c81));+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), 0, 3);+ /* buf[11] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, WCONST(0x5fb712ae6e2bf361, 0x5fb712ae));+ /* buf[12] */+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_R2, 0, 7);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xb39b23bc2e8ca90b, 0xb39b23bc));+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R0, 0, 11);+ /* buf[13] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, WCONST(0xea0d741f26e89c46, 0xea0d741f));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0xc044fde6924e3481, 0xc044fde6));+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_TMP_DEST_REG, 0, 15);+ /* buf[14] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_R2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, WCONST(0x1924870a8cbb8438, 0x1924870a));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x8a6f2d6d843695f2, 0x8a6f2d6d));+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_S2, 0, SLJIT_S0, 0, SLJIT_IMM, WCONST(0x51a168c8a4455d05, 0x51a168c8) - 15 * (sljit_sw)sizeof(sljit_sw));+ /* buf[15] */+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM, SLJIT_MEM1(SLJIT_S2), WCONST(0x51a168c8a4455d05, 0x51a168c8), SLJIT_S1, 0, SLJIT_TMP_DEST_REG, 0, 14);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0xb306c6cc487a0da9, 0xb306c6cc));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x1f1225bb6d81ca32, 0x1f1225bb));+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM, SLJIT_TMP_DEST_REG, 0, SLJIT_R1, 0, SLJIT_TMP_DEST_REG, 0, 11);+ /* buf[16] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x5f279c812b0ab7d5, 0x5f279c81));+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 0x35cd, SLJIT_TMP_DEST_REG, 0, 14);+ /* buf[17] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0xb602ce3980d682a1, 0xb602ce39));+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x8b4af3507c1d9267, 0x8b4af350), SLJIT_TMP_DEST_REG, 0, 9);+ /* buf[18] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x7cb59a42d7509b8e, 0x7cb59a42));+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0xc5960ef485d721a3, 0xc5960ef4), SLJIT_TMP_DEST_REG, 0, 1);+ /* buf[19] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 19 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0x8e2c4e79b79500a8, 0x8e2c4e79));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0x5ce8fa2c60c7c10c, 0x5ce8fa2c));+ /* buf[20] */+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM | SLJIT_SRC2_UNDEFINED, SLJIT_MEM1(SLJIT_S0), 20 * sizeof(sljit_sw), SLJIT_R0, 0, SLJIT_R1, 0, 7);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0xbdfe33c03babe728, 0xbdfe33c0));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, WCONST(0x6dda8d28a705b87a, 0x6dda8d28));+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM | SLJIT_SRC2_UNDEFINED, SLJIT_R2, 0, SLJIT_R1, 0, SLJIT_R2, 0, 9);+ /* buf[21] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 21 * sizeof(sljit_sw), SLJIT_R2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0xadb9530fe12dca23, 0xadb9530f));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, WCONST(0x678fe74fab8bcc2b, 0x678fe74f));+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM | SLJIT_SRC2_UNDEFINED, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_R2, 0, 11);+ /* buf[22] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 22 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);++ FAILED(buf[0] != WCONST(0x915913186f5f108b, 0x91591318), "test80 case 1 failed\n");+ FAILED(buf[1] != WCONST(0xcb2107ff2255b44c, 0xcb2107fd), "test80 case 2 failed\n");+ FAILED(buf[2] != WCONST(0xae417901641f9a3d, 0xae417900), "test80 case 3 failed\n");+ FAILED(buf[3] != WCONST(0x5c812dc2debd43bd, 0x5c812d07), "test80 case 4 failed\n");+ FAILED(buf[4] != WCONST(0x105a67b72622d685, 0x105a6581), "test80 case 5 failed\n");+ FAILED(buf[5] != WCONST(0xf235323868952f74, 0xf2352db1), "test80 case 6 failed\n");+ FAILED(buf[6] != WCONST(0xd9d661d03a6603dc, 0xd9d6496b), "test80 case 7 failed\n");+ FAILED(buf[7] != WCONST(0xd0006b870b6eb176, 0xd000468e), "test80 case 8 failed\n");+ FAILED(buf[8] != WCONST(0x97ebad3c7ff8ea, 0x97ebac), "test80 case 9 failed\n");+ FAILED(buf[9] != WCONST(0xca7f4f79782e79b5, 0xca7f4f79), "test80 case 10 failed\n");+ FAILED(buf[10] != WCONST(0x871ec3e50fce8717, 0x871ec3e0), "test80 case 11 failed\n");+ FAILED(buf[11] != WCONST(0x4ae85214236008a8, 0x4ae85212), "test80 case 12 failed\n");+ FAILED(buf[12] != WCONST(0xaeddc0849702cee5, 0xaeddc04d), "test80 case 13 failed\n");+ FAILED(buf[13] != WCONST(0x8cb9053093d5010b, 0x8cb903bc), "test80 case 14 failed\n");+ FAILED(buf[14] != WCONST(0x6900bd4641291c46, 0x6900741f), "test80 case 15 failed\n");+ FAILED(buf[15] != WCONST(0xe47fe81832380438, 0xe47fc70a), "test80 case 16 failed\n");+ FAILED(buf[16] != WCONST(0x4434a23856cb9da9, 0x44349ecc), "test80 case 17 failed\n");+ FAILED(buf[17] != WCONST(0xe7204ac2adf575cd, 0xe72075cd), "test80 case 18 failed\n");+ FAILED(buf[18] != WCONST(0x90e766522922d467, 0x90e76550), "test80 case 19 failed\n");+ FAILED(buf[19] != WCONST(0xbf01437a347858bf, 0xbf014378), "test80 case 20 failed\n");+ FAILED(buf[20] != WCONST(0x2a964aa1b7586a8, 0x2a96479), "test80 case 21 failed\n");+ FAILED(buf[21] != WCONST(0x7318850e471cdb28, 0x731883c0), "test80 case 22 failed\n");+ FAILED(buf[22] != WCONST(0x2cf3d06c3f8f2223, 0x2cf3cb0f), "test80 case 23 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test81(void)+{+ /* Test compare select operation. */+ executable_code code;+ struct sljit_compiler *compiler = sljit_create_compiler(NULL);+ sljit_s32 i;+ sljit_sw buf[18];++ if (verbose)+ printf("Run test81\n");++ for (i = 0; i < 18; i++)+ buf[i] = -1;++ buf[3] = -59878;+ buf[4] = 1;++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 5, 5, 2 * sizeof(sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 48962);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -78345);+ sljit_emit_select(compiler, SLJIT_COMPARE_SELECT | SLJIT_SIG_LESS, SLJIT_S1, SLJIT_R1, 0, SLJIT_R0);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_S1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 49245);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 78049);+ sljit_emit_select(compiler, SLJIT_COMPARE_SELECT | SLJIT_LESS_EQUAL, SLJIT_R2, SLJIT_R2, 0, SLJIT_S1);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 1);+ sljit_emit_select(compiler, SLJIT_COMPARE_SELECT | SLJIT_GREATER, SLJIT_R3, SLJIT_IMM, 69456, SLJIT_R3);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, 57891);+ sljit_emit_select(compiler, SLJIT_COMPARE_SELECT | SLJIT_SIG_GREATER_EQUAL, SLJIT_S2, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_S3);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_S2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 4 * sizeof(sljit_sw));+ sljit_emit_select(compiler, SLJIT_COMPARE_SELECT | SLJIT_LESS_EQUAL, SLJIT_R0, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 0, SLJIT_S0);+ /* buf[4] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0, SLJIT_IMM, 1);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 4);+ sljit_emit_select(compiler, SLJIT_COMPARE_SELECT | SLJIT_SIG_GREATER | SLJIT_32, SLJIT_R1, SLJIT_IMM, WCONST(0x123400000000, 0) + 6, SLJIT_R0);+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R1, 0, SLJIT_R1, 0);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 758);+ sljit_emit_select(compiler, SLJIT_COMPARE_SELECT | SLJIT_LESS | SLJIT_32, SLJIT_R3, SLJIT_IMM, 1000, SLJIT_R0);+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_R3, 0);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 96456);+ sljit_emit_select(compiler, SLJIT_COMPARE_SELECT | SLJIT_GREATER_EQUAL, SLJIT_TMP_DEST_REG, SLJIT_IMM, 10000, SLJIT_TMP_DEST_REG);+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, 59734);+ sljit_emit_select(compiler, SLJIT_COMPARE_SELECT | SLJIT_SIG_LESS_EQUAL, SLJIT_TMP_DEST_REG, SLJIT_IMM, -459, SLJIT_R4);+ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 89213);+ sljit_emit_select(compiler, SLJIT_COMPARE_SELECT | SLJIT_GREATER, SLJIT_R2, SLJIT_IMM, -7, SLJIT_R2);+ /* buf[9] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8);+ sljit_emit_select(compiler, SLJIT_COMPARE_SELECT | SLJIT_SIG_GREATER, SLJIT_R0, SLJIT_IMM, 5, SLJIT_R0);+ /* buf[10] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -487);+ sljit_emit_select(compiler, SLJIT_COMPARE_SELECT | SLJIT_SIG_LESS, SLJIT_R3, SLJIT_IMM, 900, SLJIT_R2);+ /* buf[11] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_R3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 67042);+ sljit_emit_select(compiler, SLJIT_COMPARE_SELECT | SLJIT_LESS, SLJIT_S1, SLJIT_IMM, -88, SLJIT_S1);+ /* buf[12] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_S1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, -15892);+ sljit_emit_select(compiler, SLJIT_COMPARE_SELECT | SLJIT_SIG_GREATER, SLJIT_S3, SLJIT_IMM, 1, SLJIT_S3);+ /* buf[13] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_S3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -39746);+ sljit_emit_select(compiler, SLJIT_COMPARE_SELECT | SLJIT_SIG_LESS, SLJIT_R1, SLJIT_IMM, 0, SLJIT_R0);+ /* buf[14] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0);+ sljit_emit_select(compiler, SLJIT_COMPARE_SELECT | SLJIT_SIG_LESS_EQUAL | SLJIT_32, SLJIT_R1, SLJIT_IMM, WCONST(0x123400000000, 0) - 1, SLJIT_R1);+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R1, 0, SLJIT_R1, 0);+ /* buf[15] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 35891);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -24196);+ sljit_emit_select(compiler, SLJIT_COMPARE_SELECT | SLJIT_SIG_GREATER, SLJIT_R1, SLJIT_R1, 0, SLJIT_S3);+ /* buf[16] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -41682);+ sljit_emit_select(compiler, SLJIT_COMPARE_SELECT | SLJIT_SIG_GREATER, SLJIT_S1, SLJIT_S1, 0, SLJIT_S1);+ /* buf[17] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_sw), SLJIT_S1, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);++ FAILED(buf[0] != -78345, "test81 case 1 failed\n");+ FAILED(buf[1] != 49245, "test81 case 2 failed\n");+ FAILED(buf[2] != 69456, "test81 case 3 failed\n");+ FAILED(buf[3] != 57891, "test81 case 4 failed\n");+ FAILED(buf[4] != 2, "test81 case 5 failed\n");+ FAILED(buf[5] != 6, "test81 case 6 failed\n");+ FAILED(buf[6] != 758, "test81 case 7 failed\n");+ FAILED(buf[7] != 96456, "test81 case 8 failed\n");+ FAILED(buf[8] != -459, "test81 case 9 failed\n");+ FAILED(buf[9] != -7, "test81 case 10 failed\n");+ FAILED(buf[10] != 8, "test81 case 11 failed\n");+ FAILED(buf[11] != -487, "test81 case 12 failed\n");+ FAILED(buf[12] != 67042, "test81 case 13 failed\n");+ FAILED(buf[13] != 1, "test81 case 14 failed\n");+ FAILED(buf[14] != -39746, "test81 case 15 failed\n");+ FAILED(buf[15] != -1, "test81 case 16 failed\n");+ FAILED(buf[16] != 35891, "test81 case 17 failed\n");+ FAILED(buf[17] != -41682, "test81 case 18 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++#include "sljitTestCall.h"+#include "sljitTestFloat.h"+#include "sljitTestSimd.h"+#include "sljitTestBuffers.h"+#include "sljitTestSerialize.h"++int sljit_test(int argc, char* argv[])+{+ sljit_s32 has_arg = (argc >= 2 && argv[1][0] == '-' && argv[1][2] == '\0');+ verbose = has_arg && argv[1][1] == 'v';+ silent = has_arg && argv[1][1] == 's';++ if (!verbose && !silent)+ printf("Pass -v to enable verbose, -s to disable this hint.\n\n");++#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)+ test_exec_allocator();+#endif /* !SLJIT_CONFIG_UNSUPPORTED */+ test_macros();+ test1();+ test2();+ test3();+ test4();+ test5();+ test6();+ test7();+ test8();+ test9();+ test10();+ test11();+ test12();+ test13();+ test14();+ test15();+ test16();+ test17();+ test18();+ test19();+ test20();+ test21();+ test22();+ test23();+ test24();+ test25();+ test26();+ test27();+ test28();+ test29();+ test30();+ test31();+ test32();+ test33();+ test34();+ test35();+ test36();+ test37();+ test38();+ test39();+ test40();+ test41();+ test42();+ test43();+ test44();+ test45();+ test46();+ test47();+ test48();+ test49();+ test50();+ test51();+ test52();+ test53();+ test54();+ test55();+ test56();+ test57();+ test58();+ test59();+ test60();+ test61();+ test62();+ test63();+ test64();+ test65();+ test66();+ test67();+ test68();+ test69();+ test70();+ test71();+ test72();+ test73();+ test74();+ test75();+ test76();+ test77();+ test78();+ test79();+ test80();+ test81();++ if (verbose)+ printf("---- Call tests ----\n");++ test_call1();+ test_call2();+ test_call3();+ test_call4();+ test_call5();+ test_call6();+ test_call7();+ test_call8();+ test_call9();+ test_call10();+ test_call11();+ test_call12();+ test_call13();++ if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) {+ if (verbose)+ printf("---- Float tests ----\n");+ test_float1();+ test_float2();+ test_float3();+ test_float4();+ test_float5();+ test_float6();+ test_float7();+ test_float8();+ test_float9();+ test_float10();+ test_float11();+ test_float12();+ test_float13();+ test_float14();+ test_float15();+ test_float16();+ test_float17();+ test_float18();+ test_float19();+ test_float20();+ test_float21();+ test_float22();+ test_float23();+ } else {+ if (verbose)+ printf("no fpu available, fpu tests are skipped\n");+ successful_tests += 23;+ }++ if (sljit_has_cpu_feature(SLJIT_HAS_SIMD)) {+ if (verbose)+ printf("---- SIMD tests ----\n");+ test_simd1();+ test_simd2();+ test_simd3();+ test_simd4();+ test_simd5();+ test_simd6();+ test_simd7();+ test_simd8();+ test_simd9();+ test_simd10();+ test_simd11();+ } else {+ if (verbose)+ printf("no simd available, simd tests are skipped\n");+ successful_tests += 11;+ }++ if (verbose)+ printf("---- Serialize tests ----\n");++ test_buffer1();+ test_buffer2();+ test_buffer3();+ test_buffer4();+ test_buffer5();++ test_serialize1();+ test_serialize2();+ test_serialize3();+ test_serialize4();++#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)+ sljit_free_unused_memory_exec();+#endif /* SLJIT_EXECUTABLE_ALLOCATOR */++# define TEST_COUNT 137++ printf("SLJIT tests: ");+ if (successful_tests == TEST_COUNT)+ printf("all tests " COLOR_GREEN "PASSED" COLOR_DEFAULT " ");+ else+ printf(COLOR_RED "%d" COLOR_DEFAULT " (" COLOR_RED "%d%%" COLOR_DEFAULT ") tests " COLOR_RED "FAILED" COLOR_DEFAULT " ", TEST_COUNT - successful_tests, (TEST_COUNT - successful_tests) * 100 / TEST_COUNT);+ printf("on " COLOR_ARCH "%s" COLOR_DEFAULT " (%s)\n", sljit_get_platform_name(), sljit_has_cpu_feature(SLJIT_HAS_SIMD) ? "with simd" : (sljit_has_cpu_feature(SLJIT_HAS_FPU) ? "with fpu" : "basic"));++ return TEST_COUNT - successful_tests;++# undef TEST_COUNT+}++#ifdef _MSC_VER+#pragma warning(pop)+#endif /* _MSC_VER */
+ src/c/pcre2/deps/sljit/test_src/sljitTestBuffers.h view
@@ -0,0 +1,627 @@+/*+ * 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 void test_buffer1(void)+{+ /* Test aligned labels. */+ executable_code code;+ struct sljit_compiler *compiler = sljit_create_compiler(NULL);+ struct sljit_label *label[12];+ struct sljit_jump *jump[3];+ sljit_s32 i;+ sljit_uw buf[8];+ sljit_uw addr[2];++ if (verbose)+ printf("Run test_buffer1\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 8; i++)+ buf[i] = ~(sljit_uw)0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 5, 5, 2 * sizeof(sljit_sw));++ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_S0, 0);+ jump[0] = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_MEM1(SLJIT_R1), 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, 85603);++ label[0] = sljit_emit_aligned_label(compiler, SLJIT_LABEL_ALIGN_16, NULL);+ label[1] = sljit_emit_label(compiler);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R0, 0);++ label[2] = sljit_emit_label(compiler);+ label[3] = sljit_emit_aligned_label(compiler, SLJIT_LABEL_ALIGN_16, NULL);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1000);+ sljit_set_label(sljit_emit_cmp(compiler, SLJIT_LESS_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 17000), label[1]);++ label[4] = sljit_emit_aligned_label(compiler, SLJIT_LABEL_ALIGN_2, NULL);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, 46789);++ /* The SLJIT_JUMP_IF_NON_ZERO is the default. */+ jump[1] = sljit_emit_op2cmpz(compiler, SLJIT_SUB, SLJIT_S1, 0, SLJIT_R4, 0, SLJIT_IMM, 578);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);++ label[5] = sljit_emit_aligned_label(compiler, SLJIT_LABEL_ALIGN_8, NULL);+ label[6] = sljit_emit_label(compiler);+ sljit_set_label(jump[1], label[6]);++ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R4, 0);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_S1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (5 * sizeof(sljit_sw)) >> 1);+ /* buf[5] */+ sljit_set_label(sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_MEM2(SLJIT_R1, SLJIT_S1), 1), label[3]);++ label[7] = sljit_emit_aligned_label(compiler, SLJIT_LABEL_ALIGN_4, NULL);+ sljit_set_label(jump[0], label[7]);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 69743);++ label[8] = sljit_emit_aligned_label(compiler, SLJIT_LABEL_ALIGN_1, NULL);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R1, 0);++ label[9] = sljit_emit_aligned_label(compiler, SLJIT_LABEL_ALIGN_16, NULL);+ jump[2] = sljit_emit_jump(compiler, SLJIT_JUMP);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);+ sljit_set_label(jump[2], sljit_emit_label(compiler));++ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_IMM, 50923);++ sljit_emit_return_void(compiler);++ label[10] = sljit_emit_aligned_label(compiler, SLJIT_LABEL_ALIGN_8, NULL);+ sljit_emit_op0(compiler, SLJIT_NOP);+ sljit_emit_op0(compiler, SLJIT_NOP);+ label[11] = sljit_emit_aligned_label(compiler, SLJIT_LABEL_ALIGN_8, NULL);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ FAILED((sljit_get_label_abs_addr(label[0]) & 0xf) != 0, "test_buffer1 case 1 failed\n");+ FAILED(label[2] == label[3], "test_buffer1 case 2 failed\n");+ FAILED((sljit_get_label_abs_addr(label[3]) & 0xf) != 0, "test_buffer1 case 3 failed\n");+ FAILED((sljit_get_label_abs_addr(label[4]) & 0x1) != 0, "test_buffer1 case 4 failed\n");+ FAILED((sljit_get_label_abs_addr(label[5]) & 0x7) != 0, "test_buffer1 case 5 failed\n");+ FAILED(label[5] != label[6], "test_buffer1 case 6 failed\n");+ FAILED((sljit_get_label_abs_addr(label[7]) & 0x3) != 0, "test_buffer1 case 7 failed\n");+ FAILED(label[7] == label[8], "test_buffer1 case 8 failed\n");+ FAILED((sljit_get_label_abs_addr(label[9]) & 0xf) != 0, "test_buffer1 case 9 failed\n");+ FAILED((sljit_get_label_abs_addr(label[10]) & 0x7) != 0, "test_buffer1 case 10 failed\n");+ FAILED((sljit_get_label_abs_addr(label[11]) & 0x7) != 0, "test_buffer1 case 11 failed\n");++ addr[0] = sljit_get_label_addr(label[7]);+ addr[1] = sljit_get_label_addr(label[3]);++ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);++ FAILED(buf[0] != addr[0], "test_buffer1 case 12 failed\n");+ FAILED(buf[1] != 85603, "test_buffer1 case 13 failed\n");+ FAILED(buf[2] != 17000, "test_buffer1 case 14 failed\n");+ FAILED(buf[3] != 46789, "test_buffer1 case 15 failed\n");+ FAILED(buf[4] != 46211, "test_buffer1 case 16 failed\n");+ FAILED(buf[5] != addr[1], "test_buffer1 case 17 failed\n");+ FAILED(buf[6] != 69743, "test_buffer1 case 18 failed\n");+ FAILED(buf[7] != 50923, "test_buffer1 case 19 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test_buffer2(void)+{+ /* Test read-only buffers. */+ executable_code code;+ struct sljit_compiler *compiler = sljit_create_compiler(NULL);+ struct sljit_read_only_buffer ro_buffers[4];+ struct sljit_jump *jump[4];+ struct sljit_label *label;+ sljit_sw executable_offset;+ sljit_sw buf[3];+ sljit_sw *ptr_sw;+ sljit_u8 *ptr_u8;+ sljit_s32 *ptr_s32;++ if (verbose)+ printf("Run test_buffer2\n");++ FAILED(!compiler, "cannot create compiler\n");++ buf[0] = -1;+ buf[1] = -1;+ buf[2] = -1;++ ro_buffers[0].next = ro_buffers + 1;+ ro_buffers[0].size = 8 * sizeof(sljit_sw);+ ro_buffers[1].next = ro_buffers + 2;+ ro_buffers[1].size = 0;+ ro_buffers[2].next = NULL;+ ro_buffers[2].size = 1;+ ro_buffers[3].next = NULL;+ ro_buffers[3].size = 5 * 4;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS3V(P, P, P), 5, 5, 2 * sizeof(sljit_sw));++ jump[0] = sljit_emit_cmp(compiler, SLJIT_EQUAL, SLJIT_S1, 0, SLJIT_IMM, -1);++ jump[1] = sljit_emit_op_addr(compiler, SLJIT_MOV_ABS_ADDR, SLJIT_R0, 0);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM2(SLJIT_R0, SLJIT_S1), SLJIT_WORD_SHIFT);++ jump[2] = sljit_emit_op_addr(compiler, SLJIT_MOV_ABS_ADDR, SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_R1), 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ jump[3] = sljit_emit_jump(compiler, SLJIT_JUMP);+ sljit_set_label(jump[0], sljit_emit_label(compiler));++ label = sljit_emit_aligned_label(compiler, SLJIT_LABEL_ALIGN_W, ro_buffers);+ sljit_set_label(jump[1], ro_buffers[0].u.label);+ sljit_set_label(jump[2], ro_buffers[2].u.label);++ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 58961);++ sljit_set_label(jump[3], sljit_emit_label(compiler));++ jump[0] = sljit_emit_cmp(compiler, SLJIT_EQUAL, SLJIT_S2, 0, SLJIT_IMM, -1);++ jump[1] = sljit_emit_op_addr(compiler, SLJIT_MOV_ABS_ADDR, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R1, 0, SLJIT_MEM2(SLJIT_R0, SLJIT_S2), 2);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R1, 0);++ jump[2] = sljit_emit_jump(compiler, SLJIT_JUMP);+ sljit_set_label(jump[0], sljit_emit_label(compiler));++ sljit_emit_aligned_label(compiler, SLJIT_LABEL_ALIGN_4, ro_buffers + 3);+ sljit_set_label(jump[1], ro_buffers[3].u.label);++ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_IMM, 63901);++ sljit_set_label(jump[2], sljit_emit_label(compiler));++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ executable_offset = sljit_get_executable_offset(compiler);+ FAILED(label != ro_buffers[0].u.label, "test_buffer2 case 1 failed\n");+ FAILED(ro_buffers[1].u.label != ro_buffers[2].u.label, "test_buffer2 case 2 failed\n");+ ro_buffers[0].u.addr = sljit_get_label_abs_addr(ro_buffers[0].u.label);+ ro_buffers[2].u.addr = sljit_get_label_abs_addr(ro_buffers[2].u.label);+ ro_buffers[3].u.addr = sljit_get_label_abs_addr(ro_buffers[3].u.label);+ FAILED((ro_buffers[0].u.addr & ((1 << SLJIT_LABEL_ALIGN_W) - 1)) != 0, "test_buffer2 case 3 failed\n");+ FAILED((ro_buffers[3].u.addr & 0x3) != 0, "test_buffer2 case 4 failed\n");++ sljit_free_compiler(compiler);++ code.func3((sljit_sw)&buf, -1, -1);++ FAILED(buf[0] != 58961, "test_buffer2 case 4 failed\n");+ FAILED(buf[1] != -1, "test_buffer2 case 5 failed\n");+ FAILED(buf[2] != 63901, "test_buffer2 case 6 failed\n");++ ptr_sw = (sljit_sw*)sljit_read_only_buffer_start_writing(ro_buffers[0].u.addr, ro_buffers[0].size, executable_offset);+ ptr_sw[0] = 85372;+ ptr_sw[4] = -92714;+ ptr_sw[7] = 60824;+ sljit_read_only_buffer_end_writing(ro_buffers[0].u.addr, ro_buffers[0].size, executable_offset);++ ptr_u8 = (sljit_u8*)sljit_read_only_buffer_start_writing(ro_buffers[2].u.addr, ro_buffers[2].size, executable_offset);+ ptr_u8[0] = 174;+ sljit_read_only_buffer_end_writing(ro_buffers[2].u.addr, ro_buffers[2].size, executable_offset);++ ptr_s32 = (sljit_s32*)sljit_read_only_buffer_start_writing(ro_buffers[3].u.addr, ro_buffers[3].size, executable_offset);+ ptr_s32[0] = -82561;+ ptr_s32[1] = 73610;+ ptr_s32[4] = -38219;+ sljit_read_only_buffer_end_writing(ro_buffers[3].u.addr, ro_buffers[3].size, executable_offset);++ code.func3((sljit_sw)&buf, 0, 0);++ FAILED(buf[0] != 85372, "test_buffer2 case 7 failed\n");+ FAILED(buf[1] != 174, "test_buffer2 case 8 failed\n");+ FAILED(buf[2] != -82561, "test_buffer2 case 9 failed\n");++ code.func3((sljit_sw)&buf, 4, 1);++ FAILED(buf[0] != -92714, "test_buffer2 case 10 failed\n");+ FAILED(buf[1] != 174, "test_buffer2 case 11 failed\n");+ FAILED(buf[2] != 73610, "test_buffer2 case 12 failed\n");++ code.func3((sljit_sw)&buf, 7, 4);++ FAILED(buf[0] != 60824, "test_buffer2 case 13 failed\n");+ FAILED(buf[1] != 174, "test_buffer2 case 14 failed\n");+ FAILED(buf[2] != -38219, "test_buffer2 case 15 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test_buffer3(void)+{+ /* Test read-only buffers. */+ executable_code code;+ struct sljit_compiler *compiler = sljit_create_compiler(NULL);+ struct sljit_read_only_buffer ro_buffers[2];+ struct sljit_jump *jump[4];+ struct sljit_label *label[8];+ sljit_sw executable_offset;+ sljit_sw buf[2];+ sljit_uw *ptr_uw;++ if (verbose)+ printf("Run test_buffer3\n");++ FAILED(!compiler, "cannot create compiler\n");++ ro_buffers[0].next = ro_buffers + 1;+ ro_buffers[0].size = 4 * sizeof(sljit_sw);+ ro_buffers[1].next = NULL;+ ro_buffers[1].size = 3 * sizeof(sljit_sw);++ sljit_emit_enter(compiler, 0, SLJIT_ARGS3V(P, P, P), 5, 5, 2 * sizeof(sljit_sw));++ jump[0] = sljit_emit_op_addr(compiler, SLJIT_MOV_ABS_ADDR, SLJIT_TMP_DEST_REG, 0);+ sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM2(SLJIT_TMP_DEST_REG, SLJIT_S1), SLJIT_WORD_SHIFT);++ label[0] = sljit_emit_label(compiler);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 83974);+ jump[1] = sljit_emit_jump(compiler, SLJIT_JUMP);++ label[1] = sljit_emit_label(compiler);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 65803);+ jump[2] = sljit_emit_jump(compiler, SLJIT_JUMP);++ label[2] = sljit_emit_label(compiler);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, -38405);+ jump[3] = sljit_emit_jump(compiler, SLJIT_JUMP);++ label[3] = sljit_emit_label(compiler);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 74198);++ label[4] = sljit_emit_label(compiler);+ sljit_set_label(jump[1], label[4]);+ sljit_set_label(jump[2], label[4]);+ sljit_set_label(jump[3], label[4]);++ jump[1] = sljit_emit_op_addr(compiler, SLJIT_MOV_ABS_ADDR, SLJIT_TMP_DEST_REG, 0);+ sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_MEM2(SLJIT_TMP_DEST_REG, SLJIT_S2), 0);++ sljit_emit_return_void(compiler);++ label[4] = sljit_emit_label(compiler);+ sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_TMP_DEST_REG, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 63891);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_TMP_DEST_REG, 0);++ label[5] = sljit_emit_label(compiler);+ sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_TMP_DEST_REG, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -27019);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R1, 0);+ sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_TMP_DEST_REG, 0);++ label[6] = sljit_emit_label(compiler);+ sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_TMP_DEST_REG, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 95486);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R2, 0);+ sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_TMP_DEST_REG, 0);++ label[7] = sljit_emit_aligned_label(compiler, SLJIT_LABEL_ALIGN_W, ro_buffers);+ sljit_set_label(jump[0], ro_buffers[0].u.label);+ sljit_set_label(jump[1], ro_buffers[1].u.label);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ executable_offset = sljit_get_executable_offset(compiler);+ ro_buffers[0].u.addr = sljit_get_label_abs_addr(ro_buffers[0].u.label);+ ro_buffers[1].u.addr = sljit_get_label_abs_addr(ro_buffers[1].u.label);++ ptr_uw = (sljit_uw*)sljit_read_only_buffer_start_writing(ro_buffers[0].u.addr, ro_buffers[0].size, executable_offset);+ ptr_uw[0] = sljit_get_label_addr(label[0]);+ ptr_uw[1] = sljit_get_label_addr(label[1]);+ ptr_uw[2] = sljit_get_label_addr(label[2]);+ ptr_uw[3] = sljit_get_label_addr(label[3]);+ sljit_read_only_buffer_end_writing(ro_buffers[0].u.addr, ro_buffers[0].size, executable_offset);++ ptr_uw = (sljit_uw*)sljit_read_only_buffer_start_writing(ro_buffers[1].u.addr, ro_buffers[1].size, executable_offset);+ ptr_uw[0] = sljit_get_label_addr(label[4]);+ ptr_uw[1] = sljit_get_label_addr(label[5]);+ ptr_uw[2] = sljit_get_label_addr(label[6]);+ sljit_read_only_buffer_end_writing(ro_buffers[1].u.addr, ro_buffers[1].size, executable_offset);++ sljit_free_compiler(compiler);++ code.func3((sljit_sw)&buf, 0, 0);++ FAILED(buf[0] != 83974, "test_buffer3 case 1 failed\n");+ FAILED(buf[1] != 63891, "test_buffer3 case 2 failed\n");++ code.func3((sljit_sw)&buf, 3, sizeof(sljit_uw));++ FAILED(buf[0] != 74198, "test_buffer3 case 3 failed\n");+ FAILED(buf[1] != -27019, "test_buffer3 case 4 failed\n");++ code.func3((sljit_sw)&buf, 1, 2 * sizeof(sljit_uw));++ FAILED(buf[0] != 65803, "test_buffer3 case 5 failed\n");+ FAILED(buf[1] != 95486, "test_buffer3 case 6 failed\n");++ code.func3((sljit_sw)&buf, 2, 0);++ FAILED(buf[0] != -38405, "test_buffer3 case 7 failed\n");+ FAILED(buf[1] != 63891, "test_buffer3 case 8 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test_buffer4(void)+{+ /* Test read-only buffers. */+ executable_code code;+ struct sljit_compiler *compiler = sljit_create_compiler(NULL);+ struct sljit_read_only_buffer ro_buffers[2];+ struct sljit_jump *jump[7];+ struct sljit_label *label;+ sljit_sw executable_offset;+ sljit_uw buf[8];+ sljit_uw addr[2];+ sljit_s32 i;+ sljit_uw *ptr_uw;++ if (verbose)+ printf("Run test_buffer4\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 8; i++)+ buf[i] = ~(sljit_uw)0;+ buf[3] = 60439;+ buf[5] = 74901;++ ro_buffers[0].next = ro_buffers + 1;+ ro_buffers[0].size = 3 * sizeof(sljit_sw);+ ro_buffers[1].next = NULL;+ ro_buffers[1].size = sizeof(sljit_sw);++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 5, 5, 8 * sizeof(sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 58321);+ jump[0] = sljit_emit_op_addr(compiler, SLJIT_ADD_ABS_ADDR, SLJIT_R0, 0);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -45209);+ jump[1] = sljit_emit_op_addr(compiler, SLJIT_ADD_ABS_ADDR, SLJIT_S1, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_S1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 3 * sizeof(sljit_sw), SLJIT_IMM, 29614);+ jump[2] = sljit_emit_op_addr(compiler, SLJIT_ADD_ABS_ADDR, SLJIT_MEM1(SLJIT_SP), 3 * sizeof(sljit_sw));+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), 3 * sizeof(sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 3);+ /* buf[3] */+ jump[3] = sljit_emit_op_addr(compiler, SLJIT_ADD_ABS_ADDR, SLJIT_MEM2(SLJIT_R1, SLJIT_S1), SLJIT_WORD_SHIFT);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, -71694);+ jump[4] = sljit_emit_op_addr(compiler, SLJIT_ADD_ABS_ADDR, SLJIT_TMP_DEST_REG, 0);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ /* buf[5] */+ jump[5] = sljit_emit_op_addr(compiler, SLJIT_ADD_ABS_ADDR, SLJIT_MEM0(), (sljit_sw)(buf + 5));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 68531);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -84012);+ jump[6] = sljit_emit_op_addr(compiler, SLJIT_ADD_ABS_ADDR, SLJIT_R1, 0);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R1, 0);+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_return_void(compiler);++ label = sljit_emit_aligned_label(compiler, SLJIT_LABEL_ALIGN_W, ro_buffers);+ sljit_set_label(jump[0], label);+ sljit_set_label(jump[1], label);+ sljit_set_label(jump[2], label);+ sljit_set_label(jump[3], label);+ sljit_set_label(jump[4], label);++ label = sljit_emit_aligned_label(compiler, SLJIT_LABEL_ALIGN_W, ro_buffers + 1);+ sljit_set_label(jump[5], label);+ sljit_set_label(jump[6], label);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ executable_offset = sljit_get_executable_offset(compiler);+ addr[0] = sljit_get_label_abs_addr(ro_buffers[0].u.label);+ addr[1] = sljit_get_label_abs_addr(ro_buffers[1].u.label);++ sljit_free_compiler(compiler);++ ptr_uw = (sljit_uw*)sljit_read_only_buffer_start_writing(addr[0], ro_buffers[0].size, executable_offset);+ ptr_uw[0] = 0;+ sljit_read_only_buffer_end_writing(addr[0], ro_buffers[0].size, executable_offset);++ ptr_uw = (sljit_uw*)sljit_read_only_buffer_start_writing(addr[1], ro_buffers[1].size, executable_offset);+ ptr_uw[0] = 0;+ sljit_read_only_buffer_end_writing(addr[1], ro_buffers[1].size, executable_offset);++ code.func1((sljit_sw)&buf);++ FAILED((addr[0] & (sizeof(sljit_sw) - 1)) != 0, "test_buffer4 case 1 failed\n");+ FAILED((addr[1] & (sizeof(sljit_sw) - 1)) != 0, "test_buffer4 case 2 failed\n");+ FAILED(buf[0] != addr[0] + 58321, "test_buffer4 case 3 failed\n");+ FAILED(buf[1] != addr[0] - 45209, "test_buffer4 case 4 failed\n");+ FAILED(buf[2] != addr[0] + 29614, "test_buffer4 case 5 failed\n");+ FAILED(buf[3] != addr[0] + 60439, "test_buffer4 case 6 failed\n");+ FAILED(buf[4] != addr[0] - 71694, "test_buffer4 case 7 failed\n");+ FAILED(buf[5] != addr[1] + 74901, "test_buffer4 case 8 failed\n");+ FAILED(buf[6] != addr[1] - 84012, "test_buffer4 case 9 failed\n");+ FAILED(buf[7] != 68531, "test_buffer4 case 10 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test_buffer5(void)+{+ /* Test code rewriting in buffers. */+ executable_code code;+ struct sljit_compiler *compiler = sljit_create_compiler(NULL);+ struct sljit_read_only_buffer ro_buffers[1];+ struct sljit_generate_code_buffer code_buffer;+ struct sljit_label *label[2];+ sljit_sw executable_offset;+ sljit_sw buf[3];+ sljit_uw addr[2];+ sljit_s32 i;+ void *dyn_code;++ if (verbose)+ printf("Run test_buffer5\n");++ FAILED(!compiler, "cannot create compiler\n");++ ro_buffers[0].next = NULL;+ ro_buffers[0].size = 127;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 5, 5, 8 * sizeof(sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, -598461);+ label[0] = sljit_emit_aligned_label(compiler, SLJIT_LABEL_ALIGN_1, ro_buffers);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);+ label[1] = sljit_emit_label(compiler);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, 613802);+ sljit_emit_return_void(compiler);++ /* Initial code. */+ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ executable_offset = sljit_get_executable_offset(compiler);+ addr[0] = sljit_get_label_abs_addr(label[0]);+ addr[1] = sljit_get_label_addr(label[1]);++ sljit_free_compiler(compiler);++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_set_context(compiler, 0, SLJIT_ARGS1V(P), 5, 5, 8 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_IMM, -305814);+ sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_IMM, (sljit_sw)addr[1]);++ code_buffer.buffer = sljit_read_only_buffer_start_writing(addr[0], ro_buffers[0].size, executable_offset);+ code_buffer.size = ro_buffers[0].size;+ code_buffer.executable_offset = executable_offset;++ dyn_code = sljit_generate_code(compiler, SLJIT_GENERATE_CODE_BUFFER | SLJIT_GENERATE_CODE_NO_CONTEXT, &code_buffer);+ CHECK(compiler);+#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)+ FAILED((sljit_uw)dyn_code != addr[0] + 1, "test_buffer5 case 1 failed\n");+#else /* !SLJIT_CONFIG_ARM_THUMB2 */+ FAILED((sljit_uw)dyn_code != addr[0], "test_buffer5 case 1 failed\n");+#endif++ sljit_read_only_buffer_end_writing(addr[0], ro_buffers[0].size, executable_offset);+ sljit_free_compiler(compiler);++ for (i = 0; i < 3; i++)+ buf[i] = -1;++ code.func1((sljit_sw)&buf);+ FAILED(buf[0] != -598461, "test_buffer5 case 2 failed\n");+ FAILED(buf[1] != 613802, "test_buffer5 case 3 failed\n");+ FAILED(buf[2] != -305814, "test_buffer5 case 4 failed\n");++ /* Code modification. */+ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_set_context(compiler, 0, SLJIT_ARGS1V(P), 5, 5, 8 * sizeof(sljit_sw));+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_S0, 0, SLJIT_IMM, 1);+ sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_IMM, (sljit_sw)addr[1]);++ code_buffer.buffer = sljit_read_only_buffer_start_writing(addr[0], ro_buffers[0].size, executable_offset);+ code_buffer.size = ro_buffers[0].size;+ code_buffer.executable_offset = executable_offset;++ dyn_code = sljit_generate_code(compiler, SLJIT_GENERATE_CODE_BUFFER | SLJIT_GENERATE_CODE_NO_CONTEXT, &code_buffer);+ CHECK(compiler);+#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)+ FAILED((sljit_uw)dyn_code != addr[0] + 1, "test_buffer5 case 5 failed\n");+#else /* !SLJIT_CONFIG_ARM_THUMB2 */+ FAILED((sljit_uw)dyn_code != addr[0], "test_buffer5 case 5 failed\n");+#endif++ sljit_read_only_buffer_end_writing(addr[0], ro_buffers[0].size, executable_offset);+ sljit_free_compiler(compiler);++ for (i = 0; i < 3; i++)+ buf[i] = -1;++ code.func1((sljit_sw)&buf);+ FAILED(buf[0] != -598461, "test_buffer5 case 6 failed\n");+ FAILED(buf[1] != 613802, "test_buffer5 case 7 failed\n");+ FAILED(buf[2] != (sljit_sw)buf + 1, "test_buffer5 case 8 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}
+ src/c/pcre2/deps/sljit/test_src/sljitTestCall.h view
@@ -0,0 +1,2109 @@+/*+ * 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_sw func(sljit_sw a, sljit_sw b, sljit_sw c)+{+ return a + b + c + 5;+}++static sljit_sw func4(sljit_sw a, sljit_sw b, sljit_sw c, sljit_sw d)+{+ return func(a, b, c) + d;+}++static sljit_sw func2(sljit_sw a, sljit_sw b)+{+ return a + b + 3;+}++static void test_call1(void)+{+ /* Test function call. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_jump* jump = NULL;+ sljit_sw buf[10];+ sljit_sw res;++ if (verbose)+ printf("Run test_call1\n");++ FAILED(!compiler, "cannot create compiler\n");+ buf[0] = 0;+ buf[1] = 0;+ buf[2] = 0;+ buf[3] = 0;+ buf[4] = 0;+ buf[5] = 0;+ buf[6] = 0;+ buf[7] = 0;+ buf[8] = SLJIT_FUNC_ADDR(func);+ buf[9] = 0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 4, 2, 0);++ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 5);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 7);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -3);+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(func));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_RETURN_REG, 0);++ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -5);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -10);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 2);+ jump = sljit_emit_call(compiler, SLJIT_CALL | SLJIT_REWRITABLE_JUMP, SLJIT_ARGS3(W, W, W, W));+ sljit_set_target(jump, (sljit_uw)-1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_RETURN_REG, 0);++ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(func));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 40);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -3);+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0);++ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -60);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(func));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -30);+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0);++ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 10);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 16);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(func));+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_R2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0);++ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 100);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 110);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 120);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(func));+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_R3, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0);++ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 2);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 3);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(func));+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_S1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0);++ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 2);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 3);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -6);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(func4));+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W), SLJIT_S1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0);++ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -10);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -16);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 6);+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0);++ /* buf[9] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 5);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 8);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(func2));+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_R2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0);++ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_set_jump_addr(sljit_get_jump_addr(jump), SLJIT_FUNC_UADDR(func), sljit_get_executable_offset(compiler));+ sljit_free_compiler(compiler);++ res = code.func1((sljit_sw)&buf);+ sljit_free_code(code.code, NULL);++ FAILED(res != 16, "test_call1 case 1 failed\n");+ FAILED(buf[0] != 14, "test_call1 case 2 failed\n");+ FAILED(buf[1] != -8, "test_call1 case 3 failed\n");+ FAILED(buf[2] != SLJIT_FUNC_ADDR(func) + 42, "test_call1 case 4 failed\n");+ FAILED(buf[3] != SLJIT_FUNC_ADDR(func) - 85, "test_call1 case 5 failed\n");+ FAILED(buf[4] != SLJIT_FUNC_ADDR(func) + 31, "test_call1 case 6 failed\n");+ FAILED(buf[5] != 335, "test_call1 case 7 failed\n");+ FAILED(buf[6] != 11, "test_call1 case 8 failed\n");+ FAILED(buf[7] != 5, "test_call1 case 9 failed\n");+ FAILED(buf[8] != -15, "test_call1 case 10 failed\n");+ FAILED(buf[9] != 16, "test_call1 case 11 failed\n");++ successful_tests++;+}++static void test_call2(void)+{+ /* Ackermann benchmark. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_label *entry;+ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_jump *jump1;+ struct sljit_jump *jump2;+ sljit_sw res;++ if (verbose)+ printf("Run test_call2\n");++ FAILED(!compiler, "cannot create compiler\n");++ entry = sljit_emit_label(compiler);+ sljit_emit_enter(compiler, 0, SLJIT_ARGS2(W, W, W), 3, 2, 0);+ /* If x == 0. */+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_S0, 0, SLJIT_IMM, 0);+ jump1 = sljit_emit_jump(compiler, SLJIT_EQUAL);+ /* If y == 0. */+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_S1, 0, SLJIT_IMM, 0);+ jump2 = sljit_emit_jump(compiler, SLJIT_EQUAL);++ /* Ack(x,y-1). */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 1);+ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W));+ sljit_set_label(jump, entry);++ /* Returns with Ack(x-1, Ack(x,y-1)). */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_RETURN_REG, 0);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 1);+ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W));+ sljit_set_label(jump, entry);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);++ /* Returns with y+1. */+ label = sljit_emit_label(compiler);+ sljit_set_label(jump1, label);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1, SLJIT_S1, 0);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);++ /* Returns with Ack(x-1,1) */+ label = sljit_emit_label(compiler);+ sljit_set_label(jump2, label);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1);+ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W));+ sljit_set_label(jump, entry);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ /* For benchmarking. */+ /* FAILED(code.func2(3, 11) != 16381, "test_call2 case 1 failed\n"); */++ res = code.func2(3, 3);+ sljit_free_code(code.code, NULL);++ FAILED(res != 61, "test_call2 case 1 failed\n");++ successful_tests++;+}++static sljit_f64 test_call3_f1(sljit_f32 a, sljit_f32 b, sljit_f64 c)+{+ return (sljit_f64)a + (sljit_f64)b + c;+}++static sljit_f32 test_call3_f2(sljit_sw a, sljit_f64 b, sljit_f32 c)+{+ return (sljit_f32)((sljit_f64)a + b + (sljit_f64)c);+}++static sljit_f64 test_call3_f3(sljit_sw a, sljit_f32 b, sljit_sw c)+{+ return (sljit_f64)a + (sljit_f64)b + (sljit_f64)c;+}++static sljit_f64 test_call3_f4(sljit_f32 a, sljit_sw b)+{+ return (sljit_f64)a + (sljit_f64)b;+}++static sljit_f32 test_call3_f5(sljit_f32 a, sljit_f64 b, sljit_s32 c)+{+ return (sljit_f32)((sljit_f64)a + b + (sljit_f64)c);+}++static sljit_sw test_call3_f6(sljit_f64 a, sljit_sw b)+{+ return (sljit_sw)(a + (sljit_f64)b);+}++static void test_call3(void)+{+ /* Check function calls with floating point arguments. */+ executable_code code;+ struct sljit_compiler* compiler;+ struct sljit_jump* jump = NULL;+ sljit_f64 dbuf[7];+ sljit_f32 sbuf[7];+ sljit_sw wbuf[2];++ if (verbose)+ printf("Run test_call3\n");++ if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) {+ if (verbose)+ printf("no fpu available, test_call3 skipped\n");+ successful_tests++;+ return;+ }++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ dbuf[0] = 5.25;+ dbuf[1] = 0.0;+ dbuf[2] = 2.5;+ dbuf[3] = 0.0;+ dbuf[4] = 0.0;+ dbuf[5] = 0.0;+ dbuf[6] = -18.0;++ sbuf[0] = 6.75f;+ sbuf[1] = -3.5f;+ sbuf[2] = 1.5f;+ sbuf[3] = 0.0f;+ sbuf[4] = 0.0f;++ wbuf[0] = 0;+ wbuf[1] = 0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS3V(P, P, P), 3 | SLJIT_ENTER_FLOAT(4), 3, sizeof(sljit_sw));++ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(F64, F32, F32, F64), SLJIT_IMM, SLJIT_FUNC_ADDR(test_call3_f1));+ /* dbuf[1] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64), SLJIT_FR0, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64));+ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS3(F64, F32, F32, F64));+ sljit_set_target(jump, SLJIT_FUNC_UADDR(test_call3_f1));+ /* dbuf[3] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f64), SLJIT_FR0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test_call3_f2));+ sljit_get_local_base(compiler, SLJIT_R1, 0, -16);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 16);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f32));+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(F32, W, F64, F32), SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0);+ /* sbuf[3] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f32), SLJIT_FR0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -4);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 9);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), 0);+ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS3(F64, W, F32, W));+ sljit_set_target(jump, SLJIT_FUNC_UADDR(test_call3_f3));+ /* dbuf[4] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_f64), SLJIT_FR0, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f32));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -6);+ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS2(F64, F32, W));+ sljit_set_target(jump, SLJIT_FUNC_UADDR(test_call3_f4));+ /* dbuf[5] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_f64), SLJIT_FR0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test_call3_f5));+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8);+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(F32, F32, F64, 32), SLJIT_MEM1(SLJIT_SP), 0);+ /* sbuf[4] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_f32), SLJIT_FR0, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_f64));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test_call3_f6));+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, F64, W), SLJIT_R0, 0);+ /* wbuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 0, SLJIT_R0, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_f64));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 319);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test_call3_f6));+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, F64, W), SLJIT_R1, 0);+ /* wbuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func3((sljit_sw)&dbuf, (sljit_sw)&sbuf, (sljit_sw)&wbuf);+ sljit_free_code(code.code, NULL);++ FAILED(dbuf[1] != 8.5, "test_call3 case 1 failed\n");+ FAILED(dbuf[3] != 0.5, "test_call3 case 2 failed\n");+ FAILED(sbuf[3] != 17.75, "test_call3 case 3 failed\n");+ FAILED(dbuf[4] != 11.75, "test_call3 case 4 failed\n");+ FAILED(dbuf[5] != -9.5, "test_call3 case 5 failed\n");+ FAILED(sbuf[4] != 12, "test_call3 case 6 failed\n");+ FAILED(wbuf[0] != SLJIT_FUNC_ADDR(test_call3_f6) - 18, "test_call3 case 7 failed\n");+ FAILED(wbuf[1] != 301, "test_call3 case 8 failed\n");++ successful_tests++;+}++static sljit_sw test_call4_f1(sljit_sw a, sljit_s32 b, sljit_sw c, sljit_sw d)+{+ return (sljit_sw)(a + b + c + d - SLJIT_FUNC_ADDR(test_call4_f1));+}++static sljit_s32 test_call4_f2(sljit_f64 a, sljit_f32 b, sljit_f64 c, sljit_sw d)+{+ return (sljit_s32)(a + b + c + (sljit_f64)d);+}++static sljit_f32 test_call4_f3(sljit_f32 a, sljit_s32 b, sljit_f64 c, sljit_sw d)+{+ return (sljit_f32)(a + (sljit_f64)b + c + (sljit_f64)d);+}++static sljit_f32 test_call4_f4(sljit_f32 a, sljit_f64 b, sljit_f32 c, sljit_f64 d)+{+ return (sljit_f32)(a + b + c + (sljit_f64)d);+}++static void test_call4(void)+{+ /* Check function calls with four arguments. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_jump* jump = NULL;+ sljit_sw wbuf[5];+ sljit_f64 dbuf[3];+ sljit_f32 sbuf[4];++ if (verbose)+ printf("Run test_call4\n");++ wbuf[0] = 0;+ wbuf[1] = 0;+ wbuf[2] = SLJIT_FUNC_ADDR(test_call4_f1);+ wbuf[3] = 0;+ wbuf[4] = 0;++ if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) {+ dbuf[0] = 5.125;+ dbuf[1] = 6.125;+ dbuf[2] = 4.25;++ sbuf[0] = 0.75;+ sbuf[1] = -1.5;+ sbuf[2] = 0.0;+ sbuf[3] = 0.0;+ }++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS3V(P, P, P), 4 | SLJIT_ENTER_FLOAT(4), 3, sizeof(sljit_sw));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 33);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, -20);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test_call4_f1));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -40);+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, 32, W, W), SLJIT_R2, 0);+ /* wbuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test_call4_f1));+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, -25);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 100);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -10);+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, 32, W, W), SLJIT_R0, 0);+ /* wbuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 231);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 2);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test_call4_f1) - 100);+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, 32, W, W), SLJIT_MEM2(SLJIT_R0, SLJIT_R2), SLJIT_WORD_SHIFT);+ /* wbuf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0);++ if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) {+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S2), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f64));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -100);+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(32, F64, F32, F64, W), SLJIT_IMM, SLJIT_FUNC_ADDR(test_call4_f2));+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_R0, 0);+ /* wbuf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f64));+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 36);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 41);+ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS4(F32, F32, 32, F64, W));+ sljit_set_target(jump, SLJIT_FUNC_UADDR(test_call4_f3));+ /* sbuf[2] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S2), 2 * sizeof(sljit_f32), SLJIT_FR0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test_call4_f4));+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S2), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S1), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR3, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f64));+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(F32, F32, F64, F32, F64), SLJIT_R0, 0);+ /* sbuf[2] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S2), 3 * sizeof(sljit_f32), SLJIT_FR0, 0);+ }++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func3((sljit_sw)&wbuf, (sljit_sw)&dbuf, (sljit_sw)&sbuf);+ sljit_free_code(code.code, NULL);++ FAILED(wbuf[0] != -27, "test_call4 case 1 failed\n");+ FAILED(wbuf[1] != 65, "test_call4 case 2 failed\n");+ FAILED(wbuf[3] != (sljit_sw)wbuf + 133, "test_call4 case 3 failed\n");++ if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) {+ FAILED(wbuf[4] != -88, "test_call4 case 4 failed\n");+ FAILED(sbuf[2] != 79.75f, "test_call4 case 5 failed\n");+ FAILED(sbuf[3] != 8.625f, "test_call4 case 6 failed\n");+ }++ successful_tests++;+}++static sljit_sw test_call5_f1(sljit_sw a)+{+ return a + 10000;+}++static sljit_sw test_call5_f2(sljit_sw a, sljit_s32 b, sljit_s32 c, sljit_sw d)+{+ return a | b | c | d;+}++static sljit_sw test_call5_f3(sljit_sw a, sljit_s32 b, sljit_s32 c, sljit_sw d)+{+ SLJIT_UNUSED_ARG(a);+ return b | c | d;+}++static sljit_sw test_call5_f4(void)+{+ return 7461932;+}++static void test_call5(void)+{+ /* Test tail calls. */+ executable_code code;+ struct sljit_compiler* compiler;+ struct sljit_jump *jump;+ sljit_uw jump_addr;+ sljit_sw executable_offset;+ sljit_sw res;++ if (verbose)+ printf("Run test_call5\n");++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, W), 4, 4, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, -1);+ sljit_emit_icall(compiler, SLJIT_CALL | SLJIT_CALL_RETURN, SLJIT_ARGS1(W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(test_call5_f1));+ /* Should crash. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ res = code.func1(7987);+ sljit_free_code(code.code, NULL);++ FAILED(res != 17987, "test_call5 case 1 failed\n");++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, W), 1, 4, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, -1);+ jump = sljit_emit_call(compiler, SLJIT_CALL | SLJIT_REWRITABLE_JUMP | SLJIT_CALL_RETURN, SLJIT_ARGS1(W, W));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);++ sljit_set_target(jump, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ executable_offset = sljit_get_executable_offset(compiler);+ jump_addr = sljit_get_jump_addr(jump);+ sljit_free_compiler(compiler);++ sljit_set_jump_addr(jump_addr, SLJIT_FUNC_UADDR(test_call5_f1), executable_offset);++ res = code.func1(3903);+ sljit_free_code(code.code, NULL);++ FAILED(res != 13903, "test_call5 case 2 failed\n");++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 4, 2, SLJIT_MAX_LOCAL_SIZE);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test_call5_f2));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x28000000);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0x00140000);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_IMM, 0x00002800);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 0x00000041);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -1);+ sljit_emit_icall(compiler, SLJIT_CALL | SLJIT_CALL_RETURN, SLJIT_ARGS4(W, W, 32, 32, W), SLJIT_MEM1(SLJIT_SP), 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ res = code.func0();+ sljit_free_code(code.code, NULL);++ FAILED(res != 0x28142841, "test_call5 case 3 failed\n");++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 4, 4, SLJIT_MAX_LOCAL_SIZE);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test_call5_f2));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0x81000000);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0x00480000);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_IMM, 0x00002100);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 0x00000014);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -1);+ sljit_emit_icall(compiler, SLJIT_CALL | SLJIT_CALL_RETURN, SLJIT_ARGS4(W, W, 32, 32, W), SLJIT_S3, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ res = code.func0();+ sljit_free_code(code.code, NULL);++ FAILED(res != (sljit_sw)0x81482114, "test_call5 case 4 failed\n");++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 4, 0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test_call5_f3));+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0x342);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_IMM, 0x451000);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 0x21000000);+ sljit_emit_icall(compiler, SLJIT_CALL | SLJIT_CALL_RETURN, SLJIT_ARGS4(W, W, 32, 32, W), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ res = code.func0();+ sljit_free_code(code.code, NULL);++ FAILED(res != 0x21451342, "test_call5 case 5 failed\n");++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 1, 0, 9);+ sljit_emit_icall(compiler, SLJIT_CALL | SLJIT_CALL_RETURN, SLJIT_ARGS0(W), SLJIT_IMM, SLJIT_FUNC_ADDR(test_call5_f4));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ res = code.func0();+ sljit_free_code(code.code, NULL);++ FAILED(res != 7461932, "test_call5 case 6 failed\n");++ successful_tests++;+}++static sljit_sw test_call6_f5(sljit_f64 a, sljit_f64 b, sljit_f64 c, sljit_f64 d)+{+ if (a == 1345.5 && b == -8724.25 && c == 9034.75 && d == 6307.5)+ return 8920567;+ return 0;+}++static sljit_sw test_call6_f6(sljit_f64 a, sljit_f64 b, sljit_f64 c, sljit_sw d)+{+ if (a == 4061.25 && b == -3291.75 && c == 8703.5 && d == 1706)+ return 5074526;+ return 0;+}++static void test_call6(void)+{+ /* Test tail calls. */+ executable_code code;+ struct sljit_compiler* compiler;+ struct sljit_jump *jump;+ sljit_sw res;+ sljit_sw wbuf[1];+ sljit_f64 dbuf[4];++ if (verbose)+ printf("Run test_call6\n");++ if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) {+ if (verbose)+ printf("no fpu available, test_call6 skipped\n");+ successful_tests++;+ return;+ }++ /* Next test. */++ dbuf[0] = 9034.75;+ dbuf[1] = 6307.5;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2(W, F32, F64), 1 | SLJIT_ENTER_FLOAT(4), 1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf);+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_F32, SLJIT_FR0, 0, SLJIT_FR0, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_R0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR3, 0, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64));+ sljit_emit_icall(compiler, SLJIT_CALL | SLJIT_CALL_RETURN, SLJIT_ARGS4(W, F64, F64, F64, F64), SLJIT_IMM, SLJIT_FUNC_ADDR(test_call6_f5));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ res = code.test_call6_f1(1345.5f, -8724.25);+ sljit_free_code(code.code, NULL);++ FAILED(res != 8920567, "test_call6 case 1 failed\n");++ /* Next test. */++ wbuf[0] = SLJIT_FUNC_ADDR(test_call6_f5);++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS4(W, F64, F64, F64, F64), 1 | SLJIT_ENTER_FLOAT(4), 0, 0);+ sljit_emit_icall(compiler, SLJIT_CALL | SLJIT_CALL_RETURN, SLJIT_ARGS4(W, F64, F64, F64, F64), SLJIT_MEM0(), (sljit_sw)wbuf);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ res = code.test_call6_f2(1345.5, -8724.25, 9034.75, 6307.5);+ sljit_free_code(code.code, NULL);++ FAILED(res != 8920567, "test_call6 case 2 failed\n");++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS3(W, F64, F64, F64), 1 | SLJIT_ENTER_FLOAT(4), 0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1706);+ jump = sljit_emit_call(compiler, SLJIT_CALL | SLJIT_CALL_RETURN, SLJIT_ARGS4(W, F64, F64, F64, W));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);++ sljit_set_target(jump, SLJIT_FUNC_UADDR(test_call6_f6));++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ res = code.test_call6_f3(4061.25, -3291.75, 8703.5);+ sljit_free_code(code.code, NULL);++ FAILED(res != 5074526, "test_call6 case 3 failed\n");++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS3(W, F64, F64, F64), (SLJIT_NUMBER_OF_SCRATCH_REGISTERS + 1) | SLJIT_ENTER_FLOAT(4), 0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1706);+ jump = sljit_emit_call(compiler, SLJIT_CALL | SLJIT_CALL_RETURN, SLJIT_ARGS4(W, F64, F64, F64, W));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);++ sljit_set_target(jump, SLJIT_FUNC_UADDR(test_call6_f6));++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ res = code.test_call6_f3(4061.25, -3291.75, 8703.5);+ sljit_free_code(code.code, NULL);++ FAILED(res != 5074526, "test_call6 case 4 failed\n");++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS3(W, F64, F64, F64), (SLJIT_NUMBER_OF_SCRATCH_REGISTERS + 1) | SLJIT_ENTER_FLOAT(3), 1, SLJIT_MAX_LOCAL_SIZE);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1706);+ jump = sljit_emit_call(compiler, SLJIT_CALL | SLJIT_CALL_RETURN, SLJIT_ARGS4(W, F64, F64, F64, W));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);++ sljit_set_target(jump, SLJIT_FUNC_UADDR(test_call6_f6));++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ res = code.test_call6_f3(4061.25, -3291.75, 8703.5);+ sljit_free_code(code.code, NULL);++ FAILED(res != 5074526, "test_call6 case 5 failed\n");++ successful_tests++;+}++static void test_call7(void)+{+ /* Test register argument and keep saved registers. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_jump* jump;+ sljit_sw buf[9];+ sljit_s32 i;++ if (verbose)+ printf("Run test_call7\n");++ for (i = 0; i < 9; i++)+ buf[i] = -1;++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), 4, 2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 7945);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -9267);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 4309);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -8321);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 6803);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -5497);++ jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS4(W, W, W, W, W));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_S0, 0);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S1, 0);+ sljit_emit_return_void(compiler);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG, SLJIT_ARGS4(W, W_R, W_R, W_R, W_R), 4, 2, 32);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&buf);+ /* buf[3-6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 6028);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 4982);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -1289);++ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ sljit_free_code(code.code, NULL);++ FAILED(buf[0] != 6028, "test_call7 case 1 failed\n");+ FAILED(buf[1] != 6803, "test_call7 case 2 failed\n");+ FAILED(buf[2] != -5497, "test_call7 case 3 failed\n");+ FAILED(buf[3] != 7945, "test_call7 case 4 failed\n");+ FAILED(buf[4] != -9267, "test_call7 case 5 failed\n");+ FAILED(buf[5] != 4309, "test_call7 case 6 failed\n");+ FAILED(buf[6] != -8321, "test_call7 case 7 failed\n");++ /* Next test. */++ for (i = 0; i < 9; i++)+ buf[i] = -1;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), 4, 2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -2608);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 4751);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 5740);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -9704);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -8749);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 9213);++ jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS4(W, W, W, W, W));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_S0, 0);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S1, 0);+ sljit_emit_return_void(compiler);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(1), SLJIT_ARGS4(W, W_R, W_R, W_R, W_R), 6, 2, SLJIT_MAX_LOCAL_SIZE);+ sljit_set_context(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(1), SLJIT_ARGS4(W, W_R, W_R, W_R, W_R), 6, 2, SLJIT_MAX_LOCAL_SIZE);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)&buf);+ /* buf[3-7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_sw), SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_sw), SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_sw), SLJIT_R2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 7 * sizeof(sljit_sw), SLJIT_R3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -7351);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 3628);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 0);++ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ sljit_free_code(code.code, NULL);++ FAILED(buf[0] != -7351, "test_call7 case 8 failed\n");+ FAILED(buf[1] != 3628, "test_call7 case 9 failed\n");+ FAILED(buf[2] != 9213, "test_call7 case 10 failed\n");+ FAILED(buf[3] != -8749, "test_call7 case 11 failed\n");+ FAILED(buf[4] != -2608, "test_call7 case 12 failed\n");+ FAILED(buf[5] != 4751, "test_call7 case 13 failed\n");+ FAILED(buf[6] != 5740, "test_call7 case 14 failed\n");+ FAILED(buf[7] != -9704, "test_call7 case 15 failed\n");+ FAILED(buf[8] != -1, "test_call7 case 16 failed\n");++ /* Next test. */++ for (i = 0; i < 9; i++)+ buf[i] = -1;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), 4, 2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8653);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 7245);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -3610);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 4591);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -2865);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 2510);++ jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS4V(W, W, W, W));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S0, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_S1, 0);+ sljit_emit_return_void(compiler);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(2), SLJIT_ARGS4(W, W_R, W_R, W_R, W_R), 4, 3, SLJIT_MAX_LOCAL_SIZE);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, (sljit_sw)&buf);+ /* buf[2-7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 2 * sizeof(sljit_sw), SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 3 * sizeof(sljit_sw), SLJIT_S1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 4 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 5 * sizeof(sljit_sw), SLJIT_R1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 6 * sizeof(sljit_sw), SLJIT_R2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 7 * sizeof(sljit_sw), SLJIT_R3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 5789);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -9214);++ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ sljit_free_code(code.code, NULL);++ FAILED(buf[0] != 5789, "test_call7 case 17 failed\n");+ FAILED(buf[1] != -9214, "test_call7 case 18 failed\n");+ FAILED(buf[2] != -2865, "test_call7 case 19 failed\n");+ FAILED(buf[3] != 2510, "test_call7 case 20 failed\n");+ FAILED(buf[4] != 8653, "test_call7 case 21 failed\n");+ FAILED(buf[5] != 7245, "test_call7 case 22 failed\n");+ FAILED(buf[6] != -3610, "test_call7 case 23 failed\n");+ FAILED(buf[7] != 4591, "test_call7 case 24 failed\n");+ FAILED(buf[8] != -1, "test_call7 case 25 failed\n");++ /* Next test. */++ for (i = 0; i < 9; i++)+ buf[i] = -1;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), 2, 3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 6071);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -3817);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 9250);++ jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS0(W));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_S0, 0);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S1, 0);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 3 * sizeof(sljit_sw), SLJIT_S2, 0);+ sljit_emit_return_void(compiler);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(2), SLJIT_ARGS0(W), 4, 3, SLJIT_MAX_LOCAL_SIZE);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 4 * sizeof(sljit_sw), SLJIT_S0, 0);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 5 * sizeof(sljit_sw), SLJIT_S1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -6278);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1467);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 7150 - 1467);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 8413);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 4892);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -7513);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -1);++ jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG | SLJIT_CALL_RETURN, SLJIT_ARGS4(W, W, W, W, W));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG, SLJIT_ARGS4(W, W_R, W_R, W_R, W_R), 4, 2, 256);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&buf);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_R1, 0);+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R2, 0);+ /* buf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -1);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_IMM, 6923);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ sljit_free_code(code.code, NULL);++ FAILED(buf[0] != 6923, "test_call7 case 26 failed\n");+ FAILED(buf[1] != 4892, "test_call7 case 27 failed\n");+ FAILED(buf[2] != -7513, "test_call7 case 28 failed\n");+ FAILED(buf[3] != 9250, "test_call7 case 29 failed\n");+ FAILED(buf[4] != 6071, "test_call7 case 30 failed\n");+ FAILED(buf[5] != -3817, "test_call7 case 31 failed\n");+ FAILED(buf[6] != -6278, "test_call7 case 32 failed\n");+ FAILED(buf[7] != 7150, "test_call7 case 33 failed\n");+ FAILED(buf[8] != 8413, "test_call7 case 34 failed\n");++ successful_tests++;+}++static void test_call8(void)+{+ /* Test register argument and keep saved registers. */+ executable_code code;+ struct sljit_compiler* compiler;+ struct sljit_jump* jump;+ sljit_sw buf[9];+ sljit_f64 dbuf[3];+ sljit_s32 i;++ if (verbose)+ printf("Run test_call8\n");++ for (i = 0; i < 8; i++)+ buf[i] = -1;++ if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) {+ if (verbose)+ printf("no fpu available, test_call8 skipped\n");+ successful_tests++;+ return;+ }++ /* Next test. */++ for (i = 0; i < 9; i++)+ buf[i] = -1;++ dbuf[0] = 4061.25;+ dbuf[1] = -3291.75;+ dbuf[2] = 8703.5;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), 2 | SLJIT_ENTER_FLOAT(3), 3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&dbuf);+ /* dbuf[0] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_R1), 0);+ /* dbuf[1] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_f64));+ /* dbuf[2] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_f64));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1706);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -8956);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 4381);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -5314);++ jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS4(W, F64, F64, F64, W));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_S0, 0);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S1, 0);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 3 * sizeof(sljit_sw), SLJIT_S2, 0);+ sljit_emit_return_void(compiler);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(1), SLJIT_ARGS4(W, F64, F64, F64, W_R), 1 | SLJIT_ENTER_FLOAT(3), 3, SLJIT_MAX_LOCAL_SIZE);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)&buf);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_sw), SLJIT_S0, 0);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_sw), SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)&dbuf);+ /* dbuf[0] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_FR2, 0);+ /* dbuf[1] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f64), SLJIT_FR0, 0);+ /* dbuf[2] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f64), SLJIT_FR1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2784);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 1503);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -1);++ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ sljit_free_code(code.code, NULL);++ FAILED(buf[0] != 2784, "test_call8 case 1 failed\n");+ FAILED(buf[1] != 1503, "test_call8 case 2 failed\n");+ FAILED(buf[2] != 4381, "test_call8 case 3 failed\n");+ FAILED(buf[3] != -5314, "test_call8 case 4 failed\n");+ FAILED(buf[4] != -8956, "test_call8 case 5 failed\n");+ FAILED(buf[5] != 1706, "test_call8 case 6 failed\n");+ FAILED(buf[6] != -1, "test_call8 case 7 failed\n");+ FAILED(dbuf[0] != 8703.5, "test_call8 case 8 failed\n");+ FAILED(dbuf[1] != 4061.25, "test_call8 case 9 failed\n");+ FAILED(dbuf[2] != -3291.75, "test_call8 case 10 failed\n");++ /* Next test. */++ for (i = 0; i < 9; i++)+ buf[i] = -1;++ dbuf[0] = 4061.25;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), 3 | SLJIT_ENTER_FLOAT(1), 3, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM0(), (sljit_sw)&dbuf);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8793);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -4027);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 2910);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 4619);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -1502);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 5316);++ jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS4V(F64, W, W, W));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S0, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_S1, 0);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_sw), SLJIT_S2, 0);+ sljit_emit_return_void(compiler);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(2), SLJIT_ARGS4V(F64, W_R, W_R, W_R), 3 | SLJIT_ENTER_FLOAT(3), 3, SLJIT_MAX_LOCAL_SIZE);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, (sljit_sw)&buf);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 3 * sizeof(sljit_sw), SLJIT_S0, 0);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 4 * sizeof(sljit_sw), SLJIT_S1, 0);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 5 * sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 6 * sizeof(sljit_sw), SLJIT_R1, 0);+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 7 * sizeof(sljit_sw), SLJIT_R2, 0);++ sljit_emit_fop1(compiler, SLJIT_NEG_F64, SLJIT_MEM0(), (sljit_sw)&dbuf, SLJIT_FR0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 7839);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -9215);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -1);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ sljit_free_code(code.code, NULL);++ FAILED(buf[0] != 7839, "test_call8 case 11 failed\n");+ FAILED(buf[1] != -9215, "test_call8 case 12 failed\n");+ FAILED(buf[2] != 5316, "test_call8 case 13 failed\n");+ FAILED(buf[3] != 4619, "test_call8 case 14 failed\n");+ FAILED(buf[4] != -1502, "test_call8 case 15 failed\n");+ FAILED(buf[5] != 8793, "test_call8 case 16 failed\n");+ FAILED(buf[6] != -4027, "test_call8 case 17 failed\n");+ FAILED(buf[7] != 2910, "test_call8 case 18 failed\n");+ FAILED(buf[8] != -1, "test_call8 case 19 failed\n");+ FAILED(dbuf[0] != -4061.25, "test_call8 case 20 failed\n");++ /* Next test. */++ for (i = 0; i < 9; i++)+ buf[i] = -1;++ dbuf[0] = 4061.25;+ dbuf[1] = -3291.75;+ dbuf[2] = 8703.5;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), 2, 3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 7869);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -5406);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 4951);++ jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS0(W));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_S0, 0);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S1, 0);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 3 * sizeof(sljit_sw), SLJIT_S2, 0);+ sljit_emit_return_void(compiler);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(2), SLJIT_ARGS0(W), 1 | SLJIT_ENTER_FLOAT(3), 3, SLJIT_MAX_LOCAL_SIZE);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 4 * sizeof(sljit_sw), SLJIT_S0, 0);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 5 * sizeof(sljit_sw), SLJIT_S1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf);+ /* dbuf[0] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_R0), 0);+ /* dbuf[1] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64));+ /* dbuf[2] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_f64));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1706);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 4713);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -2078);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -1);++ jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG | SLJIT_CALL_RETURN, SLJIT_ARGS4(W, F64, F64, F64, W));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG, SLJIT_ARGS4(W, F64, F64, F64, W_R), 1 | SLJIT_ENTER_FLOAT(3), 0, 256);++ /* buf[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)&buf[6], SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf);+ /* dbuf[0] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_FR2, 0);+ /* dbuf[1] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_FR0, 0);+ /* dbuf[2] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_f64), SLJIT_FR1, 0);++ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_IMM, 5074);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ sljit_free_code(code.code, NULL);++ FAILED(buf[0] != 5074, "test_call8 case 20 failed\n");+ FAILED(buf[1] != 4713, "test_call8 case 22 failed\n");+ FAILED(buf[2] != -2078, "test_call8 case 23 failed\n");+ FAILED(buf[3] != 4951, "test_call8 case 24 failed\n");+ FAILED(buf[4] != 7869, "test_call8 case 25 failed\n");+ FAILED(buf[5] != -5406, "test_call8 case 26 failed\n");+ FAILED(buf[6] != 1706, "test_call8 case 27 failed\n");+ FAILED(buf[7] != -1, "test_call8 case 28 failed\n");+ FAILED(dbuf[0] != 8703.5, "test_call8 case 29 failed\n");+ FAILED(dbuf[1] != 4061.25, "test_call8 case 30 failed\n");+ FAILED(dbuf[2] != -3291.75, "test_call8 case 31 failed\n");++ successful_tests++;+}++static void test_call9(void)+{+ /* Test register register preservation in keep saveds mode. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw buf[6 + SLJIT_NUMBER_OF_REGISTERS];+ struct sljit_jump* jump;+ sljit_s32 i;++ if (verbose)+ printf("Run test_call9\n");++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), SLJIT_NUMBER_OF_REGISTERS - 3, 3, 0);++ for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS - 3; i++)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, 8469 + 1805 * i);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 3671);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 2418);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 1597);++ jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS4V(W, W, W, W));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)(buf + 6), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 3 * sizeof(sljit_sw), SLJIT_S0, 0);+ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 4 * sizeof(sljit_sw), SLJIT_S1, 0);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 5 * sizeof(sljit_sw), SLJIT_S2, 0);++ for (i = 1; i < SLJIT_NUMBER_OF_REGISTERS - 3; i++)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), (6 + i) * (sljit_sw)sizeof(sljit_sw), SLJIT_R(i), 0);++ sljit_emit_return_void(compiler);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(3), SLJIT_ARGS4V(W_R, W_R, W_R, W_R), 4, 3, SLJIT_MAX_LOCAL_SIZE);+ sljit_set_context(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(3), SLJIT_ARGS4V(W_R, W_R, W_R, W_R), 4, 3, SLJIT_MAX_LOCAL_SIZE);++ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)(buf + 0), SLJIT_S0, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)(buf + 1), SLJIT_S1, 0);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)(buf + 2), SLJIT_S2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 6501);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 7149);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 5732);++ jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG | SLJIT_CALL_RETURN, SLJIT_ARGS0V());+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM0(), 0);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(3), SLJIT_ARGS0V(), 4, 3, SLJIT_MAX_LOCAL_SIZE / 2);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func0();+ sljit_free_code(code.code, NULL);++ FAILED(buf[0] != 3671, "test_call9 case 1 failed\n");+ FAILED(buf[1] != 2418, "test_call9 case 2 failed\n");+ FAILED(buf[2] != 1597, "test_call9 case 3 failed\n");+ FAILED(buf[3] != 6501, "test_call9 case 4 failed\n");+ FAILED(buf[4] != 7149, "test_call9 case 5 failed\n");+ FAILED(buf[5] != 5732, "test_call9 case 6 failed\n");++ for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS - 3; i++) {+ FAILED(buf[6 + i] != 8469 + 1805 * i, "test_call9 case 7 failed\n");+ }++ successful_tests++;+}++static void test_call10(void)+{+ /* Test return with floating point value. */+ executable_code code;+ struct sljit_compiler* compiler;+ struct sljit_jump* jump;+ sljit_f64 dbuf[2];+ sljit_f32 sbuf[2];++ if (verbose)+ printf("Run test_call10\n");++ if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) {+ if (verbose)+ printf("no fpu available, test_call10 skipped\n");+ successful_tests++;+ return;+ }++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(F64, W), 0 | SLJIT_ENTER_FLOAT(3), 1, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_return(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ dbuf[0] = 35.125;+ dbuf[0] = code.test_call10_f2((sljit_sw)dbuf);+ sljit_free_code(code.code, NULL);++ FAILED(dbuf[0] != 35.125, "test_call10 case 1 failed\n");++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(F32, W), 0 | SLJIT_ENTER_FLOAT(1), 1, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_RETURN_FREG, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_return(compiler, SLJIT_MOV_F32, SLJIT_RETURN_FREG, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ sbuf[0] = -9027.5;+ sbuf[0] = code.test_call10_f1((sljit_sw)sbuf);+ sljit_free_code(code.code, NULL);++ FAILED(sbuf[0] != -9027.5, "test_call10 case 2 failed\n");++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(F32, W), 0 | SLJIT_ENTER_FLOAT(1), 1, sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_return(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_SP), 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ sbuf[0] = -6.75;+ sbuf[0] = code.test_call10_f1((sljit_sw)sbuf);+ sljit_free_code(code.code, NULL);++ FAILED(sbuf[0] != -6.75, "test_call10 case 3 failed\n");++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(F64, W), 0 | SLJIT_ENTER_FLOAT(1), 1, 2 * sizeof(sljit_f64));+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_f64), SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_return(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_f64));++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ dbuf[0] = 45.125;+ dbuf[0] = code.test_call10_f2((sljit_sw)dbuf);+ sljit_free_code(code.code, NULL);++ FAILED(dbuf[0] != 45.125, "test_call10 case 4 failed\n");++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), 1 | SLJIT_ENTER_FLOAT(1), 0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)dbuf - 33);+ jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS1(F64, W));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)dbuf);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_RETURN_FREG, 0);+ sljit_emit_return_void(compiler);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG, SLJIT_ARGS1(F64, W_R), 1 | SLJIT_ENTER_FLOAT(1), 0, 0);+ sljit_emit_return(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 33);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ dbuf[0] = 2571.75;+ dbuf[1] = 0;+ code.func0();+ sljit_free_code(code.code, NULL);++ FAILED(dbuf[1] != 2571.75, "test_call10 case 5 failed\n");++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), 1 | SLJIT_ENTER_FLOAT(1), 0, 0);+ jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS0(F32));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)sbuf);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f32), SLJIT_RETURN_FREG, 0);+ sljit_emit_return_void(compiler);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG, SLJIT_ARGS0(F32), 0 | SLJIT_ENTER_FLOAT(1), 0, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_RETURN_FREG, 0, SLJIT_MEM0(), (sljit_sw)sbuf);+ sljit_emit_return(compiler, SLJIT_MOV_F32, SLJIT_RETURN_FREG, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ sbuf[0] = 6310.25;+ sbuf[1] = 0;+ code.func0();+ sljit_free_code(code.code, NULL);++ FAILED(sbuf[1] != 6310.25, "test_call10 case 6 failed\n");++ successful_tests++;+}++static void test_call11(void)+{+ /* Test return_to operation. */+ executable_code code, code2;+ struct sljit_compiler* compiler;+ struct sljit_jump* jump;+ struct sljit_label* label;+ sljit_s32 i;+ sljit_sw buf[3];++ if (verbose)+ printf("Run test_call11\n");++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 2, 1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -7602);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_S0, 0);+ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);+ label = sljit_emit_label(compiler);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_RETURN_REG, 0);+ sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN);+ sljit_emit_return_void(compiler);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(W_R, W_R), 2, 0, 256);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 256 - sizeof(sljit_sw), SLJIT_IMM, -1);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 8945);+ sljit_emit_return_to(compiler, SLJIT_MEM1(SLJIT_R1), 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ buf[0] = (sljit_sw)sljit_get_label_addr(label);+ buf[1] = 0;++ sljit_free_compiler(compiler);+ code.func1((sljit_sw)buf);+ sljit_free_code(code.code, NULL);++ FAILED(buf[0] != 8945, "test_call11 case 1 failed\n");+ FAILED(buf[1] != -7602, "test_call11 case 2 failed\n");++ /* Next test. */++ for (i = 0; i < 3; i++) {+ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 2, 1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 6032);+ jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS1(W, W));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);+ label = sljit_emit_label(compiler);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)buf);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_RETURN_REG, 0);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S0, 0);+ sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN);+ sljit_emit_return_void(compiler);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(1), SLJIT_ARGS1V(W_R), 2, i == 1 ? 2 : 1, SLJIT_MAX_LOCAL_SIZE);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_R0, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw));+ if (i == 2)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 0);+ else+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S(i), 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), SLJIT_MAX_LOCAL_SIZE - sizeof(sljit_sw), SLJIT_IMM, -1);+ if (i != 0)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -3890);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 7145);+ if (i == 2)+ sljit_emit_return_to(compiler, SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_sw));+ else+ sljit_emit_return_to(compiler, SLJIT_S(i), 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ buf[0] = (sljit_sw)sljit_get_label_addr(label);+ buf[1] = 0;+ buf[2] = 0;++ sljit_free_compiler(compiler);++ code.func1((sljit_sw)buf);+ sljit_free_code(code.code, NULL);++ FAILED(buf[0] != 7145, "test_call11 case 3 failed\n");+ FAILED(buf[1] != 6032, "test_call11 case 4 failed\n");+ if (i != 0)+ FAILED(buf[2] != -3890, "test_call11 case 5 failed\n");+ }++ /* Next test. */++ for (i = 0; i < 3; i++) {+ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P_R), 2, 1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_R0, 0);+ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS1(W, W));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);+ label = sljit_emit_label(compiler);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)buf);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_RETURN_REG, 0);+ sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN);+ sljit_emit_return_void(compiler);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(W_R), 2, 1, (i == 0) ? 0 : (i == 1) ? 512 : 32768);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -1);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 0x1000);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, -4502);+ sljit_emit_return_to(compiler, SLJIT_MEM1(SLJIT_R1), -0x1000);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ buf[0] = (sljit_sw)sljit_get_label_addr(label);+ buf[1] = 0;++ sljit_free_compiler(compiler);++ code.func1((sljit_sw)buf);+ sljit_free_code(code.code, NULL);++ FAILED(buf[0] != -4502, "test_call11 case 6 failed\n");+ FAILED(buf[1] != (sljit_sw)buf, "test_call11 case 7 failed\n");+ }++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ i = SLJIT_S2;+#else+ i = SLJIT_S(SLJIT_NUMBER_OF_SAVED_REGISTERS - 1);+#endif++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 2, SLJIT_NUMBER_OF_SAVED_REGISTERS, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, i, 0, SLJIT_IMM, 2 * sizeof(sljit_sw));+ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS0(W));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);+ label = sljit_emit_label(compiler);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_S0, i), 0, SLJIT_RETURN_REG, 0);+ sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN);+ sljit_emit_return_void(compiler);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), 2, SLJIT_NUMBER_OF_SAVED_REGISTERS, 16);+ for (i = 0; i < SLJIT_NUMBER_OF_SAVED_REGISTERS; i++)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S(i), 0, SLJIT_IMM, -1);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, (sljit_sw)(buf + 3));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -3);+ sljit_emit_return_to(compiler, SLJIT_MEM2(SLJIT_RETURN_REG, SLJIT_R1), SLJIT_WORD_SHIFT);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ buf[0] = (sljit_sw)sljit_get_label_addr(label);+ buf[1] = 0;+ buf[2] = 0;++ sljit_free_compiler(compiler);++ code.func1((sljit_sw)buf);+ sljit_free_code(code.code, NULL);++ FAILED(buf[2] != (sljit_sw)(buf + 3), "test_call11 case 8 failed\n");++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(P_R, P), 2, SLJIT_NUMBER_OF_SAVED_REGISTERS, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 586000);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 392);+ sljit_emit_icall(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS0(W), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);+ label = sljit_emit_label(compiler);+ /* buf[0] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S2), 0, SLJIT_S0, 0, SLJIT_S1, 0);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_sw), SLJIT_RETURN_REG, 0);+ sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ buf[0] = (sljit_sw)sljit_get_label_addr(label);++ sljit_free_compiler(compiler);++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(2), SLJIT_ARGS0V(), 2, SLJIT_NUMBER_OF_SAVED_REGISTERS, 16);+ for (i = 2; i < SLJIT_NUMBER_OF_SAVED_REGISTERS; i++)+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S(i), 0, SLJIT_IMM, -1);+ /* buf[2] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM0(), (sljit_sw)(buf + 2), SLJIT_S0, 0, SLJIT_S1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 416000);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 931);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 2906);+ sljit_emit_return_to(compiler, SLJIT_IMM, buf[0]);++ code2.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ buf[0] = 0;+ buf[1] = 0;+ buf[2] = 0;++ code.func2(SLJIT_FUNC_ADDR(code2.func0), (sljit_sw)buf);+ sljit_free_code(code.code, NULL);+ sljit_free_code(code2.code, NULL);++ FAILED(buf[0] != 416931, "test_call11 case 9 failed\n");+ FAILED(buf[1] != 2906, "test_call11 case 10 failed\n");+ FAILED(buf[2] != 586392, "test_call11 case 11 failed\n");++ successful_tests++;+}++static void test_call12(void)+{+ /* Test get return address. */+ executable_code code;+ struct sljit_compiler* compiler;+ struct sljit_jump *jump;+ struct sljit_label *label;+ sljit_uw return_addr = 0;+ sljit_uw buf[1];++ if (verbose)+ printf("Run test_call12\n");++ /* Next test. */++ buf[0] = 0;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(W), 1, 1, 0);+ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS0(W));+ label = sljit_emit_label(compiler);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_RETURN_REG, 0);+ sljit_emit_return_void(compiler);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 1, 0, 0);+ sljit_emit_op_dst(compiler, SLJIT_GET_RETURN_ADDRESS, SLJIT_RETURN_REG, 0);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ return_addr = sljit_get_label_addr(label);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)buf);+ sljit_free_code(code.code, NULL);++ FAILED(buf[0] != return_addr, "test_call12 case 1 failed\n");++ /* Next test. */++ buf[0] = 0;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), 2, 0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -1);+ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS2V(W, W));+ label = sljit_emit_label(compiler);+ sljit_emit_return_void(compiler);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(W, W), 1, SLJIT_NUMBER_OF_SAVED_REGISTERS - 2, SLJIT_MAX_LOCAL_SIZE);+ sljit_emit_op_dst(compiler, SLJIT_GET_RETURN_ADDRESS, SLJIT_MEM0(), (sljit_sw)buf);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ return_addr = sljit_get_label_addr(label);+ sljit_free_compiler(compiler);++ code.func0();+ sljit_free_code(code.code, NULL);++ FAILED(buf[0] != return_addr, "test_call12 case 2 failed\n");++ /* Next test. */++ buf[0] = 0;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(W), 1, 3, 0);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_S2, 0, SLJIT_S0, 0, SLJIT_IMM, 16);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8);+ jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS1V(W));+ label = sljit_emit_label(compiler);+ sljit_emit_return_void(compiler);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(3), SLJIT_ARGS1V(W_R), 1, SLJIT_NUMBER_OF_SAVED_REGISTERS, SLJIT_MAX_LOCAL_SIZE >> 1);+ sljit_emit_op_dst(compiler, SLJIT_GET_RETURN_ADDRESS, SLJIT_MEM2(SLJIT_S2, SLJIT_R0), 1);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ return_addr = sljit_get_label_addr(label);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)buf);+ sljit_free_code(code.code, NULL);++ FAILED(buf[0] != return_addr, "test_call12 case 3 failed\n");++ /* Next test. */++ buf[0] = 0;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(W_R), 1, 0, 0);+ jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS1V(W));+ label = sljit_emit_label(compiler);+ sljit_emit_return_void(compiler);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG, SLJIT_ARGS1V(W_R), 1, SLJIT_NUMBER_OF_SAVED_REGISTERS >> 1, 64);+ sljit_emit_op_dst(compiler, SLJIT_GET_RETURN_ADDRESS, SLJIT_MEM1(SLJIT_SP), 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_MEM1(SLJIT_SP), 0);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ return_addr = sljit_get_label_addr(label);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)buf);+ sljit_free_code(code.code, NULL);++ FAILED(buf[0] != return_addr, "test_call12 case 4 failed\n");++ if (sljit_has_cpu_feature(SLJIT_HAS_FPU) && SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS > 0) {+ /* Next test. */++ buf[0] = 0;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(W), 1, 1, 0);+ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS0(W));+ label = sljit_emit_label(compiler);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_RETURN_REG, 0);+ sljit_emit_return_void(compiler);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 1, 3 | SLJIT_ENTER_FLOAT(SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS), 64);+ sljit_emit_op_dst(compiler, SLJIT_GET_RETURN_ADDRESS, SLJIT_RETURN_REG, 0);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ return_addr = sljit_get_label_addr(label);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)buf);+ sljit_free_code(code.code, NULL);++ FAILED(buf[0] != return_addr, "test_call12 case 5 failed\n");+ }++ successful_tests++;+}++static void test_call13(void)+{+ /* Test get return address. */+ executable_code code;+ struct sljit_compiler* compiler;+ struct sljit_jump *jump;+ void *simple_func;+ sljit_s32 i;++ if (verbose)+ printf("Run test_call13\n");++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ /* This tests expects that the two compiled codes are very close+ to each other, and above the 4GByte address space on 64 bit. */+ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), 0, 0, 0);+ sljit_emit_op2(compiler, SLJIT_ADD32, SLJIT_MEM0(), (sljit_sw)&i, SLJIT_MEM0(), (sljit_sw)&i, SLJIT_IMM, 1);+ sljit_emit_return_void(compiler);++ simple_func = sljit_generate_code(compiler, 0, NULL);+ sljit_free_compiler(compiler);++ compiler = sljit_create_compiler(NULL);+ if (compiler == NULL) {+ sljit_free_code(simple_func, NULL);+ FAILED(!compiler, "cannot create compiler\n");+ }++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 1, 0, 0);++ for (i = 0; i < 65536; i++)+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS0V(), SLJIT_IMM, SLJIT_FUNC_ADDR(simple_func));++ /* Forward jump. */+ jump = sljit_emit_jump(compiler, SLJIT_JUMP);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_set_label(jump, sljit_emit_label(compiler));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 5);+ jump = sljit_emit_cmp(compiler, SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 5);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_set_label(jump, sljit_emit_label(compiler));++ /* Forward label. */+ jump = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_set_label(jump, sljit_emit_label(compiler));++ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_IMM, 0x12345678);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ i = 0;+ FAILED(code.func0() != 0x12345678, "test_call13 case 1 failed\n");+ FAILED(i != 65536, "test_call13 case 2 failed\n");++ sljit_free_code(code.code, NULL);+ sljit_free_code(simple_func, NULL);+ successful_tests++;+}
+ src/c/pcre2/deps/sljit/test_src/sljitTestFloat.h view
@@ -0,0 +1,3059 @@+/*+ * 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 void test_float1(void)+{+ /* Test fpu monadic functions. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_f64 buf[7];+ sljit_sw buf2[6];++ if (verbose)+ printf("Run test_float1\n");++ FAILED(!compiler, "cannot create compiler\n");++ buf[0] = 7.75;+ buf[1] = -4.5;+ buf[2] = 0.0;+ buf[3] = 0.0;+ buf[4] = 0.0;+ buf[5] = 0.0;+ buf[6] = 0.0;++ buf2[0] = 10;+ buf2[1] = 10;+ buf2[2] = 10;+ buf2[3] = 10;+ buf2[4] = 10;+ buf2[5] = 10;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(P, P), 3 | SLJIT_ENTER_FLOAT(6), 2, 0);+ /* buf[2] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM0(), (sljit_sw)&buf[2], SLJIT_MEM0(), (sljit_sw)&buf[1]);+ /* buf[3] */+ sljit_emit_fop1(compiler, SLJIT_ABS_F64, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f64), SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64));+ /* buf[4] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM0(), (sljit_sw)&buf[0]);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2 * sizeof(sljit_f64));+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 0);+ sljit_emit_fop1(compiler, SLJIT_NEG_F64, SLJIT_FR2, 0, SLJIT_FR0, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR3, 0, SLJIT_FR2, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM0(), (sljit_sw)&buf[4], SLJIT_FR3, 0);+ /* buf[5] */+ sljit_emit_fop1(compiler, SLJIT_ABS_F64, SLJIT_FR4, 0, SLJIT_FR1, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_f64), SLJIT_FR4, 0);+ /* buf[6] */+ sljit_emit_fop1(compiler, SLJIT_NEG_F64, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_f64), SLJIT_FR4, 0);++ /* buf2[0] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR5, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_GREATER, SLJIT_FR5, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64));+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_F_GREATER);+ /* buf2[1] */+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_GREATER, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64), SLJIT_FR5, 0);+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_sw), SLJIT_F_GREATER);+ /* buf2[2] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_FR5, 0);+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_EQUAL, SLJIT_FR1, 0, SLJIT_FR1, 0);+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_sw), SLJIT_F_EQUAL);+ /* buf2[3] */+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_LESS, SLJIT_FR1, 0, SLJIT_FR1, 0);+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_sw), SLJIT_F_LESS);+ /* buf2[4] */+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_EQUAL, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64));+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_sw), SLJIT_F_EQUAL);+ /* buf2[5] */+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_NOT_EQUAL, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64));+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_sw), SLJIT_F_NOT_EQUAL);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)&buf, (sljit_sw)&buf2);+ sljit_free_code(code.code, NULL);++ FAILED(buf[2] != -4.5, "test_float1 case 1 failed\n");+ FAILED(buf[3] != 4.5, "test_float1 case 2 failed\n");+ FAILED(buf[4] != -7.75, "test_float1 case 3 failed\n");+ FAILED(buf[5] != 4.5, "test_float1 case 4 failed\n");+ FAILED(buf[6] != -4.5, "test_float1 case 5 failed\n");++ FAILED(buf2[0] != 1, "test_float1 case 6 failed\n");+ FAILED(buf2[1] != 0, "test_float1 case 7 failed\n");+ FAILED(buf2[2] != 1, "test_float1 case 8 failed\n");+ FAILED(buf2[3] != 0, "test_float1 case 9 failed\n");+ FAILED(buf2[4] != 0, "test_float1 case 10 failed\n");+ FAILED(buf2[5] != 1, "test_float1 case 11 failed\n");++ successful_tests++;+}++static void test_float2(void)+{+ /* Test fpu diadic functions. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_f64 buf[15];++ if (verbose)+ printf("Run test_float2\n");++ FAILED(!compiler, "cannot create compiler\n");++ buf[0] = 7.25;+ buf[1] = 3.5;+ buf[2] = 1.75;+ buf[3] = 0.0;+ buf[4] = 0.0;+ buf[5] = 0.0;+ buf[6] = 0.0;+ buf[7] = 0.0;+ buf[8] = 0.0;+ buf[9] = 0.0;+ buf[10] = 0.0;+ buf[11] = 0.0;+ buf[12] = 8.0;+ buf[13] = 4.0;+ buf[14] = 0.0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 3 | SLJIT_ENTER_FLOAT(6), 1, 0);++ /* ADD */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_f64));+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64));+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 2);+ /* buf[3] */+ sljit_emit_fop2(compiler, SLJIT_ADD_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 3, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop2(compiler, SLJIT_ADD_F64, SLJIT_FR0, 0, SLJIT_FR0, 0, SLJIT_FR1, 0);+ sljit_emit_fop2(compiler, SLJIT_ADD_F64, SLJIT_FR1, 0, SLJIT_FR0, 0, SLJIT_FR1, 0);+ /* buf[4] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 4, SLJIT_FR0, 0);+ /* buf[5] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 5, SLJIT_FR1, 0);++ /* SUB */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR3, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 2);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 2);+ /* buf[6] */+ sljit_emit_fop2(compiler, SLJIT_SUB_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 6, SLJIT_FR3, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_R1), SLJIT_F64_SHIFT);+ sljit_emit_fop2(compiler, SLJIT_SUB_F64, SLJIT_FR2, 0, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 2);+ sljit_emit_fop2(compiler, SLJIT_SUB_F64, SLJIT_FR3, 0, SLJIT_FR2, 0, SLJIT_FR3, 0);+ /* buf[7] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 7, SLJIT_FR2, 0);+ /* buf[8] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 8, SLJIT_FR3, 0);++ /* MUL */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1);+ /* buf[9] */+ sljit_emit_fop2(compiler, SLJIT_MUL_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 9, SLJIT_MEM2(SLJIT_S0, SLJIT_R1), SLJIT_F64_SHIFT, SLJIT_FR1, 0);+ sljit_emit_fop2(compiler, SLJIT_MUL_F64, SLJIT_FR1, 0, SLJIT_FR1, 0, SLJIT_FR2, 0);+ sljit_emit_fop2(compiler, SLJIT_MUL_F64, SLJIT_FR5, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 2, SLJIT_FR2, 0);+ /* buf[10] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 10, SLJIT_FR1, 0);+ /* buf[11] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 11, SLJIT_FR5, 0);++ /* DIV */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR5, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 12);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 13);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR4, 0, SLJIT_FR5, 0);+ /* buf[12] */+ sljit_emit_fop2(compiler, SLJIT_DIV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 12, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 12, SLJIT_FR1, 0);+ sljit_emit_fop2(compiler, SLJIT_DIV_F64, SLJIT_FR5, 0, SLJIT_FR5, 0, SLJIT_FR1, 0);+ sljit_emit_fop2(compiler, SLJIT_DIV_F64, SLJIT_FR4, 0, SLJIT_FR1, 0, SLJIT_FR4, 0);+ /* buf[13] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 13, SLJIT_FR5, 0);+ /* buf[14] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 14, SLJIT_FR4, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ sljit_free_code(code.code, NULL);++ FAILED(buf[3] != 10.75, "test_float2 case 1 failed\n");+ FAILED(buf[4] != 5.25, "test_float2 case 2 failed\n");+ FAILED(buf[5] != 7.0, "test_float2 case 3 failed\n");+ FAILED(buf[6] != 0.0, "test_float2 case 4 failed\n");+ FAILED(buf[7] != 5.5, "test_float2 case 5 failed\n");+ FAILED(buf[8] != 3.75, "test_float2 case 6 failed\n");+ FAILED(buf[9] != 24.5, "test_float2 case 7 failed\n");+ FAILED(buf[10] != 38.5, "test_float2 case 8 failed\n");+ FAILED(buf[11] != 9.625, "test_float2 case 9 failed\n");+ FAILED(buf[12] != 2.0, "test_float2 case 10 failed\n");+ FAILED(buf[13] != 2.0, "test_float2 case 11 failed\n");+ FAILED(buf[14] != 0.5, "test_float2 case 12 failed\n");++ successful_tests++;+}++static void test_float3(void)+{+ /* Floating point set flags. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_s32 i;++ sljit_sw buf[16];+ union {+ sljit_f64 value;+ struct {+ sljit_s32 value1;+ sljit_s32 value2;+ } u;+ } dbuf[4];++ if (verbose)+ printf("Run test_float3\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 16; i++)+ buf[i] = 5;++ /* Two NaNs */+ dbuf[0].u.value1 = 0x7fffffff;+ dbuf[0].u.value2 = 0x7fffffff;+ dbuf[1].u.value1 = 0x7fffffff;+ dbuf[1].u.value2 = 0x7fffffff;+ dbuf[2].value = -13.0;+ dbuf[3].value = 27.0;++ SLJIT_ASSERT(sizeof(sljit_f64) == 8 && sizeof(sljit_s32) == 4 && sizeof(dbuf[0]) == 8);++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(P, P), 1 | SLJIT_ENTER_FLOAT(4), 2, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), 0);+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_UNORDERED, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f64), SLJIT_FR0, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f64));+ /* buf[0] */+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_UNORDERED);+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_ORDERED, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f64), SLJIT_FR0, 0);+ /* buf[1] */+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_ORDERED);++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f64));+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_UNORDERED, SLJIT_FR1, 0, SLJIT_FR2, 0);+ /* buf[2] */+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_UNORDERED);+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_ORDERED, SLJIT_FR1, 0, SLJIT_FR2, 0);+ /* buf[3] */+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_ORDERED);+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_LESS, SLJIT_FR1, 0, SLJIT_FR2, 0);+ /* buf[4] */+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_F_LESS);+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_GREATER_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0);+ /* buf[5] */+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_F_GREATER_EQUAL);+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_GREATER, SLJIT_FR1, 0, SLJIT_FR2, 0);+ /* buf[6] */+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_F_GREATER);+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_LESS_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0);+ /* buf[7] */+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_F_LESS_EQUAL);+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0);+ /* buf[8] */+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_F_EQUAL);+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_NOT_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0);+ /* buf[9] */+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_F_NOT_EQUAL);++ sljit_emit_fop2(compiler, SLJIT_ADD_F64, SLJIT_FR3, 0, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f64));+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_UNORDERED, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f64));+ /* buf[10] */+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_UNORDERED);+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_EQUAL, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f64));+ /* buf[11] */+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_F_EQUAL);++ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_ORDERED, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f64), SLJIT_FR0, 0);+ /* buf[12] */+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_ORDERED);++ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_UNORDERED, SLJIT_FR3, 0, SLJIT_FR2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 0);+ /* buf[13] */+ cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_UNORDERED);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)&buf, (sljit_sw)&dbuf);++ FAILED(buf[0] != 1, "test_float3 case 1 failed\n");+ FAILED(buf[1] != 2, "test_float3 case 2 failed\n");+ FAILED(buf[2] != 2, "test_float3 case 3 failed\n");+ FAILED(buf[3] != 1, "test_float3 case 4 failed\n");+ FAILED(buf[4] != 1, "test_float3 case 5 failed\n");+ FAILED(buf[5] != 2, "test_float3 case 6 failed\n");+ FAILED(buf[6] != 2, "test_float3 case 7 failed\n");+ FAILED(buf[7] != 1, "test_float3 case 8 failed\n");+ FAILED(buf[8] != 2, "test_float3 case 9 failed\n");+ FAILED(buf[9] != 1, "test_float3 case 10 failed\n");+ FAILED(buf[10] != 2, "test_float3 case 11 failed\n");+ FAILED(buf[11] != 1, "test_float3 case 12 failed\n");+ FAILED(buf[12] != 2, "test_float3 case 13 failed\n");+ FAILED(buf[13] != 1, "test_float3 case 14 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test_float4(void)+{+ /* Test inline assembly. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_f64 buf[3];+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)+ sljit_u8 inst[16];+#else+ sljit_u32 inst;+#endif++ if (verbose)+ printf("Run test_float4\n");++ buf[0] = 13.5;+ buf[1] = -2.25;+ buf[2] = 0.0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 0 | SLJIT_ENTER_FLOAT(2), 1, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64));+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)+ /* addsd x, xm */+ inst[0] = 0xf2;+ inst[1] = 0x0f;+ inst[2] = 0x58;+ inst[3] = (sljit_u8)(0xc0 | (sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0) << 3)+ | sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR1));+ sljit_emit_op_custom(compiler, inst, 4);+#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)+ /* addsd x, xm */+ if (sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0) > 7 || sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR1) > 7) {+ inst[0] = 0;+ if (sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0) > 7)+ inst[0] |= 0x04; /* REX_R */+ if (sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR1) > 7)+ inst[0] |= 0x01; /* REX_B */+ inst[1] = 0xf2;+ inst[2] = 0x0f;+ inst[3] = 0x58;+ inst[4] = (sljit_u8)(0xc0 | ((sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0) & 0x7) << 3)+ | (sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR1) & 0x7));+ sljit_emit_op_custom(compiler, inst, 5);+ } else {+ inst[0] = 0xf2;+ inst[1] = 0x0f;+ inst[2] = 0x58;+ inst[3] = (sljit_u8)(0xc0 | (sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0) << 3)+ | sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR1));+ sljit_emit_op_custom(compiler, inst, 4);+ }+#elif (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32)+ /* vadd.f64 dd, dn, dm */+ inst = 0xee300b00 | ((sljit_u32)sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0) << 12)+ | ((sljit_u32)sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0) << 16)+ | (sljit_u32)sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR1);+ sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32));+#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)+ /* fadd rd, rn, rm */+ inst = 0x1e602800 | (sljit_u32)sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0)+ | ((sljit_u32)sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0) << 5)+ | ((sljit_u32)sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR1) << 16);+ sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32));+#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)+ /* fadd frD, frA, frB */+ inst = (63u << 26) | (21u << 1) | ((sljit_u32)sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0) << 21)+ | ((sljit_u32)sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0) << 16)+ | ((sljit_u32)sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR1) << 11);+ sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32));+#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)+ /* add.d fd, fs, ft */+ inst = (17u << 26) | (17u << 21) | ((sljit_u32)sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0) << 6)+ | ((sljit_u32)sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0) << 11)+ | ((sljit_u32)sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR1) << 16);+ sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32));+#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)+ /* fadd.d rd, rs1, rs2 */+ inst = (0x1u << 25) | (0x7u << 12) | (0x53u)+ | ((sljit_u32)sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0) << 7)+ | ((sljit_u32)sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0) << 15)+ | (sljit_u32)sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR1) << 20;+ sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32));+#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)+ /* adbr r1, r2 */+ inst = 0xb31a0000+ | ((sljit_u32)sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0) << 4)+ | (sljit_u32)sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR1);+ sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32));+#elif (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)+ /* fadd.d rd, rs1, rs2 */+ inst = (0x202u << 15)+ | ((sljit_u32)sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0))+ | ((sljit_u32)sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0) << 5)+ | (sljit_u32)sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR1) << 10;+ sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32));+#endif+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64), SLJIT_FR0, 0);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ sljit_free_code(code.code, NULL);++ FAILED(buf[2] != 11.25, "test_float4 case 1 failed\n");++ successful_tests++;+}++static void test_float5(void)+{+ /* Test floating point compare. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_jump* jump;+ sljit_sw res[4];++ union {+ sljit_f64 value;+ struct {+ sljit_u32 value1;+ sljit_u32 value2;+ } u;+ } dbuf[4];++ if (verbose)+ printf("Run test_float5\n");++ FAILED(!compiler, "cannot create compiler\n");++ dbuf[0].value = 12.125;+ /* a NaN */+ dbuf[1].u.value1 = 0x7fffffff;+ dbuf[1].u.value2 = 0x7fffffff;+ dbuf[2].value = -13.5;+ dbuf[3].value = 12.125;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 1 | SLJIT_ENTER_FLOAT(3), 1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2);+ /* dbuf[0] < dbuf[2] -> -2 */+ jump = sljit_emit_fcmp(compiler, SLJIT_F_GREATER_EQUAL, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_F64_SHIFT);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_IMM, -2);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 0);+ /* dbuf[0] and dbuf[1] is not NaN -> 5 */+ jump = sljit_emit_fcmp(compiler, SLJIT_UNORDERED, SLJIT_MEM0(), (sljit_sw)&dbuf[1], SLJIT_FR1, 0);+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_IMM, 5);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f64));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 11);+ /* dbuf[0] == dbuf[3] -> 11 */+ jump = sljit_emit_fcmp(compiler, SLJIT_F_EQUAL, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_FR2, 0);++ /* else -> -17 */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, -17);+ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ res[0] = code.func1((sljit_sw)&dbuf);+ dbuf[3].value = 12;+ res[1] = code.func1((sljit_sw)&dbuf);+ dbuf[1].value = 0;+ res[2] = code.func1((sljit_sw)&dbuf);+ dbuf[2].value = 20;+ res[3] = code.func1((sljit_sw)&dbuf);++ sljit_free_code(code.code, NULL);++ FAILED(res[0] != 11, "test_float5 case 1 failed\n");+ FAILED(res[1] != -17, "test_float5 case 2 failed\n");+ FAILED(res[2] != 5, "test_float5 case 3 failed\n");+ FAILED(res[3] != -2, "test_float5 case 4 failed\n");++ successful_tests++;+}++static void test_float6(void)+{+ /* Test single precision floating point. */++ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_f32 buf[14];+ sljit_sw buf2[6];+ struct sljit_jump* jump;++ if (verbose)+ printf("Run test_float6\n");++ FAILED(!compiler, "cannot create compiler\n");++ buf[0] = 5.5;+ buf[1] = -7.25;+ buf[2] = 0;+ buf[3] = 0;+ buf[4] = 0;+ buf[5] = 0;+ buf[6] = 0;+ buf[7] = 8.75;+ buf[8] = 0;+ buf[9] = 16.5;+ buf[10] = 0;+ buf[11] = 0;+ buf[12] = 345.75;+ buf[13] = -678.5;++ buf2[0] = -1;+ buf2[1] = -1;+ buf2[2] = -1;+ buf2[3] = -1;+ buf2[4] = -1;+ buf2[5] = -1;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(P, P), 3 | SLJIT_ENTER_FLOAT(6), 2, 0);++ /* buf[2] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR5, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_NEG_F32, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f32), SLJIT_FR0, 0);+ /* buf[3] */+ sljit_emit_fop1(compiler, SLJIT_ABS_F32, SLJIT_FR1, 0, SLJIT_FR5, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f32), SLJIT_FR1, 0);+ /* buf[4] */+ sljit_emit_fop1(compiler, SLJIT_ABS_F32, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_f32), SLJIT_FR5, 0);+ /* buf[5] */+ sljit_emit_fop1(compiler, SLJIT_NEG_F32, SLJIT_FR4, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_f32), SLJIT_FR4, 0);++ /* buf[6] */+ sljit_emit_fop2(compiler, SLJIT_ADD_F32, SLJIT_FR0, 0, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_f32), SLJIT_FR0, 0);+ /* buf[7] */+ sljit_emit_fop2(compiler, SLJIT_SUB_F32, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_f32), SLJIT_FR5, 0);+ /* buf[8] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop2(compiler, SLJIT_MUL_F32, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_f32), SLJIT_FR0, 0, SLJIT_FR0, 0);+ /* buf[9] */+ sljit_emit_fop2(compiler, SLJIT_DIV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_f32), SLJIT_FR0, 0);+ sljit_emit_fop1(compiler, SLJIT_ABS_F32, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_f32), SLJIT_FR2, 0);+ /* buf[10] */+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 0x3d0ac);+ sljit_emit_fop1(compiler, SLJIT_NEG_F32, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_R0), 0x3d0ac);+ /* buf[11] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 0x3d0ac + sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_ABS_F32, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_R0), -0x3d0ac);++ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR3, 0, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_f32));+ sljit_emit_fop2(compiler, SLJIT_ADD_F32, SLJIT_FR3, 0, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_f32), SLJIT_FR3, 0);+ /* buf[12] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_f32), SLJIT_FR3, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR3, 0, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_f32));+ sljit_emit_fop2(compiler, SLJIT_MUL_F32, SLJIT_FR1, 0, SLJIT_FR3, 0, SLJIT_FR1, 0);+ /* buf[13] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_f32), SLJIT_FR1, 0);++ /* buf2[0] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_EQUAL, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 0);+ cond_set(compiler, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_F_EQUAL);+ /* buf2[1] */+ sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_LESS, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 0);+ cond_set(compiler, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_sw), SLJIT_F_LESS);+ /* buf2[2] */+ sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0);+ cond_set(compiler, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_sw), SLJIT_F_EQUAL);+ /* buf2[3] */+ sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_GREATER_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0);+ cond_set(compiler, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_sw), SLJIT_F_GREATER_EQUAL);++ /* buf2[4] */+ jump = sljit_emit_fcmp(compiler, SLJIT_F_LESS_EQUAL | SLJIT_32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f32));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_sw), SLJIT_IMM, 7);+ sljit_set_label(jump, sljit_emit_label(compiler));++ /* buf2[5] */+ jump = sljit_emit_fcmp(compiler, SLJIT_F_GREATER | SLJIT_32, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_FR2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_sw), SLJIT_IMM, 6);+ sljit_set_label(jump, sljit_emit_label(compiler));++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)&buf, (sljit_sw)&buf2);+ sljit_free_code(code.code, NULL);++ FAILED(buf[2] != -5.5, "test_float6 case 1 failed\n");+ FAILED(buf[3] != 7.25, "test_float6 case 2 failed\n");+ FAILED(buf[4] != 7.25, "test_float6 case 3 failed\n");+ FAILED(buf[5] != -5.5, "test_float6 case 4 failed\n");+ FAILED(buf[6] != -1.75, "test_float6 case 5 failed\n");+ FAILED(buf[7] != 16.0, "test_float6 case 6 failed\n");+ FAILED(buf[8] != 30.25, "test_float6 case 7 failed\n");+ FAILED(buf[9] != 3, "test_float6 case 8 failed\n");+ FAILED(buf[10] != -5.5, "test_float6 case 9 failed\n");+ FAILED(buf[11] != 7.25, "test_float6 case 10 failed\n");+ FAILED(buf[12] != -332.75, "test_float6 case 11 failed\n");+ FAILED(buf[13] != -234591.375, "test_float6 case 12 failed\n");+ FAILED(buf2[0] != 1, "test_float6 case 13 failed\n");+ FAILED(buf2[1] != 2, "test_float6 case 14 failed\n");+ FAILED(buf2[2] != 2, "test_float6 case 15 failed\n");+ FAILED(buf2[3] != 1, "test_float6 case 16 failed\n");+ FAILED(buf2[4] != 7, "test_float6 case 17 failed\n");+ FAILED(buf2[5] != -1, "test_float6 case 18 failed\n");++ successful_tests++;+}++static void test_float7(void)+{+ /* Test floating point conversions. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ int i;+ sljit_f64 dbuf[10];+ sljit_f32 sbuf[10];+ sljit_sw wbuf[10];+ sljit_s32 ibuf[10];++ if (verbose)+ printf("Run test_float7\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 10; i++) {+ dbuf[i] = 0.0;+ sbuf[i] = 0.0;+ wbuf[i] = 0;+ ibuf[i] = 0;+ }++ dbuf[0] = 123.5;+ dbuf[1] = -367;+ dbuf[2] = 917.75;++ sbuf[0] = 476.25;+ sbuf[1] = -1689.75;++ wbuf[0] = 2345;++ ibuf[0] = 312;+ ibuf[1] = -9324;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), 3 | SLJIT_ENTER_FLOAT(6), 3, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&dbuf);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)&sbuf);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, (sljit_sw)&wbuf);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)&ibuf);++ /* sbuf[2] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_F64, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR5, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 3);+ /* sbuf[3] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_F64, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_F32_SHIFT, SLJIT_FR5, 0);+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_F32, SLJIT_FR4, 0, SLJIT_MEM1(SLJIT_S1), 0);+ /* dbuf[3] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f64), SLJIT_FR4, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR3, 0, SLJIT_MEM1(SLJIT_S1), 0);+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_F32, SLJIT_FR2, 0, SLJIT_FR3, 0);+ /* dbuf[4] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_f64), SLJIT_FR2, 0);+ /* sbuf[4] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_f32), SLJIT_FR3, 0);++ /* wbuf[1] */+ sljit_emit_fop1(compiler, SLJIT_CONV_SW_FROM_F64, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2);+ sljit_emit_fop1(compiler, SLJIT_CONV_SW_FROM_F64, SLJIT_R0, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_F64_SHIFT);+ /* wbuf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 2 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR5, 0, SLJIT_MEM1(SLJIT_S1), 0);+ /* wbuf[3] */+ sljit_emit_fop1(compiler, SLJIT_CONV_SW_FROM_F32, SLJIT_MEM1(SLJIT_S2), 3 * sizeof(sljit_sw), SLJIT_FR5, 0);+ sljit_emit_fop1(compiler, SLJIT_NEG_F32, SLJIT_FR0, 0, SLJIT_FR5, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 4);+ /* wbuf[4] */+ sljit_emit_fop1(compiler, SLJIT_CONV_SW_FROM_F32, SLJIT_MEM2(SLJIT_S2, SLJIT_R1), SLJIT_WORD_SHIFT, SLJIT_FR0, 0);+ sljit_emit_fop1(compiler, SLJIT_NEG_F64, SLJIT_FR4, 0, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64));+ /* ibuf[2] */+ sljit_emit_fop1(compiler, SLJIT_CONV_S32_FROM_F64, SLJIT_MEM1(SLJIT_R2), 2 * sizeof(sljit_s32), SLJIT_FR4, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_CONV_S32_FROM_F32, SLJIT_R0, 0, SLJIT_FR1, 0);+ /* ibuf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R2), 3 * sizeof(sljit_s32), SLJIT_R0, 0);++ /* dbuf[5] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_SW, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_f64), SLJIT_MEM1(SLJIT_S2), 0);+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_SW, SLJIT_FR2, 0, SLJIT_IMM, -6213);+ /* dbuf[6] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_f64), SLJIT_FR2, 0);+ /* dbuf[7] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_S32, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_f64), SLJIT_MEM0(), (sljit_sw)&ibuf[0]);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R2), sizeof(sljit_s32));+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_S32, SLJIT_FR1, 0, SLJIT_R0, 0);+ /* dbuf[8] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_f64), SLJIT_FR1, 0);+ /* dbuf[9] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_SW, SLJIT_MEM0(), (sljit_sw)(dbuf + 9), SLJIT_IMM, -77);+ /* sbuf[5] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_SW, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_f32), SLJIT_IMM, -123);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 7190);+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_SW, SLJIT_FR3, 0, SLJIT_R0, 0);+ /* sbuf[6] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_f32), SLJIT_FR3, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 123);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_R2, 0, SLJIT_IMM, 123 * sizeof(sljit_s32));+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_S32, SLJIT_FR1, 0, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 2);+ /* sbuf[7] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 7 * sizeof(sljit_f32), SLJIT_FR1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 3812);+ /* sbuf[8] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_S32, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_F32_SHIFT, SLJIT_R1, 0);+ /* sbuf[9] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_SW, SLJIT_MEM0(), (sljit_sw)(sbuf + 9), SLJIT_IMM, -79);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func0();+ sljit_free_code(code.code, NULL);++ FAILED(dbuf[3] != 476.25, "test_float7 case 1 failed\n");+ FAILED(dbuf[4] != 476.25, "test_float7 case 2 failed\n");+ FAILED(dbuf[5] != 2345.0, "test_float7 case 3 failed\n");+ FAILED(dbuf[6] != -6213.0, "test_float7 case 4 failed\n");+ FAILED(dbuf[7] != 312.0, "test_float7 case 5 failed\n");+ FAILED(dbuf[8] != -9324.0, "test_float7 case 6 failed\n");+ FAILED(dbuf[9] != -77.0, "test_float7 case 7 failed\n");++ FAILED(sbuf[2] != 123.5, "test_float7 case 8 failed\n");+ FAILED(sbuf[3] != 123.5, "test_float7 case 9 failed\n");+ FAILED(sbuf[4] != 476.25, "test_float7 case 10 failed\n");+ FAILED(sbuf[5] != -123, "test_float7 case 11 failed\n");+ FAILED(sbuf[6] != 7190, "test_float7 case 12 failed\n");+ FAILED(sbuf[7] != 312, "test_float7 case 13 failed\n");+ FAILED(sbuf[8] != 3812, "test_float7 case 14 failed\n");+ FAILED(sbuf[9] != -79.0, "test_float7 case 15 failed\n");++ FAILED(wbuf[1] != -367, "test_float7 case 16 failed\n");+ FAILED(wbuf[2] != 917, "test_float7 case 17 failed\n");+ FAILED(wbuf[3] != 476, "test_float7 case 18 failed\n");+ FAILED(wbuf[4] != -476, "test_float7 case 19 failed\n");++ FAILED(ibuf[2] != -917, "test_float7 case 20 failed\n");+ FAILED(ibuf[3] != -1689, "test_float7 case 21 failed\n");++ successful_tests++;+}++static void test_float8(void)+{+ /* Test floating point conversions. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ int i;+ sljit_f64 dbuf[10];+ sljit_f32 sbuf[9];+ sljit_sw wbuf[9];+ sljit_s32 ibuf[9];+ sljit_s32* dbuf_ptr = (sljit_s32*)dbuf;+ sljit_s32* sbuf_ptr = (sljit_s32*)sbuf;++ if (verbose)+ printf("Run test_float8\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 9; i++) {+ dbuf_ptr[i << 1] = -1;+ dbuf_ptr[(i << 1) + 1] = -1;+ sbuf_ptr[i] = -1;+ wbuf[i] = -1;+ ibuf[i] = -1;+ }++#if IS_64BIT+ dbuf[9] = (sljit_f64)SLJIT_W(0x1122334455);+#endif+ dbuf[0] = 673.75;+ sbuf[0] = -879.75;+ wbuf[0] = 345;+ ibuf[0] = -249;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), 3 | SLJIT_ENTER_FLOAT(3), 3, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&dbuf);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)&sbuf);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, (sljit_sw)&wbuf);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)&ibuf);++ /* dbuf[2] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_F32, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64), SLJIT_MEM1(SLJIT_S1), 0);+ /* sbuf[2] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_F64, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_S0), 0);+ /* wbuf[2] */+ sljit_emit_fop1(compiler, SLJIT_CONV_SW_FROM_F64, SLJIT_MEM1(SLJIT_S2), 2 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 0);+ /* wbuf[4] */+ sljit_emit_fop1(compiler, SLJIT_CONV_SW_FROM_F32, SLJIT_MEM1(SLJIT_S2), 4 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S1), 0);+ /* ibuf[2] */+ sljit_emit_fop1(compiler, SLJIT_CONV_S32_FROM_F64, SLJIT_MEM1(SLJIT_R2), 2 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_S0), 0);+ /* ibuf[4] */+ sljit_emit_fop1(compiler, SLJIT_CONV_S32_FROM_F32, SLJIT_MEM1(SLJIT_R2), 4 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_S1), 0);+ /* dbuf[4] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_SW, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_f64), SLJIT_MEM1(SLJIT_S2), 0);+ /* sbuf[4] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_SW, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_S2), 0);+ /* dbuf[6] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_S32, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_f64), SLJIT_MEM1(SLJIT_R2), 0);+ /* sbuf[6] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_S32, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_R2), 0);++#if IS_64BIT+ sljit_emit_fop1(compiler, SLJIT_CONV_SW_FROM_F64, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_f64));+ /* wbuf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 8 * sizeof(sljit_sw), SLJIT_R0, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_f64));+ sljit_emit_fop1(compiler, SLJIT_CONV_S32_FROM_F64, SLJIT_R0, 0, SLJIT_FR2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_AND32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0xffff);+ /* ibuf[8] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R2), 8 * sizeof(sljit_s32), SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x4455667788));+ /* dbuf[8] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_SW, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_f64), SLJIT_R0, 0);+ /* dbuf[9] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_S32, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_f64), SLJIT_IMM, SLJIT_W(0x7766554433));+#endif /* IS_64BIT */++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func0();+ sljit_free_code(code.code, NULL);++ FAILED(dbuf_ptr[(1 * 2) + 0] != -1, "test_float8 case 1 failed\n");+ FAILED(dbuf_ptr[(1 * 2) + 1] != -1, "test_float8 case 2 failed\n");+ FAILED(dbuf[2] != -879.75, "test_float8 case 3 failed\n");+ FAILED(dbuf_ptr[(3 * 2) + 0] != -1, "test_float8 case 4 failed\n");+ FAILED(dbuf_ptr[(3 * 2) + 1] != -1, "test_float8 case 5 failed\n");+ FAILED(dbuf[4] != 345, "test_float8 case 6 failed\n");+ FAILED(dbuf_ptr[(5 * 2) + 0] != -1, "test_float8 case 7 failed\n");+ FAILED(dbuf_ptr[(5 * 2) + 1] != -1, "test_float8 case 8 failed\n");+ FAILED(dbuf[6] != -249, "test_float8 case 9 failed\n");+ FAILED(dbuf_ptr[(7 * 2) + 0] != -1, "test_float8 case 10 failed\n");+ FAILED(dbuf_ptr[(7 * 2) + 1] != -1, "test_float8 case 11 failed\n");++ FAILED(sbuf_ptr[1] != -1, "test_float8 case 12 failed\n");+ FAILED(sbuf[2] != 673.75, "test_float8 case 13 failed\n");+ FAILED(sbuf_ptr[3] != -1, "test_float8 case 14 failed\n");+ FAILED(sbuf[4] != 345, "test_float8 case 15 failed\n");+ FAILED(sbuf_ptr[5] != -1, "test_float8 case 16 failed\n");+ FAILED(sbuf[6] != -249, "test_float8 case 17 failed\n");+ FAILED(sbuf_ptr[7] != -1, "test_float8 case 18 failed\n");++ FAILED(wbuf[1] != -1, "test_float8 case 19 failed\n");+ FAILED(wbuf[2] != 673, "test_float8 case 20 failed\n");+ FAILED(wbuf[3] != -1, "test_float8 case 21 failed\n");+ FAILED(wbuf[4] != -879, "test_float8 case 22 failed\n");+ FAILED(wbuf[5] != -1, "test_float8 case 23 failed\n");++ FAILED(ibuf[1] != -1, "test_float8 case 24 failed\n");+ FAILED(ibuf[2] != 673, "test_float8 case 25 failed\n");+ FAILED(ibuf[3] != -1, "test_float8 case 26 failed\n");+ FAILED(ibuf[4] != -879, "test_float8 case 27 failed\n");+ FAILED(ibuf[5] != -1, "test_float8 case 28 failed\n");++#if IS_64BIT+ FAILED(dbuf[8] != (sljit_f64)SLJIT_W(0x4455667788), "test_float8 case 29 failed\n");+ FAILED(dbuf[9] != (sljit_f64)SLJIT_W(0x66554433), "test_float8 case 30 failed\n");+ FAILED(wbuf[8] != SLJIT_W(0x1122334455), "test_float8 case 31 failed\n");+ FAILED(ibuf[8] == 0x4455, "test_float8 case 32 failed\n");+#endif /* IS_64BIT */++ successful_tests++;+}++static void test_float9(void)+{+ /* Test stack and floating point operations. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+#if !IS_X86+ sljit_uw size1, size2, size3;+ int result;+#endif+ sljit_f32 sbuf[7];++ if (verbose)+ printf("Run test_float9\n");++ FAILED(!compiler, "cannot create compiler\n");++ sbuf[0] = 245.5;+ sbuf[1] = -100.25;+ sbuf[2] = 713.75;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 3 | SLJIT_ENTER_FLOAT(6), 3, 8 * sizeof(sljit_f32));++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_f32), SLJIT_MEM1(SLJIT_SP), 0);+ /* sbuf[3] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_f32));+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_f32), SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f32));+ sljit_emit_fop2(compiler, SLJIT_ADD_F32, SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_f32));+ /* sbuf[4] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_f32));+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_f32), SLJIT_IMM, 5934);+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_S32, SLJIT_MEM1(SLJIT_SP), 3 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_f32));+ /* sbuf[5] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_SP), 3 * sizeof(sljit_f32));++#if !IS_X86+ size1 = compiler->size;+#endif+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f32));+#if !IS_X86+ size2 = compiler->size;+#endif+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR5, 0, SLJIT_FR2, 0);+#if !IS_X86+ size3 = compiler->size;+#endif+ /* sbuf[6] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_f32), SLJIT_FR5, 0);+#if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)+ result = (compiler->size - size3) == 2 && (size3 - size2) == 1 && (size2 - size1) == 2;+#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)+ result = ((compiler->size - size3) == 1 || (compiler->size - size3) == 2) && ((size3 - size2) == 1 || (size3 - size2) == 2) && ((size2 - size1) == 1 || (size2 - size1) == 2);+#elif !IS_X86+ result = (compiler->size - size3) == (size3 - size2) && (size3 - size2) == (size2 - size1);+#endif++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&sbuf);+ sljit_free_code(code.code, NULL);++ FAILED(sbuf[3] != 245.5, "test_float9 case 1 failed\n");+ FAILED(sbuf[4] != 145.25, "test_float9 case 2 failed\n");+ FAILED(sbuf[5] != 5934, "test_float9 case 3 failed\n");+ FAILED(sbuf[6] != 713.75, "test_float9 case 4 failed\n");+#if !IS_X86+ FAILED(!result, "test_float9 case 5 failed\n");+#endif++ successful_tests++;+}++static void test_float10(void)+{+ /* Test all registers provided by the CPU. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_jump* jump;+ sljit_f64 buf[3];+ sljit_s32 i;++ if (verbose)+ printf("Run test_float10\n");++ FAILED(!compiler, "cannot create compiler\n");+ buf[0] = 6.25;+ buf[1] = 17.75;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 0 | SLJIT_ENTER_FLOAT(SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS),+ 1 | SLJIT_ENTER_FLOAT(SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS), 0);++ for (i = 0; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++)+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR(i), 0, SLJIT_MEM1(SLJIT_S0), 0);++ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS0V());+ /* SLJIT_FR0 contains the first value. */+ for (i = 1; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++)+ sljit_emit_fop2(compiler, SLJIT_ADD_F64, SLJIT_FR0, 0, SLJIT_FR0, 0, SLJIT_FR(i), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64), SLJIT_FR0, 0);++ sljit_emit_return_void(compiler);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), 1 | SLJIT_ENTER_FLOAT(SLJIT_NUMBER_OF_FLOAT_REGISTERS), 0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf[1]);+ for (i = 0; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++)+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR(i), 0, SLJIT_MEM1(SLJIT_R0), 0);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ sljit_free_code(code.code, NULL);++ FAILED(buf[2] != (SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS * 17.75 + SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS * 6.25), "test_float10 case 1 failed\n");++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");+ buf[0] = -32.5;+ buf[1] = -11.25;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 0 | SLJIT_ENTER_FLOAT(SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS),+ 1 | SLJIT_ENTER_FLOAT(SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS), 0);++ for (i = 0; i < SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS; i++)+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR(i), 0, SLJIT_MEM1(SLJIT_S0), 0);+ for (i = 0; i < SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS; i++)+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FS(i), 0, SLJIT_MEM1(SLJIT_S0), 0);++ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS0V());+ /* SLJIT_FR0 contains the first value. */+ for (i = 1; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++)+ sljit_emit_fop2(compiler, SLJIT_ADD_F64, SLJIT_FR0, 0, SLJIT_FR0, 0, SLJIT_FR(i), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64), SLJIT_FR0, 0);++ sljit_emit_return_void(compiler);++ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, 0, SLJIT_ARGS0V(), 1 | SLJIT_ENTER_FLOAT(SLJIT_NUMBER_OF_FLOAT_REGISTERS), 0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf[1]);+ for (i = 0; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++)+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR(i), 0, SLJIT_MEM1(SLJIT_R0), 0);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ sljit_free_code(code.code, NULL);++ FAILED(buf[2] != (SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS * -11.25 + SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS * -32.5), "test_float10 case 2 failed\n");++ successful_tests++;+}++static void test_float11(void)+{+ /* Test float memory accesses with pre/post updates. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_u32 i;+ sljit_s32 supported[6];+ sljit_sw wbuf[6];+ sljit_f64 dbuf[4];+ sljit_f32 sbuf[4];+#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)+ static sljit_u8 expected[6] = { 1, 1, 1, 1, 0, 0 };+#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)+ static sljit_u8 expected[6] = { 1, 0, 1, 0, 1, 1 };+#else+ static sljit_u8 expected[6] = { 0, 0, 0, 0, 0, 0 };+#endif++ if (verbose)+ printf("Run test_float11\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 6; i++)+ wbuf[i] = 0;++ dbuf[0] = 66.725;+ dbuf[1] = 0.0;+ dbuf[2] = 0.0;+ dbuf[3] = 0.0;++ sbuf[0] = 0.0;+ sbuf[1] = -22.125;+ sbuf[2] = 0.0;+ sbuf[3] = 0.0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS3V(P, P, P), 4 | SLJIT_ENTER_FLOAT(4), 3, sizeof(sljit_sw));++ supported[0] = sljit_emit_fmem_update(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), 4 * sizeof(sljit_f64));+ if (supported[0] == SLJIT_SUCCESS) {+ /* dbuf[1] */+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_IMM, 4 * sizeof(sljit_f64));+ sljit_emit_fmem_update(compiler, SLJIT_MOV_F64, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), 4 * sizeof(sljit_f64));+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f64), SLJIT_FR0, 0);+ /* wbuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);+ }++ supported[1] = sljit_emit_fmem_update(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_POST, SLJIT_FR2, SLJIT_MEM1(SLJIT_R0), -(sljit_sw)sizeof(sljit_f64));+ if (supported[1] == SLJIT_SUCCESS) {+ /* dbuf[2] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_IMM, 2 * sizeof(sljit_f64));+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S1), 0);+ sljit_emit_fmem_update(compiler, SLJIT_MOV_F64 | SLJIT_MEM_STORE | SLJIT_MEM_POST, SLJIT_FR2, SLJIT_MEM1(SLJIT_R0), -(sljit_sw)sizeof(sljit_f64));+ /* wbuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0);+ }++ supported[2] = sljit_emit_fmem_update(compiler, SLJIT_MOV_F32 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE, SLJIT_FR1, SLJIT_MEM1(SLJIT_R2), -4 * (sljit_sw)sizeof(sljit_f32));+ if (supported[2] == SLJIT_SUCCESS) {+ /* sbuf[0] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S2, 0, SLJIT_IMM, 4 * sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f32));+ sljit_emit_fmem_update(compiler, SLJIT_MOV_F32 | SLJIT_MEM_STORE, SLJIT_FR1, SLJIT_MEM1(SLJIT_R2), -4 * (sljit_sw)sizeof(sljit_f32));+ /* wbuf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R2, 0);+ }++ supported[3] = sljit_emit_fmem_update(compiler, SLJIT_MOV_F32 | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_FR1, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_f32));+ if (supported[3] == SLJIT_SUCCESS) {+ /* sbuf[2] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S2, 0, SLJIT_IMM, sizeof(sljit_f32));+ sljit_emit_fmem_update(compiler, SLJIT_MOV_F32 | SLJIT_MEM_POST, SLJIT_FR1, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S2), 2 * sizeof(sljit_f32), SLJIT_FR1, 0);+ /* wbuf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R1, 0);+ }++ supported[4] = sljit_emit_fmem_update(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP, SLJIT_FR0, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0);+ if (supported[4] == SLJIT_SUCCESS) {+ /* dbuf[3] */+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 8 * sizeof(sljit_f64));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -8 * (sljit_sw)sizeof(sljit_f64));+ sljit_emit_fmem_update(compiler, SLJIT_MOV_F64, SLJIT_FR0, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f64), SLJIT_FR0, 0);+ /* wbuf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R1, 0);+ }++ supported[5] = sljit_emit_fmem_update(compiler, SLJIT_MOV_F32 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE, SLJIT_FR2, SLJIT_MEM2(SLJIT_R2, SLJIT_R1), 0);+ if (supported[5] == SLJIT_SUCCESS) {+ /* sbuf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_S2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 3 * sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f32));+ sljit_emit_fmem_update(compiler, SLJIT_MOV_F32 | SLJIT_MEM_STORE, SLJIT_FR2, SLJIT_MEM2(SLJIT_R2, SLJIT_R1), 0);+ /* wbuf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R2, 0);+ }++ SLJIT_ASSERT(sljit_emit_fmem_update(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_FR0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0) == SLJIT_ERR_UNSUPPORTED);+ SLJIT_ASSERT(sljit_emit_fmem_update(compiler, SLJIT_MOV_F32 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_POST, SLJIT_FR0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0) == SLJIT_ERR_UNSUPPORTED);++#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)+ /* TODO: at least for ARM (both V5 and V7) the range below needs further fixing */+ SLJIT_ASSERT(sljit_emit_fmem_update(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), 256) == SLJIT_ERR_UNSUPPORTED);+ SLJIT_ASSERT(sljit_emit_fmem_update(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), -257) == SLJIT_ERR_UNSUPPORTED);+#endif++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func3((sljit_sw)&wbuf, (sljit_sw)&dbuf, (sljit_sw)&sbuf);+ sljit_free_code(code.code, NULL);++ FAILED(sizeof(expected) != sizeof(supported) / sizeof(sljit_s32), "test_float11 case 1 failed\n");++ for (i = 0; i < sizeof(expected); i++) {+ if (expected[i]) {+ if (supported[i] != SLJIT_SUCCESS) {+ printf("test_float11 case %d should be supported\n", i + 1);+ return;+ }+ } else {+ if (supported[i] == SLJIT_SUCCESS) {+ printf("test_float11 case %d should not be supported\n", i + 1);+ return;+ }+ }+ }++ FAILED(supported[0] == SLJIT_SUCCESS && dbuf[1] != 66.725, "test_float11 case 2 failed\n");+ FAILED(supported[0] == SLJIT_SUCCESS && wbuf[0] != (sljit_sw)(dbuf), "test_float11 case 3 failed\n");+ FAILED(supported[1] == SLJIT_SUCCESS && dbuf[2] != 66.725, "test_float11 case 4 failed\n");+ FAILED(supported[1] == SLJIT_SUCCESS && wbuf[1] != (sljit_sw)(dbuf + 1), "test_float11 case 5 failed\n");+ FAILED(supported[2] == SLJIT_SUCCESS && sbuf[0] != -22.125, "test_float11 case 6 failed\n");+ FAILED(supported[2] == SLJIT_SUCCESS && wbuf[2] != (sljit_sw)(sbuf), "test_float11 case 7 failed\n");+ FAILED(supported[3] == SLJIT_SUCCESS && sbuf[2] != -22.125, "test_float11 case 8 failed\n");+ FAILED(supported[3] == SLJIT_SUCCESS && wbuf[3] != (sljit_sw)(sbuf + 2), "test_float11 case 9 failed\n");+ FAILED(supported[4] == SLJIT_SUCCESS && dbuf[3] != 66.725, "test_float11 case 10 failed\n");+ FAILED(supported[4] == SLJIT_SUCCESS && wbuf[4] != (sljit_sw)(dbuf), "test_float11 case 11 failed\n");+ FAILED(supported[5] == SLJIT_SUCCESS && sbuf[3] != -22.125, "test_float11 case 12 failed\n");+ FAILED(supported[5] == SLJIT_SUCCESS && wbuf[5] != (sljit_sw)(sbuf + 3), "test_float11 case 13 failed\n");++ successful_tests++;+}++static void test_float12(void)+{+ /* Test floating point argument passing to sljit_emit_enter. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw wbuf[2];+ sljit_s32 ibuf[2];+ sljit_f64 dbuf[3];+ sljit_f32 fbuf[2];++ if (verbose)+ printf("Run test_float12\n");++ wbuf[0] = 0;+ ibuf[0] = 0;+ dbuf[0] = 0;+ fbuf[0] = 0;++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS4V(32, F32, W, F64), 2 | SLJIT_ENTER_FLOAT(2), 2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)&wbuf, SLJIT_S1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM0(), (sljit_sw)&ibuf, SLJIT_S0, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM0(), (sljit_sw)&dbuf, SLJIT_FR1, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM0(), (sljit_sw)&fbuf, SLJIT_FR0, 0);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.test_float12_f1(-6834, 674.5f, 2789, -895.25);+ sljit_free_code(code.code, NULL);++ FAILED(wbuf[0] != 2789, "test_float12 case 1 failed\n");+ FAILED(ibuf[0] != -6834, "test_float12 case 2 failed\n");+ FAILED(dbuf[0] != -895.25, "test_float12 case 3 failed\n");+ FAILED(fbuf[0] != 674.5f, "test_float12 case 4 failed\n");++ ibuf[0] = 0;+ dbuf[0] = 0;+ fbuf[0] = 0;+ fbuf[1] = 0;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS4V(F32, F64, F32, 32), 1 | SLJIT_ENTER_FLOAT(3), 1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM0(), (sljit_sw)&ibuf, SLJIT_S0, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM0(), (sljit_sw)&dbuf, SLJIT_FR1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&fbuf);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_FR0, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f32), SLJIT_FR2, 0);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.test_float12_f2(-4712.5f, 5342.25, 2904.25f, -4607);+ sljit_free_code(code.code, NULL);++ FAILED(ibuf[0] != -4607, "test_float12 case 5 failed\n");+ FAILED(dbuf[0] != 5342.25, "test_float12 case 6 failed\n");+ FAILED(fbuf[0] != -4712.5f, "test_float12 case 7 failed\n");+ FAILED(fbuf[1] != 2904.25f, "test_float12 case 8 failed\n");++ ibuf[0] = 0;+ dbuf[0] = 0;+ fbuf[0] = 0;+ fbuf[1] = 0;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS4V(F64, F32, 32, F32), 1 | SLJIT_ENTER_FLOAT(3), 1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM0(), (sljit_sw)&ibuf, SLJIT_S0, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM0(), (sljit_sw)&dbuf, SLJIT_FR0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&fbuf);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_FR1, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f32), SLJIT_FR2, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.test_float12_f3(3578.5, 4619.25f, 6859, -1807.75f);+ sljit_free_code(code.code, NULL);++ FAILED(ibuf[0] != 6859, "test_float12 case 9 failed\n");+ FAILED(dbuf[0] != 3578.5, "test_float12 case 10 failed\n");+ FAILED(fbuf[0] != 4619.25f, "test_float12 case 11 failed\n");+ FAILED(fbuf[1] != -1807.75f, "test_float12 case 12 failed\n");++ ibuf[0] = 0;+ dbuf[0] = 0;+ dbuf[1] = 0;+ fbuf[0] = 0;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS4V(F64, 32, F32, F64), (SLJIT_NUMBER_OF_SCRATCH_REGISTERS + 2) | SLJIT_ENTER_FLOAT(3), 1, 33);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM0(), (sljit_sw)&ibuf, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_FR0, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_FR2, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM0(), (sljit_sw)&fbuf, SLJIT_FR1, 0);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.test_float12_f4(2740.75, -2651, -7909.25, 3671.5);+ sljit_free_code(code.code, NULL);++ FAILED(ibuf[0] != -2651, "test_float12 case 13 failed\n");+ FAILED(dbuf[0] != 2740.75, "test_float12 case 14 failed\n");+ FAILED(dbuf[1] != 3671.5, "test_float12 case 15 failed\n");+ FAILED(fbuf[0] != -7909.25, "test_float12 case 16 failed\n");++ wbuf[0] = 0;+ ibuf[0] = 0;+ ibuf[1] = 0;+ fbuf[0] = 0;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS4V(F32, 32, W, 32), 1 | SLJIT_ENTER_FLOAT(1), 3, 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)&wbuf, SLJIT_S1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&ibuf);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_s32), SLJIT_S2, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM0(), (sljit_sw)&fbuf, SLJIT_FR0, 0);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.test_float12_f5(-5219.25f, -4530, 7214, 6741);+ sljit_free_code(code.code, NULL);++ FAILED(wbuf[0] != 7214, "test_float12 case 17 failed\n");+ FAILED(ibuf[0] != -4530, "test_float12 case 18 failed\n");+ FAILED(ibuf[1] != 6741, "test_float12 case 19 failed\n");+ FAILED(fbuf[0] != -5219.25f, "test_float12 case 20 failed\n");++ wbuf[0] = 0;+ wbuf[1] = 0;+ dbuf[0] = 0;+ dbuf[1] = 0;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS4V(F64, F64, W, W), 1 | SLJIT_ENTER_FLOAT(2), 5, SLJIT_MAX_LOCAL_SIZE - 1);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_S0, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_SP), SLJIT_MAX_LOCAL_SIZE - 2 * sizeof(sljit_f64), SLJIT_FR0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&wbuf);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_S1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_FR0, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_FR1, 0);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.test_float12_f6(-3749.75, 5280.5, 9134, -6506);+ sljit_free_code(code.code, NULL);++ FAILED(wbuf[0] != 9134, "test_float12 case 21 failed\n");+ FAILED(wbuf[1] != -6506, "test_float12 case 22 failed\n");+ FAILED(dbuf[0] != -3749.75, "test_float12 case 23 failed\n");+ FAILED(dbuf[1] != 5280.5, "test_float12 case 24 failed\n");++ wbuf[0] = 0;+ dbuf[0] = 0;+ dbuf[1] = 0;+ dbuf[2] = 0;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS4V(F64, F64, W, F64), 1 | SLJIT_ENTER_FLOAT(3), 1, SLJIT_MAX_LOCAL_SIZE);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)&wbuf, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_FR0, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_FR1, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_f64), SLJIT_FR2, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.test_float12_f7(-6049.25, 7301.5, 4610, -4312.75);+ sljit_free_code(code.code, NULL);++ FAILED(wbuf[0] != 4610, "test_float12 case 25 failed\n");+ FAILED(dbuf[0] != -6049.25, "test_float12 case 26 failed\n");+ FAILED(dbuf[1] != 7301.5, "test_float12 case 27 failed\n");+ FAILED(dbuf[2] != -4312.75, "test_float12 case 28 failed\n");++ ibuf[0] = 0;+ dbuf[0] = 0;+ dbuf[1] = 0;+ dbuf[2] = 0;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS4V(F64, F64, F64, 32), 1 | SLJIT_ENTER_FLOAT(3), 1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM0(), (sljit_sw)&ibuf, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_FR0, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_FR1, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_f64), SLJIT_FR2, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.test_float12_f8(4810.5, -9148.75, 8601.25, 6703);+ sljit_free_code(code.code, NULL);++ FAILED(ibuf[0] != 6703, "test_float12 case 29 failed\n");+ FAILED(dbuf[0] != 4810.5, "test_float12 case 30 failed\n");+ FAILED(dbuf[1] != -9148.75, "test_float12 case 31 failed\n");+ FAILED(dbuf[2] != 8601.25, "test_float12 case 32 failed\n");++ successful_tests++;+}++static void test_float13(void)+{+ /* Test using all fpu registers. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_f64 buf[SLJIT_NUMBER_OF_FLOAT_REGISTERS];+ sljit_f64 buf2[2];+ struct sljit_jump *jump;+ sljit_s32 i;++ if (verbose)+ printf("Run test_float13\n");++ FAILED(!compiler, "cannot create compiler\n");++ buf2[0] = 7.75;+ buf2[1] = -8.25;++ for (i = 0; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++)+ buf[i] = 0.0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(P, P), 1 | SLJIT_ENTER_FLOAT(SLJIT_NUMBER_OF_FLOAT_REGISTERS), 2, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), 0);+ for (i = 1; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++)+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR(i), 0, SLJIT_FR0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S1, 0);+ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS1V(W));++ for (i = 0; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++)+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), i * (sljit_sw)sizeof(sljit_f64), SLJIT_FR(i), 0);+ sljit_emit_return_void(compiler);++ /* Called function. */+ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 0 | SLJIT_ENTER_FLOAT(SLJIT_NUMBER_OF_FLOAT_REGISTERS), 1, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64));+ for (i = 1; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++)+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR(i), 0, SLJIT_FR0, 0);++ sljit_set_context(compiler, 0, SLJIT_ARGS1V(P), 0 | SLJIT_ENTER_FLOAT(SLJIT_NUMBER_OF_FLOAT_REGISTERS), 1, 0);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)buf, (sljit_sw)buf2);+ sljit_free_code(code.code, NULL);++ for (i = 0; i < SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS; i++) {+ FAILED(buf[i] != -8.25, "test_float13 case 1 failed\n");+ }++ for (i = SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++) {+ FAILED(buf[i] != 7.75, "test_float13 case 2 failed\n");+ }++ /* Next test. */++ if (SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS >= 3) {+ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ buf2[0] = -6.25;+ buf2[1] = 3.75;++ for (i = 0; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++)+ buf[i] = 0.0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(P, P), 1 | SLJIT_ENTER_FLOAT(SLJIT_NUMBER_OF_FLOAT_REGISTERS - 2), 2 | SLJIT_ENTER_FLOAT(1), SLJIT_MAX_LOCAL_SIZE);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FS0, 0, SLJIT_MEM1(SLJIT_S1), 0);+ for (i = 0; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS - 2; i++)+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR(i), 0, SLJIT_FS0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S1, 0);+ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS1V(W));++ for (i = 0; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS - 2; i++)+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), i * (sljit_sw)sizeof(sljit_f64), SLJIT_FR(i), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 1) * (sljit_sw)sizeof(sljit_f64), SLJIT_FS0, 0);+ sljit_emit_return_void(compiler);++ /* Called function. */+ sljit_set_label(jump, sljit_emit_label(compiler));+ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 0 | SLJIT_ENTER_FLOAT(SLJIT_NUMBER_OF_FLOAT_REGISTERS), 1, SLJIT_MAX_LOCAL_SIZE);++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64));+ for (i = 1; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++)+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR(i), 0, SLJIT_FR0, 0);++ sljit_set_context(compiler, 0, SLJIT_ARGS1V(P), 0 | SLJIT_ENTER_FLOAT(SLJIT_NUMBER_OF_FLOAT_REGISTERS), 1, SLJIT_MAX_LOCAL_SIZE);+ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)buf, (sljit_sw)buf2);+ sljit_free_code(code.code, NULL);++ for (i = 0; i < SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS; i++) {+ FAILED(buf[i] != 3.75, "test_float13 case 3 failed\n");+ }++ for (i = SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS - 2; i++) {+ FAILED(buf[i] != -6.25, "test_float13 case 4 failed\n");+ }++ FAILED(buf[SLJIT_NUMBER_OF_FLOAT_REGISTERS - 2] != 0, "test_float13 case 5 failed\n");+ FAILED(buf[SLJIT_NUMBER_OF_FLOAT_REGISTERS - 1] != -6.25, "test_float13 case 6 failed\n");+ }++ successful_tests++;+}++static void test_float14(void)+{+ /* Test passing arguments in registers. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_sw wbuf[2];+ sljit_f64 dbuf[3];++ if (verbose)+ printf("Run test_float14\n");++ /* Next test. */++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS4V(F64, F64, F64, W_R), 1 | SLJIT_ENTER_FLOAT(3), 0, SLJIT_MAX_LOCAL_SIZE);+ /* wbuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)&wbuf, SLJIT_R0, 0);+ /* dbuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_FR0, 0);+ /* dbuf[1] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_FR1, 0);+ /* dbuf[2] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_f64), SLJIT_FR2, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.test_float14_f1(7390.25, -8045.5, 1390.75, 8201);+ sljit_free_code(code.code, NULL);++ FAILED(wbuf[0] != 8201, "test_float14 case 1 failed\n");+ FAILED(dbuf[0] != 7390.25, "test_float14 case 2 failed\n");+ FAILED(dbuf[1] != -8045.5, "test_float14 case 3 failed\n");+ FAILED(dbuf[2] != 1390.75, "test_float14 case 4 failed\n");++ /* Next test. */++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS4V(F64, F64, W, W_R), 2 | SLJIT_ENTER_FLOAT(2), 1, SLJIT_MAX_LOCAL_SIZE);+ /* wbuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&wbuf);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S0, 0);+ /* wbuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_R1, 0);+ /* dbuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_FR0, 0);+ /* dbuf[1] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_FR1, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.test_float14_f2(4892.75, -3702.5, 4731, 8530);+ sljit_free_code(code.code, NULL);++ FAILED(wbuf[0] != 4731, "test_float14 case 5 failed\n");+ FAILED(wbuf[1] != 8530, "test_float14 case 6 failed\n");+ FAILED(dbuf[0] != 4892.75, "test_float14 case 7 failed\n");+ FAILED(dbuf[1] != -3702.5, "test_float14 case 8 failed\n");++ successful_tests++;+}++static void test_float15_set(struct sljit_compiler *compiler, sljit_s32 compare, sljit_s32 type, sljit_s32 left_fr, sljit_s32 right_fr)+{+ /* Testing both sljit_emit_op_flags and sljit_emit_jump. */+ struct sljit_jump* jump;++ sljit_emit_fop1(compiler, compare | SLJIT_SET(type & 0xfe), left_fr, 0, right_fr, 0);+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_R0, 0, type);+ jump = sljit_emit_jump(compiler, type);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2);+ sljit_set_label(jump, sljit_emit_label(compiler));++ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, sizeof(sljit_s8));+}++static void test_float15(void)+{+ /* Test floating point comparison. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_s8 bbuf[96];+ sljit_s32 i;++ union {+ sljit_f64 value;+ struct {+ sljit_s32 value1;+ sljit_s32 value2;+ } u;+ } dbuf[3];++ union {+ sljit_f32 value;+ sljit_s32 value1;+ } sbuf[3];++ if (verbose)+ printf("Run test_float15\n");++ FAILED(!compiler, "cannot create compiler\n");++ dbuf[0].u.value1 = 0x7fffffff;+ dbuf[0].u.value2 = 0x7fffffff;+ dbuf[1].value = -13.0;+ dbuf[2].value = 27.0;++ sbuf[0].value1 = 0x7fffffff;+ sbuf[1].value = -13.0;+ sbuf[2].value = 27.0;++ for (i = 0; i < 96; i++)+ bbuf[i] = -3;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS3V(P, P, P), 3 | SLJIT_ENTER_FLOAT(6), 3, 0);++ i = SLJIT_CMP_F64;+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S1), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f64));+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR3, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f64));+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR4, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f64));++ while (1) {+ /* bbuf[0] and bbuf[48] */+ test_float15_set(compiler, i, SLJIT_ORDERED_EQUAL, SLJIT_FR2, SLJIT_FR3);+ /* bbuf[1] and bbuf[49] */+ test_float15_set(compiler, i, SLJIT_ORDERED_EQUAL, SLJIT_FR2, SLJIT_FR4);+ /* bbuf[2] and bbuf[50] */+ test_float15_set(compiler, i, SLJIT_ORDERED_EQUAL, SLJIT_FR0, SLJIT_FR1);+ /* bbuf[3] and bbuf[51] */+ test_float15_set(compiler, i, SLJIT_ORDERED_EQUAL, SLJIT_FR0, SLJIT_FR2);++ /* bbuf[4] and bbuf[52] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_NOT_EQUAL, SLJIT_FR2, SLJIT_FR3);+ /* bbuf[5] and bbuf[53] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_NOT_EQUAL, SLJIT_FR2, SLJIT_FR4);+ /* bbuf[6] and bbuf[54] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_NOT_EQUAL, SLJIT_FR0, SLJIT_FR1);+ /* bbuf[7] and bbuf[55] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_NOT_EQUAL, SLJIT_FR0, SLJIT_FR2);++ /* bbuf[8] and bbuf[56] */+ test_float15_set(compiler, i, SLJIT_ORDERED_LESS, SLJIT_FR2, SLJIT_FR3);+ /* bbuf[9] and bbuf[57] */+ test_float15_set(compiler, i, SLJIT_ORDERED_LESS, SLJIT_FR2, SLJIT_FR4);+ /* bbuf[10] and bbuf[58] */+ test_float15_set(compiler, i, SLJIT_ORDERED_LESS, SLJIT_FR0, SLJIT_FR1);+ /* bbuf[11] and bbuf[59] */+ test_float15_set(compiler, i, SLJIT_ORDERED_LESS, SLJIT_FR0, SLJIT_FR2);++ /* bbuf[12] and bbuf[60] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_GREATER_EQUAL, SLJIT_FR2, SLJIT_FR4);+ /* bbuf[13] and bbuf[61] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_GREATER_EQUAL, SLJIT_FR4, SLJIT_FR2);+ /* bbuf[14] and bbuf[62] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_GREATER_EQUAL, SLJIT_FR0, SLJIT_FR1);+ /* bbuf[15] and bbuf[63] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_GREATER_EQUAL, SLJIT_FR0, SLJIT_FR2);++ /* bbuf[16] and bbuf[64] */+ test_float15_set(compiler, i, SLJIT_ORDERED_GREATER, SLJIT_FR2, SLJIT_FR4);+ /* bbuf[17] and bbuf[65] */+ test_float15_set(compiler, i, SLJIT_ORDERED_GREATER, SLJIT_FR4, SLJIT_FR2);+ /* bbuf[18] and bbuf[66] */+ test_float15_set(compiler, i, SLJIT_ORDERED_GREATER, SLJIT_FR0, SLJIT_FR1);+ /* bbuf[19] and bbuf[67] */+ test_float15_set(compiler, i, SLJIT_ORDERED_GREATER, SLJIT_FR0, SLJIT_FR2);++ /* bbuf[20] and bbuf[68] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_LESS_EQUAL, SLJIT_FR2, SLJIT_FR4);+ /* bbuf[21] and bbuf[69] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_LESS_EQUAL, SLJIT_FR4, SLJIT_FR2);+ /* bbuf[22] and bbuf[70] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_LESS_EQUAL, SLJIT_FR0, SLJIT_FR1);+ /* bbuf[23] and bbuf[71] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_LESS_EQUAL, SLJIT_FR0, SLJIT_FR2);++ /* bbuf[24] and bbuf[72] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_EQUAL, SLJIT_FR2, SLJIT_FR4);+ /* bbuf[25] and bbuf[73] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_EQUAL, SLJIT_FR2, SLJIT_FR3);+ /* bbuf[26] and bbuf[74] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_EQUAL, SLJIT_FR0, SLJIT_FR1);+ /* bbuf[27] and bbuf[75] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_EQUAL, SLJIT_FR0, SLJIT_FR2);++ /* bbuf[28] and bbuf[76] */+ test_float15_set(compiler, i, SLJIT_ORDERED_NOT_EQUAL, SLJIT_FR2, SLJIT_FR3);+ /* bbuf[29] and bbuf[77] */+ test_float15_set(compiler, i, SLJIT_ORDERED_NOT_EQUAL, SLJIT_FR2, SLJIT_FR4);+ /* bbuf[30] and bbuf[78] */+ test_float15_set(compiler, i, SLJIT_ORDERED_NOT_EQUAL, SLJIT_FR0, SLJIT_FR1);+ /* bbuf[31] and bbuf[79] */+ test_float15_set(compiler, i, SLJIT_ORDERED_NOT_EQUAL, SLJIT_FR0, SLJIT_FR2);++ /* bbuf[32] and bbuf[80] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_LESS, SLJIT_FR2, SLJIT_FR4);+ /* bbuf[33] and bbuf[81] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_LESS, SLJIT_FR2, SLJIT_FR3);+ /* bbuf[34] and bbuf[82] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_LESS, SLJIT_FR0, SLJIT_FR1);+ /* bbuf[35] and bbuf[83] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_LESS, SLJIT_FR0, SLJIT_FR2);++ /* bbuf[36] and bbuf[84] */+ test_float15_set(compiler, i, SLJIT_ORDERED_GREATER_EQUAL, SLJIT_FR2, SLJIT_FR4);+ /* bbuf[37] and bbuf[85] */+ test_float15_set(compiler, i, SLJIT_ORDERED_GREATER_EQUAL, SLJIT_FR4, SLJIT_FR2);+ /* bbuf[38] and bbuf[86] */+ test_float15_set(compiler, i, SLJIT_ORDERED_GREATER_EQUAL, SLJIT_FR0, SLJIT_FR1);+ /* bbuf[39] and bbuf[87] */+ test_float15_set(compiler, i, SLJIT_ORDERED_GREATER_EQUAL, SLJIT_FR0, SLJIT_FR2);++ /* bbuf[40] and bbuf[88] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_GREATER, SLJIT_FR2, SLJIT_FR4);+ /* bbuf[41] and bbuf[89] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_GREATER, SLJIT_FR4, SLJIT_FR2);+ /* bbuf[42] and bbuf[90] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_GREATER, SLJIT_FR0, SLJIT_FR1);+ /* bbuf[43] and bbuf[91] */+ test_float15_set(compiler, i, SLJIT_UNORDERED_OR_GREATER, SLJIT_FR0, SLJIT_FR2);++ /* bbuf[44] and bbuf[92] */+ test_float15_set(compiler, i, SLJIT_ORDERED_LESS_EQUAL, SLJIT_FR2, SLJIT_FR3);+ /* bbuf[45] and bbuf[93] */+ test_float15_set(compiler, i, SLJIT_ORDERED_LESS_EQUAL, SLJIT_FR4, SLJIT_FR2);+ /* bbuf[46] and bbuf[94] */+ test_float15_set(compiler, i, SLJIT_ORDERED_LESS_EQUAL, SLJIT_FR0, SLJIT_FR1);+ /* bbuf[47] and bbuf[95] */+ test_float15_set(compiler, i, SLJIT_ORDERED_LESS_EQUAL, SLJIT_FR0, SLJIT_FR2);++ if (i == SLJIT_CMP_F32)+ break;++ i = SLJIT_CMP_F32;+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S2), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S2), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR3, 0, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR4, 0, SLJIT_MEM1(SLJIT_S2), 2 * sizeof(sljit_f32));+ }++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func3((sljit_sw)&bbuf, (sljit_sw)&dbuf, (sljit_sw)&sbuf);+ sljit_free_code(code.code, NULL);++ /* SLJIT_CMP_F64 */+ FAILED(bbuf[0] != 1, "test_float15 case 1 failed\n");+ FAILED(bbuf[1] != 2, "test_float15 case 2 failed\n");+ FAILED(bbuf[2] != 2, "test_float15 case 3 failed\n");+ FAILED(bbuf[3] != 2, "test_float15 case 4 failed\n");++ FAILED(bbuf[4] != 2, "test_float15 case 5 failed\n");+ FAILED(bbuf[5] != 1, "test_float15 case 6 failed\n");+ FAILED(bbuf[6] != 1, "test_float15 case 7 failed\n");+ FAILED(bbuf[7] != 1, "test_float15 case 8 failed\n");++ FAILED(bbuf[8] != 2, "test_float15 case 9 failed\n");+ FAILED(bbuf[9] != 1, "test_float15 case 10 failed\n");+ FAILED(bbuf[10] != 2, "test_float15 case 11 failed\n");+ FAILED(bbuf[11] != 2, "test_float15 case 12 failed\n");++ FAILED(bbuf[12] != 2, "test_float15 case 13 failed\n");+ FAILED(bbuf[13] != 1, "test_float15 case 14 failed\n");+ FAILED(bbuf[14] != 1, "test_float15 case 15 failed\n");+ FAILED(bbuf[15] != 1, "test_float15 case 16 failed\n");++ FAILED(bbuf[16] != 2, "test_float15 case 17 failed\n");+ FAILED(bbuf[17] != 1, "test_float15 case 18 failed\n");+ FAILED(bbuf[18] != 2, "test_float15 case 19 failed\n");+ FAILED(bbuf[19] != 2, "test_float15 case 20 failed\n");++ FAILED(bbuf[20] != 1, "test_float15 case 21 failed\n");+ FAILED(bbuf[21] != 2, "test_float15 case 22 failed\n");+ FAILED(bbuf[22] != 1, "test_float15 case 23 failed\n");+ FAILED(bbuf[23] != 1, "test_float15 case 24 failed\n");++ FAILED(bbuf[24] != 2, "test_float15 case 25 failed\n");+ FAILED(bbuf[25] != 1, "test_float15 case 26 failed\n");+ FAILED(bbuf[26] != 1, "test_float15 case 27 failed\n");+ FAILED(bbuf[27] != 1, "test_float15 case 28 failed\n");++ FAILED(bbuf[28] != 2, "test_float15 case 29 failed\n");+ FAILED(bbuf[29] != 1, "test_float15 case 30 failed\n");+ FAILED(bbuf[30] != 2, "test_float15 case 31 failed\n");+ FAILED(bbuf[31] != 2, "test_float15 case 32 failed\n");++ FAILED(bbuf[32] != 1, "test_float15 case 33 failed\n");+ FAILED(bbuf[33] != 2, "test_float15 case 34 failed\n");+ FAILED(bbuf[34] != 1, "test_float15 case 35 failed\n");+ FAILED(bbuf[35] != 1, "test_float15 case 36 failed\n");++ FAILED(bbuf[36] != 2, "test_float15 case 37 failed\n");+ FAILED(bbuf[37] != 1, "test_float15 case 38 failed\n");+ FAILED(bbuf[38] != 2, "test_float15 case 39 failed\n");+ FAILED(bbuf[39] != 2, "test_float15 case 40 failed\n");++ FAILED(bbuf[40] != 2, "test_float15 case 41 failed\n");+ FAILED(bbuf[41] != 1, "test_float15 case 42 failed\n");+ FAILED(bbuf[42] != 1, "test_float15 case 43 failed\n");+ FAILED(bbuf[43] != 1, "test_float15 case 44 failed\n");++ FAILED(bbuf[44] != 1, "test_float15 case 45 failed\n");+ FAILED(bbuf[45] != 2, "test_float15 case 46 failed\n");+ FAILED(bbuf[46] != 2, "test_float15 case 47 failed\n");+ FAILED(bbuf[47] != 2, "test_float15 case 48 failed\n");++ /* SLJIT_CMP_F32 */+ FAILED(bbuf[48] != 1, "test_float15 case 49 failed\n");+ FAILED(bbuf[49] != 2, "test_float15 case 50 failed\n");+ FAILED(bbuf[50] != 2, "test_float15 case 51 failed\n");+ FAILED(bbuf[51] != 2, "test_float15 case 52 failed\n");++ FAILED(bbuf[52] != 2, "test_float15 case 53 failed\n");+ FAILED(bbuf[53] != 1, "test_float15 case 54 failed\n");+ FAILED(bbuf[54] != 1, "test_float15 case 55 failed\n");+ FAILED(bbuf[55] != 1, "test_float15 case 56 failed\n");++ FAILED(bbuf[56] != 2, "test_float15 case 57 failed\n");+ FAILED(bbuf[57] != 1, "test_float15 case 58 failed\n");+ FAILED(bbuf[58] != 2, "test_float15 case 59 failed\n");+ FAILED(bbuf[59] != 2, "test_float15 case 60 failed\n");++ FAILED(bbuf[60] != 2, "test_float15 case 61 failed\n");+ FAILED(bbuf[61] != 1, "test_float15 case 62 failed\n");+ FAILED(bbuf[62] != 1, "test_float15 case 63 failed\n");+ FAILED(bbuf[63] != 1, "test_float15 case 64 failed\n");++ FAILED(bbuf[64] != 2, "test_float15 case 65 failed\n");+ FAILED(bbuf[65] != 1, "test_float15 case 66 failed\n");+ FAILED(bbuf[66] != 2, "test_float15 case 67 failed\n");+ FAILED(bbuf[67] != 2, "test_float15 case 68 failed\n");++ FAILED(bbuf[68] != 1, "test_float15 case 69 failed\n");+ FAILED(bbuf[69] != 2, "test_float15 case 70 failed\n");+ FAILED(bbuf[70] != 1, "test_float15 case 71 failed\n");+ FAILED(bbuf[71] != 1, "test_float15 case 72 failed\n");++ FAILED(bbuf[72] != 2, "test_float15 case 73 failed\n");+ FAILED(bbuf[73] != 1, "test_float15 case 74 failed\n");+ FAILED(bbuf[74] != 1, "test_float15 case 75 failed\n");+ FAILED(bbuf[75] != 1, "test_float15 case 76 failed\n");++ FAILED(bbuf[76] != 2, "test_float15 case 77 failed\n");+ FAILED(bbuf[77] != 1, "test_float15 case 78 failed\n");+ FAILED(bbuf[78] != 2, "test_float15 case 79 failed\n");+ FAILED(bbuf[79] != 2, "test_float15 case 80 failed\n");++ FAILED(bbuf[80] != 1, "test_float15 case 81 failed\n");+ FAILED(bbuf[81] != 2, "test_float15 case 82 failed\n");+ FAILED(bbuf[82] != 1, "test_float15 case 83 failed\n");+ FAILED(bbuf[83] != 1, "test_float15 case 84 failed\n");++ FAILED(bbuf[84] != 2, "test_float15 case 85 failed\n");+ FAILED(bbuf[85] != 1, "test_float15 case 86 failed\n");+ FAILED(bbuf[86] != 2, "test_float15 case 87 failed\n");+ FAILED(bbuf[87] != 2, "test_float15 case 88 failed\n");++ FAILED(bbuf[88] != 2, "test_float15 case 89 failed\n");+ FAILED(bbuf[89] != 1, "test_float15 case 90 failed\n");+ FAILED(bbuf[90] != 1, "test_float15 case 91 failed\n");+ FAILED(bbuf[91] != 1, "test_float15 case 92 failed\n");++ FAILED(bbuf[92] != 1, "test_float15 case 93 failed\n");+ FAILED(bbuf[93] != 2, "test_float15 case 94 failed\n");+ FAILED(bbuf[94] != 2, "test_float15 case 95 failed\n");+ FAILED(bbuf[95] != 2, "test_float15 case 96 failed\n");++ successful_tests++;+}++static void test_float16(void)+{+ /* Test sljit_emit_fcopy. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_f64 dbuf[4];+ sljit_f32 sbuf[2];+#if IS_64BIT+ sljit_sw wbuf[2];+ sljit_s32 ibuf[2];+#else /* !IS_64BIT */+ sljit_s32 ibuf[7];+#endif /* IS_64BIT */++ if (verbose)+ printf("Run test_float16\n");++ FAILED(!compiler, "cannot create compiler\n");++ sbuf[0] = 12345.0;+ sbuf[1] = -1.0;+ ibuf[0] = -1;+ ibuf[1] = (sljit_s32)0xc7543100;+ dbuf[0] = 123456789012345.0;+ dbuf[1] = -1.0;+#if IS_64BIT+ wbuf[0] = -1;+ wbuf[1] = (sljit_sw)0xc2fee0c29f50cb10;+#else /* !IS_64BIT */+ ibuf[2] = -1;+ ibuf[3] = -1;+ ibuf[4] = -1;+ ibuf[5] = (sljit_sw)0x9f50cb10;+ ibuf[6] = (sljit_sw)0xc2fee0c2;+#endif /* IS_64BIT */++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(W, W), 5 | SLJIT_ENTER_FLOAT(5), 5, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)ibuf);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S1), 0);+ sljit_emit_fcopy(compiler, SLJIT_COPY32_FROM_F32, SLJIT_FR2, SLJIT_R0);+ /* ibuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R3, 0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_s32));+ sljit_emit_fcopy(compiler, SLJIT_COPY32_TO_F32, SLJIT_FR4, SLJIT_R3);+ /* sbuf[1] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f32), SLJIT_FR4, 0);++#if IS_64BIT+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)wbuf);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fcopy(compiler, SLJIT_COPY_FROM_F64, SLJIT_FR1, SLJIT_S2);+ /* wbuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_S2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw));+ sljit_emit_fcopy(compiler, SLJIT_COPY_TO_F64, SLJIT_FR0, SLJIT_R3);+ /* dbuf[1] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64), SLJIT_FR0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0);+ sljit_emit_fcopy(compiler, SLJIT_COPY_TO_F64, SLJIT_FR3, SLJIT_R2);+ /* dbuf[2] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64), SLJIT_FR3, 0);+#else /* !IS_64BIT */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fcopy(compiler, SLJIT_COPY_FROM_F64, SLJIT_FR1, SLJIT_REG_PAIR(SLJIT_S3, SLJIT_S2));+ /* ibuf[2-3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 3 * sizeof(sljit_sw), SLJIT_S3, 0);++ sljit_emit_fcopy(compiler, SLJIT_COPY_FROM_F64, SLJIT_FR1, SLJIT_R2);+ /* ibuf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 4 * sizeof(sljit_sw), SLJIT_R2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_MEM1(SLJIT_R1), 5 * sizeof(sljit_sw));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R1), 6 * sizeof(sljit_sw));+ sljit_emit_fcopy(compiler, SLJIT_COPY_TO_F64, SLJIT_FR0, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R3));+ /* dbuf[1] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64), SLJIT_FR0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0);+ sljit_emit_fcopy(compiler, SLJIT_COPY_TO_F64, SLJIT_FR3, SLJIT_REG_PAIR(SLJIT_R2, SLJIT_R2));+ /* dbuf[2] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64), SLJIT_FR3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)0xc00c0000);+ sljit_emit_fcopy(compiler, SLJIT_COPY_TO_F64, SLJIT_FR3, SLJIT_R2);+ /* dbuf[3] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f64), SLJIT_FR3, 0);+#endif /* IS_64BIT */++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)dbuf, (sljit_sw)sbuf);+ sljit_free_code(code.code, NULL);++ FAILED(ibuf[0] != (sljit_s32)0x4640e400, "test_float16 case 1 failed\n");+ FAILED(sbuf[1] != -54321.0, "test_float16 case 2 failed\n");+#if IS_64BIT+ FAILED(wbuf[0] != (sljit_sw)0x42dc12218377de40, "test_float16 case 3 failed\n");+ FAILED(dbuf[1] != -543210987654321.0, "test_float16 case 4 failed\n");+ FAILED(dbuf[2] != 0.0, "test_float16 case 5 failed\n");+#else /* !IS_64BIT */+ FAILED(ibuf[2] != (sljit_sw)0x8377de40, "test_float16 case 3 failed\n");+ FAILED(ibuf[3] != (sljit_sw)0x42dc1221, "test_float16 case 4 failed\n");+ FAILED(ibuf[4] != (sljit_sw)0x42dc1221, "test_float16 case 5 failed\n");+ FAILED(dbuf[1] != -543210987654321.0, "test_float16 case 6 failed\n");+ FAILED(dbuf[2] != 0.0, "test_float16 case 7 failed\n");+ FAILED(dbuf[3] != -3.5, "test_float16 case 8 failed\n");+#endif /* IS_64BIT */++ successful_tests++;+}++static void test_float17(void)+{+ /* Test fselect operation. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_f64 dbuf[10];+ sljit_f32 sbuf[10];+ sljit_s32 i;++ if (verbose)+ printf("Run test_float17\n");++ for (i = 4; i < 10; i++)+ dbuf[i] = -1.0;+ for (i = 4; i < 10; i++)+ sbuf[i] = -1.0;++ dbuf[0] = 759.25;+ dbuf[1] = -316.25;+ dbuf[2] = 591.5;+ dbuf[3] = -801.75;++ sbuf[0] = 630.5;+ sbuf[1] = -912.75;+ sbuf[2] = 264.25;+ sbuf[3] = -407.5;++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(W, W), 3 | SLJIT_ENTER_FLOAT(4), 3, 2 * sizeof(sljit_f64));++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR3, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1);+ sljit_emit_op2u(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_fselect(compiler, SLJIT_CARRY, SLJIT_FR2, SLJIT_FR3, 0, SLJIT_FR2);+ /* dbuf[4] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_f64), SLJIT_FR2, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_s32)0x80000000);+ sljit_emit_op2u(compiler, SLJIT_ADD32 | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_IMM, -1);+ sljit_emit_fselect(compiler, SLJIT_OVERFLOW, SLJIT_FR2, SLJIT_FR2, 0, SLJIT_FR3);+ /* dbuf[5] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_f64), SLJIT_FR2, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_UNORDERED, SLJIT_FR2, 0, SLJIT_FR3, 0);+ sljit_emit_fselect(compiler, SLJIT_UNORDERED, SLJIT_FR3, SLJIT_MEM0(), (sljit_sw)(dbuf + 2), SLJIT_FR2);+ /* dbuf[6] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_f64), SLJIT_FR3, 0);+ sljit_emit_fselect(compiler, SLJIT_ORDERED, SLJIT_FR2, SLJIT_MEM0(), (sljit_sw)(dbuf + 2), SLJIT_FR2);+ /* dbuf[7] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_f64), SLJIT_FR2, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_f64), SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f64));+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_GREATER, SLJIT_FR2, 0, SLJIT_FR2, 0);+ sljit_emit_fselect(compiler, SLJIT_F_LESS_EQUAL, SLJIT_FR0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_f64), SLJIT_FR0);+ /* dbuf[8] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_f64), SLJIT_FR0, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1);+ sljit_emit_fselect(compiler, SLJIT_F_LESS_EQUAL, SLJIT_FR1, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 3, SLJIT_FR1);+ /* dbuf[9] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_f64), SLJIT_FR1, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S1), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f32));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 10);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 10);+ sljit_emit_fselect(compiler, SLJIT_EQUAL | SLJIT_32, SLJIT_FR0, SLJIT_FR1, 0, SLJIT_FR2);+ /* sbuf[4] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_f32), SLJIT_FR0, 0);+ sljit_emit_fselect(compiler, SLJIT_NOT_EQUAL | SLJIT_32, SLJIT_FR0, SLJIT_FR1, 0, SLJIT_FR2);+ /* sbuf[5] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_f32), SLJIT_FR0, 0);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, WCONST(0x1234000000, 0x123400) + 3 * sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_ORDERED_GREATER, SLJIT_FR1, 0, SLJIT_FR2, 0);+ sljit_emit_fselect(compiler, SLJIT_ORDERED_GREATER | SLJIT_32, SLJIT_FR1, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f32), SLJIT_FR2);+ /* sbuf[6] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_f32), SLJIT_FR1, 0);+ sljit_emit_fselect(compiler, SLJIT_ORDERED_GREATER | SLJIT_32, SLJIT_FR2, SLJIT_MEM1(SLJIT_R1), WCONST(-0x1234000000, -0x123400), SLJIT_FR2);+ /* sbuf[7] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 7 * sizeof(sljit_f32), SLJIT_FR2, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR3, 0, SLJIT_MEM1(SLJIT_S1), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f32));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -100);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R0, 0, SLJIT_IMM, 10);+ sljit_emit_fselect(compiler, SLJIT_SIG_LESS | SLJIT_32, SLJIT_FR2, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_FR3);+ /* sbuf[8] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 8 * sizeof(sljit_f32), SLJIT_FR2, 0);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S2, 0, SLJIT_S1, 0, SLJIT_IMM, -0x5678 + 2 * (sljit_s32)sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_ORDERED_EQUAL, SLJIT_FR3, 0, SLJIT_FR3, 0);+ sljit_emit_fselect(compiler, SLJIT_ORDERED_EQUAL | SLJIT_32, SLJIT_FR3, SLJIT_MEM1(SLJIT_S2), 0x5678, SLJIT_FR3);+ /* sbuf[9] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 9 * sizeof(sljit_f32), SLJIT_FR3, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)dbuf, (sljit_sw)sbuf);+ sljit_free_code(code.code, NULL);++ FAILED(dbuf[4] != -316.25, "test_float17 case 1 failed\n");+ FAILED(dbuf[5] != 759.25, "test_float17 case 2 failed\n");+ FAILED(dbuf[6] != 759.25, "test_float17 case 3 failed\n");+ FAILED(dbuf[7] != 591.5, "test_float17 case 4 failed\n");+ FAILED(dbuf[8] != -801.75, "test_float17 case 5 failed\n");+ FAILED(dbuf[9] != -316.25, "test_float17 case 6 failed\n");+ FAILED(sbuf[4] != 630.5, "test_float17 case 7 failed\n");+ FAILED(sbuf[5] != -912.75, "test_float17 case 8 failed\n");+ FAILED(sbuf[6] != 264.25, "test_float17 case 9 failed\n");+ FAILED(sbuf[7] != -407.5, "test_float17 case 10 failed\n");+ FAILED(sbuf[8] != -912.75, "test_float17 case 11 failed\n");+ FAILED(sbuf[9] != 264.25, "test_float17 case 12 failed\n");++ successful_tests++;+}++static void test_float18(void)+{+ /* Floating point set immediate. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_f64 dbuf[6];+ sljit_f32 sbuf[5];+ sljit_s32 check_buf[2];+ sljit_s32 i;++ if (verbose)+ printf("Run test_float18\n");++ for (i = 0; i < 6; i++)+ dbuf[i] = -1.0;++ for (i = 0; i < 5; i++)+ sbuf[i] = -1.0;++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(P, P), 2 | SLJIT_ENTER_FLOAT(4), 2, 0);++ sljit_emit_fset64(compiler, SLJIT_FR0, 0.0);+ /* dbuf[0] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_FR0, 0);+ sljit_emit_fset64(compiler, SLJIT_FR1, -0.0);+ /* dbuf[1] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64), SLJIT_FR1, 0);+ sljit_emit_fset64(compiler, SLJIT_FR2, 1.0);+ /* dbuf[2] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64), SLJIT_FR2, 0);+ sljit_emit_fset64(compiler, SLJIT_FR2, -31.0);+ /* dbuf[3] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f64), SLJIT_FR2, 0);+ sljit_emit_fset64(compiler, SLJIT_FR2, 545357837627392.0);+ /* dbuf[4] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_f64), SLJIT_FR2, 0);+ sljit_emit_fset64(compiler, SLJIT_FR0, 983752153845214.5);+ /* dbuf[5] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_f64), SLJIT_FR0, 0);++ sljit_emit_fset32(compiler, SLJIT_FR0, 0.0f);+ /* sbuf[0] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_FR0, 0);+ sljit_emit_fset32(compiler, SLJIT_FR1, -0.0f);+ /* sbuf[1] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f32), SLJIT_FR1, 0);+ sljit_emit_fset32(compiler, SLJIT_FR2, 1.0f);+ /* sbuf[2] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f32), SLJIT_FR2, 0);+ sljit_emit_fset32(compiler, SLJIT_FR2, 31.0f);+ /* sbuf[3] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f32), SLJIT_FR2, 0);+ sljit_emit_fset32(compiler, SLJIT_FR2, -811.5f);+ /* sbuf[4] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_f32), SLJIT_FR2, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)&dbuf, (sljit_sw)&sbuf);+ sljit_free_code(code.code, NULL);++ copy_u8(check_buf, 0, dbuf + 0, sizeof(sljit_f64));+ FAILED(check_buf[0] != 0, "test_float18 case 1 failed\n");+ FAILED(check_buf[1] != 0, "test_float18 case 2 failed\n");+ copy_u8(check_buf, 0, dbuf + 1, sizeof(sljit_f64));+#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+ FAILED(check_buf[0] != 0, "test_float18 case 3 failed\n");+ FAILED(check_buf[1] != (sljit_s32)0x80000000, "test_float18 case 4 failed\n");+#else /* !SLJIT_LITTLE_ENDIAN */+ FAILED(check_buf[1] != 0, "test_float18 case 3 failed\n");+ FAILED(check_buf[0] != (sljit_s32)0x80000000, "test_float18 case 4 failed\n");+#endif /* SLJIT_LITTLE_ENDIAN */+ FAILED(dbuf[2] != 1.0, "test_float18 case 5 failed\n");+ FAILED(dbuf[3] != -31.0, "test_float18 case 6 failed\n");+ FAILED(dbuf[4] != 545357837627392.0, "test_float18 case 7 failed\n");+ FAILED(dbuf[5] != 983752153845214.5, "test_float18 case 8 failed\n");++ copy_u8(check_buf, 0, sbuf + 0, sizeof(sljit_f32));+ FAILED(check_buf[0] != 0, "test_float18 case 9 failed\n");+ copy_u8(check_buf, 0, sbuf + 1, sizeof(sljit_f32));+ FAILED(check_buf[0] != (sljit_s32)0x80000000, "test_float18 case 10 failed\n");+ FAILED(sbuf[2] != 1.0, "test_float18 case 11 failed\n");+ FAILED(sbuf[3] != 31.0, "test_float18 case 12 failed\n");+ FAILED(sbuf[4] != -811.5, "test_float18 case 13 failed\n");++ successful_tests++;+}++static void test_float19(void)+{+ /* Floating point convert from unsigned. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_f64 dbuf[9];+ sljit_f32 sbuf[9];+ sljit_s32 i;+ sljit_sw value1 = WCONST(0xfffffffffffff800, 0xffffff00);+ sljit_sw value2 = WCONST(0x8000000000000801, 0x80000101);++ union {+ sljit_f64 value;+#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+ struct {+ sljit_u32 low;+ sljit_u32 high;+ } bin;+#else /* !SLJIT_LITTLE_ENDIAN */+ struct {+ sljit_u32 high;+ sljit_u32 low;+ } bin;+#endif /* SLJIT_LITTLE_ENDIAN */+ } f64_check;++ union {+ sljit_f32 value;+ sljit_u32 bin;+ } f32_check;++ if (verbose)+ printf("Run test_float19\n");++ for (i = 0; i < 9; i++)+ dbuf[i] = -1.0;++ for (i = 0; i < 9; i++)+ sbuf[i] = -1.0;++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(P, P), 4 | SLJIT_ENTER_FLOAT(4), 4, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x7fffffff);+ /* dbuf[0] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_U32, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R1, 0);+ /* sbuf[0] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_U32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1);+ /* dbuf[1] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_U32, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 3, SLJIT_IMM, (sljit_sw)0xfff00000);+ /* sbuf[1] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_U32, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), 2, SLJIT_IMM, (sljit_sw)0xfff00000);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0xffffff80);+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_U32, SLJIT_FR1, 0, SLJIT_R0, 0);+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_U32, SLJIT_FR3, 0, SLJIT_R0, 0);+ /* dbuf[2] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64), SLJIT_FR1, 0);+ /* sbuf[2] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f32), SLJIT_FR3, 0);++ /* dbuf[3] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_UW, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f64), SLJIT_IMM, (sljit_sw)0xffffff00);+ /* sbuf[3] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_UW, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f32), SLJIT_IMM, (sljit_sw)0xffffff00);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, WCONST(0x7fff000000000000, 0x7fff0000));+ /* dbuf[4] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_UW, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_f64), SLJIT_R3, 0);+ /* sbuf[4] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_UW, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_f32), SLJIT_R3, 0);++ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_UW, SLJIT_FR2, 0, SLJIT_MEM0(), (sljit_sw)&value1);+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_UW, SLJIT_FR1, 0, SLJIT_MEM0(), (sljit_sw)&value1);+ /* dbuf[5] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_f64), SLJIT_FR2, 0);+ /* sbuf[5] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_f32), SLJIT_FR1, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, WCONST(0xaaaaaaaaaaaaaaaa, 0xaaaaaaaa));+ /* dbuf[6] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_UW, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_f64), SLJIT_S3, 0);+ /* sbuf[6] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_UW, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_f32), SLJIT_S3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)&value2 + 64);+ /* dbuf[7] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_UW, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_f64), SLJIT_MEM1(SLJIT_R2), -64);+ /* sbuf[7] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_UW, SLJIT_MEM1(SLJIT_S1), 7 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_R2), -64);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, WCONST(0x8000000000000401, 0x80000001));+ /* dbuf[8] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_UW, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_f64), SLJIT_R2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, WCONST(0x8000008000000001, 0x80000081));+ /* sbuf[8] */+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_UW, SLJIT_MEM1(SLJIT_S1), 8 * sizeof(sljit_f32), SLJIT_R2, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)&dbuf, (sljit_sw)&sbuf);++ f64_check.value = dbuf[0]; /* 0x7fffffff */+ FAILED(f64_check.bin.low != 0xffc00000 || f64_check.bin.high != 0x41dfffff, "test_float19 case 1 failed\n");+ f32_check.value = sbuf[0]; /* 0x7fffffff */+ FAILED(f32_check.bin != 0x4f000000, "test_float19 case 2 failed\n");+ f64_check.value = dbuf[1]; /* 0xfff00000 */+ FAILED(f64_check.bin.low != 0 || f64_check.bin.high != 0x41effe00, "test_float19 case 3 failed\n");+ f32_check.value = sbuf[1]; /* 0xfff00000 */+ FAILED(f32_check.bin != 0x4f7ff000, "test_float19 case 4 failed\n");+ f64_check.value = dbuf[2]; /* 0xffffff80 */+ FAILED(f64_check.bin.low != 0xf0000000 || f64_check.bin.high != 0x41efffff, "test_float19 case 5 failed\n");+ f32_check.value = sbuf[2]; /* 0xffffff80 */+ FAILED(f32_check.bin != 0x4f800000, "test_float19 case 6 failed\n");+ f64_check.value = dbuf[3]; /* 0xffffff00 */+ FAILED(f64_check.bin.low != 0xe0000000 || f64_check.bin.high != 0x41efffff, "test_float19 case 7 failed\n");+ f32_check.value = sbuf[3]; /* 0xffffff00 */+ FAILED(f32_check.bin != 0x4f7fffff, "test_float19 case 8 failed\n");+#if IS_64BIT+ f64_check.value = dbuf[4]; /* 0x7fff000000000000 */+ FAILED(f64_check.bin.low != 0 || f64_check.bin.high != 0x43dfffc0, "test_float19 case 9 failed\n");+ f32_check.value = sbuf[4]; /* 0x7fff000000000000 */+ FAILED(f32_check.bin != 0x5efffe00, "test_float19 case 10 failed\n");+ f64_check.value = dbuf[5]; /* 0xfffffffffffff800 */+ FAILED(f64_check.bin.low != 0xffffffff || f64_check.bin.high != 0x43efffff, "test_float19 case 11 failed\n");+ f32_check.value = sbuf[5]; /* 0xfffffffffffff800 */+ FAILED(f32_check.bin != 0x5f800000, "test_float19 case 12 failed\n");+ f64_check.value = dbuf[6]; /* 0xffff000000000000 */+ FAILED(f64_check.bin.low != 0x55555555 || f64_check.bin.high != 0x43e55555, "test_float19 case 13 failed\n");+ f32_check.value = sbuf[6]; /* 0xffff000000000000 */+ FAILED(f32_check.bin != 0x5f2aaaab, "test_float19 case 14 failed\n");+ f64_check.value = dbuf[7]; /* 0x8000000000000801 */+ FAILED(f64_check.bin.low != 1 || f64_check.bin.high != 0x43e00000, "test_float19 case 15 failed\n");+ f32_check.value = sbuf[7]; /* 0x8000000000000801 */+ FAILED(f32_check.bin != 0x5f000000, "test_float19 case 16 failed\n");+ f64_check.value = dbuf[8]; /* 0x8000000000000401 */+ FAILED(f64_check.bin.low != 1 || f64_check.bin.high != 0x43e00000, "test_float19 case 17 failed\n");+ f32_check.value = sbuf[8]; /* 0x8000008000000001 */+ FAILED(f32_check.bin != 0x5f000001, "test_float19 case 18 failed\n");+#else /* !IS_64BIT */+ f64_check.value = dbuf[4]; /* 0x7fff0000 */+ FAILED(f64_check.bin.low != 0 || f64_check.bin.high != 0x41dfffc0, "test_float19 case 9 failed\n");+ f32_check.value = sbuf[4]; /* 0x7fff0000 */+ FAILED(f32_check.bin != 0x4efffe00, "test_float19 case 10 failed\n");+ f64_check.value = dbuf[5]; /* 0xffffff00 */+ FAILED(f64_check.bin.low != 0xe0000000 || f64_check.bin.high != 0x41efffff, "test_float19 case 11 failed\n");+ f32_check.value = sbuf[5]; /* 0xffffff00 */+ FAILED(f32_check.bin != 0x4f7fffff, "test_float19 case 12 failed\n");+ f64_check.value = dbuf[6]; /* 0xaaaaaaaa */+ FAILED(f64_check.bin.low != 0x55400000 || f64_check.bin.high != 0x41e55555, "test_float19 case 13 failed\n");+ f32_check.value = sbuf[6]; /* 0xaaaaaaaa */+ FAILED(f32_check.bin != 0x4f2aaaab, "test_float19 case 14 failed\n");+ f64_check.value = dbuf[7]; /* 0x80000101 */+ FAILED(f64_check.bin.low != 0x20200000 || f64_check.bin.high != 0x41e00000, "test_float19 case 15 failed\n");+ f32_check.value = sbuf[7]; /* 0x80000101 */+ FAILED(f32_check.bin != 0x4f000001, "test_float19 case 16 failed\n");+ f64_check.value = dbuf[8]; /* 0x80000001 */+ FAILED(f64_check.bin.low != 0x00200000 || f64_check.bin.high != 0x41e00000, "test_float19 case 17 failed\n");+ f32_check.value = sbuf[8]; /* 0x80000081 */+ FAILED(f32_check.bin != 0x4f000001, "test_float19 case 18 failed\n");+#endif /* IS_64BIT */+ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test_float20(void)+{+ /* Test fpu copysign. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ int i;++ union {+ sljit_f64 value;+ struct {+#if defined(SLJIT_LITTLE_ENDIAN) && SLJIT_LITTLE_ENDIAN+ sljit_u32 lo;+ sljit_u32 hi;+#else /* !SLJIT_LITTLE_ENDIAN */+ sljit_u32 hi;+ sljit_u32 lo;+#endif /* SLJIT_LITTLE_ENDIAN */+ } bits;+ } dbuf[8];+ union {+ sljit_f32 value;+ sljit_u32 bits;+ } sbuf[8];++ if (verbose)+ printf("Run test_float20\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 8; i++)+ dbuf[i].value = 123.0;++ for (i = 0; i < 8; i++)+ sbuf[i].value = 123.0f;++ dbuf[0].value = 1786.5;+ dbuf[1].value = -8403.25;+ dbuf[2].bits.lo = 0;+ dbuf[2].bits.hi = 0x7fff0000;+ dbuf[3].value = 9054;++ sbuf[0].value = 6371.75f;+ sbuf[1].value = -2713.5f;+ sbuf[2].bits = 0xfff00000;+ sbuf[3].value = -5791.25f;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(P, P), 2 | SLJIT_ENTER_FLOAT(6), 2, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64));+ sljit_emit_fop2r(compiler, SLJIT_COPYSIGN_F64, SLJIT_FR0, SLJIT_FR0, 0, SLJIT_FR1, 0);+ /* dbuf[4] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_f64), SLJIT_FR0, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR4, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR3, 0, SLJIT_MEM1(SLJIT_S1), 0);+ sljit_emit_fop2r(compiler, SLJIT_COPYSIGN_F32, SLJIT_FR3, SLJIT_FR4, 0, SLJIT_FR3, 0);+ /* sbuf[4] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_f32), SLJIT_FR3, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2 * sizeof(sljit_f64));+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 8 * sizeof(sljit_f64));+ sljit_emit_fop2r(compiler, SLJIT_COPYSIGN_F64, SLJIT_FR2, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 0, SLJIT_MEM1(SLJIT_R1), -7 * (sljit_sw)sizeof(sljit_f64));+ /* dbuf[5] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_f64), SLJIT_FR2, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 2);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR4, 0, SLJIT_MEM1(SLJIT_S1), 0);+ sljit_emit_fop2r(compiler, SLJIT_COPYSIGN_F32, SLJIT_FR5, SLJIT_MEM2(SLJIT_S1, SLJIT_R1), 2, SLJIT_FR4, 0);+ /* sbuf[5] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_f32), SLJIT_FR5, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR3, 0, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f64));+ sljit_emit_fop2r(compiler, SLJIT_COPYSIGN_F64, SLJIT_FR0, SLJIT_FR3, 0, SLJIT_FR2, 0);+ /* dbuf[6] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_f64), SLJIT_FR0, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f32));+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_IMM, 0x12345);+ sljit_emit_fop2r(compiler, SLJIT_COPYSIGN_F32, SLJIT_FR2, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_R0), -0x12345 + (sljit_sw)sizeof(sljit_f32));+ /* sbuf[6] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_f32), SLJIT_FR2, 0);++ sljit_emit_fop2r(compiler, SLJIT_COPYSIGN_F64, SLJIT_FR5, SLJIT_MEM0(), (sljit_sw)(dbuf + 1), SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64));+ /* dbuf[7] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_f64), SLJIT_FR5, 0);++ sljit_emit_fop2r(compiler, SLJIT_COPYSIGN_F32, SLJIT_FR4, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_MEM0(), (sljit_sw)(sbuf + 2));+ /* sbuf[7] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 7 * sizeof(sljit_f32), SLJIT_FR4, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)&dbuf, (sljit_sw)&sbuf);+ FAILED(dbuf[4].value != -1786.5, "test_float20 case 1 failed\n");+ FAILED(sbuf[4].value != 2713.5, "test_float20 case 2 failed\n");+ FAILED(dbuf[5].bits.lo != 0, "test_float20 case 3 failed\n");+ FAILED(dbuf[5].bits.hi != 0xffff0000, "test_float20 case 4 failed\n");+ FAILED(sbuf[5].bits != 0x7ff00000, "test_float20 case 5 failed\n");+ FAILED(dbuf[6].value != 9054, "test_float20 case 6 failed\n");+ FAILED(sbuf[6].value != -5791.25, "test_float20 case 7 failed\n");+ FAILED(dbuf[7].value != 8403.25, "test_float20 case 8 failed\n");+ FAILED(sbuf[7].value != -sbuf[0].value, "test_float20 case 9 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test_float21(void)+{+ /* Test f64 as f32 register pair access. */+ executable_code code;+ struct sljit_compiler* compiler;+ sljit_f32 buf[10];+ sljit_sw num;+ sljit_s32 i;++ if (verbose)+ printf("Run test_float21\n");++ if (!sljit_has_cpu_feature(SLJIT_HAS_F64_AS_F32_PAIR)) {+ if (verbose)+ printf("f32 register pairs are not available, test_float21 skipped\n");+ successful_tests++;+ return;+ }++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ buf[0] = -45.25;+ buf[1] = 33.5;+ buf[2] = -104.75;++ for (i = 3; i < 10; i++)+ buf[i] = -1.0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 3 | SLJIT_ENTER_FLOAT(4), 2 | SLJIT_ENTER_FLOAT(2), 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_F64_SECOND(SLJIT_FR0), 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f32));++ sljit_emit_fop1(compiler, SLJIT_NEG_F32, SLJIT_F64_SECOND(SLJIT_FR0), 0, SLJIT_F64_SECOND(SLJIT_FR0), 0);+ /* buf[3] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f32), SLJIT_F64_SECOND(SLJIT_FR0), 0);++ sljit_emit_fop1(compiler, SLJIT_ABS_F32, SLJIT_F64_SECOND(SLJIT_FR0), 0, SLJIT_FR0, 0);+ /* buf[4] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_f32), SLJIT_F64_SECOND(SLJIT_FR0), 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f32));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 89);+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_SW, SLJIT_F64_SECOND(SLJIT_FR1), 0, SLJIT_R0, 0);+ /* buf[5] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_f32), SLJIT_F64_SECOND(SLJIT_FR1), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_F64_SECOND(SLJIT_FR1), 0, SLJIT_FR1, 0);+ /* num */+ sljit_emit_fop1(compiler, SLJIT_CONV_SW_FROM_F32, SLJIT_MEM0(), (sljit_sw)&num, SLJIT_F64_SECOND(SLJIT_FR1), 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FS1, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_F64_SECOND(SLJIT_FS1), 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f32));+ sljit_emit_fop2(compiler, SLJIT_ADD_F32, SLJIT_F64_SECOND(SLJIT_FS1), 0, SLJIT_FS1, 0, SLJIT_F64_SECOND(SLJIT_FS1), 0);+ /* buf[6] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_f32), SLJIT_F64_SECOND(SLJIT_FS1), 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f32));+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_F64_SECOND(SLJIT_FR1), 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop2r(compiler, SLJIT_COPYSIGN_F32, SLJIT_F64_SECOND(SLJIT_FR1), SLJIT_FR1, 0, SLJIT_F64_SECOND(SLJIT_FR1), 0);+ /* buf[7] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_f32), SLJIT_F64_SECOND(SLJIT_FR1), 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_F64_SECOND(SLJIT_FS0), 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fset32(compiler, SLJIT_F64_SECOND(SLJIT_FS0), -78.75f);+ /* buf[8] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_f32), SLJIT_F64_SECOND(SLJIT_FS0), 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_F64_SECOND(SLJIT_FR3), 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f32));+ sljit_emit_fcopy(compiler, SLJIT_COPY32_TO_F32, SLJIT_F64_SECOND(SLJIT_FR3), SLJIT_S1);+ /* buf[9] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_f32), SLJIT_F64_SECOND(SLJIT_FR3), 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ sljit_free_code(code.code, NULL);++ FAILED(buf[3] != -33.5, "test_float21 case 1 failed\n");+ FAILED(buf[4] != 45.25, "test_float21 case 2 failed\n");+ FAILED(buf[5] != 89.0, "test_float21 case 3 failed\n");+ FAILED(num != -104, "test_float21 case 4 failed\n");+ FAILED(buf[6] != -11.75, "test_float21 case 5 failed\n");+ FAILED(buf[7] != -33.5, "test_float21 case 6 failed\n");+ FAILED(buf[8] != -78.75, "test_float21 case 7 failed\n");+ FAILED(buf[9] != -45.25, "test_float21 case 8 failed\n");++ successful_tests++;+}++static void test_float22(void)+{+ /* Test float to int conversion corner cases. */+ executable_code code;+ struct sljit_compiler *compiler = sljit_create_compiler(NULL);+ struct sljit_label *label;+ int i;++ union {+ sljit_f64 value_f64;+ sljit_uw value_uw;+ sljit_u32 value_u32;++ struct {+#if defined(SLJIT_LITTLE_ENDIAN) && SLJIT_LITTLE_ENDIAN+ sljit_u32 lo;+ sljit_u32 hi;+#else /* !SLJIT_LITTLE_ENDIAN */+ sljit_u32 hi;+ sljit_u32 lo;+#endif /* SLJIT_LITTLE_ENDIAN */+ } bits;+ } dbuf[32];+ union {+ sljit_f32 value_f32;+ sljit_u32 bits;+ } sbuf[6];++ const sljit_uw min_uw = (sljit_uw)1 << ((sizeof(sljit_uw) * 8) - 1);+ const sljit_u32 min_u32 = (sljit_u32)1 << 31;++#if SLJIT_CONV_MAX_FLOAT == SLJIT_CONV_RESULT_MIN_INT+ const sljit_uw large_pos_uw = min_uw;+ const sljit_u32 large_pos_u32 = min_u32;+#else+ const sljit_uw large_pos_uw = min_uw - 1;+ const sljit_u32 large_pos_u32 = min_u32 - 1;+#endif++#if SLJIT_CONV_MIN_FLOAT == SLJIT_CONV_RESULT_MIN_INT+ const sljit_uw large_neg_uw = min_uw;+ const sljit_u32 large_neg_u32 = min_u32;+#else+ const sljit_uw large_neg_uw = min_uw - 1;+ const sljit_u32 large_neg_u32 = min_u32 - 1;+#endif++#if SLJIT_CONV_NAN_FLOAT == SLJIT_CONV_RESULT_MIN_INT+ const sljit_uw nan_uw = min_uw;+ const sljit_u32 nan_u32 = min_u32;+#elif SLJIT_CONV_NAN_FLOAT == SLJIT_CONV_RESULT_MAX_INT+ const sljit_uw nan_uw = min_uw - 1;+ const sljit_u32 nan_u32 = min_u32 - 1;+#else+ const sljit_uw nan_uw = 0;+ const sljit_u32 nan_u32 = 0;+#endif++ if (verbose)+ printf("Run test_float22\n");++ FAILED(!compiler, "cannot create compiler\n");++ for (i = 0; i < 31; i++)+ dbuf[i].value_f64 = 123.0;++ /* Large positive integer */+ dbuf[0].bits.hi = (sljit_u32)0x7fe << 20;+ dbuf[0].bits.lo = 0;+ /* Large negative integer */+ dbuf[1].bits.hi = (sljit_u32)0xffe << 20;+ dbuf[1].bits.lo = 0;+ /* Positive infinity */+ dbuf[2].bits.hi = (sljit_u32)0x7ff << 20;+ dbuf[2].bits.lo = 0;+ /* Negative infinity */+ dbuf[3].bits.hi = (sljit_u32)0xfff << 20;+ dbuf[3].bits.lo = 0;+ /* Canonical NaN */+ dbuf[4].bits.hi = (sljit_u32)0xfff << 19;+ dbuf[4].bits.lo = 0;+ /* NaN */+ dbuf[5].bits.hi = (sljit_u32)0xfff << 20;+ dbuf[5].bits.lo = 1;++ /* Large positive integer */+ sbuf[0].bits = (sljit_u32)0x7f000000;+ /* Large negative integer */+ sbuf[1].bits = (sljit_u32)0xff000000;+ /* Positive infinity */+ sbuf[2].bits = (sljit_u32)0x7f800000;+ /* Negative infinity */+ sbuf[3].bits = (sljit_u32)0xff800000;+ /* Canonical NaN */+ sbuf[4].bits = (sljit_u32)0x7fc00000;+ /* NaN */+ sbuf[5].bits = (sljit_u32)0x7f800001;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(P, P), 2 | SLJIT_ENTER_FLOAT(2), 2, 0);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 6 * sizeof(sljit_f64));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_R0, 0);++ label = sljit_emit_label(compiler);+ /* dbuf[6 - 17] */+ sljit_emit_fop1(compiler, SLJIT_CONV_SW_FROM_F64, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_CONV_S32_FROM_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2 * sizeof(sljit_f64));+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, sizeof(sljit_f64));+ sljit_set_label(sljit_emit_cmp(compiler, SLJIT_LESS, SLJIT_S0, 0, SLJIT_R1, 0), label);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 6 * sizeof(sljit_f32));++ label = sljit_emit_label(compiler);+ /* dbuf[18 - 29] */+ sljit_emit_fop1(compiler, SLJIT_CONV_SW_FROM_F32, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_MEM1(SLJIT_S1), 0);+ sljit_emit_fop1(compiler, SLJIT_CONV_S32_FROM_F32, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_MEM1(SLJIT_S1), 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2 * sizeof(sljit_f64));+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, sizeof(sljit_f32));+ sljit_set_label(sljit_emit_cmp(compiler, SLJIT_LESS, SLJIT_S1, 0, SLJIT_R1, 0), label);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)&dbuf, (sljit_sw)&sbuf);+ sljit_free_code(code.code, NULL);++ /* Large integer */+ FAILED(dbuf[6].value_uw != large_pos_uw, "test_float22 case 1 failed\n");+ FAILED(dbuf[7].value_u32 != large_pos_u32, "test_float22 case 2 failed\n");+ FAILED(dbuf[8].value_uw != large_neg_uw, "test_float22 case 3 failed\n");+ FAILED(dbuf[9].value_u32 != large_neg_u32, "test_float22 case 4 failed\n");+ /* Infinity */+ FAILED(dbuf[10].value_uw != large_pos_uw, "test_float22 case 5 failed\n");+ FAILED(dbuf[11].value_u32 != large_pos_u32, "test_float22 case 6 failed\n");+ FAILED(dbuf[12].value_uw != large_neg_uw, "test_float22 case 7 failed\n");+ FAILED(dbuf[13].value_u32 != large_neg_u32, "test_float22 case 8 failed\n");+ /* NaN */+ FAILED(dbuf[14].value_uw != nan_uw, "test_float22 case 9 failed\n");+ FAILED(dbuf[15].value_u32 != nan_u32, "test_float22 case 10 failed\n");+ FAILED(dbuf[16].value_uw != nan_uw, "test_float22 case 11 failed\n");+ FAILED(dbuf[17].value_u32 != nan_u32, "test_float22 case 12 failed\n");++ /* Large integer */+ FAILED(dbuf[18].value_uw != large_pos_uw, "test_float22 case 13 failed\n");+ FAILED(dbuf[19].value_u32 != large_pos_u32, "test_float22 case 14 failed\n");+ FAILED(dbuf[20].value_uw != large_neg_uw, "test_float22 case 15 failed\n");+ FAILED(dbuf[21].value_u32 != large_neg_u32, "test_float22 case 16 failed\n");+ /* Infinity */+ FAILED(dbuf[22].value_uw != large_pos_uw, "test_float22 case 17 failed\n");+ FAILED(dbuf[23].value_u32 != large_pos_u32, "test_float22 case 18 failed\n");+ FAILED(dbuf[24].value_uw != large_neg_uw, "test_float22 case 19 failed\n");+ FAILED(dbuf[25].value_u32 != large_neg_u32, "test_float22 case 20 failed\n");+ /* NaN */+ FAILED(dbuf[26].value_uw != nan_uw, "test_float22 case 21 failed\n");+ FAILED(dbuf[27].value_u32 != nan_u32, "test_float22 case 22 failed\n");+ FAILED(dbuf[28].value_uw != nan_uw, "test_float22 case 23 failed\n");+ FAILED(dbuf[29].value_u32 != nan_u32, "test_float22 case 24 failed\n");++ FAILED(dbuf[30].value_f64 != 123.0, "test_float22 case 25 failed\n");++ successful_tests++;+}++static void test_float23(void)+{+ /* Test accessing named temporary registers. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ sljit_s32 i;+ sljit_f64 dbuf[48];+ sljit_sw buf[2];++ if (verbose)+ printf("Run test_float23\n");++ for (i = 0; i < 48; i++)+ dbuf[i] = 0.0;+ for (i = 0; i < 2; i++)+ buf[i] = -1;++ dbuf[47] = 5620347186.75;+ dbuf[46] = -920341623479.5;+ *(sljit_f32*)(dbuf + 45) = -852601.25f;+ *(sljit_f32*)(dbuf + 44) = 45813.75f;+ dbuf[43] = 89025461287.0;++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(P, P), 3 | SLJIT_ENTER_FLOAT(6), 3, 2 * sizeof(sljit_f64));++ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_GREATER_EQUAL, SLJIT_MEM1(SLJIT_S0), 47 * sizeof(sljit_f64), SLJIT_MEM1(SLJIT_S0), 46 * sizeof(sljit_f64));+ sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_F_GREATER_EQUAL);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 2);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_TMP_DEST_REG, 0);++ sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_LESS, SLJIT_MEM1(SLJIT_S0), 44 * sizeof(sljit_f64), SLJIT_MEM1(SLJIT_S0), 45 * sizeof(sljit_f64));+ sljit_emit_op_flags(compiler, SLJIT_MOV32, SLJIT_TMP_DEST_REG, 0, SLJIT_F_LESS);+ sljit_emit_op2(compiler, SLJIT_SUB32, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 5);+ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 47 * sizeof(sljit_f64));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(dbuf + 46) + WCONST(0x36b16b16b16b16b1, 0x36b16b16));+ sljit_emit_fop2(compiler, SLJIT_SUB_F64, SLJIT_TMP_DEST_FREG, 0, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_R1), -WCONST(0x36b16b16b16b16b1, 0x36b16b16));+ /* dbuf[0] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_TMP_DEST_FREG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(dbuf + 45) + WCONST(0x385d85d85d85d85d, 0x385d85d8));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, (sljit_sw)(dbuf + 44) - WCONST(0x1f90f90f90f90f90, 0x1f90f90f));+ sljit_emit_fop2(compiler, SLJIT_ADD_F32, SLJIT_TMP_DEST_FREG, 0, SLJIT_MEM1(SLJIT_R1), -WCONST(0x385d85d85d85d85d, 0x385d85d8), SLJIT_MEM1(SLJIT_S2), WCONST(0x1f90f90f90f90f90, 0x1f90f90f));+ /* dbuf[1] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64), SLJIT_TMP_DEST_FREG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, (sljit_sw)(dbuf + 47) - WCONST(0x642e42e42e42e42e, 0x642e42e4));+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_TMP_DEST_FREG, 0, SLJIT_MEM1(SLJIT_TMP_DEST_REG), WCONST(0x642e42e42e42e42e, 0x642e42e4));+ /* dbuf[2] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64), SLJIT_TMP_DEST_FREG, 0);++ sljit_emit_fset64(compiler, SLJIT_FR0, 823412786.25);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_f64), SLJIT_FR0, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_TMP_DEST_FREG, 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_f64));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, (sljit_sw)(dbuf + 3) - WCONST(0x3a8ba8ba8ba8ba8b, 0x3a8ba8ba));+ /* dbuf[3] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_TMP_DEST_REG), WCONST(0x3a8ba8ba8ba8ba8b, 0x3a8ba8ba), SLJIT_TMP_DEST_FREG, 0);++ sljit_emit_fset32(compiler, SLJIT_FR3, -583562.5);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_TMP_DEST_FREG, 0, SLJIT_FR3, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, (4 * sizeof(sljit_f64)) >> 1);+ /* dbuf[4] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM2(SLJIT_S0, SLJIT_TMP_DEST_REG), 1, SLJIT_TMP_DEST_FREG, 0);++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_TMP_DEST_FREG, 0, SLJIT_MEM1(SLJIT_S0), 43 * sizeof(sljit_f64));+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 47 * sizeof(sljit_f64));+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_TMP_DEST_FREG, 0);+ /* dbuf[5] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_f64), SLJIT_FR1, 0);++ sljit_emit_fset64(compiler, SLJIT_TMP_DEST_FREG, 485123045937643.75);+ sljit_emit_fset64(compiler, SLJIT_FR1, -8345295078926845.25);+ /* dbuf[6] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_f64), SLJIT_TMP_DEST_FREG, 0);+ /* dbuf[7] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_f64), SLJIT_FR1, 0);++ sljit_emit_fset32(compiler, SLJIT_TMP_DEST_FREG, -683573.75);+ /* dbuf[8] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_f64), SLJIT_TMP_DEST_FREG, 0);++ sljit_emit_fset64(compiler, SLJIT_TMP_DEST_FREG, 5.0);+ /* dbuf[9] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_f64), SLJIT_TMP_DEST_FREG, 0);++ /* Only signed operations are supported for float temporary reg. */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1234567);+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_SW, SLJIT_TMP_DEST_FREG, 0, SLJIT_R0, 0);+ /* dbuf[10] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_f64), SLJIT_TMP_DEST_FREG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_IMM, 56789);+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_S32, SLJIT_TMP_DEST_FREG, 0, SLJIT_R2, 0);+ /* dbuf[11] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_f64), SLJIT_TMP_DEST_FREG, 0);++ sljit_emit_fset64(compiler, SLJIT_TMP_DEST_FREG, 216.75);+ sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_F64, SLJIT_TMP_DEST_FREG, 0, SLJIT_TMP_DEST_FREG, 0);+ /* dbuf[12] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_f64), SLJIT_TMP_DEST_FREG, 0);++ sljit_emit_fset32(compiler, SLJIT_TMP_DEST_FREG, 684.25);+ sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_F32, SLJIT_TMP_DEST_FREG, 0, SLJIT_TMP_DEST_FREG, 0);+ /* dbuf[13] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_f64), SLJIT_TMP_DEST_FREG, 0);++ sljit_emit_fset64(compiler, SLJIT_TMP_DEST_FREG, 5173049682.25);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, (sljit_sw)(dbuf + 46) + WCONST(0x13b73b73b73b73b7, 0x13b73b73));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8);+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 10);+ sljit_emit_fselect(compiler, SLJIT_SIG_GREATER_EQUAL, SLJIT_TMP_DEST_FREG, SLJIT_MEM1(SLJIT_TMP_DEST_REG), -WCONST(0x13b73b73b73b73b7, 0x13b73b73), SLJIT_TMP_DEST_FREG);+ /* dbuf[14] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_f64), SLJIT_TMP_DEST_FREG, 0);++ sljit_emit_fset32(compiler, SLJIT_TMP_DEST_FREG, 51730.5f);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, (sljit_sw)(dbuf + 45) - WCONST(0x768e68e68e68e68e, 0x768e68e6));+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER_EQUAL, SLJIT_R0, 0, SLJIT_IMM, -10);+ sljit_emit_fselect(compiler, SLJIT_SIG_GREATER_EQUAL | SLJIT_32, SLJIT_TMP_DEST_FREG, SLJIT_MEM1(SLJIT_TMP_DEST_REG), WCONST(0x768e68e68e68e68e, 0x768e68e6), SLJIT_TMP_DEST_FREG);+ /* dbuf[15] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_f64), SLJIT_TMP_DEST_FREG, 0);++ sljit_emit_fset64(compiler, SLJIT_TMP_DEST_FREG, -857230956376.5);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x6820820820820820, 0x68208208));+ sljit_emit_fset64(compiler, SLJIT_FR2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(dbuf + 43) - WCONST(0x4d58d58d58d58d58, 0x4d58d58d));+ sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 8);+ sljit_emit_fselect(compiler, SLJIT_EQUAL, SLJIT_FR2, SLJIT_MEM1(SLJIT_R1), WCONST(0x4d58d58d58d58d58, 0x4d58d58d), SLJIT_FR2);+ /* dbuf[16] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_f64), SLJIT_FR2, 0);+ /* dbuf[17] */+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_f64), SLJIT_TMP_DEST_FREG, 0);+ /* dbuf[18] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_f64), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)&dbuf, (sljit_sw)&buf);++ FAILED(buf[0] != 3, "test_float23 case 1 failed\n");+ FAILED(*(sljit_s32*)(buf + 1) != -5, "test_float23 case 2 failed\n");+ FAILED(dbuf[0] != 925961970666.25, "test_float23 case 3 failed\n");+ FAILED(*(sljit_f32*)(dbuf + 1) != -806787.5f, "test_float23 case 4 failed\n");+ FAILED(dbuf[2] != 5620347186.75, "test_float23 case 5 failed\n");+ FAILED(dbuf[3] != 823412786.25, "test_float23 case 6 failed\n");+ FAILED(*(sljit_f32*)(dbuf + 4) != -583562.5, "test_float23 case 7 failed\n");+ FAILED(dbuf[5] != 89025461287.0, "test_float23 case 8 failed\n");+ FAILED(dbuf[6] != 485123045937643.75, "test_float23 case 9 failed\n");+ FAILED(dbuf[7] != -8345295078926845.25, "test_float23 case 10 failed\n");+ FAILED(*(sljit_f32*)(dbuf + 8) != -683573.75, "test_float23 case 11 failed\n");+ FAILED(dbuf[9] != 5, "test_float23 case 12 failed\n");+ FAILED(dbuf[10] != 1234567.0, "test_float23 case 13 failed\n");+ FAILED(*(sljit_f32*)(dbuf + 11) != 56789.0, "test_float23 case 14 failed\n");+ FAILED(*(sljit_f32*)(dbuf + 12) != 216.75, "test_float23 case 15 failed\n");+ FAILED(dbuf[13] != 684.25, "test_float23 case 16 failed\n");+ FAILED(dbuf[14] != 5173049682.25, "test_float23 case 17 failed\n");+ FAILED(*(sljit_f32*)(dbuf + 15) != -852601.25f, "test_float23 case 18 failed\n");+ FAILED(dbuf[16] != 89025461287.0, "test_float23 case 19 failed\n");+ FAILED(dbuf[17] != -857230956376.5, "test_float23 case 20 failed\n");+ FAILED(*(sljit_sw*)(dbuf + 18) != WCONST(0x6820820820820820, 0x68208208), "test_float23 case 21 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}
+ src/c/pcre2/deps/sljit/test_src/sljitTestSerialize.h view
@@ -0,0 +1,501 @@+/*+ * 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 void test_serialize1(void)+{+ /* Test serializing large code. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_label *label;+ struct sljit_jump *jump1;+ struct sljit_jump *jump2;+ struct sljit_jump *mov_addr;+ sljit_sw executable_offset;+ sljit_uw const_addr;+ sljit_uw jump_addr;+ sljit_uw label_addr;+ sljit_sw buf[3];+ sljit_uw* serialized_buffer;+ sljit_uw serialized_size;+ sljit_s32 i;++ if (verbose)+ printf("Run test_serialize1\n");++ FAILED(!compiler, "cannot create compiler\n");+ buf[0] = 0;+ buf[1] = 0;+ buf[2] = 0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 3, 2, 0);++ jump1 = sljit_emit_jump(compiler, SLJIT_JUMP);+ label = sljit_emit_label(compiler);+ jump2 = sljit_emit_jump(compiler, SLJIT_JUMP);+ sljit_set_label(jump2, label);+ label = sljit_emit_label(compiler);+ sljit_set_label(jump1, label);++ mov_addr = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_R2, 0);+ /* buf[0] */+ sljit_emit_const(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, -1234);++ sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_R2, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, -1234);++ label = sljit_emit_label(compiler);+ sljit_set_label(mov_addr, label);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 7);+ for (i = 0; i < 4096; i++)+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 3);++ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R1, 0);++ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_IMM, -56789);+ jump1 = sljit_emit_jump(compiler, SLJIT_JUMP | SLJIT_REWRITABLE_JUMP);+ label = sljit_emit_label(compiler);+ sljit_set_label(jump1, label);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_IMM, 0);+ label = sljit_emit_label(compiler);++ serialized_buffer = sljit_serialize_compiler(compiler, 0, &serialized_size);+ FAILED(!serialized_buffer, "cannot serialize compiler\n");+ sljit_free_compiler(compiler);++ /* Continue code generation. */+ compiler = sljit_deserialize_compiler(serialized_buffer, serialized_size, 0, (void*)&label_addr);+ SLJIT_ASSERT(sljit_compiler_get_allocator_data(compiler) == (void*)&label_addr);+ SLJIT_ASSERT(sljit_compiler_get_user_data(compiler) == NULL);+ sljit_compiler_set_user_data(compiler, (void*)&jump_addr);+ SLJIT_ASSERT(sljit_compiler_get_user_data(compiler) == (void*)&jump_addr);+ SLJIT_FREE(serialized_buffer, NULL);+ FAILED(!compiler, "cannot deserialize compiler\n");++ jump1 = sljit_emit_jump(compiler, SLJIT_JUMP);+ label = sljit_emit_label(compiler);+ jump2 = sljit_emit_jump(compiler, SLJIT_JUMP);+ sljit_set_label(jump2, label);+ label = sljit_emit_label(compiler);+ sljit_set_label(jump1, label);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ executable_offset = sljit_get_executable_offset(compiler);+ const_addr = sljit_get_const_addr(sljit_get_first_const(compiler));+ jump1 = sljit_get_next_jump(sljit_get_next_jump(sljit_get_next_jump(sljit_get_first_jump(compiler))));+ SLJIT_ASSERT(!sljit_jump_is_mov_addr(jump1));+ jump_addr = sljit_get_jump_addr(jump1);+ label = sljit_get_next_label(sljit_get_next_label(sljit_get_next_label(sljit_get_next_label(sljit_get_first_label(compiler)))));+ label_addr = sljit_get_label_addr(label);+ sljit_free_compiler(compiler);++ sljit_set_const(const_addr, SLJIT_MOV, 87654, executable_offset);+ sljit_set_jump_addr(jump_addr, label_addr, executable_offset);++ code.func1((sljit_sw)&buf);+ FAILED(buf[0] != 87654, "test_serialize1 case 1 failed\n");+ FAILED(buf[1] != 7 + 4096 * 3, "test_serialize1 case 2 failed\n");+ FAILED(buf[2] != -56789, "test_serialize1 case 3 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test_serialize2(void)+{+ /* Test serializing jumps/labels. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_label *label;+ struct sljit_jump *jump;+ sljit_uw* serialized_buffer;+ sljit_uw serialized_size;+ sljit_sw buf[3];++ if (verbose)+ printf("Run test_serialize2\n");++ FAILED(!compiler, "cannot create compiler\n");+ buf[0] = 0;+ buf[1] = 0;+ buf[2] = 0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS2V(P, W), 3, 3, 32);+ sljit_emit_cmp(compiler, SLJIT_EQUAL, SLJIT_S1, 0, SLJIT_IMM, 37);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), 0);++ sljit_emit_label(compiler);+ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, -5678);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 16, SLJIT_IMM, -8765);++ sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_S2, 0);+ sljit_emit_cmp(compiler, SLJIT_NOT_EQUAL, SLJIT_S2, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), 0);++ serialized_buffer = sljit_serialize_compiler(compiler, 0, &serialized_size);+ FAILED(!serialized_buffer, "cannot serialize compiler\n");+ sljit_free_compiler(compiler);++ /* Continue code generation. */+ compiler = sljit_deserialize_compiler(serialized_buffer, serialized_size, 0, NULL);+ SLJIT_FREE(serialized_buffer, NULL);+ FAILED(!compiler, "cannot deserialize compiler\n");++ label = sljit_emit_label(compiler);+ SLJIT_ASSERT(sljit_get_label_index(label) == 1);+ jump = sljit_get_first_jump(compiler);+ SLJIT_ASSERT(!sljit_jump_is_mov_addr(jump));+ SLJIT_ASSERT(!sljit_jump_has_label(jump) && !sljit_jump_has_target(jump));+ sljit_set_label(jump, label);++ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, 3456);++ label = sljit_get_first_label(compiler);+ SLJIT_ASSERT(sljit_get_label_index(label) == 0);+ jump = sljit_emit_jump(compiler, SLJIT_JUMP);+ sljit_set_label(jump, label);++ sljit_emit_label(compiler);++ serialized_buffer = sljit_serialize_compiler(compiler, 0, &serialized_size);+ FAILED(!serialized_buffer, "cannot serialize compiler\n");+ sljit_free_compiler(compiler);++ /* Continue code generation. */+ compiler = sljit_deserialize_compiler(serialized_buffer, serialized_size, 0, NULL);+ SLJIT_FREE(serialized_buffer, NULL);+ FAILED(!compiler, "cannot deserialize compiler\n");++ sljit_emit_return_void(compiler);++ jump = sljit_get_first_jump(compiler);+ SLJIT_ASSERT(sljit_jump_has_label(jump) && !sljit_jump_has_target(jump));+ jump = sljit_get_next_jump(jump);+ SLJIT_ASSERT(sljit_jump_is_mov_addr(jump));+ jump = sljit_get_next_jump(jump);+ SLJIT_ASSERT(!sljit_jump_is_mov_addr(jump));+ SLJIT_ASSERT(!sljit_jump_has_label(jump) && !sljit_jump_has_target(jump));++ label = sljit_emit_label(compiler);+ sljit_set_label(jump, label);++ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), 16);+ sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_S2, 0);++ label = sljit_get_first_label(compiler);+ SLJIT_ASSERT(sljit_get_label_index(label) == 0);+ label = sljit_get_next_label(label);+ SLJIT_ASSERT(sljit_get_label_index(label) == 1);+ label = sljit_get_next_label(label);+ SLJIT_ASSERT(sljit_get_label_index(label) == 2);+ jump = sljit_get_next_jump(sljit_get_first_jump(compiler));+ SLJIT_ASSERT(sljit_jump_is_mov_addr(jump));+ sljit_set_label(jump, label);+ label = sljit_get_next_label(label);+ SLJIT_ASSERT(sljit_get_label_index(label) == 3);+ SLJIT_ASSERT(sljit_get_next_label(label) == NULL);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)&buf, 37);+ FAILED(buf[0] != -5678, "test_serialize2 case 1 failed\n");+ FAILED(buf[1] != 3456, "test_serialize2 case 2 failed\n");+ FAILED(buf[2] != -8765, "test_serialize2 case 3 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test_serialize3_f1(sljit_sw a, sljit_sw b, sljit_sw c)+{+ sljit_sw* ptr = (sljit_sw*)c;+ ptr[0] = a;+ ptr[1] = b;+}++static void test_serialize3(void)+{+ /* Test serializing consts/calls. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_label *label;+ struct sljit_jump *jump;+ struct sljit_const *const_;+ sljit_sw executable_offset;+ sljit_uw* serialized_buffer;+ sljit_uw serialized_size;+ sljit_sw buf[6];+ sljit_sw label_addr;+ sljit_s32 i;++ if (verbose)+ printf("Run test_serialize3\n");++ FAILED(!compiler, "cannot create compiler\n");+ for (i = 0; i < 6 ; i++)+ buf[i] = 0;++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 3, 3, 32);++ sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_R0, 0);+ sljit_emit_const(compiler, SLJIT_MOV, SLJIT_R1, 0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_S0, 0);+ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS3V(W, W, W));+ /* buf[0], buf[1] */+ sljit_set_target(jump, SLJIT_FUNC_UADDR(test_serialize3_f1));++ serialized_buffer = sljit_serialize_compiler(compiler, 0, &serialized_size);+ FAILED(!serialized_buffer, "cannot serialize compiler\n");+ sljit_free_compiler(compiler);++ /* Continue code generation. */+ compiler = sljit_deserialize_compiler(serialized_buffer, serialized_size, 0, NULL);+ SLJIT_FREE(serialized_buffer, NULL);+ FAILED(!compiler, "cannot deserialize compiler\n");++ sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_R0, 0);+ sljit_emit_const(compiler, SLJIT_MOV, SLJIT_R1, 0, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S0, 0, SLJIT_IMM, 2 * sizeof(sljit_sw));+ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS3V(W, W, W));+ /* buf[2], buf[3] */+ sljit_set_target(jump, SLJIT_FUNC_UADDR(test_serialize3_f1));++ serialized_buffer = sljit_serialize_compiler(compiler, 0, &serialized_size);+ FAILED(!serialized_buffer, "cannot serialize compiler\n");+ sljit_free_compiler(compiler);++ /* Continue code generation. */+ compiler = sljit_deserialize_compiler(serialized_buffer, serialized_size, 0, NULL);+ SLJIT_FREE(serialized_buffer, NULL);+ FAILED(!compiler, "cannot deserialize compiler\n");++ sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_R0, 0);+ sljit_emit_const(compiler, SLJIT_MOV, SLJIT_R1, 0, 0);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S0, 0, SLJIT_IMM, 4 * sizeof(sljit_sw));+ jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS3V(W, W, W));+ /* buf[4], buf[5] */+ sljit_set_target(jump, SLJIT_FUNC_UADDR(test_serialize3_f1));++ sljit_emit_return_void(compiler);+ SLJIT_ASSERT(sljit_get_first_label(compiler) == NULL);+ label = sljit_emit_label(compiler);+ SLJIT_ASSERT(sljit_get_label_index(label) == 0);++ jump = sljit_get_first_jump(compiler);+ SLJIT_ASSERT(sljit_jump_is_mov_addr(jump));+ sljit_set_label(jump, label);+ jump = sljit_get_next_jump(jump);+ SLJIT_ASSERT(!sljit_jump_is_mov_addr(jump));+ SLJIT_ASSERT(sljit_jump_has_target(jump) && sljit_jump_get_target(jump) == SLJIT_FUNC_UADDR(test_serialize3_f1));+ jump = sljit_get_next_jump(jump);+ SLJIT_ASSERT(sljit_jump_is_mov_addr(jump));+ sljit_set_label(jump, label);+ jump = sljit_get_next_jump(jump);+ SLJIT_ASSERT(!sljit_jump_is_mov_addr(jump));+ SLJIT_ASSERT(sljit_jump_has_target(jump) && sljit_jump_get_target(jump) == SLJIT_FUNC_UADDR(test_serialize3_f1));+ jump = sljit_get_next_jump(jump);+ SLJIT_ASSERT(sljit_jump_is_mov_addr(jump));+ sljit_set_label(jump, label);+ jump = sljit_get_next_jump(jump);+ SLJIT_ASSERT(sljit_jump_has_target(jump) && sljit_jump_get_target(jump) == SLJIT_FUNC_UADDR(test_serialize3_f1));+ SLJIT_ASSERT(sljit_get_next_jump(jump) == NULL);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ executable_offset = sljit_get_executable_offset(compiler);++ const_ = sljit_get_first_const(compiler);+ sljit_set_const(sljit_get_const_addr(const_), SLJIT_MOV, 0x5678, executable_offset);+ const_ = sljit_get_next_const(const_);+ sljit_set_const(sljit_get_const_addr(const_), SLJIT_MOV, -0x9876, executable_offset);+ const_ = sljit_get_next_const(const_);+ sljit_set_const(sljit_get_const_addr(const_), SLJIT_MOV, 0x2345, executable_offset);+ SLJIT_ASSERT(sljit_get_next_const(const_) == NULL);++ label_addr = (sljit_sw)sljit_get_label_addr(label);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);+ FAILED(buf[0] != label_addr, "test_serialize3 case 1 failed\n");+ FAILED(buf[1] != 0x5678, "test_serialize3 case 2 failed\n");+ FAILED(buf[2] != label_addr, "test_serialize3 case 3 failed\n");+ FAILED(buf[3] != -0x9876, "test_serialize3 case 4 failed\n");+ FAILED(buf[4] != label_addr, "test_serialize3 case 5 failed\n");+ FAILED(buf[5] != 0x2345, "test_serialize3 case 6 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}++static void test_serialize4(void)+{+ /* Test serializing aligned labels. */+ executable_code code;+ struct sljit_compiler* compiler = sljit_create_compiler(NULL);+ struct sljit_label *label[9];+ struct sljit_jump *jump[3];+ sljit_uw* serialized_buffer;+ sljit_uw serialized_size;+ sljit_s32 i;+ sljit_uw buf[8];+ sljit_uw addr[4];++ if (verbose)+ printf("Run test_serialize4\n");++ for (i = 0; i < 8; i++)+ buf[i] = ~(sljit_uw)0;++ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, 0, SLJIT_ARGS1V(P), 5, 5, 2 * sizeof(sljit_sw));++ /* buf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_S0, 0);+ jump[0] = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_MEM1(SLJIT_R1), 0);++ /* buf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_S0, 0);+ jump[1] = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_MEM0(), (sljit_sw)(buf + 1));++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);+ /* buf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_IMM, 39417);++ label[0] = sljit_emit_aligned_label(compiler, SLJIT_LABEL_ALIGN_8, NULL);+ label[1] = sljit_emit_label(compiler);+ /* buf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0);++ label[2] = sljit_emit_label(compiler);+ label[3] = sljit_emit_aligned_label(compiler, SLJIT_LABEL_ALIGN_16, NULL);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1000);+ sljit_set_label(sljit_emit_cmp(compiler, SLJIT_LESS_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 13999), label[1]);++ label[4] = sljit_emit_aligned_label(compiler, SLJIT_LABEL_ALIGN_4, NULL);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 52891);++ /* The SLJIT_JUMP_IF_NON_ZERO is the default. */+ jump[2] = sljit_emit_op2cmpz(compiler, SLJIT_ADD, SLJIT_S4, 0, SLJIT_R2, 0, SLJIT_IMM, 831);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0);++ label[5] = sljit_emit_aligned_label(compiler, SLJIT_LABEL_ALIGN_16, NULL);+ label[6] = sljit_emit_label(compiler);+ sljit_set_label(jump[2], label[6]);++ /* buf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R2, 0);+ /* buf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_S4, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (6 * sizeof(sljit_sw)) >> 1);+ /* buf[6] */+ sljit_set_label(sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_MEM2(SLJIT_R1, SLJIT_S1), 1), label[3]);++ label[7] = sljit_emit_aligned_label(compiler, SLJIT_LABEL_ALIGN_4, NULL);+ sljit_set_label(jump[0], label[7]);++ FAILED(label[0] != label[1], "test_serialize4 case 1 failed\n");+ FAILED(label[2] == label[3], "test_serialize4 case 2 failed\n");+ FAILED(label[5] != label[6], "test_serialize4 case 3 failed\n");++ serialized_buffer = sljit_serialize_compiler(compiler, 0, &serialized_size);+ FAILED(!serialized_buffer, "cannot serialize compiler\n");+ sljit_free_compiler(compiler);++ /* Continue code generation. */+ compiler = sljit_deserialize_compiler(serialized_buffer, serialized_size, 0, NULL);+ SLJIT_FREE(serialized_buffer, NULL);+ FAILED(!compiler, "cannot deserialize compiler\n");++ label[0] = sljit_get_first_label(compiler);+ label[2] = sljit_get_next_label(label[0]);+ label[3] = sljit_get_next_label(label[2]);+ label[4] = sljit_get_next_label(label[3]);+ label[5] = sljit_get_next_label(label[4]);+ label[7] = sljit_get_next_label(label[5]);+ SLJIT_ASSERT(sljit_get_next_label(label[7]) == NULL);++ jump[0] = sljit_get_first_jump(compiler);+ jump[1] = sljit_get_next_jump(jump[0]);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0);++ label[8] = sljit_emit_aligned_label(compiler, SLJIT_LABEL_ALIGN_16, NULL);+ sljit_set_label(sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_S3, 0), label[0]);+ /* buf[7] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_S3, 0);++ sljit_set_label(jump[1], label[8]);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);++ FAILED((sljit_get_label_abs_addr(label[0]) & 0x7) != 0, "test_serialize4 case 4 failed\n");+ FAILED((sljit_get_label_abs_addr(label[3]) & 0xf) != 0, "test_serialize4 case 5 failed\n");+ FAILED((sljit_get_label_abs_addr(label[4]) & 0x3) != 0, "test_serialize4 case 6 failed\n");+ FAILED((sljit_get_label_abs_addr(label[5]) & 0xf) != 0, "test_serialize4 case 7 failed\n");+ FAILED((sljit_get_label_abs_addr(label[7]) & 0x3) != 0, "test_serialize4 case 8 failed\n");+ FAILED((sljit_get_label_abs_addr(label[8]) & 0xf) != 0, "test_serialize4 case 9 failed\n");++ addr[0] = sljit_get_label_addr(label[7]);+ addr[1] = sljit_get_label_addr(label[8]);+ addr[2] = sljit_get_label_addr(label[3]);+ addr[3] = sljit_get_label_addr(label[0]);++ sljit_free_compiler(compiler);++ code.func1((sljit_sw)&buf);++ FAILED(buf[0] != addr[0], "test_serialize4 case 10 failed\n");+ FAILED(buf[1] != addr[1], "test_serialize4 case 11 failed\n");+ FAILED(buf[2] != 39417, "test_serialize4 case 12 failed\n");+ FAILED(buf[3] != 13000, "test_serialize4 case 13 failed\n");+ FAILED(buf[4] != 52891, "test_serialize4 case 14 failed\n");+ FAILED(buf[5] != 53722, "test_serialize4 case 15 failed\n");+ FAILED(buf[6] != addr[2], "test_serialize4 case 16 failed\n");+ FAILED(buf[7] != addr[3], "test_serialize4 case 17 failed\n");++ sljit_free_code(code.code, NULL);+ successful_tests++;+}
+ src/c/pcre2/deps/sljit/test_src/sljitTestSimd.h view
@@ -0,0 +1,2722 @@+/*+ * 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.+ */++#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)++#define SIMD_RUN_START \+ while (1) {++#define SIMD_RUN_END \+ if (options == SLJIT_ENTER_USE_VEX) \+ break; \+ options = SLJIT_ENTER_USE_VEX; \+ }++#else /* !SLJIT_CONFIG_X86 */+#define SIMD_RUN_START+#define SIMD_RUN_END+#endif /* SLJIT_CONFIG_X86 */++static void simd_set(sljit_u8* buf, sljit_u8 start, sljit_s32 length)+{+ do {+ *buf++ = start;+ start = (sljit_u8)(start + 103);++ if (start == 0xaa)+ start = 0xab;+ } while (--length != 0);+}++static sljit_s32 check_simd_mov(sljit_u8* buf, sljit_u8 start, sljit_s32 length)+{+ if (buf[-1] != 0xaa || buf[length] != 0xaa)+ return 0;++ do {+ if (*buf++ != start)+ return 0;++ start = (sljit_u8)(start + 103);++ if (start == 0xaa)+ start = 0xab;+ } while (--length != 0);++ return 1;+}++static void test_simd1(void)+{+ /* Test simd data transfer. */+ executable_code code;+ struct sljit_compiler* compiler;+ sljit_s32 options = 0;+ sljit_s32 i, type;+ sljit_u8 supported[2];+ sljit_u8* buf;+ sljit_u8 data[63 + 880];+ sljit_s32 vs0 = SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS > 0 ? SLJIT_VS0 : SLJIT_VR5;++ SLJIT_ASSERT(sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR0) != -1+ && sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_TMP_DEST_VREG) != -1);++ SLJIT_ASSERT(SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS == 0+ || sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VS0) != -1);++ if (verbose)+ printf("Run test_simd1\n");++ SIMD_RUN_START++ /* Buffer is 64 byte aligned. */+ buf = (sljit_u8*)(((sljit_sw)data + (sljit_sw)63) & ~(sljit_sw)63);++ for (i = 0; i < 880; i++)+ buf[i] = 0xaa;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ simd_set(buf + 0, 81, 16);+ simd_set(buf + 65, 213, 16);+ simd_set(buf + 104, 33, 16);+ simd_set(buf + 160, 140, 16);+ simd_set(buf + 210, 7, 16);+ simd_set(buf + 256, 239, 16);+ simd_set(buf + 312, 176, 16);+ simd_set(buf + 368, 88, 8);+ simd_set(buf + 393, 197, 8);+ simd_set(buf + 416, 58, 16);+ simd_set(buf + 432, 203, 16);+ simd_set(buf + 496, 105, 16);+ simd_set(buf + 560, 19, 16);+ simd_set(buf + 616, 202, 8);+ simd_set(buf + 648, 123, 8);+ simd_set(buf + 704, 85, 32);+ simd_set(buf + 801, 215, 32);++ sljit_emit_enter(compiler, options, SLJIT_ARGS1V(P), 2 | SLJIT_ENTER_VECTOR(6), 2 | SLJIT_ENTER_VECTOR(SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS > 0 ? 2 : 0), 64);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_8 | SLJIT_SIMD_MEM_ALIGNED_128;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ /* buf[32] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 32);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 65);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 82 >> 1);+ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_8 | SLJIT_SIMD_MEM_UNALIGNED;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 0);+ /* buf[82] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM2(SLJIT_S0, SLJIT_R1), 1);++ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 70001);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 70001);+ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_MEM_ALIGNED_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_R0), 70001 + 104);+ /* buf[136] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_R1), 136 - 70001);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_FLOAT | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_MEM_ALIGNED_128;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM0(), (sljit_sw)(buf + 160));+ /* buf[192] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM0(), (sljit_sw)(buf + 192));++ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 1001);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 1001);+ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_FLOAT | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_MEM_ALIGNED_16;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_R0), 1001 + 210);+ /* buf[230] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_R1), 230 - 1001);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 256 >> 3);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 288 >> 3);+ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_FLOAT | SLJIT_SIMD_ELEM_64 | SLJIT_SIMD_MEM_ALIGNED_128;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 3);+ /* buf[288] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM2(SLJIT_S0, SLJIT_R1), 3);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_FLOAT | SLJIT_SIMD_ELEM_64 | SLJIT_SIMD_MEM_ALIGNED_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 312);+ /* buf[344] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 344);++ type = SLJIT_SIMD_REG_64 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_MEM_ALIGNED_64;+ supported[0] = sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 368) != SLJIT_ERR_UNSUPPORTED;+ /* buf[384] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 384);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 393);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 402);+ type = SLJIT_SIMD_REG_64 | SLJIT_SIMD_ELEM_64 | SLJIT_SIMD_MEM_UNALIGNED;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 0);+ /* buf[402] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM2(SLJIT_S0, SLJIT_R1), 0);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_16 | SLJIT_SIMD_MEM_ALIGNED_128;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 416);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 432);+ /* buf[464] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 464);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_16;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 496);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 480);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_VR3, 0);+ /* buf[528] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 528);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 560);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 544);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_VR0, 0);+ /* buf[592] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 592);++ type = SLJIT_SIMD_REG_64 | SLJIT_SIMD_ELEM_8;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 616);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 608);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_VR5, 0);+ /* buf[632] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 632);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 648);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 640);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, vs0, 0);+ /* buf[664] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 664);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_MEM_ALIGNED_256;+ supported[1] = sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 704) != SLJIT_ERR_UNSUPPORTED;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_32, SLJIT_VR2, vs0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 384);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM2(SLJIT_R1, SLJIT_S1), 1);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_16;+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 801 - 32);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_R0), 32);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_SP), 0);+ sljit_get_local_base(compiler, SLJIT_R1, 0, 128);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_R1), -128);+ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_16 | SLJIT_SIMD_MEM_ALIGNED_16;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM0(), (sljit_sw)(buf + 834));++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)buf);+ sljit_free_code(code.code, NULL);++ FAILED(!check_simd_mov(buf + 32, 81, 16), "test_simd1 case 1 failed\n");+ FAILED(!check_simd_mov(buf + 82, 213, 16), "test_simd1 case 2 failed\n");+ FAILED(!check_simd_mov(buf + 136, 33, 16), "test_simd1 case 3 failed\n");+ FAILED(!check_simd_mov(buf + 192, 140, 16), "test_simd1 case 4 failed\n");+ FAILED(!check_simd_mov(buf + 230, 7, 16), "test_simd1 case 5 failed\n");+ FAILED(!check_simd_mov(buf + 288, 239, 16), "test_simd1 case 6 failed\n");+ FAILED(!check_simd_mov(buf + 344, 176, 16), "test_simd1 case 7 failed\n");++ if (supported[0]) {+ SLJIT_ASSERT(sljit_get_register_index(SLJIT_SIMD_REG_64, SLJIT_VR0) != -1+ && sljit_get_register_index(SLJIT_SIMD_REG_64, SLJIT_TMP_DEST_VREG) != -1);+ FAILED(!check_simd_mov(buf + 384, 88, 8), "test_simd1 case 8 failed\n");+ FAILED(!check_simd_mov(buf + 402, 197, 8), "test_simd1 case 9 failed\n");+ }++ FAILED(!check_simd_mov(buf + 464, sljit_has_cpu_feature(SLJIT_SIMD_REGS_ARE_PAIRS) ? 203 : 58, 16), "test_simd1 case 10 failed\n");+ FAILED(!check_simd_mov(buf + 528, 105, 16), "test_simd1 case 11 failed\n");+ FAILED(!check_simd_mov(buf + 592, 19, 16), "test_simd1 case 12 failed\n");++ if (supported[0]) {+ FAILED(!check_simd_mov(buf + 632, 202, 8), "test_simd1 case 13 failed\n");+ FAILED(!check_simd_mov(buf + 664, 123, 8), "test_simd1 case 14 failed\n");+ }++ if (supported[1]) {+ SLJIT_ASSERT(sljit_get_register_index(SLJIT_SIMD_REG_256, SLJIT_VR0) != -1+ && sljit_get_register_index(SLJIT_SIMD_REG_256, SLJIT_TMP_DEST_VREG) != -1);+ FAILED(!check_simd_mov(buf + 768, 85, 32), "test_simd1 case 15 failed\n");+ FAILED(!check_simd_mov(buf + 834, 215, 32), "test_simd1 case 16 failed\n");+ }++ SIMD_RUN_END++ successful_tests++;+}++static sljit_s32 check_simd_lane_mov(sljit_u8* buf, sljit_s32 length, sljit_s32 elem_size, sljit_s32 is_odd)+{+ sljit_s32 count = (length / elem_size) >> 1;+ sljit_s32 value = 180 + length - elem_size;+ sljit_s32 i;++ if (!is_odd)+ value -= elem_size;++ do {+ if (is_odd) {+ for (i = 0; i < elem_size; i++)+ if (*buf++ != 0xaa)+ return 0;+ }++ for (i = 0; i < elem_size; i++)+ if (*buf++ != value++)+ return 0;++ if (!is_odd) {+ for (i = 0; i < elem_size; i++)+ if (*buf++ != 0xaa)+ return 0;+ }++ value -= 3 * elem_size;+ } while (--count != 0);++ return 1;+}++static void test_simd2(void)+{+ /* Test simd lane data transfer. */+ executable_code code;+ struct sljit_compiler* compiler;+ sljit_s32 options = 0;+ sljit_s32 i, type;+ sljit_u8 supported[1];+ sljit_u8* buf;+ sljit_u8 data[63 + 576];+ sljit_f64 tmp[1];+ sljit_u32 f32_result = 0;+ sljit_sw result[6];+ sljit_s32 result32[5];+ sljit_s32 vs0 = SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS > 0 ? SLJIT_VS0 : SLJIT_VR5;++ if (verbose)+ printf("Run test_simd2\n");++ SIMD_RUN_START++ /* Buffer is 64 byte aligned. */+ buf = (sljit_u8*)(((sljit_sw)data + (sljit_sw)63) & ~(sljit_sw)63);++ for (i = 0; i < 64; i++)+ buf[i] = (sljit_u8)(180 + i);++ for (i = 64; i < 576; i++)+ buf[i] = 0xaa;++ for (i = 0; i < 6; i++)+ result[i] = 0;++ for (i = 0; i < 5; i++)+ result32[i] = 0;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, options, SLJIT_ARGS1V(P), 4 | SLJIT_ENTER_FLOAT(5) | SLJIT_ENTER_VECTOR(6), 4 | SLJIT_ENTER_VECTOR(SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS > 0 ? 2 : 0), 16);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)tmp - 100000);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)tmp + 1000);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 100000 / 2);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_8;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 64);++ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, 14, SLJIT_R2, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, 0, SLJIT_R2, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, 12, SLJIT_MEM1(SLJIT_SP), 0);+ sljit_get_local_base(compiler, SLJIT_R2, 0, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, 2, SLJIT_MEM1(SLJIT_R2), 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, 10, SLJIT_MEM0(), (sljit_sw)tmp);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, 4, SLJIT_MEM0(), (sljit_sw)tmp);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, 8, SLJIT_R3, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, 6, SLJIT_R3, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, 6, SLJIT_MEM1(SLJIT_R0), 100000);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, 8, SLJIT_MEM1(SLJIT_R1), -1000);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, 4, SLJIT_MEM2(SLJIT_R0, SLJIT_S1), 1);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, 10, SLJIT_MEM1(SLJIT_R1), -1000);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, 2, SLJIT_MEM1(SLJIT_R1), -1000);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, 12, SLJIT_MEM2(SLJIT_R0, SLJIT_S1), 1);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, 0, SLJIT_S2, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, 14, SLJIT_S2, 0);+ /* buf[128] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 128);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 64);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, 1, SLJIT_R2, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR5, 15, SLJIT_IMM, 181 + 0xffff00);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 183 + 0xffff00);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR5, 13, SLJIT_R2, 0);+ for (i = 5; i < 16; i += 2) {+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | SLJIT_32 | type, SLJIT_VR0, i, SLJIT_R2, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | SLJIT_32 | type, SLJIT_VR5, 16 - i, SLJIT_R2, 0);+ }+ /* buf[144] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 144);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_16;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 64);++ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, 6, SLJIT_R2, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, 0, SLJIT_R2, 0);+ sljit_get_local_base(compiler, SLJIT_R2, 0, 4);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, 4, SLJIT_MEM1(SLJIT_R2), 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, 2, SLJIT_MEM1(SLJIT_SP), 4);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, 2, SLJIT_MEM0(), (sljit_sw)tmp);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, 4, SLJIT_MEM0(), (sljit_sw)tmp);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, 0, SLJIT_S3, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, 6, SLJIT_S3, 0);+ /* buf[160] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 160);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 64);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, 7, SLJIT_MEM1(SLJIT_R0), 100000);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, 1, SLJIT_MEM1(SLJIT_R1), -1000);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, 5, SLJIT_MEM2(SLJIT_R0, SLJIT_S1), 1);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, 3, SLJIT_MEM1(SLJIT_R1), -1000);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, 3, SLJIT_MEM1(SLJIT_R1), -1000);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, 5, SLJIT_MEM2(SLJIT_R0, SLJIT_S1), 1);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, 1, SLJIT_S2, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, 7, SLJIT_S2, 0);+ /* buf[176] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 176);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 64);++ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, 2, SLJIT_R2, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, 0, SLJIT_R2, 0);+ sljit_get_local_base(compiler, SLJIT_R2, 0, 8);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, 0, SLJIT_MEM1(SLJIT_R2), 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, 2, SLJIT_MEM1(SLJIT_SP), 8);+ /* buf[192] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 192);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 64);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, 3, SLJIT_S3, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, 1, SLJIT_S3, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, 1, SLJIT_MEM1(SLJIT_R0), 100000);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, 3, SLJIT_MEM1(SLJIT_R1), -1000);+ /* buf[208] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 208);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 64);++ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, 0, SLJIT_R2, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR5, 0, SLJIT_R2, 0);+ /* buf[224] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 224);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 64);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, 1, SLJIT_MEM1(SLJIT_R1), -1000);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, 1, SLJIT_MEM2(SLJIT_R0, SLJIT_S1), 1);+ /* buf[240] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 240);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_FLOAT | SLJIT_SIMD_ELEM_32;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 64);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_VR3, 0);++ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, 2, SLJIT_FR1, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, 0, SLJIT_FR1, 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM0(), (sljit_sw)&f32_result, SLJIT_FR1, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, 0, SLJIT_FR0, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, 2, SLJIT_FR0, 0);+ /* buf[256] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 256);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 64);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, 3, SLJIT_FR2, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, 1, SLJIT_FR2, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, 1, SLJIT_FR4, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, 3, SLJIT_FR4, 0);+ /* buf[272] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 272);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 64);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, 2, SLJIT_MEM1(SLJIT_SP), 4);+ sljit_get_local_base(compiler, SLJIT_R2, 0, 4);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, 0, SLJIT_MEM1(SLJIT_R2), 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, 0, SLJIT_MEM1(SLJIT_R0), 100000);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, 2, SLJIT_MEM1(SLJIT_R1), -1000);+ /* buf[288] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 288);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 64);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, 3, SLJIT_MEM1(SLJIT_R1), -1000);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, 1, SLJIT_MEM2(SLJIT_R0, SLJIT_S1), 1);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, 1, SLJIT_MEM0(), (sljit_sw)tmp);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, 3, SLJIT_MEM0(), (sljit_sw)tmp);+ /* buf[304] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 304);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_FLOAT | SLJIT_SIMD_ELEM_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 64);++ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, 0, SLJIT_FR4, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, 0, SLJIT_FR4, 0);+ /* buf[320] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 320);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 64);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, 1, SLJIT_FR2, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, 1, SLJIT_FR2, 0);+ /* buf[336] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 336);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 64);+ sljit_get_local_base(compiler, SLJIT_R2, 0, 8);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, 0, SLJIT_MEM1(SLJIT_R2), 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, 0, SLJIT_MEM1(SLJIT_SP), 8);+ /* buf[352] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 352);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 64);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, 1, SLJIT_MEM1(SLJIT_R0), 100000);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, 1, SLJIT_MEM1(SLJIT_R1), -1000);+ /* buf[368] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 368);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)result);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | SLJIT_SIMD_REG_128, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 64);+ type = SLJIT_SIMD_STORE | SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_8;+ sljit_emit_simd_lane_mov(compiler, type, SLJIT_VR1, 6, SLJIT_R0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, -1);+ sljit_emit_simd_lane_mov(compiler, type | SLJIT_SIMD_LANE_SIGNED, SLJIT_VR1, 13, SLJIT_S3, 0);+ /* result[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R2), 0, SLJIT_R0, 0);+ /* result[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R2), sizeof(sljit_sw), SLJIT_S3, 0);++ type = SLJIT_SIMD_STORE | SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_16;+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -1);+ sljit_emit_simd_lane_mov(compiler, type, SLJIT_VR1, 5, SLJIT_R3, 0);+ sljit_emit_simd_lane_mov(compiler, type | SLJIT_SIMD_LANE_SIGNED, SLJIT_VR1, 7, SLJIT_R1, 0);+ /* result[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R2), sizeof(sljit_sw) * 2, SLJIT_R3, 0);+ /* result[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R2), sizeof(sljit_sw) * 3, SLJIT_R1, 0);++ type = SLJIT_SIMD_STORE | SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32;+ sljit_emit_simd_lane_mov(compiler, type, SLJIT_VR1, 2, SLJIT_S3, 0);+ sljit_emit_simd_lane_mov(compiler, type | SLJIT_SIMD_LANE_SIGNED, SLJIT_VR1, 3, SLJIT_R0, 0);+ /* result[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R2), sizeof(sljit_sw) * 4, SLJIT_S3, 0);+ /* result[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R2), sizeof(sljit_sw) * 5, SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)result32);+ type = SLJIT_SIMD_STORE | SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_8 | SLJIT_32;+ sljit_emit_simd_lane_mov(compiler, type, SLJIT_VR1, 0, SLJIT_R3, 0);+ sljit_emit_simd_lane_mov(compiler, type | SLJIT_SIMD_LANE_SIGNED, SLJIT_VR1, 3, SLJIT_S2, 0);+ /* result32[0] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R2), 0, SLJIT_R3, 0);+ /* result32[1] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R2), sizeof(sljit_s32), SLJIT_S2, 0);++ type = SLJIT_SIMD_STORE | SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_16 | SLJIT_32;+ sljit_emit_simd_lane_mov(compiler, type, SLJIT_VR1, 0, SLJIT_R1, 0);+ sljit_emit_simd_lane_mov(compiler, type | SLJIT_SIMD_LANE_SIGNED, SLJIT_VR1, 3, SLJIT_S3, 0);+ /* result32[2] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R2), sizeof(sljit_s32) * 2, SLJIT_R1, 0);+ /* result32[3] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R2), sizeof(sljit_s32) * 3, SLJIT_S3, 0);++ type = SLJIT_SIMD_STORE | SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32 | SLJIT_32;+ sljit_emit_simd_lane_mov(compiler, type | SLJIT_SIMD_LANE_SIGNED, SLJIT_VR1, 0, SLJIT_R0, 0);+ /* result32[4] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R2), sizeof(sljit_s32) * 4, SLJIT_R0, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)tmp - 100000);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)tmp + 1000);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_8;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 64);+ supported[0] = sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, 30, SLJIT_MEM1(SLJIT_R1), -1000) != SLJIT_ERR_UNSUPPORTED;+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, 0, SLJIT_MEM1(SLJIT_R1), -1000);++ for (i = 2; i < 32; i += 2) {+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, 30 - i, SLJIT_R2, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, i, SLJIT_R2, 0);+ }+ /* buf[384] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 384);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_16;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 64);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, 1, SLJIT_MEM1(SLJIT_SP), 8);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, 15, SLJIT_MEM1(SLJIT_SP), 8);++ for (i = 3; i < 16; i += 2) {+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, i, SLJIT_R2, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, 16 - i, SLJIT_R2, 0);+ }+ /* buf[416] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 416);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_32;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 64);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, 6, SLJIT_MEM1(SLJIT_R0), 100000);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, 0, SLJIT_MEM0(), (sljit_sw)tmp);++ for (i = 2; i < 8; i += 2) {+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, 6 - i, SLJIT_S1, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, i, SLJIT_S1, 0);+ }+ /* buf[448] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 448);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 64);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -1000);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, 1, SLJIT_MEM1(SLJIT_R0), 100000);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, 3, SLJIT_MEM2(SLJIT_R1, SLJIT_S1), 0);++ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, 3, SLJIT_S1, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, 1, SLJIT_S1, 0);+ /* buf[480] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 480);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_FLOAT;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 64);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, 1, SLJIT_MEM1(SLJIT_SP), 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, 7, SLJIT_MEM1(SLJIT_SP), 0);++ for (i = 3; i < 8; i += 2) {+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, i, SLJIT_FR2, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, 8 - i, SLJIT_FR2, 0);+ }+ /* buf[512] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 512);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_64 | SLJIT_SIMD_FLOAT;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 64);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, 2, SLJIT_MEM0(), (sljit_sw)tmp);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, 0, SLJIT_MEM1(SLJIT_R0), 100000);++ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, 0, SLJIT_FR0, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, 2, SLJIT_FR0, 0);+ /* buf[544] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 544);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)buf);+ sljit_free_code(code.code, NULL);++ FAILED(!check_simd_lane_mov(buf + 128, 16, 1, 0), "test_simd2 case 1 failed\n");+ FAILED(!check_simd_lane_mov(buf + 144, 16, 1, 1), "test_simd2 case 2 failed\n");+ FAILED(!check_simd_lane_mov(buf + 160, 16, 2, 0), "test_simd2 case 3 failed\n");+ FAILED(!check_simd_lane_mov(buf + 176, 16, 2, 1), "test_simd2 case 4 failed\n");+ FAILED(!check_simd_lane_mov(buf + 192, 16, 4, 0), "test_simd2 case 5 failed\n");+ FAILED(!check_simd_lane_mov(buf + 208, 16, 4, 1), "test_simd2 case 6 failed\n");+#if IS_64BIT+ FAILED(!check_simd_lane_mov(buf + 224, 16, 8, 0), "test_simd2 case 7 failed\n");+ FAILED(!check_simd_lane_mov(buf + 240, 16, 8, 1), "test_simd2 case 8 failed\n");+#endif /* IS_64BIT */+ FAILED(!check_simd_lane_mov(buf + 256, 16, 4, 0), "test_simd2 case 9 failed\n");+ FAILED(!check_simd_lane_mov(buf + 272, 16, 4, 1), "test_simd2 case 10 failed\n");+ FAILED(!check_simd_lane_mov(buf + 288, 16, 4, 0), "test_simd2 case 11 failed\n");+ FAILED(!check_simd_lane_mov(buf + 304, 16, 4, 1), "test_simd2 case 12 failed\n");+ FAILED(f32_result != LITTLE_BIG(0xbfbebdbc, 0xbcbdbebf), "test_simd2 case 13 failed\n");+ FAILED(!check_simd_lane_mov(buf + 320, 16, 8, 0), "test_simd2 case 14 failed\n");+ FAILED(!check_simd_lane_mov(buf + 336, 16, 8, 1), "test_simd2 case 15 failed\n");+ FAILED(!check_simd_lane_mov(buf + 352, 16, 8, 0), "test_simd2 case 16 failed\n");+ FAILED(!check_simd_lane_mov(buf + 368, 16, 8, 1), "test_simd2 case 17 failed\n");+ FAILED(result[0] != 186, "test_simd2 case 18 failed\n");+ FAILED(result[1] != -63, "test_simd2 case 19 failed\n");+ FAILED(result[2] != LITTLE_BIG(49086, 48831), "test_simd2 case 20 failed\n");+ FAILED(result[3] != LITTLE_BIG(-15422, -15677), "test_simd2 case 21 failed\n");+ FAILED(result[4] != LITTLE_BIG(WCONST(3216948668, -1078018628), WCONST(3166551743, -1128415553)), "test_simd2 case 22 failed\n");+ FAILED(result[5] != LITTLE_BIG(-1010646592, -1061043517), "test_simd2 case 23 failed\n");+ FAILED(result32[0] != 180, "test_simd2 case 24 failed\n");+ FAILED(result32[1] != -73, "test_simd2 case 25 failed\n");+ FAILED(result32[2] != LITTLE_BIG(46516, 46261), "test_simd2 case 26 failed\n");+ FAILED(result32[3] != LITTLE_BIG(-17478, -17733), "test_simd2 case 27 failed\n");+ FAILED(result32[4] != LITTLE_BIG(-1212762700, -1263159625), "test_simd2 case 28 failed\n");++ if (supported[0]) {+ FAILED(!check_simd_lane_mov(buf + 384, 32, 1, 0), "test_simd2 case 29 failed\n");+ FAILED(!check_simd_lane_mov(buf + 416, 32, 2, 1), "test_simd2 case 30 failed\n");+ FAILED(!check_simd_lane_mov(buf + 448, 32, 4, 0), "test_simd2 case 31 failed\n");+#if IS_64BIT+ FAILED(!check_simd_lane_mov(buf + 480, 32, 8, 1), "test_simd2 case 32 failed\n");+#endif /* IS_64BIT */+ FAILED(!check_simd_lane_mov(buf + 512, 32, 4, 1), "test_simd2 case 33 failed\n");+ FAILED(!check_simd_lane_mov(buf + 544, 32, 8, 0), "test_simd2 case 34 failed\n");+ }++ SIMD_RUN_END++ successful_tests++;+}++static sljit_s32 check_simd_replicate(sljit_u8* buf, sljit_s32 length, sljit_s32 elem_size, sljit_s32 value)+{+ sljit_s32 count = length / elem_size;+ sljit_s32 i;++ do {+ for (i = 0; i < elem_size; i++)+ if (*buf++ != value++)+ return 0;++ value -= elem_size;+ } while (--count != 0);++ return 1;+}++static sljit_s32 check_simd_replicate_u32(sljit_u8* buf, sljit_s32 length, sljit_u32 value)+{+ sljit_s32 count = length / 4;+ sljit_u32 start_value = value;+ sljit_s32 i;++ do {+ for (i = 0; i < 4; i++) {+ if (*buf++ != (value & 0xff))+ return 0;+ value >>= 8;+ }++ value = start_value;+ } while (--count != 0);++ return 1;+}++static void test_simd3(void)+{+ /* Test simd replicate scalar to all lanes. */+ executable_code code;+ struct sljit_compiler* compiler;+ sljit_s32 options = 0;+ sljit_s32 i, type;+ sljit_u8 supported[1];+ sljit_u8* buf;+ sljit_u8 data[63 + 768];+ sljit_s32 vs0 = SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS > 0 ? SLJIT_VS0 : SLJIT_VR5;++ if (verbose)+ printf("Run test_simd3\n");++ SIMD_RUN_START++ /* Buffer is 64 byte aligned. */+ buf = (sljit_u8*)(((sljit_sw)data + (sljit_sw)63) & ~(sljit_sw)63);++ for (i = 0; i < 32; i++)+ buf[i] = (sljit_u8)(200 + i);++ for (i = 32; i < 768; i++)+ buf[i] = 0xaa;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, options, SLJIT_ARGS1V(P), 4 | SLJIT_ENTER_FLOAT(6) | SLJIT_ENTER_VECTOR(6), 4 | SLJIT_ENTER_VECTOR(SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS > 0 ? 2 : 0), 16);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_8;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0xffff00 + 78);+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR0, SLJIT_R2, 0);+ /* buf[48] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 48);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR3, SLJIT_IMM, 0xffff00 + 253);+ /* buf[64] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 64);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_SP), 3, SLJIT_IMM, 42);+ sljit_emit_simd_replicate(compiler, type, vs0, SLJIT_MEM1(SLJIT_SP), 3);+ /* buf[80] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 80);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 15);+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR5, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 0);+ /* buf[96] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 96);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_16;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), 24);+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR3, SLJIT_R1, 0);+ /* buf[112] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 112);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_replicate(compiler, type, vs0, SLJIT_MEM0(), (sljit_sw)(buf + 10));+ /* buf[128] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 128);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 10000 + 20);+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR0, SLJIT_MEM1(SLJIT_R0), -10000);+ /* buf[144] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 144);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_S3, 0, SLJIT_MEM1(SLJIT_S0), 28);+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR1, SLJIT_S3, 0);+ /* buf[160] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 160);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_MEM1(SLJIT_SP), 4, SLJIT_MEM1(SLJIT_S0), 12);+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR5, SLJIT_MEM1(SLJIT_SP), 4);+ /* buf[176] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 176);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R2, 0, SLJIT_S0, 0, SLJIT_IMM, 100000 - 24);+ sljit_emit_simd_replicate(compiler, type, vs0, SLJIT_MEM1(SLJIT_R2), 100000);+ /* buf[192] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 192);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_S0), 8);+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR2, SLJIT_S1, 0);+ /* buf[208] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 208);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 3);+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR0, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 3);+ /* buf[224] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 224);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_replicate(compiler, type, vs0, SLJIT_MEM0(), (sljit_sw)buf);+ /* buf[240] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 240);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_FLOAT | SLJIT_SIMD_ELEM_32;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 4);+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR1, SLJIT_FR2, 0);+ /* buf[256] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 256);++ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR4, 0, SLJIT_MEM1(SLJIT_S0), 20);+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR4, SLJIT_FR4, 0);+ /* buf[272] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 272);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_SP), 4, SLJIT_MEM1(SLJIT_S0), 12);+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR0, SLJIT_MEM1(SLJIT_SP), 4);+ /* buf[288] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 288);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_FLOAT | SLJIT_SIMD_ELEM_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 16);+ sljit_emit_simd_replicate(compiler, type, vs0, SLJIT_FR0, 0);+ /* buf[304] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 304);++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR5, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR5, SLJIT_FR5, 0);+ /* buf[320] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 320);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S0, 0, SLJIT_IMM, 10000 + 8);+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR1, SLJIT_MEM1(SLJIT_R2), -10000);+ /* buf[336] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 336);++ /* Test constant values. */+ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32;+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR0, SLJIT_IMM, WCONST(0xff00123456, 0x123456));+ /* buf[352] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 352);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_16;+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR1, SLJIT_IMM, 0xff0000);+ /* buf[368] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 368);++ sljit_emit_simd_replicate(compiler, type, SLJIT_VR2, SLJIT_IMM, 0x1ffff);+ /* buf[384] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 384);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_FLOAT | SLJIT_SIMD_ELEM_64;+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR3, SLJIT_IMM, 0);+ /* buf[400] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 400);++ /* Test ARM constant values. */+ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_16;+ sljit_emit_simd_replicate(compiler, type, vs0, SLJIT_IMM, 0xff0034);+ /* buf[416] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 416);++ sljit_emit_simd_replicate(compiler, type, SLJIT_VR5, SLJIT_IMM, 0xff45ff);+ /* buf[432] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 432);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32;+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR0, SLJIT_IMM, 0xb3);+ /* buf[448] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 448);++ sljit_emit_simd_replicate(compiler, type, SLJIT_VR1, SLJIT_IMM, (sljit_sw)0xffff46ff);+ /* buf[464] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 464);++ sljit_emit_simd_replicate(compiler, type, vs0, SLJIT_IMM, 0x4c0000);+ /* buf[480] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 480);++ sljit_emit_simd_replicate(compiler, type, SLJIT_VR3, SLJIT_IMM, 0x71ffffff);+ /* buf[496] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 496);++ sljit_emit_simd_replicate(compiler, type, SLJIT_VR4, SLJIT_IMM, 0x9eff);+ /* buf[512] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 512);++ sljit_emit_simd_replicate(compiler, type, SLJIT_VR5, SLJIT_IMM, (sljit_sw)0xff070000);+ /* buf[528] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 528);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_8;+ supported[0] = sljit_emit_simd_replicate(compiler, type, SLJIT_VR2, SLJIT_IMM, 0xffff00 + 181) != SLJIT_ERR_UNSUPPORTED;+ /* buf[544] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 544);++ sljit_emit_simd_replicate(compiler, type, vs0, SLJIT_IMM, 0xffff00);+ /* buf[576] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 576);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_16;+ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), 30);+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR1, SLJIT_R1, 0);+ /* buf[608] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 608);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_32;+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 4);+ /* buf[640] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 640);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_64;+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 4);+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR0, SLJIT_MEM2(SLJIT_R1, SLJIT_S1), 2);+ /* buf[672] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 672);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_FLOAT;+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 20);+ sljit_emit_simd_replicate(compiler, type, SLJIT_VR1, SLJIT_FR2, 0);+ /* buf[704] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 704);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_64 | SLJIT_SIMD_FLOAT;+ sljit_emit_simd_replicate(compiler, type, vs0, SLJIT_MEM0(), (sljit_sw)(buf + 8));+ /* buf[736] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 736);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)buf);+ sljit_free_code(code.code, NULL);++ FAILED(!check_simd_replicate(buf + 48, 16, 1, 78), "test_simd3 case 1 failed\n");+ FAILED(!check_simd_replicate(buf + 64, 16, 1, 253), "test_simd3 case 2 failed\n");+ FAILED(!check_simd_replicate(buf + 80, 16, 1, 42), "test_simd3 case 3 failed\n");+ FAILED(!check_simd_replicate(buf + 96, 16, 1, 215), "test_simd3 case 4 failed\n");+ FAILED(!check_simd_replicate(buf + 112, 16, 2, 224), "test_simd3 case 5 failed\n");+ FAILED(!check_simd_replicate(buf + 128, 16, 2, 210), "test_simd3 case 6 failed\n");+ FAILED(!check_simd_replicate(buf + 144, 16, 2, 220), "test_simd3 case 7 failed\n");+ FAILED(!check_simd_replicate(buf + 160, 16, 4, 228), "test_simd3 case 8 failed\n");+ FAILED(!check_simd_replicate(buf + 176, 16, 4, 212), "test_simd3 case 9 failed\n");+ FAILED(!check_simd_replicate(buf + 192, 16, 4, 224), "test_simd3 case 10 failed\n");+#if IS_64BIT+ FAILED(!check_simd_replicate(buf + 208, 16, 8, 208), "test_simd3 case 11 failed\n");+ FAILED(!check_simd_replicate(buf + 224, 16, 8, 224), "test_simd3 case 12 failed\n");+ FAILED(!check_simd_replicate(buf + 240, 16, 8, 200), "test_simd3 case 13 failed\n");+#endif /* IS_64BIT */+ FAILED(!check_simd_replicate(buf + 256, 16, 4, 204), "test_simd3 case 14 failed\n");+ FAILED(!check_simd_replicate(buf + 272, 16, 4, 220), "test_simd3 case 15 failed\n");+ FAILED(!check_simd_replicate(buf + 288, 16, 4, 212), "test_simd3 case 16 failed\n");+ FAILED(!check_simd_replicate(buf + 304, 16, 8, 216), "test_simd3 case 17 failed\n");+ FAILED(!check_simd_replicate(buf + 320, 16, 8, 200), "test_simd3 case 18 failed\n");+ FAILED(!check_simd_replicate(buf + 336, 16, 8, 208), "test_simd3 case 19 failed\n");+ FAILED(!check_simd_replicate_u32(buf + 352, 16, LITTLE_BIG(0x123456, 0x56341200)), "test_simd3 case 20 failed\n");+ FAILED(!check_simd_replicate_u32(buf + 368, 16, 0), "test_simd3 case 21 failed\n");+ FAILED(!check_simd_replicate_u32(buf + 384, 16, 0xffffffff), "test_simd3 case 22 failed\n");+ FAILED(!check_simd_replicate_u32(buf + 400, 16, 0), "test_simd3 case 23 failed\n");+ FAILED(!check_simd_replicate_u32(buf + 416, 16, LITTLE_BIG(0x340034, 0x34003400)), "test_simd3 case 24 failed\n");+ FAILED(!check_simd_replicate_u32(buf + 432, 16, LITTLE_BIG(0x45ff45ff, 0xff45ff45)), "test_simd3 case 25 failed\n");+ FAILED(!check_simd_replicate_u32(buf + 448, 16, LITTLE_BIG(0xb3, 0xb3000000)), "test_simd3 case 26 failed\n");+ FAILED(!check_simd_replicate_u32(buf + 464, 16, LITTLE_BIG(0xffff46ff, 0xff46ffff)), "test_simd3 case 27 failed\n");+ FAILED(!check_simd_replicate_u32(buf + 480, 16, LITTLE_BIG(0x4c0000, 0x4c00)), "test_simd3 case 28 failed\n");+ FAILED(!check_simd_replicate_u32(buf + 496, 16, LITTLE_BIG(0x71ffffff, 0xffffff71)), "test_simd3 case 29 failed\n");+ FAILED(!check_simd_replicate_u32(buf + 512, 16, LITTLE_BIG(0x9eff, 0xff9e0000)), "test_simd3 case 30 failed\n");+ FAILED(!check_simd_replicate_u32(buf + 528, 16, LITTLE_BIG(0xff070000, 0x07ff)), "test_simd3 case 31 failed\n");++ if (supported[0]) {+ FAILED(!check_simd_replicate(buf + 544, 32, 1, 181), "test_simd3 case 32 failed\n");+ FAILED(!check_simd_replicate(buf + 576, 32, 1, 0), "test_simd3 case 33 failed\n");+ FAILED(!check_simd_replicate(buf + 608, 32, 2, 230), "test_simd3 case 34 failed\n");+ FAILED(!check_simd_replicate(buf + 640, 32, 4, 204), "test_simd3 case 35 failed\n");+#if IS_64BIT+ FAILED(!check_simd_replicate(buf + 672, 32, 8, 216), "test_simd3 case 36 failed\n");+#endif /* IS_64BIT */+ FAILED(!check_simd_replicate(buf + 704, 32, 4, 220), "test_simd3 case 37 failed\n");+ FAILED(!check_simd_replicate(buf + 736, 32, 8, 208), "test_simd3 case 38 failed\n");+ }++ SIMD_RUN_END++ successful_tests++;+}++static void test_simd4(void)+{+ /* Test simd replicate lane to all lanes. */+ executable_code code;+ struct sljit_compiler* compiler;+ sljit_s32 options = 0;+ sljit_s32 i, type;+ sljit_u8 supported[1];+ sljit_u8* buf;+ sljit_u8 data[63 + 992];+ sljit_s32 vs0 = SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS > 0 ? SLJIT_VS0 : SLJIT_VR5;++ if (verbose)+ printf("Run test_simd4\n");++ SIMD_RUN_START++ /* Buffer is 64 byte aligned. */+ buf = (sljit_u8*)(((sljit_sw)data + (sljit_sw)63) & ~(sljit_sw)63);++ for (i = 0; i < 32; i++)+ buf[i] = (sljit_u8)(100 + i);++ for (i = 32; i < 992; i++)+ buf[i] = 0xaa;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, options, SLJIT_ARGS1V(P), 4 | SLJIT_ENTER_VECTOR(6), 4 | SLJIT_ENTER_VECTOR(SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS > 0 ? 2 : 0), 16);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_8;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR0, SLJIT_VR0, 0);+ /* buf[48] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 48);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 16);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR2, SLJIT_VR1, 12);+ /* buf[64] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 64);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR3, SLJIT_VR5, 6);+ /* buf[80] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 80);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 16);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR3, SLJIT_VR3, 9);+ /* buf[96] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 96);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_lane_replicate(compiler, type, vs0, SLJIT_VR0, 10);+ /* buf[112] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 112);+ /* buf[128] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 128);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_16;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR0, SLJIT_VR0, 0);+ /* buf[144] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 144);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 16);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR1, SLJIT_VR1, 3);+ /* buf[160] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 160);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 16);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR0, SLJIT_VR4, 5);+ /* buf[176] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 176);+ /* buf[192] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 192);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR3, SLJIT_VR3, 0);+ /* buf[208] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 208);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 16);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR1, SLJIT_VR1, 2);+ /* buf[224] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 224);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR5, SLJIT_VR2, 3);+ /* buf[240] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 240);+ /* buf[256] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 256);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 16);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR1, SLJIT_VR1, 0);+ /* buf[272] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 272);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR0, SLJIT_VR0, 1);+ /* buf[288] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 288);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 16);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_lane_replicate(compiler, type, vs0, SLJIT_VR3, 1);+ /* buf[304] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 304);+ /* buf[320] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 320);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_FLOAT | SLJIT_SIMD_ELEM_32;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR2, SLJIT_VR2, 0);+ /* buf[336] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 336);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 16);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR0, SLJIT_VR0, 3);+ /* buf[352] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 352);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR5, SLJIT_VR0, 1);+ /* buf[368] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 368);+ /* buf[384] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 384);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_FLOAT | SLJIT_SIMD_ELEM_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 16);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR4, SLJIT_VR4, 0);+ /* buf[400] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 400);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR1, SLJIT_VR1, 1);+ /* buf[416] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 416);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 16);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR0, SLJIT_VR2, 1);+ /* buf[432] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 432);+ /* buf[448] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 448);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_8;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 0);+ supported[0] = sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR2, SLJIT_VR2, 0) != SLJIT_ERR_UNSUPPORTED;+ /* buf[480] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 480);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR0, SLJIT_VR4, 13);+ /* buf[512] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 512);++ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR1, SLJIT_VR4, 6);+ /* buf[544] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 544);++ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR4, SLJIT_VR4, 28);+ /* buf[576] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 576);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_16;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR2, SLJIT_VR1, 0);+ /* buf[608] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 608);++ sljit_emit_simd_lane_replicate(compiler, type, vs0, SLJIT_VR1, 2);+ /* buf[640] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 640);++ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR1, SLJIT_VR1, 13);+ /* buf[672] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 672);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_32;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR0, SLJIT_VR5, 0);+ /* buf[704] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 704);++ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR5, SLJIT_VR5, 5);+ /* buf[736] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 736);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_replicate(compiler, type, vs0, SLJIT_VR0, 0);+ /* buf[768] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 768);++ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR0, SLJIT_VR0, 1);+ /* buf[800] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 800);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_FLOAT;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR2, SLJIT_VR1, 0);+ /* buf[832] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 832);++ sljit_emit_simd_lane_replicate(compiler, type, vs0, SLJIT_VR1, 1);+ /* buf[864] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 864);++ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR1, SLJIT_VR1, 4);+ /* buf[896] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 896);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_64 | SLJIT_SIMD_FLOAT;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_replicate(compiler, type, SLJIT_VR1, vs0, 0);+ /* buf[928] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 928);++ sljit_emit_simd_lane_replicate(compiler, type, vs0, vs0, 2);+ /* buf[960] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 960);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)buf);+ sljit_free_code(code.code, NULL);++ FAILED(!check_simd_replicate(buf + 48, 16, 1, 100), "test_simd4 case 1 failed\n");+ FAILED(!check_simd_replicate(buf + 64, 16, 1, 128), "test_simd4 case 2 failed\n");+ FAILED(!check_simd_replicate(buf + 80, 16, 1, 106), "test_simd4 case 3 failed\n");+ FAILED(!check_simd_replicate(buf + 96, 16, 1, 125), "test_simd4 case 4 failed\n");+ FAILED(!check_simd_replicate(buf + 112, 16, 1, 110), "test_simd4 case 5 failed\n");+ FAILED(!check_simd_replicate(buf + 128, 16, 16, 100), "test_simd4 case 6 failed\n");+ FAILED(!check_simd_replicate(buf + 144, 16, 2, 100), "test_simd4 case 7 failed\n");+ FAILED(!check_simd_replicate(buf + 160, 16, 2, 122), "test_simd4 case 8 failed\n");+ FAILED(!check_simd_replicate(buf + 176, 16, 2, 126), "test_simd4 case 9 failed\n");+ FAILED(!check_simd_replicate(buf + 192, 16, 16, 116), "test_simd4 case 10 failed\n");+ FAILED(!check_simd_replicate(buf + 208, 16, 4, 100), "test_simd4 case 11 failed\n");+ FAILED(!check_simd_replicate(buf + 224, 16, 4, 124), "test_simd4 case 12 failed\n");+ FAILED(!check_simd_replicate(buf + 240, 16, 4, 112), "test_simd4 case 13 failed\n");+ FAILED(!check_simd_replicate(buf + 256, 16, 16, 100), "test_simd4 case 14 failed\n");+ FAILED(!check_simd_replicate(buf + 272, 16, 8, 116), "test_simd4 case 15 failed\n");+ FAILED(!check_simd_replicate(buf + 288, 16, 8, 108), "test_simd4 case 16 failed\n");+ FAILED(!check_simd_replicate(buf + 304, 16, 8, 124), "test_simd4 case 17 failed\n");+ FAILED(!check_simd_replicate(buf + 320, 16, 16, 116), "test_simd4 case 18 failed\n");+ FAILED(!check_simd_replicate(buf + 336, 16, 4, 100), "test_simd4 case 19 failed\n");+ FAILED(!check_simd_replicate(buf + 352, 16, 4, 128), "test_simd4 case 20 failed\n");+ FAILED(!check_simd_replicate(buf + 368, 16, 4, 104), "test_simd4 case 21 failed\n");+ FAILED(!check_simd_replicate(buf + 384, 16, 16, 100), "test_simd4 case 22 failed\n");+ FAILED(!check_simd_replicate(buf + 400, 16, 8, 116), "test_simd4 case 23 failed\n");+ FAILED(!check_simd_replicate(buf + 416, 16, 8, 108), "test_simd4 case 24 failed\n");+ FAILED(!check_simd_replicate(buf + 432, 16, 8, 124), "test_simd4 case 25 failed\n");+ FAILED(!check_simd_replicate(buf + 448, 16, 16, 116), "test_simd4 case 26 failed\n");++ if (supported[0]) {+ FAILED(!check_simd_replicate(buf + 480, 32, 1, 100), "test_simd4 case 27 failed\n");+ FAILED(!check_simd_replicate(buf + 512, 32, 1, 113), "test_simd4 case 28 failed\n");+ FAILED(!check_simd_replicate(buf + 544, 32, 1, 106), "test_simd4 case 29 failed\n");+ FAILED(!check_simd_replicate(buf + 576, 32, 1, 128), "test_simd4 case 30 failed\n");+ FAILED(!check_simd_replicate(buf + 608, 32, 2, 100), "test_simd4 case 31 failed\n");+ FAILED(!check_simd_replicate(buf + 640, 32, 2, 104), "test_simd4 case 32 failed\n");+ FAILED(!check_simd_replicate(buf + 672, 32, 2, 126), "test_simd4 case 33 failed\n");+ FAILED(!check_simd_replicate(buf + 704, 32, 4, 100), "test_simd4 case 34 failed\n");+ FAILED(!check_simd_replicate(buf + 736, 32, 4, 120), "test_simd4 case 35 failed\n");+ FAILED(!check_simd_replicate(buf + 768, 32, 8, 100), "test_simd4 case 36 failed\n");+ FAILED(!check_simd_replicate(buf + 800, 32, 8, 108), "test_simd4 case 37 failed\n");+ FAILED(!check_simd_replicate(buf + 832, 32, 4, 100), "test_simd4 case 38 failed\n");+ FAILED(!check_simd_replicate(buf + 864, 32, 4, 104), "test_simd4 case 39 failed\n");+ FAILED(!check_simd_replicate(buf + 896, 32, 4, 116), "test_simd4 case 40 failed\n");+ FAILED(!check_simd_replicate(buf + 928, 32, 8, 100), "test_simd4 case 41 failed\n");+ FAILED(!check_simd_replicate(buf + 960, 32, 8, 116), "test_simd4 case 42 failed\n");+ }++ SIMD_RUN_END++ successful_tests++;+}++static sljit_s32 check_simd_lane_mov_zero(sljit_u8* buf, sljit_s32 length, sljit_s32 elem_size, sljit_s32 start, sljit_s32 value)+{+ sljit_s32 i;++ for (i = 0; i < start; i++)+ if (*buf++ != 0)+ return 0;++ for (i = 0; i < elem_size; i++)+ if (*buf++ != value++)+ return 0;++ for (i = start + elem_size; i < length; i++)+ if (*buf++ != 0)+ return 0;++ return 1;+}++static void test_simd5(void)+{+ /* Test simd zero register before move to lane. */+ executable_code code;+ struct sljit_compiler* compiler;+ sljit_s32 options = 0;+ sljit_s32 i, type;+ sljit_u8 supported[1];+ sljit_u8* buf;+ sljit_u8 data[63 + 672];+ sljit_s32 vs0 = SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS > 0 ? SLJIT_VS0 : SLJIT_VR5;++ if (verbose)+ printf("Run test_simd5\n");++ SIMD_RUN_START++ /* Buffer is 64 byte aligned. */+ buf = (sljit_u8*)(((sljit_sw)data + (sljit_sw)63) & ~(sljit_sw)63);++ for (i = 0; i < 64; i++)+ buf[i] = (sljit_u8)(100 + i);++ for (i = 64; i < 672; i++)+ buf[i] = 0xaa;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, options, SLJIT_ARGS1V(P), 4 | SLJIT_ENTER_FLOAT(6) | SLJIT_ENTER_VECTOR(6), 4 | SLJIT_ENTER_VECTOR(SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS > 0 ? 2 : 0), 16);+ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 100000);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 10000);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_8;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0xffff00 + 85);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR0, 0, SLJIT_R2, 0);+ /* buf[64] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 64);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, vs0, 0, SLJIT_IMM, 0xffff00 + 18);+ /* buf[80] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 80);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_SP), 10, SLJIT_IMM, 170);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | SLJIT_32 | type, SLJIT_VR5, 5, SLJIT_MEM1(SLJIT_SP), 10);+ /* buf[96] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 96);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_16;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, LITTLE_BIG(0x789a6d6c, 0x789a6c6d));+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR1, 0, SLJIT_S2, 0);+ /* buf[112] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 112);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | SLJIT_32 | type, SLJIT_VR4, 0, SLJIT_IMM, LITTLE_BIG(0xff8382, 0xff8283));+ /* buf[128] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 128);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, vs0, 3, SLJIT_MEM1(SLJIT_R0), 100004);+ /* buf[144] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 144);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_S0), 4);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | SLJIT_32 | type, SLJIT_VR2, 0, SLJIT_R2, 0);+ /* buf[160] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 160);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR5, 0, SLJIT_IMM, LITTLE_BIG(0x29282726, 0x26272829));+ /* buf[176] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 176);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 3);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | SLJIT_32 | type, SLJIT_VR1, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_R2), 2);+ /* buf[192] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 192);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR3, 3, SLJIT_MEM1(SLJIT_R1), -10000 + 8);+ /* buf[208] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 208);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, vs0, 0, SLJIT_S2, 0);+ /* buf[224] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 224);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR4, 0,+ SLJIT_IMM, LITTLE_BIG(WCONST(0xe3e2e1e0dfdedddc, 0), WCONST(0xdcdddedfe0e1e2e3, 0)));+ /* buf[240] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 240);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 8);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR3, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_R2), 0);+ /* buf[256] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 256);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR1, 1, SLJIT_MEM1(SLJIT_R0), 100000);+ /* buf[272] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 272);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_FLOAT | SLJIT_SIMD_ELEM_32;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 12);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR0, 0, SLJIT_FR0, 0);+ /* buf[288] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 288);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR5, 0, SLJIT_MEM1(SLJIT_S0), 4);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR2, 0, SLJIT_FR5, 0);+ /* buf[304] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 304);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 1);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR1, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_R2), 3);+ /* buf[320] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 320);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR4, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR4, 1, SLJIT_FR4, 0);+ /* buf[336] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 336);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_FLOAT | SLJIT_SIMD_ELEM_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 8);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR2, 0, SLJIT_FR2, 0);+ /* buf[352] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 352);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR4, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR3, 0, SLJIT_FR4, 0);+ /* buf[368] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 368);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR1, 0, SLJIT_MEM0(), (sljit_sw)(buf + 8));+ /* buf[384] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 384);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR2, 1, SLJIT_FR2, 0);+ /* buf[400] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 400);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_8;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 215);+ supported[0] = sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR0, 0, SLJIT_R2, 0) != SLJIT_ERR_UNSUPPORTED;+ /* buf[416] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 416);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, vs0, 17, SLJIT_IMM, 78);+ /* buf[448] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 448);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_16;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 0xff3433);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR1, 4, SLJIT_S1, 0);+ /* buf[480] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 480);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_32;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR5, 5, SLJIT_MEM1(SLJIT_S0), 60);+ /* buf[512] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 512);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR4, 3, SLJIT_MEM0(), (sljit_sw)buf + 32);+ /* buf[544] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 544);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_FLOAT;+ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 48);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR2, 3, SLJIT_FR2, 0);+ /* buf[576] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 576);++ sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR3, 0, SLJIT_MEM1(SLJIT_S0), 8);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR3, 6, SLJIT_FR3, 0);+ /* buf[608] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 608);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_64 | SLJIT_SIMD_FLOAT;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_SP), 8, SLJIT_MEM1(SLJIT_S0), 40);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LANE_ZERO | type, SLJIT_VR0, 3, SLJIT_MEM1(SLJIT_SP), 8);+ /* buf[640] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 640);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)buf);+ sljit_free_code(code.code, NULL);++ FAILED(!check_simd_lane_mov_zero(buf + 64, 16, 1, 0, 85), "test_simd5 case 1 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 80, 16, 1, 0, 18), "test_simd5 case 2 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 96, 16, 1, 5, 170), "test_simd5 case 3 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 112, 16, 2, 0, 108), "test_simd5 case 4 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 128, 16, 2, 0, 130), "test_simd5 case 5 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 144, 16, 2, 6, 104), "test_simd5 case 6 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 160, 16, 4, 0, 104), "test_simd5 case 7 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 176, 16, 4, 0, 38), "test_simd5 case 8 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 192, 16, 4, 0, 112), "test_simd5 case 9 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 208, 16, 4, 12, 108), "test_simd5 case 10 failed\n");+#if IS_64BIT+ FAILED(!check_simd_lane_mov_zero(buf + 224, 16, 8, 0, 100), "test_simd5 case 11 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 240, 16, 8, 0, 220), "test_simd5 case 12 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 256, 16, 8, 0, 108), "test_simd5 case 13 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 272, 16, 8, 8, 100), "test_simd5 case 14 failed\n");+#endif /* IS_64BIT */+ FAILED(!check_simd_lane_mov_zero(buf + 288, 16, 4, 0, 112), "test_simd5 case 15 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 304, 16, 4, 0, 104), "test_simd5 case 16 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 320, 16, 4, 0, 108), "test_simd5 case 17 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 336, 16, 4, 4, 100), "test_simd5 case 18 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 352, 16, 8, 0, 108), "test_simd5 case 19 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 368, 16, 8, 0, 100), "test_simd5 case 20 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 384, 16, 8, 0, 108), "test_simd5 case 21 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 400, 16, 8, 8, 100), "test_simd5 case 22 failed\n");++ if (supported[0]) {+ FAILED(!check_simd_lane_mov_zero(buf + 416, 32, 1, 0, 215), "test_simd5 case 23 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 448, 32, 1, 17, 78), "test_simd5 case 24 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 480, 32, 2, 8, 51), "test_simd5 case 25 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 512, 32, 4, 20, 160), "test_simd5 case 26 failed\n");+#if IS_64BIT+ FAILED(!check_simd_lane_mov_zero(buf + 544, 32, 8, 24, 132), "test_simd5 case 27 failed\n");+#endif /* IS_64BIT */+ FAILED(!check_simd_lane_mov_zero(buf + 576, 32, 4, 12, 148), "test_simd5 case 28 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 608, 32, 4, 24, 108), "test_simd5 case 29 failed\n");+ FAILED(!check_simd_lane_mov_zero(buf + 640, 32, 8, 24, 140), "test_simd5 case 30 failed\n");+ }++ SIMD_RUN_END++ successful_tests++;+}++static void init_simd_extend(sljit_u8* buf, sljit_s32 length, sljit_s32 elem_size, sljit_s32 is_float, sljit_s32 data)+{+ sljit_u8* end = buf + length;++ do {+ if (elem_size == 1)+ *buf = (sljit_u8)data;+ else if (elem_size == 2)+ *(sljit_u16*)buf = (sljit_u16)data;+ else if (!is_float)+ *(sljit_u32*)buf = (sljit_u32)data;+ else+ *(sljit_f32*)buf = (sljit_f32)data;++ buf += elem_size;+ data++;+ } while (buf < end);+}++static sljit_s32 check_simd_extend_unsigned(sljit_u8* buf, sljit_s32 length, sljit_s32 elem_size, sljit_u32 mask)+{+ sljit_s32 data;+ sljit_u8* end = buf + length;++ if (elem_size == 2)+ data = -(length >> 2);+ else if (elem_size == 4)+ data = -(length >> 3);+ else+ data = -(length >> 4);++ do {+ if (elem_size == 2) {+ if (*(sljit_u16*)buf != ((sljit_u16)data & mask))+ return 0;+ } else if (elem_size == 4) {+ if (*(sljit_u32*)buf != ((sljit_u32)data & mask))+ return 0;+ } else {+#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+ if (*(sljit_u32*)buf != ((sljit_u32)data & mask) || *(sljit_u32*)(buf + 4) != 0)+ return 0;+#else /* !SLJIT_LITTLE_ENDIAN */+ if (*(sljit_u32*)(buf + 4) != ((sljit_u32)data & mask) || *(sljit_u32*)buf != 0)+ return 0;+#endif /* SLJIT_LITTLE_ENDIAN */+ }++ buf += elem_size;+ data++;+ } while (buf < end);++ return 1;+}++static sljit_s32 check_simd_extend_signed(sljit_u8* buf, sljit_s32 length, sljit_s32 elem_size, sljit_s32 is_float)+{+ sljit_s32 data;+ sljit_u8* end = buf + length;++ if (elem_size == 2)+ data = -(length >> 2);+ else if (elem_size == 4)+ data = -(length >> 3);+ else if (!is_float)+ data = -(length >> 4);+ else+ data = 1000;++ do {+ if (elem_size == 2) {+ if (*(sljit_s16*)buf != data)+ return 0;+ } else if (elem_size == 4) {+ if (*(sljit_s32*)buf != data)+ return 0;+ } else if (!is_float) {+#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+ if (*(sljit_s32*)buf != data)+ return 0;+ if (*(sljit_s32*)(buf + 4) != (data >> 31))+ return 0;+#else /* !SLJIT_LITTLE_ENDIAN */+ if (*(sljit_s32*)(buf + 4) != data)+ return 0;+ if (*(sljit_s32*)buf != (data >> 31))+ return 0;+#endif /* SLJIT_LITTLE_ENDIAN */+ } else {+ if (*(sljit_f64*)buf != (sljit_f64)data)+ return 0;+ }++ buf += elem_size;+ data++;+ } while (buf < end);++ return 1;+}++static void test_simd6(void)+{+ /* Test simd extension operation. */+ executable_code code;+ struct sljit_compiler* compiler;+ sljit_s32 options = 0;+ sljit_s32 i, type;+ sljit_u8 supported[2];+ sljit_u8* buf;+ sljit_u8 data[63 + 1088];+ sljit_s32 vs0 = SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS > 0 ? SLJIT_VS0 : SLJIT_VR5;++ if (verbose)+ printf("Run test_simd6\n");++ SIMD_RUN_START++ /* Buffer is 64 byte aligned. */+ buf = (sljit_u8*)(((sljit_sw)data + (sljit_sw)63) & ~(sljit_sw)63);++ for (i = 0; i < 1088; i++)+ buf[i] = 0xaa;++ init_simd_extend(buf + 0, 16, 1, 0, -8);+ init_simd_extend(buf + 32, 16, 2, 0, -4);+ init_simd_extend(buf + 64, 16, 4, 0, -2);+ init_simd_extend(buf + 96, 16, 4, 1, 1000);+ init_simd_extend(buf + 128, 8, 1, 0, -4);+ init_simd_extend(buf + 160, 8, 2, 0, -2);+ init_simd_extend(buf + 192, 8, 4, 0, -1);+ init_simd_extend(buf + 224, 8, 4, 1, 1000);+ init_simd_extend(buf + 256, 4, 1, 0, -2);+ init_simd_extend(buf + 288, 4, 2, 0, -1);+ init_simd_extend(buf + 320, 2, 1, 0, -1);++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, options, SLJIT_ARGS1V(P), 4 | SLJIT_ENTER_VECTOR(6), 4 | SLJIT_ENTER_VECTOR(SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS > 0 ? 2 : 0), 32);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_8 | SLJIT_SIMD_EXTEND_16;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 128);+ sljit_emit_simd_extend(compiler, type, SLJIT_VR2, SLJIT_VR0, 0);+ /* buf[352] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 352);++ sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_EXTEND_SIGNED, SLJIT_VR1, SLJIT_VR0, 0);+ /* buf[368] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 368);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 128);+ sljit_emit_simd_extend(compiler, type, SLJIT_VR0, SLJIT_MEM1(SLJIT_R1), 0);+ /* buf[384] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 384);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 128);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_SP), 0);+ sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_EXTEND_SIGNED, vs0, SLJIT_MEM1(SLJIT_SP), 0);+ /* buf[400] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 400);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_16 | SLJIT_SIMD_EXTEND_32;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 160);+ sljit_emit_simd_extend(compiler, type, SLJIT_VR4, SLJIT_VR4, 0);+ /* buf[416] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 416);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 160);+ sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_EXTEND_SIGNED, SLJIT_VR0, SLJIT_VR4, 0);+ /* buf[432] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 432);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 40);+ sljit_emit_simd_extend(compiler, type, SLJIT_VR1, SLJIT_MEM2(SLJIT_S0, SLJIT_R2), 2);+ /* buf[448] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 448);++ sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_EXTEND_SIGNED, vs0, SLJIT_MEM0(), (sljit_sw)(buf + 160));+ /* buf[464] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 464);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_EXTEND_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 192);+ sljit_emit_simd_extend(compiler, type, SLJIT_VR0, SLJIT_VR2, 0);+ /* buf[480] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 480);++ sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_EXTEND_SIGNED, SLJIT_VR3, SLJIT_VR2, 0);+ /* buf[496] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 496);++ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 10000 - 192);+ sljit_emit_simd_extend(compiler, type, SLJIT_VR2, SLJIT_MEM1(SLJIT_R0), 10000);+ /* buf[512] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 512);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 100000 + 192);+ sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_EXTEND_SIGNED, vs0, SLJIT_MEM1(SLJIT_R0), -100000);+ /* buf[528] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 528);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_FLOAT | SLJIT_SIMD_EXTEND_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 224);+ sljit_emit_simd_extend(compiler, type, vs0, vs0, 0);+ /* buf[544] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 544);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 224);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_SP), 0);+ sljit_emit_simd_extend(compiler, type, SLJIT_VR3, SLJIT_MEM1(SLJIT_SP), 0);+ /* buf[560] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 560);++ sljit_emit_simd_extend(compiler, type, SLJIT_VR5, SLJIT_VR1, 0);+ /* buf[576] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR5, SLJIT_MEM1(SLJIT_S0), 576);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_8 | SLJIT_SIMD_EXTEND_32;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 256);+ sljit_emit_simd_extend(compiler, type, SLJIT_VR0, SLJIT_VR2, 0);+ /* buf[592] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 592);++ sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_EXTEND_SIGNED, SLJIT_VR2, SLJIT_VR2, 0);+ /* buf[608] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 608);++ sljit_emit_simd_extend(compiler, type, vs0, SLJIT_MEM1(SLJIT_S0), 256);+ /* buf[624] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 624);++ sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_EXTEND_SIGNED, SLJIT_VR4, SLJIT_MEM0(), (sljit_sw)(buf + 256));+ /* buf[640] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 640);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_8 | SLJIT_SIMD_EXTEND_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 320);+ sljit_emit_simd_extend(compiler, type, SLJIT_VR0, vs0, 0);+ /* buf[656] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 656);++ sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_EXTEND_SIGNED, SLJIT_VR0, vs0, 0);+ /* buf[672] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 672);++ sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_S0), 320);+ sljit_emit_simd_extend(compiler, type, SLJIT_VR3, SLJIT_MEM1(SLJIT_SP), 0);+ /* buf[688] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 688);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 320);+ sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_EXTEND_SIGNED, SLJIT_VR3, SLJIT_MEM2(SLJIT_S0, SLJIT_S2), 0);+ /* buf[704] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 704);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_16 | SLJIT_SIMD_EXTEND_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 288);+ sljit_emit_simd_extend(compiler, type, SLJIT_VR2, SLJIT_VR0, 0);+ /* buf[720] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 720);++ sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_EXTEND_SIGNED, SLJIT_VR0, SLJIT_VR0, 0);+ /* buf[736] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 736);++ sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R2, 0, SLJIT_S0, 0, SLJIT_IMM, 100000 - 288);+ sljit_emit_simd_extend(compiler, type, vs0, SLJIT_MEM1(SLJIT_R2), 100000);+ /* buf[752] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 752);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S2, 0, SLJIT_S0, 0, SLJIT_IMM, 10000 + 288);+ sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_EXTEND_SIGNED, SLJIT_VR1, SLJIT_MEM1(SLJIT_S2), -10000);+ /* buf[768] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 768);++ type = SLJIT_SIMD_REG_64 | SLJIT_SIMD_ELEM_8 | SLJIT_SIMD_EXTEND_16;+ supported[0] = sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 256) != SLJIT_ERR_UNSUPPORTED;+ sljit_emit_simd_extend(compiler, type, vs0, SLJIT_VR1, 0);+ /* buf[784] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 784);++ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S0, 0, SLJIT_IMM, 256);+ sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_EXTEND_SIGNED, SLJIT_VR2, SLJIT_MEM1(SLJIT_R2), 0);+ /* buf[792] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 792);++ type = SLJIT_SIMD_REG_64 | SLJIT_SIMD_ELEM_8 | SLJIT_SIMD_EXTEND_32;+ sljit_emit_simd_extend(compiler, type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 320);+ /* buf[800] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 800);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 320);+ sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_EXTEND_SIGNED, SLJIT_VR2, vs0, 0);+ /* buf[808] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 808);++ type = SLJIT_SIMD_REG_64 | SLJIT_SIMD_ELEM_16 | SLJIT_SIMD_EXTEND_32;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 288);+ sljit_emit_simd_extend(compiler, type, SLJIT_VR2, SLJIT_VR1, 0);+ /* buf[816] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 816);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 288);+ sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_EXTEND_SIGNED, vs0, SLJIT_MEM2(SLJIT_S1, SLJIT_S0), 0);+ /* buf[824] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 824);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_8 | SLJIT_SIMD_EXTEND_16;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 0);+ supported[1] = sljit_emit_simd_extend(compiler, type, SLJIT_VR4, SLJIT_VR1, 0) != SLJIT_ERR_UNSUPPORTED;+ /* buf[832] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 832);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_8 | SLJIT_SIMD_EXTEND_32;+ sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_EXTEND_SIGNED, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 128);+ /* buf[864] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 864);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_8 | SLJIT_SIMD_EXTEND_64;+ sljit_emit_simd_extend(compiler, type, vs0, SLJIT_MEM0(), (sljit_sw)(buf + 256));+ /* buf[896] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 896);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_16 | SLJIT_SIMD_EXTEND_32;+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_S0, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 16);+ sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_EXTEND_SIGNED, SLJIT_VR0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 1);+ /* buf[928] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 928);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_16 | SLJIT_SIMD_EXTEND_64;+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S1, 0, SLJIT_S0, 0, SLJIT_IMM, 100000 + 160);+ sljit_emit_simd_extend(compiler, type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S1), -100000);+ /* buf[960] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 960);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_EXTEND_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 64);+ sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_EXTEND_SIGNED, SLJIT_VR0, vs0, 0);+ /* buf[992] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 992);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_EXTEND_64 | SLJIT_SIMD_FLOAT;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 96);+ sljit_emit_simd_extend(compiler, type, SLJIT_VR2, SLJIT_VR2, 0);+ /* buf[1024] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 1024);++ sljit_emit_simd_extend(compiler, type, SLJIT_VR4, SLJIT_MEM0(), (sljit_sw)(buf + 96));+ /* buf[1056] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 1056);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)buf);+ sljit_free_code(code.code, NULL);++ FAILED(!check_simd_extend_unsigned(buf + 352, 16, 2, 0xff), "test_simd6 case 1 failed\n");+ FAILED(!check_simd_extend_signed(buf + 368, 16, 2, 0), "test_simd6 case 2 failed\n");+ FAILED(!check_simd_extend_unsigned(buf + 384, 16, 2, 0xff), "test_simd6 case 3 failed\n");+ FAILED(!check_simd_extend_signed(buf + 400, 16, 2, 0), "test_simd6 case 4 failed\n");+ FAILED(!check_simd_extend_unsigned(buf + 416, 16, 4, 0xffff), "test_simd6 case 5 failed\n");+ FAILED(!check_simd_extend_signed(buf + 432, 16, 4, 0), "test_simd6 case 6 failed\n");+ FAILED(!check_simd_extend_unsigned(buf + 448, 16, 4, 0xffff), "test_simd6 case 7 failed\n");+ FAILED(!check_simd_extend_signed(buf + 464, 16, 4, 0), "test_simd6 case 8 failed\n");+ FAILED(!check_simd_extend_unsigned(buf + 480, 16, 8, 0xffffffff), "test_simd6 case 9 failed\n");+ FAILED(!check_simd_extend_signed(buf + 496, 16, 8, 0), "test_simd6 case 10 failed\n");+ FAILED(!check_simd_extend_unsigned(buf + 512, 16, 8, 0xffffffff), "test_simd6 case 11 failed\n");+ FAILED(!check_simd_extend_signed(buf + 528, 16, 8, 0), "test_simd6 case 12 failed\n");+ FAILED(!check_simd_extend_signed(buf + 544, 16, 8, 1), "test_simd6 case 13 failed\n");+ FAILED(!check_simd_extend_signed(buf + 560, 16, 8, 1), "test_simd6 case 14 failed\n");+ FAILED(!check_simd_extend_signed(buf + 576, 16, 8, 1), "test_simd6 case 15 failed\n");+ FAILED(!check_simd_extend_unsigned(buf + 592, 16, 4, 0xff), "test_simd6 case 16 failed\n");+ FAILED(!check_simd_extend_signed(buf + 608, 16, 4, 0), "test_simd6 case 17 failed\n");+ FAILED(!check_simd_extend_unsigned(buf + 624, 16, 4, 0xff), "test_simd6 case 18 failed\n");+ FAILED(!check_simd_extend_signed(buf + 640, 16, 4, 0), "test_simd6 case 19 failed\n");+ FAILED(!check_simd_extend_unsigned(buf + 656, 16, 8, 0xff), "test_simd6 case 20 failed\n");+ FAILED(!check_simd_extend_signed(buf + 672, 16, 8, 0), "test_simd6 case 21 failed\n");+ FAILED(!check_simd_extend_unsigned(buf + 688, 16, 8, 0xff), "test_simd6 case 22 failed\n");+ FAILED(!check_simd_extend_signed(buf + 704, 16, 8, 0), "test_simd6 case 23 failed\n");+ FAILED(!check_simd_extend_unsigned(buf + 720, 16, 8, 0xffff), "test_simd6 case 24 failed\n");+ FAILED(!check_simd_extend_signed(buf + 736, 16, 8, 0), "test_simd6 case 25 failed\n");+ FAILED(!check_simd_extend_unsigned(buf + 752, 16, 8, 0xffff), "test_simd6 case 26 failed\n");+ FAILED(!check_simd_extend_signed(buf + 768, 16, 8, 0), "test_simd6 case 27 failed\n");++ if (supported[0]) {+ FAILED(!check_simd_extend_unsigned(buf + 784, 8, 2, 0xff), "test_simd6 case 28 failed\n");+ FAILED(!check_simd_extend_signed(buf + 792, 8, 2, 0), "test_simd6 case 29 failed\n");+ FAILED(!check_simd_extend_unsigned(buf + 800, 8, 4, 0xff), "test_simd6 case 30 failed\n");+ FAILED(!check_simd_extend_signed(buf + 808, 8, 4, 0), "test_simd6 case 31 failed\n");+ FAILED(!check_simd_extend_unsigned(buf + 816, 8, 4, 0xffff), "test_simd6 case 32 failed\n");+ FAILED(!check_simd_extend_signed(buf + 824, 8, 4, 0), "test_simd6 case 33 failed\n");+ }++ if (supported[1]) {+ FAILED(!check_simd_extend_unsigned(buf + 832, 32, 2, 0xff), "test_simd6 case 34 failed\n");+ FAILED(!check_simd_extend_signed(buf + 864, 32, 4, 0), "test_simd6 case 35 failed\n");+ FAILED(!check_simd_extend_unsigned(buf + 896, 32, 8, 0xff), "test_simd6 case 36 failed\n");+ FAILED(!check_simd_extend_signed(buf + 928, 32, 4, 0), "test_simd6 case 37 failed\n");+ FAILED(!check_simd_extend_unsigned(buf + 960, 32, 8, 0xffff), "test_simd6 case 38 failed\n");+ FAILED(!check_simd_extend_signed(buf + 992, 32, 8, 0), "test_simd6 case 39 failed\n");+ FAILED(!check_simd_extend_signed(buf + 1024, 32, 8, 1), "test_simd6 case 40 failed\n");+ FAILED(!check_simd_extend_signed(buf + 1056, 32, 8, 1), "test_simd6 case 41 failed\n");+ }++ SIMD_RUN_END++ successful_tests++;+}++static void init_simd_sign(sljit_u8* buf, sljit_s32 length, sljit_s32 elem_size, sljit_u32 data)+{+#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)+ sljit_u8* end = buf + length;++ do {+ if (elem_size == 1)+ *buf = (sljit_u8)(((data & 0x1) << 7) + 0x7f);+ else if (elem_size == 2)+ *(sljit_u16*)buf = (sljit_u16)(((data & 0x1) << 15) + 0x7fff);+ else if (elem_size == 4)+ *(sljit_u32*)buf = (sljit_u32)(((data & 0x1) << 31) + 0x7fffffff);+ else {+ *(sljit_u32*)buf = 0xffffffff;+ *(sljit_u32*)(buf + 4) = (sljit_u32)(((data & 0x1) << 31) + 0x7fffffff);+ }++ data >>= 1;+ buf += elem_size;+ } while (buf < end);+#else /* !SLJIT_LITTLE_ENDIAN */+ sljit_u8* current = buf + length - elem_size;++ do {+ if (elem_size == 1)+ *current = (sljit_u8)(((data & 0x1) << 7) + 0x7f);+ else if (elem_size == 2)+ *(sljit_u16*)current = (sljit_u16)(((data & 0x1) << 15) + 0x7fff);+ else if (elem_size == 4)+ *(sljit_u32*)current = (sljit_u32)(((data & 0x1) << 31) + 0x7fffffff);+ else {+ *(sljit_u32*)(current + 4) = 0xffffffff;+ *(sljit_u32*)current = (sljit_u32)(((data & 0x1) << 31) + 0x7fffffff);+ }++ data >>= 1;+ current -= elem_size;+ } while (current >= buf);+#endif /* SLJIT_LITTLE_ENDIAN */+}++static void test_simd7(void)+{+ /* Test simd sign extraction operation. */+ executable_code code;+ struct sljit_compiler* compiler;+ sljit_s32 options = 0;+ sljit_s32 i, type;+ sljit_u8 supported[2];+ sljit_u8* buf;+ sljit_u8 data[63 + 320];+ sljit_s32 vs0 = SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS > 0 ? SLJIT_VS0 : SLJIT_VR5;+ sljit_uw resw[10];+ sljit_u32 res32[7];++ if (verbose)+ printf("Run test_simd7\n");++ SIMD_RUN_START++ /* Buffer is 64 byte aligned. */+ buf = (sljit_u8*)(((sljit_sw)data + (sljit_sw)63) & ~(sljit_sw)63);++ for (i = 0; i < 10; i++)+ resw[i] = (sljit_uw)-1;+ for (i = 0; i < 7; i++)+ res32[i] = (sljit_u32)-1;++ init_simd_sign(buf + 0, 16, 1, 0x8fa3);+ init_simd_sign(buf + 16, 16, 1, 0x34d5);+ init_simd_sign(buf + 32, 16, 2, 0xa6);+ init_simd_sign(buf + 48, 16, 2, 0x5e);+ init_simd_sign(buf + 64, 16, 4, 0xd);+ init_simd_sign(buf + 80, 16, 4, 0x5);+ init_simd_sign(buf + 96, 16, 8, 0x2);+ init_simd_sign(buf + 112, 16, 8, 0x1);+ init_simd_sign(buf + 128, 16, 1, 0x0);+ memset(buf + 128, 0, 8);+ memset(buf + 136, 255, 8);++ init_simd_sign(buf + 144, 8, 1, 0x45);+ init_simd_sign(buf + 152, 8, 2, 0x9);+ init_simd_sign(buf + 160, 8, 4, 0x1);++ init_simd_sign(buf + 192, 32, 1, 0x51e83b71);+ init_simd_sign(buf + 224, 32, 2, 0xc90d);+ init_simd_sign(buf + 256, 32, 4, 0xa5);+ init_simd_sign(buf + 288, 32, 8, 0x9);++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, options, SLJIT_ARGS3V(P, P, P), 4 | SLJIT_ENTER_VECTOR(6), 4 | SLJIT_ENTER_VECTOR(SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS > 0 ? 2 : 0), 16);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_8;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_R0, 0);+ /* resw[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R0, 0);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 16);+ /* resw[1] */+ sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_uw));++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_16;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_R2, 0);+ /* resw[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_uw), SLJIT_R2, 0);++ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 48);+ sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | type | SLJIT_32, SLJIT_VR4, SLJIT_MEM1(SLJIT_SP), 4);+ /* res32[0] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S2), 0, SLJIT_MEM1(SLJIT_SP), 4);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 64);+ sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | type | SLJIT_32, vs0, SLJIT_R1, 0);+ /* res32[1] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_u32), SLJIT_R1, 0);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_FLOAT;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 80);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 4);+ /* res32[2] */+ sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | type | SLJIT_32, SLJIT_VR1, SLJIT_MEM2(SLJIT_S2, SLJIT_R1), 1);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_64 | SLJIT_SIMD_FLOAT;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 96);+ sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_S3, 0);+ /* resw[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_uw), SLJIT_S3, 0);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 112);+ /* resw[4] */+ sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM0(), (sljit_sw)(resw + 4));++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_8;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 128);+ /* resw[5] */+ sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_uw));++ type = SLJIT_SIMD_REG_64 | SLJIT_SIMD_ELEM_8;+ supported[0] = sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 144) != SLJIT_ERR_UNSUPPORTED;+ sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_R0, 0);+ /* resw[6] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_uw), SLJIT_R0, 0);++ type = SLJIT_SIMD_REG_64 | SLJIT_SIMD_ELEM_16;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 152);+ /* res32[4] */+ sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | type | SLJIT_32, SLJIT_VR0, SLJIT_MEM1(SLJIT_S2), 4 * sizeof(sljit_u32));++ type = SLJIT_SIMD_REG_64 | SLJIT_SIMD_ELEM_32;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 160);+ /* resw[7] */+ sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S1), 7 * sizeof(sljit_uw));++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_8;+ supported[1] = sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 192) != SLJIT_ERR_UNSUPPORTED;+ sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | type | SLJIT_32, SLJIT_VR2, SLJIT_R2, 0);+ /* res32[5] */+ sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S2), 5 * sizeof(sljit_u32), SLJIT_R2, 0);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_16;+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_S1, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_uw));+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 224);+ /* resw[8] */+ sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM2(SLJIT_R2, SLJIT_R1), 3);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_32;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 256);+ /* resw[9] */+ sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S1), 9 * sizeof(sljit_uw));++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_64 | SLJIT_SIMD_FLOAT;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 288);+ /* res32[6] */+ sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | type | SLJIT_32, SLJIT_VR0, SLJIT_MEM0(), (sljit_sw)(res32 + 6));++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func3((sljit_sw)buf, (sljit_sw)resw, (sljit_sw)res32);+ sljit_free_code(code.code, NULL);++ FAILED(resw[0] != 0x8fa3, "test_simd7 case 1 failed\n");+ FAILED(resw[1] != 0x34d5, "test_simd7 case 2 failed\n");+ FAILED(resw[2] != 0xa6, "test_simd7 case 3 failed\n");+ FAILED(res32[0] != 0x5e, "test_simd7 case 4 failed\n");+ FAILED(res32[1] != 0xd, "test_simd7 case 5 failed\n");+ FAILED(res32[2] != 0x5, "test_simd7 case 6 failed\n");+ FAILED(res32[3] != (sljit_u32)-1, "test_simd7 case 7 failed\n");+ FAILED(resw[3] != 0x2, "test_simd7 case 8 failed\n");+ FAILED(resw[4] != 0x1, "test_simd7 case 9 failed\n");+ FAILED(resw[5] != LITTLE_BIG(0xff00, 0xff), "test_simd7 case 10 failed\n");++ if (supported[0]) {+ FAILED(resw[6] != 0x45, "test_simd7 case 11 failed\n");+ FAILED(res32[4] != 0x9, "test_simd7 case 12 failed\n");+ FAILED(resw[7] != 0x1, "test_simd7 case 13 failed\n");+ }++ if (supported[1]) {+ FAILED(res32[5] != 0x51e83b71, "test_simd7 case 14 failed\n");+ FAILED(resw[8] != 0xc90d, "test_simd7 case 15 failed\n");+ FAILED(resw[9] != 0xa5, "test_simd7 case 16 failed\n");+ FAILED(res32[6] != 0x9, "test_simd7 case 17 failed\n");+ }++ SIMD_RUN_END++ successful_tests++;+}++static void init_simd_u32(sljit_u8* buf, sljit_s32 length, sljit_u32 data)+{+ sljit_u32* current = (sljit_u32*)buf;+ sljit_u32* end = (sljit_u32*)(buf + length);++ while (current < end)+ *current++ = data;+}++static sljit_s32 check_simd_u32(sljit_u8* buf, sljit_s32 length, sljit_u32 data)+{+ sljit_u32* current = (sljit_u32*)buf;+ sljit_u32* end = (sljit_u32*)(buf + length);++ while (current < end) {+ if (*current++ != data)+ return 0;+ }++ return 1;+}++static void test_simd8(void)+{+ /* Test simd binary logical operation. */+ executable_code code;+ struct sljit_compiler* compiler;+ sljit_s32 options = 0;+ sljit_s32 i, type;+ sljit_u8 supported[2];+ sljit_u8* buf;+ sljit_u8 data[63 + 1024];+ sljit_s32 vs0 = SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS > 0 ? SLJIT_VS1 : SLJIT_VR5;++ if (verbose)+ printf("Run test_simd8\n");++ SIMD_RUN_START++ /* Buffer is 64 byte aligned. */+ buf = (sljit_u8*)(((sljit_sw)data + (sljit_sw)63) & ~(sljit_sw)63);++ for (i = 0; i < 1024; i++)+ buf[i] = 0xaa;++ init_simd_u32(buf, 32, 0x00ff00ff);+ init_simd_u32(buf + 32, 32, 0x0000ffff);++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, options, SLJIT_ARGS3V(P, P, P), 4 | SLJIT_ENTER_VECTOR(6), 4 | SLJIT_ENTER_VECTOR(SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS > 0 ? 2 : 0), 16);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_8;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | type, SLJIT_VR0, SLJIT_VR0, SLJIT_VR2, 0);+ /* buf[64] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 64);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_FLOAT;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_OR | type, SLJIT_VR2, SLJIT_VR0, SLJIT_VR2, 0);+ /* buf[80] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 80);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_16;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_XOR | type, SLJIT_VR4, vs0, SLJIT_VR2, 0);+ /* buf[96] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 96);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_64 | SLJIT_SIMD_FLOAT;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | type, SLJIT_VR1, SLJIT_VR2, SLJIT_VR0, 0);+ /* buf[112] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 112);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_128;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_OR | type, vs0, SLJIT_VR0, vs0, 0);+ /* buf[128] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 128);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_FLOAT;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_XOR | type, SLJIT_VR2, SLJIT_VR4, SLJIT_VR0, 0);+ /* buf[144] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 144);++ type = SLJIT_SIMD_REG_64 | SLJIT_SIMD_ELEM_32;+ supported[0] = sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0) != SLJIT_ERR_UNSUPPORTED;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | type, SLJIT_VR4, SLJIT_VR0, SLJIT_VR4, 0);+ /* buf[160] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 160);++ type = SLJIT_SIMD_REG_64 | SLJIT_SIMD_ELEM_64 | SLJIT_SIMD_FLOAT;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_OR | type, SLJIT_VR0, SLJIT_VR2, vs0, 0);+ /* buf[168] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 168);++ type = SLJIT_SIMD_REG_64 | SLJIT_SIMD_ELEM_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_XOR | type, vs0, SLJIT_VR0, SLJIT_VR2, 0);+ /* buf[176] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 176);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_8;+ supported[1] = sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | type | SLJIT_SIMD_TEST, SLJIT_VR0, SLJIT_VR0, SLJIT_VR2, 0) != SLJIT_ERR_UNSUPPORTED;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | type, SLJIT_VR0, SLJIT_VR0, SLJIT_VR2, 0);+ /* buf[192] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 192);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_256;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_OR | type, vs0, SLJIT_VR0, SLJIT_VR2, 0);+ /* buf[224] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 224);++ type = SLJIT_SIMD_REG_256 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_FLOAT;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_XOR | type, SLJIT_VR3, SLJIT_VR1, SLJIT_VR3, 0);+ /* buf[256] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 256);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)buf);+ sljit_free_code(code.code, NULL);++ FAILED(!check_simd_u32(buf + 64, 16, 0x000000ff), "test_simd8 case 1 failed\n");+ FAILED(!check_simd_u32(buf + 80, 16, 0x00ffffff), "test_simd8 case 2 failed\n");+ FAILED(!check_simd_u32(buf + 96, 16, 0x00ffff00), "test_simd8 case 3 failed\n");+ FAILED(!check_simd_u32(buf + 112, 16, 0x000000ff), "test_simd8 case 4 failed\n");+ FAILED(!check_simd_u32(buf + 128, 16, 0x00ffffff), "test_simd8 case 5 failed\n");+ FAILED(!check_simd_u32(buf + 144, 16, 0x00ffff00), "test_simd8 case 6 failed\n");++ if (supported[0]) {+ FAILED(!check_simd_u32(buf + 160, 8, 0x000000ff), "test_simd8 case 7 failed\n");+ FAILED(!check_simd_u32(buf + 168, 8, 0x00ffffff), "test_simd8 case 8 failed\n");+ FAILED(!check_simd_u32(buf + 176, 8, 0x00ffff00), "test_simd8 case 9 failed\n");+ }++ if (supported[1]) {+ FAILED(!check_simd_u32(buf + 192, 32, 0x000000ff), "test_simd8 case 10 failed\n");+ FAILED(!check_simd_u32(buf + 224, 32, 0x00ffffff), "test_simd8 case 11 failed\n");+ FAILED(!check_simd_u32(buf + 256, 32, 0x00ffff00), "test_simd8 case 12 failed\n");+ }++ SIMD_RUN_END++ successful_tests++;+}++static void test_simd9(void)+{+ /* Test accessing named temporary registers. */+ executable_code code;+ struct sljit_compiler* compiler;+ sljit_s32 options = 0;+ sljit_s32 i, type;+ sljit_u8* buf;+ sljit_u8 data[63 + 512];+ sljit_sw wbuf[16];++ if (verbose)+ printf("Run test_simd9\n");++ SIMD_RUN_START++ /* Buffer is 64 byte aligned. */+ buf = (sljit_u8*)(((sljit_sw)data + (sljit_sw)63) & ~(sljit_sw)63);++ for (i = 0; i < 512; i++)+ buf[i] = 0xaa;++ for (i = 0; i < 16; i++)+ wbuf[i] = -1;++ simd_set(buf, 53, 16);+ simd_set(buf + 16, 106, 16);+ simd_set(buf + 32, 216, 16);+ simd_set(buf + 48, 97, 16);++ *(sljit_s32*)(wbuf + 6) = 0x345678ab;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, options, SLJIT_ARGS2V(P, P), 4 | SLJIT_ENTER_VECTOR(6), 4, 16);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_MEM_ALIGNED_128;+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x1ca0ca0ca0ca0ca0, 0x1ca0ca0c));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, (sljit_sw)(buf) + WCONST(0x49b29b29b29b29b2, 0x49b29b29));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)(buf + 80) - WCONST(0x2835835835835835, 0x28358358));+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_TMP_DEST_VREG, SLJIT_MEM1(SLJIT_S2), -WCONST(0x49b29b29b29b29b2, 0x49b29b29));+ /* buf[80] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_TMP_DEST_VREG, SLJIT_MEM1(SLJIT_R2), WCONST(0x2835835835835835, 0x28358358));+ /* wbuf[0] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_TMP_DEST_REG, 0);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_16 | SLJIT_SIMD_MEM_ALIGNED_128;+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, (sljit_sw)(buf + 16) + WCONST(0x4d63d63d63d63d63, 0x4d63d63d));+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_TMP_DEST_VREG, SLJIT_MEM1(SLJIT_TMP_DEST_REG), -WCONST(0x4d63d63d63d63d63, 0x4d63d63d));+ /* wbuf[1] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, (sljit_sw)(buf + 112) - WCONST(0x739f39f39f39f39f, 0x739f39f3));+ /* buf[112] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_TMP_DEST_VREG, SLJIT_MEM1(SLJIT_TMP_DEST_REG), WCONST(0x739f39f39f39f39f, 0x739f39f3));+ /* wbuf[2] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_16;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, 2, SLJIT_TMP_DEST_REG, 0);+ /* wbuf[3] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x3b59b59b59b59b59, 0x3b59b59b));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0xcc1234);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, 4, SLJIT_R2, 0);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, 4, SLJIT_S2, 0);+ /* wbuf[4] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_sw), SLJIT_S2, 0);+ /* wbuf[5] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32;+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, (sljit_sw)(wbuf + 6) - WCONST(0x4261261261261261, 0x42612612));+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, 3, SLJIT_MEM1(SLJIT_TMP_DEST_REG), WCONST(0x4261261261261261, 0x42612612));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, (sljit_sw)(wbuf + 7) + WCONST(0x57d37d37d37d37d3, 0x57d37d37));+ /* wbuf[7] */+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, 3, SLJIT_MEM1(SLJIT_TMP_DEST_REG), -WCONST(0x57d37d37d37d37d3, 0x57d37d37));++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32;+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 0x5763a80);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(buf + 16) - WCONST(0x69a09a09a09a09a0, 0x69a09a09));+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_R1), WCONST(0x69a09a09a09a09a0, 0x69a09a09));+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, 1, SLJIT_TMP_DEST_REG, 0);+ /* wbuf[8] */+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR3, 1, SLJIT_MEM1(SLJIT_S1), 8 * sizeof(sljit_sw));++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_8;+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, WCONST(0x4e7ce7ce7ce7ce7c, 0x4e7ce7ce));+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)(wbuf + 6) + WCONST(0x20ab0ab0ab0ab0ab, 0x20ab0ab0));+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM0(), (sljit_sw)buf);+ sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, 1, SLJIT_MEM1(SLJIT_R2), -WCONST(0x20ab0ab0ab0ab0ab, 0x20ab0ab0));+ /* wbuf[9] */+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 9 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func2((sljit_sw)buf, (sljit_sw)wbuf);+ sljit_free_code(code.code, NULL);++ FAILED(!check_simd_mov(buf + 80, 53, 16), "test_simd9 case 1 failed\n");+ FAILED(wbuf[0] != WCONST(0x1ca0ca0ca0ca0ca0, 0x1ca0ca0c), "test_simd9 case 2 failed\n");+ FAILED(wbuf[1] != (sljit_sw)(buf + 16) + WCONST(0x4d63d63d63d63d63, 0x4d63d63d), "test_simd9 case 3 failed\n");+ FAILED(!check_simd_mov(buf + 112, 106, 16), "test_simd9 case 4 failed\n");+ FAILED(wbuf[2] != (sljit_sw)(buf + 112) - WCONST(0x739f39f39f39f39f, 0x739f39f3), "test_simd9 case 5 failed\n");+ FAILED(wbuf[3] != LITTLE_BIG(0xdb74, 0x74db), "test_simd9 case 5 failed\n");+ FAILED(wbuf[4] != 0x1234, "test_simd9 case 6 failed\n");+ FAILED(wbuf[5] != WCONST(0x3b59b59b59b59b59, 0x3b59b59b), "test_simd9 case 7 failed\n");+ FAILED(*(sljit_s32*)(wbuf + 7) != 0x345678ab, "test_simd9 case 8 failed\n");+ FAILED(*(sljit_s32*)(wbuf + 8) != 0x5763a80, "test_simd9 case 9 failed\n");+ FAILED(wbuf[9] != WCONST(0x4e7ce7ce7ce7ce7c, 0x4e7ce7ce), "test_simd9 case 10 failed\n");++ SIMD_RUN_END++ successful_tests++;+}++static void test_simd10(void)+{+ /* Test simd binary logical operation with memory operands. */+ executable_code code;+ struct sljit_compiler* compiler;+ sljit_s32 options = 0;+ sljit_s32 i, type;+ sljit_u8 supported[1];+ sljit_u8* buf;+ sljit_u8 data[63 + 288];+ sljit_s32 vs0 = SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS > 0 ? SLJIT_VS1 : SLJIT_VR5;++ if (verbose)+ printf("Run test_simd10\n");++ SIMD_RUN_START++ /* Buffer is 64 byte aligned. */+ buf = (sljit_u8*)(((sljit_sw)data + (sljit_sw)63) & ~(sljit_sw)63);++ for (i = 0; i < 288; i++)+ buf[i] = 0xaa;++ init_simd_u32(buf, 32, 0x00ff00ff);+ init_simd_u32(buf + 32, 32, 0x0000ffff);+ init_simd_u32(buf + 64, 32, LITTLE_BIG(0x04050607, 0x07060504));+ *(sljit_u32*)(buf + 96 + 4) = LITTLE_BIG(0x12345678, 0x78563412);+ init_simd_u32(buf + 128, 32, LITTLE_BIG(0x080b090a, 0x0a090b08));+ *(sljit_u32*)(buf + 160 + 8) = LITTLE_BIG(0x11223344, 0x44332211);++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, options, SLJIT_ARGS2V(P, P), 4 | SLJIT_ENTER_VECTOR(6), 4 | SLJIT_ENTER_VECTOR(SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS > 0 ? 2 : 0), 32);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_8 | SLJIT_SIMD_MEM_ALIGNED_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | type, SLJIT_VR0, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 32);+ /* buf[192] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 192);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_MEM_ALIGNED_128;+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 32 >> 2);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_XOR | type, SLJIT_VR4, SLJIT_VR2, SLJIT_MEM2(SLJIT_S0, SLJIT_R1), 2);+ /* buf[208] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 208);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_FLOAT | SLJIT_SIMD_ELEM_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_SP), 16);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR3, SLJIT_MEM1(SLJIT_S0), 32);+ sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_OR | type, vs0, SLJIT_VR3, SLJIT_MEM1(SLJIT_SP), 16);+ /* buf[224] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, vs0, SLJIT_MEM1(SLJIT_S0), 224);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_8;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 64);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 96);+ sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_SHUFFLE | type, SLJIT_VR1, SLJIT_VR2, SLJIT_VR1, 0);+ /* buf[240] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR1, SLJIT_MEM1(SLJIT_S0), 240);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_8 | SLJIT_SIMD_MEM_ALIGNED_128;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 160);+ sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S0, 0, SLJIT_IMM, WCONST(0xcba2ba2ba2ba2ba2, 0xcba2ba2b) + 128);+ sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_SHUFFLE | type, SLJIT_VR4, SLJIT_VR4, SLJIT_MEM1(SLJIT_R2), -WCONST(0xcba2ba2ba2ba2ba2, 0xcba2ba2b));+ /* buf[256] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR4, SLJIT_MEM1(SLJIT_S0), 256);++ type = SLJIT_SIMD_REG_64 | SLJIT_SIMD_ELEM_8;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 96);+ supported[0] = sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_SHUFFLE | type, SLJIT_VR2, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 64) != SLJIT_ERR_UNSUPPORTED;+ /* buf[272] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR2, SLJIT_MEM1(SLJIT_S0), 272);++ type = SLJIT_SIMD_REG_64 | SLJIT_SIMD_ELEM_8 | SLJIT_SIMD_MEM_ALIGNED_64;+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, vs0, SLJIT_MEM1(SLJIT_S0), 96);+ sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 64);+ sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_SHUFFLE | type, SLJIT_VR0, vs0, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 0);+ /* buf[280] */+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR0, SLJIT_MEM1(SLJIT_S0), 280);++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)buf);+ sljit_free_code(code.code, NULL);++ FAILED(!check_simd_u32(buf + 192, 16, 0x000000ff), "test_simd10 case 1 failed\n");+ FAILED(!check_simd_u32(buf + 208, 16, 0x00ffff00), "test_simd10 case 2 failed\n");+ FAILED(!check_simd_u32(buf + 224, 16, 0x00ffffff), "test_simd10 case 3 failed\n");+ FAILED(!check_simd_u32(buf + 240, 16, LITTLE_BIG(0x78563412, 0x12345678)), "test_simd10 case 4 failed\n");+ FAILED(!check_simd_u32(buf + 256, 16, LITTLE_BIG(0x44113322, 0x22331144)), "test_simd10 case 5 failed\n");++ if (supported[0]) {+ FAILED(!check_simd_u32(buf + 272, 8, LITTLE_BIG(0x78563412, 0x12345678)), "test_simd10 case 6 failed\n");+ FAILED(!check_simd_u32(buf + 280, 8, LITTLE_BIG(0x78563412, 0x12345678)), "test_simd10 case 7 failed\n");+ }++ SIMD_RUN_END++ successful_tests++;+}++static void test_simd11(void)+{+ /* Test simd binary logical operation with memory operands. */+ executable_code code;+ struct sljit_compiler* compiler;+ sljit_s32 options = 0;+ sljit_s32 i, type, run;+ sljit_u8* buf;+ sljit_u8 data[63 + 32 + (32 * SLJIT_NUMBER_OF_VECTOR_REGISTERS)];++ if (verbose)+ printf("Run test_simd11\n");++ SIMD_RUN_START++ for (run = 0; run < 2; run++) {+ /* Buffer is 64 byte aligned. */+ buf = (sljit_u8*)(((sljit_sw)data + (sljit_sw)63) & ~(sljit_sw)63);++ for (i = 24; i < 32 + (32 * SLJIT_NUMBER_OF_VECTOR_REGISTERS); i++)+ buf[i] = 0xaa;++ simd_set(buf, 87, 16);+ *(sljit_f64*)(buf + 16) = 1.0;++ compiler = sljit_create_compiler(NULL);+ FAILED(!compiler, "cannot create compiler\n");++ sljit_emit_enter(compiler, options, SLJIT_ARGS2V(P, P), 4 | SLJIT_ENTER_VECTOR(SLJIT_NUMBER_OF_VECTOR_REGISTERS), 4 | SLJIT_ENTER_FLOAT(SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS), 0);++ if (run == 1)+ sljit_set_context(compiler, options, SLJIT_ARGS2V(P, P), 4 | SLJIT_ENTER_VECTOR(SLJIT_NUMBER_OF_VECTOR_REGISTERS), 4 | SLJIT_ENTER_FLOAT(SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS), 0);++ type = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_8 | SLJIT_SIMD_MEM_ALIGNED_128;+ for (i = 0; i < SLJIT_NUMBER_OF_VECTOR_REGISTERS; i++) {+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_LOAD | type, SLJIT_VR(i), SLJIT_MEM1(SLJIT_S0), 0);+ sljit_emit_simd_mov(compiler, SLJIT_SIMD_STORE | type, SLJIT_VR(i), SLJIT_MEM1(SLJIT_S0), (i + 1) * 32);+ }++ if (SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS > 0) {+ for (i = 0; i < SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS; i++) {+ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FS(i), 0, SLJIT_MEM1(SLJIT_S0), 16);+ }++ for (i = 1; i < SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS; i++) {+ sljit_emit_fop2(compiler, SLJIT_ADD_F64, SLJIT_FS0, 0, SLJIT_FS0, 0, SLJIT_FS(i), 0);+ }++ sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 16, SLJIT_FS0, 0);+ }++ sljit_emit_return_void(compiler);++ code.code = sljit_generate_code(compiler, 0, NULL);+ CHECK(compiler);+ sljit_free_compiler(compiler);++ code.func1((sljit_sw)buf);+ sljit_free_code(code.code, NULL);++ for (i = 0; i < SLJIT_NUMBER_OF_VECTOR_REGISTERS; i++) {+ FAILED(!check_simd_mov(buf + ((i + 1) * 32), 87, 16), "test_simd11 case 1 failed\n");+ }++ if (SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS > 0) {+ FAILED(*(double*)(buf + 16) != SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS, "test_simd11 case 2 failed\n");+ }+ }++ SIMD_RUN_END++ successful_tests++;+}++#undef SIMD_RUN_START+#undef SIMD_RUN_END
+ src/c/pcre2/maint/cmake-tests/build-interface/main.c view
@@ -0,0 +1,11 @@+#define PCRE2_CODE_UNIT_WIDTH 8+#include <pcre2.h>+#include <stdio.h>++int main(void)+{+ char version_str[32];+ pcre2_config(PCRE2_CONFIG_VERSION, version_str);+ printf("Using PCRE2 version: %s\n", version_str);+ return 0;+}
+ src/c/pcre2/maint/cmake-tests/install-interface/main.c view
@@ -0,0 +1,11 @@+#define PCRE2_CODE_UNIT_WIDTH 8+#include <pcre2.h>+#include <stdio.h>++int main(void)+{+ char version_str[32];+ pcre2_config(PCRE2_CONFIG_VERSION, version_str);+ printf("Using PCRE2 version: %s\n", version_str);+ return 0;+}
src/c/pcre2/maint/ucptest.c view
@@ -82,21 +82,16 @@ The command "list" must be followed by one of property names script, bool, type, gbreak or bidi. The defined values for that property are listed. */ --#ifdef HAVE_CONFIG_H-#include "../src/config.h"-#endif--#ifndef SUPPORT_UNICODE-#error "Unicode support not enabled"-#endif- #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "../src/pcre2_internal.h" #include "../src/pcre2_ucp.h"++#ifndef SUPPORT_UNICODE+#error "Unicode support not enabled"+#endif #ifdef HAVE_UNISTD_H #include <unistd.h>
src/c/pcre2/maint/utf8.c view
@@ -2,43 +2,48 @@ * PCRE maintainers' helper program: UTF-8 converter * ****************************************************/ -/* This is a test program for converting character code points to UTF-8 and+/* This is a test program for converting character codepoints to UTF-8 and vice versa. Note that this program conforms to the original definition of UTF-8, which allows codepoints up to 7fffffff. The more recent definition-limits the validity of Unicode UTF-8 codepoints to a maximum of 10ffffff, and-forbids the "surrogate" code points. This program now gives warnings for these-invalid code points.+limits the validity of Unicode UTF-8 codepoints to a maximum of 10ffff, and+forbids the "surrogate" codepoints. This program now gives warnings for these+invalid codepoints. -The arguments are either single code point values written as U+hh.. or 0xhh..-for conversion to UTF-8, or sequences of hex values, written without 0x and-optionally including spaces (but such arguments must be quoted), for conversion-from UTF-8 to codepoints. For example:+The arguments are either single codepoint values written as U+hh.. or 0xhh..+for conversion to UTF-8, or sequences of hex values, written without a prefix+and optionally including spaces (but such arguments must be quoted), for+encoding from UTF-8 code units to Unicode codepoints. For example: -./utf8 0x1234-U+00001234 => e1 88 b4+ ./utf8 0x1234+ U+00001234 => e1 88 b4 -./utf8 "e1 88 b4"-U+00001234 <= e1 88 b4+ ./utf8 "e1 88 b4"+ U+00001234 <= e1 88 b4 In the second case, a number of UTF-8 characters can be present in one argument. In other words, each such argument is interpreted (after ignoring spaces) as a string of UTF-8 bytes representing a string of characters: -./utf8 "65 e188b4 77"-0x00000065 <= 65-0x00001234 <= e1 88 b4-0x00000077 <= 77+ ./utf8 "65 e188b4 77"+ 0x00000065 <= 65+ 0x00001234 <= e1 88 b4+ 0x00000077 <= 77 If the option -s is given, the sequence of UTF-bytes is written out between-angle brackets at the end of the line. On a UTF-8 terminal, this will show the-appropriate graphic for the code point.+angle brackets at the end of the line, if valid. On a UTF-8 terminal, this+should show the appropriate graphic for the character or a question mark. +if the option -b is given, a file with the encoded bytes is written for use+with pcre2test in utf8_input format.+ Errors provoke error messages, but the program carries on with the next-argument. The return code is always zero.+argument. The return code is always zero unless there was nothing to process+or an invalid option was provided and the "usage" was printed. Philip Hazel-Original creation data: unknown+Original creation date: unknown Code extended and tidied to avoid compiler warnings: 26 March 2020+Support for encoding utf8_input; 31 August 2025 */ @@ -46,6 +51,7 @@ #include <stdlib.h> #include <ctype.h> #include <string.h>+#include <errno.h> /* The valid ranges for UTF-8 characters are: @@ -61,10 +67,10 @@ static const unsigned int utf8_table1[] = { 0x0000007f, 0x000007ff, 0x0000ffff, 0x001fffff, 0x03ffffff, 0x7fffffff}; -static const int utf8_table2[] = {+static const unsigned char utf8_table2[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}; -static const int utf8_table3[] = {+static const unsigned char utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01}; @@ -80,7 +86,7 @@ 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+ 0 if input codepoint is too big */ static size_t@@ -96,7 +102,7 @@ *buffer-- = 0x80 | (cvalue & 0x3f); cvalue >>= 6; }-*buffer = utf8_table2[i] | cvalue;+*buffer = (unsigned char)(utf8_table2[i] | cvalue); return i + 1; } @@ -126,7 +132,7 @@ */ static int-utf82ord(unsigned char *buffer, unsigned char *buffend,+utf82ord(const unsigned char *buffer, const unsigned char *buffend, long unsigned int *vptr, int *lenptr) { unsigned int c = *buffer++;@@ -162,7 +168,7 @@ /* i now has a value in the range 1-5 */ -s = 6*i;+s = 6 * i; d = (c & utf8_table3[i]) << s; for (j = 0; j < i; j++)@@ -201,7 +207,26 @@ return i + 1; } +/**********************************************+* Usage *+**********************************************/ +static void+usage(const char *argv0)+{+printf("%s [option ..] argument ..\n\n", argv0);+puts("Encode/decode Unicode codepoints with UTF-8 code units\n");+puts("The arguments are either single codepoint values written as U+hh..");+puts("or 0xhh.. for conversion to UTF-8, or sequences of hex values,");+puts("written without a prefix and optionally including spaces (but such");+puts("arguments must be quoted), for encoding from UTF-8 code units to");+puts("Unicode codepoints.");+puts("For details on usage and examples read the comments in source code.\n");+puts("Options:\n");+puts(" -h|--help\tthis help");+puts(" -s\t\tprint character");+puts(" -b[=<file>]\twrite encoded data to file (default: testinput11)\n");+} /************************************************* * Main Program *@@ -213,52 +238,109 @@ int i = 1; int show = 0; unsigned char buffer[64];+const char *argv0 = "utf8";+FILE *f = NULL; -if (argc > 1 && strcmp(argv[1], "-s") == 0)+for (int c = argc; c-- > 1; i++) {- show = 1;- i = 2;+ const char *x = argv[i];++ if (*x++ != '-') break;+ if (*x == '-' && *++x == 0)+ {+ i++;+ break;+ }+ switch (*x++)+ {+ case 's': show = 1; break;+ case 'b':+ {+ const char *output = "testinput11";+ if (*x++ == '=' && *x != 0) output = x;+ f = fopen(output, "wb");+ }+ break;+ default:+ {+ const char last_option = x[-1];+ argv0 = argv[0];+ usage(argv0);+ return (last_option != 'h');+ }+ } } +if (i >= argc)+ {+ usage(argv0);+ return 1;+ }+ for (; i < argc; i++) {- char *x = argv[i];- char *endptr;- if (strncmp(x, "0x", 2) == 0 || strncmp(x, "U+", 2) == 0)+ const char *x = argv[i];++ if (strlen(x) >= 3 &&+ (strncmp(x, "0x", 2) == 0 || strncmp(x, "U+", 2) == 0) &&+ isxdigit(x[2])) {- size_t rc, j;- unsigned long int d = strtoul(x+2, &endptr, 16);- if (*endptr != 0)+ size_t rc;+ unsigned long d;+ char *endptr;+ int utf8_input = 0;++ errno = 0;+ d = strtoul(x + 2, &endptr, 16);+ if (errno != 0 || *endptr != 0) { printf("** Invalid hex number %s\n", x); continue; /* With next argument */ }+ if (d > 0xffffffff)+ {+ puts("** Code points must fit an uint32_t");+ continue;+ }+ else if (f != NULL && d > 0x7fffffff)+ {+ buffer[0] = 0xff;+ fwrite(buffer, 1, 1, f);+ utf8_input = 1;+ d &= 0x7fffffff;+ }+ rc = ord2utf8(d, buffer); printf("U+%08lx => ", d); if (rc == 0)- printf("** Code point greater than 0x7fffffff cannot be encoded");+ fputs("** -b needed for codepoints greater than 0x7fffffff", stdout); else {+ size_t j;+ for (j = 0; j < rc; j++) printf("%02x ", buffer[j]);- if (show)+ if (f != NULL) fwrite(buffer, rc, 1, f);+ if (utf8_input)+ fputs("** Not valid UTF-8, top bit set", stdout);+ else if (d > 0x10ffff)+ fputs("** Invalid Unicode (greater than U+10ffff)", stdout);+ else if (0xd800 <= d && d <= 0xdfff)+ fputs("** Invalid Unicode (UTF-16 surrogate)", stdout);+ else if (show) {- printf(">");+ putchar('>'); for (j = 0; j < rc; j++) printf("%c", buffer[j]);- printf("< ");+ putchar('<'); }- if (d >= 0xd800 && d <= 0xdfff)- printf("** Invalid Unicode (surrogate)");- else if (d > 0x10ffff)- printf("** Invalid Unicode (greater than U+10ffff)"); }- printf("\n");+ putchar('\n'); } else { unsigned char *bptr;- unsigned char *buffend;+ const unsigned char *buffend;+ unsigned char y = 0; int len = 0;- int y = 0; int z = 0; for (;;)@@ -271,7 +353,8 @@ len = -1; break; }- y = y * 16 + tolower(*x) - ((isdigit(*x))? '0' : 'W');+ y = y * 16 ++ (unsigned char)(tolower(*x) - ((isdigit(*x))? '0' : 'a' - 10)); x++; if (z) {@@ -297,36 +380,37 @@ { printf("U+%08lx <= ", d); for (j = 0; j < rc; j++) printf("%02x ", bptr[j]);- if (show)+ if (d <= 0x10ffff && (d < 0xd800 || 0xdfff < d) && show) {- printf(">");+ putchar('>'); for (j = 0; j < rc; j++) printf("%c", bptr[j]);- printf("<");+ putchar('<'); }- printf("\n");+ putchar('\n'); bptr += rc; } else if (rc == -4) { printf("U+%08lx <= ", d); for (j = 0; j < offset; j++) printf("%02x ", bptr[j]);- printf("** Overlong UTF-8 sequence\n");+ puts("** Overlong UTF-8 sequence"); bptr += offset; } else { switch (rc) {- case 0: printf("** First byte missing 0x40 bit");+ case 0: fputs("** First byte missing 0x40 bit", stdout); break; - case -1: printf("** First byte has too many high-order bits");+ case -1: fputs("** First byte has too many high-order bits", stdout); break; - case -2: printf("** Incomplete UTF-8 sequence at end of string");+ case -2: fputs("** Incomplete UTF-8 sequence at end of string",+ stdout); break; - case -3: printf("** Incomplete UTF-8 sequence");+ case -3: fputs("** Incomplete UTF-8 sequence", stdout); break; default: printf("** Unexpected return %d from utf82ord()", rc);@@ -334,12 +418,14 @@ } printf(" at offset %d in string ", offset); while (bptr < buffend) printf("%02x ", *bptr++);- printf("\n");+ putchar('\n'); break; } } } }++if (f != NULL) fclose(f); return 0; }
src/c/pcre2/src/pcre2_auto_possess.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-2024 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -38,17 +38,19 @@ ----------------------------------------------------------------------------- */ + /* This module contains functions that scan a compiled pattern and change repeats into possessive repeats where possible. */ -#ifdef HAVE_CONFIG_H-#include "config.h"-#endif+#include "pcre2_internal.h" -#include "pcre2_internal.h" +/* This macro represents the max size of list[] and that is used to keep+track of UCD info in several places, it should be kept on sync with the+value used by GenerateUcd.py */+#define MAX_LIST 8 /************************************************* * Tables for auto-possessification *@@ -64,7 +66,7 @@ because of what their opcode values are, but the table values should always be zero because property types are handled separately in the code. The last four columns apply to items that cannot be repeated, so there is no need to have-rows for them. Note that OP_DIGIT etc. are generated only when PCRE_UCP is+rows for them. Note that OP_DIGIT etc. are generated only when PCRE2_UCP is *not* set. When it is set, \d etc. are converted into OP_(NOT_)PROP codes. */ #define APTROWS (LAST_AUTOTAB_LEFT_OP - FIRST_AUTOTAB_OP + 1)@@ -123,21 +125,21 @@ */ static const uint8_t propposstab[PT_TABSIZE][PT_TABSIZE] = {-/* ANY LAMP GC PC SC SCX ALNUM SPACE PXSPACE WORD CLIST UCNC BIDICL BOOL */- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_ANY */- { 0, 3, 0, 0, 0, 0, 3, 1, 1, 0, 0, 0, 0, 0 }, /* PT_LAMP */- { 0, 0, 2, 4, 0, 0, 9, 10, 10, 11, 0, 0, 0, 0 }, /* PT_GC */- { 0, 0, 5, 2, 0, 0, 15, 16, 16, 17, 0, 0, 0, 0 }, /* PT_PC */- { 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_SC */- { 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_SCX */- { 0, 3, 6, 12, 0, 0, 3, 1, 1, 0, 0, 0, 0, 0 }, /* PT_ALNUM */- { 0, 1, 7, 13, 0, 0, 1, 3, 3, 1, 0, 0, 0, 0 }, /* PT_SPACE */- { 0, 1, 7, 13, 0, 0, 1, 3, 3, 1, 0, 0, 0, 0 }, /* PT_PXSPACE */- { 0, 0, 8, 14, 0, 0, 0, 1, 1, 3, 0, 0, 0, 0 }, /* PT_WORD */- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_CLIST */- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 }, /* PT_UCNC */- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_BIDICL */- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } /* PT_BOOL */+/* LAMP GC PC SC SCX ALNUM SPACE PXSPACE WORD CLIST UCNC BIDICL BOOL */+ { 3, 0, 0, 0, 0, 3, 1, 1, 0, 0, 0, 0, 0 }, /* PT_LAMP */+ { 0, 2, 4, 0, 0, 9, 10, 10, 11, 0, 0, 0, 0 }, /* PT_GC */+ { 0, 5, 2, 0, 0, 15, 16, 16, 17, 0, 0, 0, 0 }, /* PT_PC */+ { 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_SC */+ { 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_SCX */+ { 3, 6, 12, 0, 0, 3, 1, 1, 0, 0, 0, 0, 0 }, /* PT_ALNUM */+ { 1, 7, 13, 0, 0, 1, 3, 3, 1, 0, 0, 0, 0 }, /* PT_SPACE */+ { 1, 7, 13, 0, 0, 1, 3, 3, 1, 0, 0, 0, 0 }, /* PT_PXSPACE */+ { 0, 8, 14, 0, 0, 0, 1, 1, 3, 0, 0, 0, 0 }, /* PT_WORD */+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_CLIST */+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 }, /* PT_UCNC */+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_BIDICL */+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } /* PT_BOOL */+ /* PT_ANY does not need a record. */ }; /* This table is used to check whether auto-possessification is possible@@ -199,7 +201,7 @@ check_char_prop(uint32_t c, unsigned int ptype, unsigned int pdata, BOOL negated) {-BOOL ok;+BOOL ok, rc; const uint32_t *p; const ucd_record *prop = GET_UCD(c); @@ -240,12 +242,13 @@ { HSPACE_CASES: VSPACE_CASES:- return negated;+ rc = negated;+ break; default:- return (PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == negated;+ rc = (PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == negated; }- break; /* Control never reaches here */+ return rc; case PT_WORD: return (PRIV(ucp_gentype)[prop->chartype] == ucp_L ||@@ -259,7 +262,10 @@ if (c < *p) return !negated; if (c == *p++) return negated; }- break; /* Control never reaches here */+ /* LCOV_EXCL_START */+ PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */+ break;+ /* LCOV_EXCL_STOP */ /* Haven't yet thought these through. */ @@ -328,6 +334,7 @@ PCRE2_UCHAR c = *code; PCRE2_UCHAR base; PCRE2_SPTR end;+PCRE2_SPTR class_end; uint32_t chr; #ifdef SUPPORT_UNICODE@@ -450,10 +457,12 @@ code += 2; do {- if (clist_dest >= list + 8)+ if (clist_dest >= list + MAX_LIST) {- /* Early return if there is not enough space. This should never- happen, since all clists are shorter than 5 character now. */+ /* Early return if there is not enough space. GenerateUcd.py+ generated a list with more than 5 characters and something+ must be done about that going forward. */+ PCRE2_DEBUG_UNREACHABLE(); /* Remove if it ever triggers */ list[2] = code[0]; list[3] = code[1]; return code;@@ -473,11 +482,13 @@ case OP_CLASS: #ifdef SUPPORT_WIDE_CHARS case OP_XCLASS:- if (c == OP_XCLASS)+ case OP_ECLASS:+ if (c == OP_XCLASS || c == OP_ECLASS) end = code + GET(code, 0) - 1; else #endif end = code + 32 / sizeof(PCRE2_UCHAR);+ class_end = end; switch(*end) {@@ -505,6 +516,7 @@ break; } list[2] = (uint32_t)(end - code);+ list[3] = (uint32_t)(end - class_end); return end; } @@ -537,7 +549,7 @@ const uint32_t *base_list, PCRE2_SPTR base_end, int *rec_limit) { PCRE2_UCHAR c;-uint32_t list[8];+uint32_t list[MAX_LIST]; const uint32_t *chr_ptr; const uint32_t *ochr_ptr; const uint32_t *list_ptr;@@ -581,7 +593,7 @@ continue; } - /* At the end of a branch, skip to the end of the group. */+ /* At the end of a branch, skip to the end of the group and process it. */ if (c == OP_ALT) {@@ -638,19 +650,29 @@ return FALSE; break; - /* Atomic sub-patterns and assertions can always auto-possessify their- 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. */+ /* Atomic sub-patterns and forward 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. */ case OP_ASSERT: case OP_ASSERT_NOT: case OP_ONCE: return !entered_a_group; + /* Fixed-length lookbehinds can be treated the same way, but variable+ length lookbehinds must not auto-possessify their last iterator. Note+ that in order to identify a variable length lookbehind we must check+ through all branches, because some may be of fixed length. */+ case OP_ASSERTBACK: case OP_ASSERTBACK_NOT:- return (bracode[1+LINK_SIZE] == OP_VREVERSE)? FALSE : !entered_a_group;+ do+ {+ if (bracode[1+LINK_SIZE] == OP_VREVERSE) return FALSE; /* Variable */+ bracode += GET(bracode, 1);+ }+ while (*bracode == OP_ALT);+ return !entered_a_group; /* Not variable length */ /* Non-atomic assertions - don't possessify last iterator. This needs more thought. */@@ -748,12 +770,12 @@ if (base_list[0] == OP_CLASS) #endif {- set1 = (uint8_t *)(base_end - base_list[2]);+ set1 = (const uint8_t *)(base_end - base_list[2]); list_ptr = list; } else {- set1 = (uint8_t *)(code - list[2]);+ set1 = (const uint8_t *)(code - list[2]); list_ptr = base_list; } @@ -762,13 +784,14 @@ { case OP_CLASS: case OP_NCLASS:- set2 = (uint8_t *)+ set2 = (const uint8_t *) ((list_ptr == list ? code : base_end) - list_ptr[2]); break; #ifdef SUPPORT_WIDE_CHARS case OP_XCLASS:- xclass_flags = (list_ptr == list ? code : base_end) - list_ptr[2] + LINK_SIZE;+ xclass_flags = (list_ptr == list ? code : base_end) -+ list_ptr[2] + LINK_SIZE; if ((*xclass_flags & XCL_HASPROP) != 0) return FALSE; if ((*xclass_flags & XCL_MAP) == 0) {@@ -777,29 +800,29 @@ /* Might be an empty repeat. */ continue; }- set2 = (uint8_t *)(xclass_flags + 1);+ set2 = (const uint8_t *)(xclass_flags + 1); break; #endif case OP_NOT_DIGIT: invert_bits = TRUE;- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case OP_DIGIT:- set2 = (uint8_t *)(cb->cbits + cbit_digit);+ set2 = (const uint8_t *)(cb->cbits + cbit_digit); break; case OP_NOT_WHITESPACE: invert_bits = TRUE;- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case OP_WHITESPACE:- set2 = (uint8_t *)(cb->cbits + cbit_space);+ set2 = (const uint8_t *)(cb->cbits + cbit_space); break; case OP_NOT_WORDCHAR: invert_bits = TRUE;- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case OP_WORDCHAR:- set2 = (uint8_t *)(cb->cbits + cbit_word);+ set2 = (const uint8_t *)(cb->cbits + cbit_word); break; default:@@ -1080,11 +1103,11 @@ case OP_NCLASS: if (chr > 255) return FALSE;- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case OP_CLASS: if (chr > 255) break;- class_bitset = (uint8_t *)+ class_bitset = (const uint8_t *) ((list_ptr == list ? code : base_end) - list_ptr[2]); if ((class_bitset[chr >> 3] & (1u << (chr & 7))) != 0) return FALSE; break;@@ -1092,10 +1115,19 @@ #ifdef SUPPORT_WIDE_CHARS case OP_XCLASS: if (PRIV(xclass)(chr, (list_ptr == list ? code : base_end) -- list_ptr[2] + LINK_SIZE, utf)) return FALSE;+ list_ptr[2] + LINK_SIZE, (const uint8_t*)cb->start_code, utf))+ return FALSE; break;-#endif + case OP_ECLASS:+ if (PRIV(eclass)(chr,+ (list_ptr == list ? code : base_end) - list_ptr[2] + LINK_SIZE,+ (list_ptr == list ? code : base_end) - list_ptr[3],+ (const uint8_t*)cb->start_code, utf))+ return FALSE;+ break;+#endif /* SUPPORT_WIDE_CHARS */+ default: return FALSE; }@@ -1109,8 +1141,10 @@ if (list[1] == 0) return TRUE; } -/* Control never reaches here. There used to be a fail-save return FALSE; here,-but some compilers complain about an unreachable statement. */+/* LCOV_EXCL_START */+PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */+return FALSE; /* Avoid compiler warnings */+/* LCOV_EXCL_STOP */ } @@ -1140,7 +1174,7 @@ PCRE2_UCHAR c; PCRE2_SPTR end; PCRE2_UCHAR *repeat_opcode;-uint32_t list[8];+uint32_t list[MAX_LIST]; int rec_limit = 1000; /* Was 10,000 but clang+ASAN uses a lot of stack. */ BOOL utf = (cb->external_options & PCRE2_UTF) != 0; BOOL ucp = (cb->external_options & PCRE2_UCP) != 0;@@ -1149,7 +1183,13 @@ { c = *code; - if (c >= OP_TABLE_LENGTH) return -1; /* Something gone wrong */+ /* LCOV_EXCL_START */+ if (c >= OP_TABLE_LENGTH)+ {+ PCRE2_DEBUG_UNREACHABLE();+ return -1; /* Something gone wrong */+ }+ /* LCOV_EXCL_STOP */ if (c >= OP_STAR && c <= OP_TYPEPOSUPTO) {@@ -1198,10 +1238,14 @@ } c = *code; }- else if (c == OP_CLASS || c == OP_NCLASS || c == OP_XCLASS)+ else if (c == OP_CLASS || c == OP_NCLASS+#ifdef SUPPORT_WIDE_CHARS+ || c == OP_XCLASS || c == OP_ECLASS+#endif+ ) { #ifdef SUPPORT_WIDE_CHARS- if (c == OP_XCLASS)+ if (c == OP_XCLASS || c == OP_ECLASS) repeat_opcode = code + GET(code, 1); else #endif@@ -1211,7 +1255,7 @@ if (c >= OP_CRSTAR && c <= OP_CRMINRANGE) { /* The return from get_chr_property_list() will never be NULL when- *code (aka c) is one of the three class opcodes. However, gcc with+ *code (aka c) is one of the four class opcodes. However, gcc with -fanalyzer notes that a NULL return is possible, and grumbles. Hence we put in a check. */ @@ -1279,6 +1323,7 @@ #ifdef SUPPORT_WIDE_CHARS case OP_XCLASS:+ case OP_ECLASS: code += GET(code, 1); break; #endif
src/c/pcre2/src/pcre2_chkdint.c view
@@ -37,16 +37,16 @@ ----------------------------------------------------------------------------- */ + /* This file contains functions to implement checked integer operation */ -#ifndef PCRE2_PCRE2TEST-#ifdef HAVE_CONFIG_H-#include "config.h"-#endif +#ifndef PCRE2_PCRE2TEST #include "pcre2_internal.h" #endif ++ /************************************************* * Checked Integer Multiplication * *************************************************/@@ -74,9 +74,7 @@ #else INT64_OR_DOUBLE m; -#ifdef PCRE2_DEBUG-if (a < 0 || b < 0) abort();-#endif+PCRE2_ASSERT(a >= 0 && b >= 0); m = (INT64_OR_DOUBLE)a * (INT64_OR_DOUBLE)b; @@ -93,4 +91,4 @@ return FALSE; } -/* End of pcre_chkdint.c */+/* End of pcre2_chkdint.c */
src/c/pcre2/src/pcre2_compile.c view
@@ -39,10956 +39,11298 @@ */ -#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;+#include "pcre2_compile.h"++++#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 */++/* 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+#define CHAR_OUTPUT(c) (c)+#define CHAR_OUTPUT_HEX(c) (c)+#define CHAR_INPUT(c) (c)+#define CHAR_INPUT_HEX(c) (c)+#include "pcre2_printint_inc.h"+#undef PRINTABLE+#undef CHAR_OUTPUT+#undef CHAR_OUTPUT_HEX+#undef CHAR_INPUT+#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++/* Function definitions to allow mutual recursion */++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)++/* 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 */+ SIZEOFFSET, /* META_OFFSET */+ 0, /* META_SCS */+ 1, /* META_CAPTURE_NAME */+ 1, /* META_CAPTURE_NUMBER */+ 0, /* META_DOLLAR */+ 0, /* META_DOT */+ 0, /* META_ESCAPE - one more for ESC_P and ESC_p */+ 0, /* META_KET */+ 0, /* META_NOCAPTURE */+ 2, /* 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 */+ 0, /* META_ECLASS_AND */+ 0, /* META_ECLASS_OR */+ 0, /* META_ECLASS_SUB */+ 0, /* META_ECLASS_XOR */+ 0 /* META_ECLASS_NOT */+};++/* Types for skipping parts of a parsed pattern. */++enum { PSKIP_ALT, PSKIP_CLASS, PSKIP_KET };++/* 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, /* 1 */ 0,+ /* 2 */ 0, /* 3 */ 0,+ /* 4 */ 0, /* 5 */ 0,+ /* 6 */ 0, /* 7 */ 0,+ /* 8 */ 0, /* 9 */ 0,+ /* : */ ESCAPES_FIRST+0x0a, /* ; */ ESCAPES_FIRST+0x0b,+ /* < */ ESCAPES_FIRST+0x0c, /* = */ ESCAPES_FIRST+0x0d,+ /* > */ ESCAPES_FIRST+0x0e, /* ? */ ESCAPES_FIRST+0x0f,+ /* @ */ ESCAPES_FIRST+0x10, /* A */ -ESC_A,+ /* B */ -ESC_B, /* C */ -ESC_C,+ /* D */ -ESC_D, /* E */ -ESC_E,+ /* F */ 0, /* G */ -ESC_G,+ /* H */ -ESC_H, /* I */ 0,+ /* J */ 0, /* K */ -ESC_K,+ /* L */ 0, /* M */ 0,+ /* N */ -ESC_N, /* O */ 0,+ /* P */ -ESC_P, /* Q */ -ESC_Q,+ /* R */ -ESC_R, /* S */ -ESC_S,+ /* T */ 0, /* U */ 0,+ /* V */ -ESC_V, /* W */ -ESC_W,+ /* X */ -ESC_X, /* Y */ 0,+ /* Z */ -ESC_Z, /* [ */ ESCAPES_FIRST+0x2b,+ /* \ */ ESCAPES_FIRST+0x2c, /* ] */ ESCAPES_FIRST+0x2d,+ /* ^ */ ESCAPES_FIRST+0x2e, /* _ */ ESCAPES_FIRST+0x2f,+ /* ` */ ESCAPES_FIRST+0x30, /* a */ CHAR_BEL,+ /* b */ -ESC_b, /* c */ 0,+ /* d */ -ESC_d, /* e */ CHAR_ESC,+ /* f */ CHAR_FF, /* g */ 0,+ /* h */ -ESC_h, /* i */ 0,+ /* j */ 0, /* k */ -ESC_k,+ /* l */ 0, /* m */ 0,+ /* n */ CHAR_LF, /* o */ 0,+ /* p */ -ESC_p, /* q */ 0,+ /* r */ CHAR_CR, /* s */ -ESC_s,+ /* t */ CHAR_HT, /* u */ 0,+ /* v */ -ESC_v, /* w */ -ESC_w,+ /* x */ 0, /* y */ 0,+ /* z */ -ESC_z+};++#else++/* This is the "abnormal" table for EBCDIC systems without UTF-8 support.+It runs from 'a' to '9'. Our EBCDIC support can be provided via the compiler,+which can interpret character literals like 'a' or '[' in an EBCDIC codepage;+in this case, there is wide variance between codepages on the interpretation of+characters between the letters ('[' and '{' and so on are placed in all sorts of+different positions in the table). Thankfully however, all EBCDIC codepages+place the letters and digits in the same location, so we hardcode that here.+Our EBCDIC support can also be provided via numeric literals instead of+character literals, so either way, 'CHAR_a' will be 0x81 when PCRE2 is compiled+in EBCDIC mode. */++#define ESCAPES_FIRST CHAR_a+#define ESCAPES_LAST CHAR_9+#define UPPER_CASE(c) (c+64)++static const short int escapes[] = {+ /* 0x81 a */ CHAR_BEL, /* 0x82 b */ -ESC_b,+ /* 0x83 c */ 0, /* 0x84 d */ -ESC_d,+ /* 0x85 e */ CHAR_ESC, /* 0x86 f */ CHAR_FF,+ /* 0x87 g */ 0, /* 0x88 h */ -ESC_h,+ /* 0x89 i */ 0, /* 0x8a */ ESCAPES_FIRST+0x09,+ /* 0x8b */ ESCAPES_FIRST+0x0a, /* 0x8c */ ESCAPES_FIRST+0x0b,+ /* 0x8d */ ESCAPES_FIRST+0x0c, /* 0x8e */ ESCAPES_FIRST+0x0d,+ /* 0x8f */ ESCAPES_FIRST+0x0e, /* 0x90 */ ESCAPES_FIRST+0x0f,+ /* 0x91 j */ 0, /* 0x92 k */ -ESC_k,+ /* 0x93 l */ 0, /* 0x94 m */ 0,+ /* 0x95 n */ CHAR_LF, /* 0x96 o */ 0,+ /* 0x97 p */ -ESC_p, /* 0x98 q */ 0,+ /* 0x99 r */ CHAR_CR, /* 0x9a */ ESCAPES_FIRST+0x19,+ /* 0x9b */ ESCAPES_FIRST+0x1a, /* 0x9c */ ESCAPES_FIRST+0x1b,+ /* 0x9d */ ESCAPES_FIRST+0x1c, /* 0x9e */ ESCAPES_FIRST+0x1d,+ /* 0x9f */ ESCAPES_FIRST+0x1e, /* 0xa0 */ ESCAPES_FIRST+0x1f,+ /* 0xa1 */ ESCAPES_FIRST+0x20, /* 0xa2 s */ -ESC_s,+ /* 0xa3 t */ CHAR_HT, /* 0xa4 u */ 0,+ /* 0xa5 v */ -ESC_v, /* 0xa6 w */ -ESC_w,+ /* 0xa7 x */ 0, /* 0xa8 y */ 0,+ /* 0xa9 z */ -ESC_z, /* 0xaa */ ESCAPES_FIRST+0x29,+ /* 0xab */ ESCAPES_FIRST+0x2a, /* 0xac */ ESCAPES_FIRST+0x2b,+ /* 0xad */ ESCAPES_FIRST+0x2c, /* 0xae */ ESCAPES_FIRST+0x2d,+ /* 0xaf */ ESCAPES_FIRST+0x2e, /* 0xb0 */ ESCAPES_FIRST+0x2f,+ /* 0xb1 */ ESCAPES_FIRST+0x30, /* 0xb2 */ ESCAPES_FIRST+0x31,+ /* 0xb3 */ ESCAPES_FIRST+0x32, /* 0xb4 */ ESCAPES_FIRST+0x33,+ /* 0xb5 */ ESCAPES_FIRST+0x34, /* 0xb6 */ ESCAPES_FIRST+0x35,+ /* 0xb7 */ ESCAPES_FIRST+0x36, /* 0xb8 */ ESCAPES_FIRST+0x37,+ /* 0xb9 */ ESCAPES_FIRST+0x38, /* 0xba */ ESCAPES_FIRST+0x39,+ /* 0xbb */ ESCAPES_FIRST+0x3a, /* 0xbc */ ESCAPES_FIRST+0x3b,+ /* 0xbd */ ESCAPES_FIRST+0x3c, /* 0xbe */ ESCAPES_FIRST+0x3d,+ /* 0xbf */ ESCAPES_FIRST+0x3e, /* 0xc0 */ ESCAPES_FIRST+0x3f,+ /* 0xc1 A */ -ESC_A, /* 0xc2 B */ -ESC_B,+ /* 0xc3 C */ -ESC_C, /* 0xc4 D */ -ESC_D,+ /* 0xc5 E */ -ESC_E, /* 0xc6 F */ 0,+ /* 0xc7 G */ -ESC_G, /* 0xc8 H */ -ESC_H,+ /* 0xc9 I */ 0, /* 0xca */ ESCAPES_FIRST+0x49,+ /* 0xcb */ ESCAPES_FIRST+0x4a, /* 0xcc */ ESCAPES_FIRST+0x4b,+ /* 0xcd */ ESCAPES_FIRST+0x4c, /* 0xce */ ESCAPES_FIRST+0x4d,+ /* 0xcf */ ESCAPES_FIRST+0x4e, /* 0xd0 */ ESCAPES_FIRST+0x4f,+ /* 0xd1 J */ 0, /* 0xd2 K */ -ESC_K,+ /* 0xd3 L */ 0, /* 0xd4 M */ 0,+ /* 0xd5 N */ -ESC_N, /* 0xd6 O */ 0,+ /* 0xd7 P */ -ESC_P, /* 0xd8 Q */ -ESC_Q,+ /* 0xd9 R */ -ESC_R, /* 0xda */ ESCAPES_FIRST+0x59,+ /* 0xdb */ ESCAPES_FIRST+0x5a, /* 0xdc */ ESCAPES_FIRST+0x5b,+ /* 0xdd */ ESCAPES_FIRST+0x5c, /* 0xde */ ESCAPES_FIRST+0x5d,+ /* 0xdf */ ESCAPES_FIRST+0x5e, /* 0xe0 */ ESCAPES_FIRST+0x5f,+ /* 0xe1 */ ESCAPES_FIRST+0x60, /* 0xe2 S */ -ESC_S,+ /* 0xe3 T */ 0, /* 0xe4 U */ 0,+ /* 0xe5 V */ -ESC_V, /* 0xe6 W */ -ESC_W,+ /* 0xe7 X */ -ESC_X, /* 0xe8 Y */ 0,+ /* 0xe9 Z */ -ESC_Z, /* 0xea */ ESCAPES_FIRST+0x69,+ /* 0xeb */ ESCAPES_FIRST+0x6a, /* 0xec */ ESCAPES_FIRST+0x6b,+ /* 0xed */ ESCAPES_FIRST+0x6c, /* 0xee */ ESCAPES_FIRST+0x6d,+ /* 0xef */ ESCAPES_FIRST+0x6e, /* 0xf0 0 */ 0,+ /* 0xf1 1 */ 0, /* 0xf2 2 */ 0,+ /* 0xf3 3 */ 0, /* 0xf4 4 */ 0,+ /* 0xf5 5 */ 0, /* 0xf6 6 */ 0,+ /* 0xf7 7 */ 0, /* 0xf8 8 */ 0,+ /* 0xf9 9 */ 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[] = {+ CHAR_COMMERCIAL_AT, CHAR_A, CHAR_B, CHAR_C, CHAR_D, CHAR_E, CHAR_F, CHAR_G,+ CHAR_H, CHAR_I, CHAR_J, CHAR_K, CHAR_L, CHAR_M, CHAR_N, CHAR_O, CHAR_P,+ CHAR_Q, CHAR_R, CHAR_S, CHAR_T, CHAR_U, CHAR_V, CHAR_W, CHAR_X, CHAR_Y,+ CHAR_Z, CHAR_LEFT_SQUARE_BRACKET, CHAR_BACKSLASH, CHAR_RIGHT_SQUARE_BRACKET,+ CHAR_CIRCUMFLEX_ACCENT, CHAR_UNDERSCORE+};++#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_scs0+ STRING_scan_substring0+ 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 },+ { 3, META_SCS },+ { 14, META_SCS },+ { 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 stored in pcre2_compile.h - these must+be kept in sync with posix_names, posix_name_lengths, posix_class_maps,+and posix_substitutes. */++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 };++/* 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. */++const int PRIV(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 */+};+#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|PCRE2_ALT_EXTENDED_CLASS)++#define PUBLIC_LITERAL_COMPILE_EXTRA_OPTIONS \+ (PCRE2_EXTRA_MATCH_LINE|PCRE2_EXTRA_MATCH_WORD| \+ PCRE2_EXTRA_CASELESS_RESTRICT|PCRE2_EXTRA_TURKISH_CASING)++#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|PCRE2_EXTRA_PYTHON_OCTAL|PCRE2_EXTRA_NO_BS0| \+ PCRE2_EXTRA_NEVER_CALLOUT)++/* 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_XOPT, /* Value is an xoption 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 */+ PSO_OPTMZ /* Value is an optimization bit */+ };++typedef struct pso {+ const char *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[] = {+ { STRING_UTFn_RIGHTPAR, PSO_OPT, PCRE2_UTF },+ { STRING_UTF_RIGHTPAR, 4, PSO_OPT, PCRE2_UTF },+ { STRING_UCP_RIGHTPAR, 4, PSO_OPT, PCRE2_UCP },+ { STRING_NOTEMPTY_RIGHTPAR, 9, PSO_FLG, PCRE2_NOTEMPTY_SET },+ { STRING_NOTEMPTY_ATSTART_RIGHTPAR, 17, PSO_FLG, PCRE2_NE_ATST_SET },+ { STRING_NO_AUTO_POSSESS_RIGHTPAR, 16, PSO_OPTMZ, PCRE2_OPTIM_AUTO_POSSESS },+ { STRING_NO_DOTSTAR_ANCHOR_RIGHTPAR, 18, PSO_OPTMZ, PCRE2_OPTIM_DOTSTAR_ANCHOR },+ { STRING_NO_JIT_RIGHTPAR, 7, PSO_FLG, PCRE2_NOJIT },+ { STRING_NO_START_OPT_RIGHTPAR, 13, PSO_OPTMZ, PCRE2_OPTIM_START_OPTIMIZE },+ { STRING_CASELESS_RESTRICT_RIGHTPAR, 18, PSO_XOPT, PCRE2_EXTRA_CASELESS_RESTRICT },+ { STRING_TURKISH_CASING_RIGHTPAR, 15, PSO_XOPT, PCRE2_EXTRA_TURKISH_CASING },+ { STRING_LIMIT_HEAP_EQ, 11, PSO_LIMH, 0 },+ { STRING_LIMIT_MATCH_EQ, 12, PSO_LIMM, 0 },+ { STRING_LIMIT_DEPTH_EQ, 12, PSO_LIMD, 0 },+ { STRING_LIMIT_RECURSION_EQ, 16, PSO_LIMD, 0 },+ { STRING_CR_RIGHTPAR, 3, PSO_NL, PCRE2_NEWLINE_CR },+ { STRING_LF_RIGHTPAR, 3, PSO_NL, PCRE2_NEWLINE_LF },+ { STRING_CRLF_RIGHTPAR, 5, PSO_NL, PCRE2_NEWLINE_CRLF },+ { STRING_ANY_RIGHTPAR, 4, PSO_NL, PCRE2_NEWLINE_ANY },+ { STRING_NUL_RIGHTPAR, 4, PSO_NL, PCRE2_NEWLINE_NUL },+ { STRING_ANYCRLF_RIGHTPAR, 8, PSO_NL, PCRE2_NEWLINE_ANYCRLF },+ { STRING_BSR_ANYCRLF_RIGHTPAR, 12, PSO_BSR, PCRE2_BSR_ANYCRLF },+ { 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, 0, /* CLASS, NCLASS, XCLASS, ECLASS */+ 0, 0, /* REF, REFI */+ 0, 0, /* DNREF, DNREFI */+ 0, 0, /* RECURSE, CALLOUT */+};++/* Compile-time check that the table has the correct size. */+STATIC_ASSERT(sizeof(opcode_possessify) == OP_CALLOUT+1, opcode_possessify);+++#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)? CHAR_P:CHAR_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_OFFSET:+ fprintf(stderr, "META_OFFSET offset=");+ GETOFFSET(offset, pptr);+ fprintf(stderr, "%zd", offset);+ break;++ case META_SCS:+ fprintf(stderr, "META (*scan_substring:");+ break;++ case META_CAPTURE_NAME:+ fprintf(stderr, "META_CAPTURE_NAME length=%d relative_offset=%d", *pptr++, (int)meta_arg);+ break;++ case META_CAPTURE_NUMBER:+ fprintf(stderr, "META_CAPTURE_NUMBER %d relative_offset=%d", *pptr++, (int)meta_arg);+ 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;++ case META_ECLASS_AND: fprintf(stderr, "META_ECLASS_AND"); break;+ case META_ECLASS_OR: fprintf(stderr, "META_ECLASS_OR"); break;+ case META_ECLASS_SUB: fprintf(stderr, "META_ECLASS_SUB"); break;+ case META_ECLASS_XOR: fprintf(stderr, "META_ECLASS_XOR"); break;+ case META_ECLASS_NOT: fprintf(stderr, "META_ECLASS_NOT"); 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;+ you must not pass a value for max_value larger than+ INT_MAX/10 - 1 because this function relies on max_value to+ avoid integer overflow+ 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;++PCRE2_ASSERT(max_value <= INT_MAX/10 - 1);++*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;+ while (ptr < ptrend && IS_DIGIT(*ptr)) ptr++;+ 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 (n > (uint32_t)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 -(n+1). 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 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+ bracount the number of capturing parentheses encountered so far+ isclass TRUE if in 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, uint32_t bracount,+ 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)+ {+#ifndef EBCDIC+ if (utf)+ {+ ptr = p + 2;+ escape = 0; /* Not a fancy escape after all */+ goto COME_FROM_NU;+ }+#endif++ /* Improve error offset. */+ ptr = p + 2;+ while (ptr < ptrend && XDIGIT(*ptr) != 0xff) ptr++;+ while (ptr < ptrend && (*ptr == CHAR_SPACE || *ptr == CHAR_HT)) ptr++;+ if (ptr < ptrend && *ptr == CHAR_RIGHT_CURLY_BRACKET) ptr++;++ *errorcodeptr = ERR93;+ }++ /* Give an error in contexts where quantifiers are not allowed+ (character classes; substitution strings). */++ else if (isclass || cb == NULL)+ {+ ptr++; /* Skip over the opening brace */+ *errorcodeptr = ERR37;+ }++ /* 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)+ {+ ptr++; /* Skip over the opening brace */+ *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_0 && c <= CHAR_9) && c != CHAR_c && c != CHAR_o &&+ c != CHAR_x && c != CHAR_g)+ {+ *errorcodeptr = ERR3;+ goto EXIT;+ }+ 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 */+ {+ if (isclass) break; /* In a class, just treat as '\u' literal */+ 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 (offset+ by 1), ESC_k for a named back reference, and ESC_g for a named or+ numbered subroutine call.++ The above describes the \g behaviour inside patterns. Inside replacement+ strings (pcre2_substitute) we support only \g<nameornum> for Python+ compatibility. Return ESG_g for the named case, and -(num+1) for the+ numbered case.+ */++ case CHAR_g:+ if (isclass) break;++ if (ptr >= ptrend)+ {+ *errorcodeptr = ERR57;+ break;+ }++ if (cb == NULL)+ {+ PCRE2_SPTR p;+ /* Substitution strings */+ if (*ptr != CHAR_LESS_THAN_SIGN)+ {+ *errorcodeptr = ERR57;+ break;+ }++ p = ptr + 1;++ if (!read_number(&p, ptrend, -1, MAX_GROUP_NUMBER, ERR61, &s,+ errorcodeptr))+ {+ if (*errorcodeptr == 0) escape = ESC_g; /* No number found */+ break;+ }++ if (p >= ptrend || *p != CHAR_GREATER_THAN_SIGN)+ {+ ptr = p;+ *errorcodeptr = ERR119; /* Missing terminator for number */+ break;+ }++ /* This is the reason that back references are returned as -(s+1) rather+ than just -s. In a pattern, \0 is not a back reference, but \g<0> is+ valid in a substitution string, so this must be representable. */+ ptr = p + 1;+ escape = -(s+1);+ 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, 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)+ {+ ptr = p;+ *errorcodeptr = ERR119; /* Missing terminator for number */+ break;+ }+ ptr = p + 1;+ }++ /* Read an undelimited number */++ else+ {+ if (!read_number(&ptr, ptrend, bracount, MAX_GROUP_NUMBER, ERR61, &s,+ errorcodeptr))+ {+ if (*errorcodeptr == 0) *errorcodeptr = ERR57; /* No number found */+ break;+ }+ }++ if (s <= 0)+ {+ *errorcodeptr = ERR15;+ break;+ }++ escape = -(s+1);+ 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). This is the "Perl+ style" of handling ambiguous octal/backrefences such as \12.++ There is an alternative disambiguation strategy, selected by+ PCRE2_EXTRA_PYTHON_OCTAL, which follows Python's behaviour. An octal must+ have either a leading zero, or exactly three octal digits; otherwise it's+ a backreference. The disambiguation is stable, and does not depend on how+ many capture groups are defined (it's simply an invalid backreference if+ there is no corresponding capture group). Additionally, octal values above+ \377 (\xff) are rejected.++ 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)+ {+ /* Fall through to octal handling; never a backreference inside a class. */+ }+ else if ((xoptions & PCRE2_EXTRA_PYTHON_OCTAL) != 0)+ {+ /* Python-style disambiguation. */+ if (ptr[-1] <= CHAR_7 && ptr + 1 < ptrend && ptr[0] >= CHAR_0 &&+ ptr[0] <= CHAR_7 && ptr[1] >= CHAR_0 && ptr[1] <= CHAR_7)+ {+ /* We peeked a three-digit octal, so fall through */+ }+ else+ {+ /* We are at a digit, so the only possible error from read_number() is+ a number that is too large. */+ ptr--; /* Back to the digit */++ if (!read_number(&ptr, ptrend, -1, MAX_GROUP_NUMBER, 0, &s, errorcodeptr))+ {+ *errorcodeptr = ERR61;+ break;+ }++ escape = -(s+1);+ break;+ }+ }+ else+ {+ /* Perl-style disambiguation. */+ 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. Because+ that number might be still valid if read as an octal, errorcodeptr is not+ set on failure and therefore a sentinel value of INT_MAX is used instead+ of the original value, and will be used later to properly set the error,+ if not falling through. */++ if (!read_number(&ptr, ptrend, -1, MAX_GROUP_NUMBER, 0, &s, errorcodeptr))+ s = INT_MAX;++ /* \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 (s < 10 || c >= CHAR_8 || (unsigned)s <= bracount)+ {+ /* s > MAX_GROUP_NUMBER should not be possible because of read_number(),+ but we keep it just to be safe and because it will also catch the+ sentinel value that was set on failure by that function. */++ if ((unsigned)s > MAX_GROUP_NUMBER)+ {+ PCRE2_ASSERT(s == INT_MAX);+ *errorcodeptr = ERR61;+ }+ else escape = -(s+1); /* 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;++ PCRE2_FALLTHROUGH /* 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/32-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 (c > 0xff)+ {+ if ((xoptions & PCRE2_EXTRA_PYTHON_OCTAL) != 0) *errorcodeptr = ERR102;+#if PCRE2_CODE_UNIT_WIDTH == 8+ else if (!utf) *errorcodeptr = ERR51;+#endif+ }++ /* PCRE2_EXTRA_NO_BS0 disables the NUL escape '\0' but doesn't affect+ two- or three-character octal escapes \00 and \000, nor \x00. */++ if ((xoptions & PCRE2_EXTRA_NO_BS0) != 0 && c == 0 && i == 1)+ *errorcodeptr = ERR98;+ 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)+ {+ *errorcodeptr = ERR55;+ break;+ }+ ptr++;++ 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 >= 0x20000000u) { 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 (utf && c >= 0xd800 && c <= 0xdfff &&+ (xoptions & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)+ {+ *errorcodeptr = ERR73;+ }+ else if (ptr < ptrend && *ptr == CHAR_RIGHT_CURLY_BRACKET)+ {+ ptr++;+ }+ else+ {+ *errorcodeptr = ERR64;+ goto ESCAPE_FAILED_FORWARD;+ }+ 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 (utf && c >= 0xd800 && c <= 0xdfff &&+ (xoptions & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)+ {+ *errorcodeptr = ERR73;+ }+ else if (ptr < ptrend && *ptr == CHAR_RIGHT_CURLY_BRACKET)+ {+ ptr++;+ }++ /* 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+ {+ *errorcodeptr = ERR67;+ goto ESCAPE_FAILED_FORWARD;+ }+ } /* End of \x{} processing */++ /* Read a up to two hex digits after \x */++ else+ {+ /* Perl has the surprising/broken behaviour that \x without following+ hex digits is treated as an escape for NUL. Their source code laments+ this but keeps it for backwards compatibility. A warning is printed+ when "use warnings" is enabled. Because we don't have warnings, we+ simply forbid it. */+ if (ptr >= ptrend || (cc = XDIGIT(*ptr)) == 0xff)+ {+ /* Not a hex digit */+ *errorcodeptr = ERR78;+ break;+ }+ ptr++;+ c = cc;++ /* With "use re 'strict'" Perl actually requires exactly two digits (error+ for \x, \xA and \xAAA). While \x was already rejected, this seems overly+ strict, and there seems little incentive to align with that, given the+ backwards-compatibility cost.++ For comparison, note that other engines disagree. For example:+ - Java allows 1 or 2 hex digits. Error if 0 digits. No error if >2 digits+ - .NET requires 2 hex digits. Error if 0, 1 digits. No error if >2 digits.+ */+ 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. */++ case CHAR_c:+ 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;+ goto ESCAPE_FAILED_FORWARD;+ }+ 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 = (CHAR_BACKSLASH == 188 && CHAR_GRAVE_ACCENT == 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;+ goto ESCAPE_FAILED_FORWARD;+ }+ }+#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;+ break;+ }+ }++/* Set the pointer to the next character before returning. */++EXIT:+*ptrptr = ptr;+*chptr = c;+return escape;++/* Some errors need to indicate the next character. */++ESCAPE_FAILED_FORWARD:+ptr++;+#ifdef SUPPORT_UNICODE+if (utf) FORWARDCHARTEST(ptr, ptrend);+#endif+goto EXIT;+}++++#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+ utf true if the input is UTF-encoded+ 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 utf, BOOL *negptr, uint16_t *ptypeptr,+ uint16_t *pdataptr, int *errorcodeptr, compile_block *cb)+{+uint32_t c;+ptrdiff_t i;+PCRE2_SIZE bot, top;+PCRE2_SPTR ptr = *ptrptr;+PCRE2_UCHAR name[50];+PCRE2_UCHAR *vptr = NULL;+uint16_t ptscript = PT_NOTSCRIPT;++#ifndef MAYBE_UTF_MULTI+(void)utf; /* Avoid compiler warning */+#endif++if (ptr >= cb->end_pattern) goto ERROR_RETURN;+GETCHARINCTEST(c, ptr);+*negptr = FALSE;++/* \P or \p can be followed by a name in {}, optionally preceded by ^ for+negation. We must be handling Unicode encoding here, though we may be compiling+for UTF-8 input in an EBCDIC environment. (PCRE2 does not support both EBCDIC+input and Unicode input in the same build.) In accordance with Unicode's "loose+matching" rules, ASCII white space, hyphens, and underscores are ignored. We+don't use isspace() or tolower() because (a) code points may be greater than+255, and (b) they wouldn't work when compiling for Unicode in an EBCDIC+environment. */++if (c == CHAR_LEFT_CURLY_BRACKET)+ {+ if (ptr >= cb->end_pattern) goto ERROR_RETURN;++ for (i = 0; i < (int)(sizeof(name) / sizeof(PCRE2_UCHAR)) - 1; i++)+ {+ REDO:++ if (ptr >= cb->end_pattern) goto ERROR_RETURN;+ GETCHARINCTEST(c, ptr);++ /* Skip ignorable Unicode characters. */++ if (c == CHAR_UNDERSCORE || c == CHAR_MINUS || c == CHAR_SPACE ||+ (c >= CHAR_HT && c <= CHAR_CR))+ {+ goto REDO;+ }++ /* The first significant character being circumflex negates the meaning of+ the item. */++ if (i == 0 && !*negptr && c == CHAR_CIRCUMFLEX_ACCENT)+ {+ *negptr = TRUE;+ goto REDO;+ }++ if (c == CHAR_RIGHT_CURLY_BRACKET) break;++ /* Names consist of ASCII letters and digits, but equals and colon may also+ occur as a name/value separator. We must also allow for \p{L&}. A simple+ check for a value between '&' and 'z' suffices because anything else in a+ name or value will cause an "unknown property" error anyway. */++ if (c < CHAR_AMPERSAND || c > CHAR_z) goto ERROR_RETURN;++ /* Lower case a capital letter or remember where the name/value separator+ is. */++ if (c >= CHAR_A && c <= CHAR_Z) c |= 0x20;+ else if ((c == CHAR_COLON || c == CHAR_EQUALS_SIGN) && vptr == NULL)+ vptr = name + i;++ name[i] = c;+ }++ /* Error if the loop didn't end with '}' - either we hit the end of the+ pattern or the name was longer than any legal property name. */++ 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 (c >= CHAR_A && c <= CHAR_Z)+ {+ name[0] = c | 0x20; /* Lower case */+ name[1] = 0;+ }+else if (c >= CHAR_a && c <= CHAR_z)+ {+ name[0] = c;+ name[1] = 0;+ }+else goto ERROR_RETURN;++*ptrptr = ptr; /* Update pattern pointer */++/* 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 the 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);++/* If this logic were ever to change, the matching function in pcre2_substitute.c+ought to be updated to match. */++/* 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;+ PCRE2_SPTR p = ptr;++ GETCHARINC(c, p); /* Peek at next character */+ type = UCD_CHARTYPE(c);++ if (type == ucp_Nd)+ {+ ptr = p;+ *errorcodeptr = ERR44;+ goto FAILED;+ }++ for(;;)+ {+ if (type != ucp_Nd && PRIV(ucp_gentype)[type] != ucp_L &&+ c != CHAR_UNDERSCORE) break;+ ptr = p; /* Accept character and peek again */+ if (p >= ptrend) break;+ GETCHARINC(c, p);+ 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))+ {+ ++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 (terminator != 0)+ {+ if (ptr >= ptrend || *ptr != (PCRE2_UCHAR)terminator)+ {+ *errorcodeptr = ERR42;+ goto FAILED;+ }+ ptr++;+ }+ }++*ptrptr = ptr;+return TRUE;++FAILED:+*ptrptr = ptr;+return FALSE;+}++++/**************************************************+* Parse capturing bracket argument list *+**************************************************/++/* Reads a list of capture references. The references+can be numbers or names.++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+ parsed_pattern the parsed pattern pointer+ offset last known offset+ errcodeptr where to put an error code+ cb pointer to the compile data block++Returns: updated parsed_pattern pointer on success+ NULL otherwise+*/++static uint32_t *+parse_capture_list(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend,+ BOOL utf, uint32_t *parsed_pattern, PCRE2_SIZE offset,+ int *errorcodeptr, compile_block *cb)+{+PCRE2_SIZE next_offset;+PCRE2_SPTR ptr = *ptrptr;+PCRE2_SPTR name;+PCRE2_UCHAR terminator;+uint32_t meta, namelen;+int i;++if (ptr >= ptrend || *ptr != CHAR_LEFT_PARENTHESIS)+ {+ *errorcodeptr = ERR118;+ goto FAILED;+ }++for (;;)+ {+ ptr++;+ next_offset = (PCRE2_SIZE)(ptr - cb->start_pattern);++ if (ptr >= ptrend)+ {+ *errorcodeptr = ERR117;+ goto FAILED;+ }++ /* Handle [+-]number cases */+ if (read_number(&ptr, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61,+ &i, errorcodeptr))+ {+ PCRE2_ASSERT(i >= 0);+ if (i <= 0)+ {+ *errorcodeptr = ERR15;+ goto FAILED;+ }+ meta = META_CAPTURE_NUMBER;+ namelen = (uint32_t)i;+ }+ else if (*errorcodeptr != 0) goto FAILED; /* Number too big */+ else+ {+ /* Handle 'name' or <name> cases. */+ if (*ptr == CHAR_LESS_THAN_SIGN)+ terminator = CHAR_GREATER_THAN_SIGN;+ else if (*ptr == CHAR_APOSTROPHE)+ terminator = CHAR_APOSTROPHE;+ else+ {+ *errorcodeptr = ERR117;+ goto FAILED;+ }++ if (!read_name(&ptr, ptrend, utf, terminator, &next_offset,+ &name, &namelen, errorcodeptr, cb)) goto FAILED;++ meta = META_CAPTURE_NAME;+ }++ PCRE2_ASSERT(next_offset > 0);+ if (offset == 0 || (next_offset - offset) >= 0x10000)+ {+ *parsed_pattern++ = META_OFFSET;+ PUTOFFSET(next_offset, parsed_pattern);+ offset = next_offset;+ }++ /* The offset is encoded as a relative offset, because for some+ inputs such as ",2" in (1,2,3), we only have space for two uint32_t+ values, and an opcode and absolute offset may require three uint32_t+ values. */+ *parsed_pattern++ = meta | (uint32_t)(next_offset - offset);+ *parsed_pattern++ = namelen;+ offset = next_offset;++ if (ptr >= ptrend) goto UNCLOSED_PARENTHESIS;++ if (*ptr == CHAR_RIGHT_PARENTHESIS) break;++ if (*ptr != CHAR_COMMA)+ {+ *errorcodeptr = ERR24;+ goto FAILED;+ }+ }++*ptrptr = ptr + 1;+return parsed_pattern;++UNCLOSED_PARENTHESIS:+*errorcodeptr = ERR14;++FAILED:+*ptrptr = ptr;+return NULL;+}++++/*************************************************+* 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;+ PCRE2_FALLTHROUGH /* Fall through */+ case ESC_d:+ ascii_option = PCRE2_EXTRA_ASCII_BSD;+ break;++ case ESC_S:+ prop = ESC_P;+ PCRE2_FALLTHROUGH /* Fall through */+ case ESC_s:+ ascii_option = PCRE2_EXTRA_ASCII_BSS;+ break;++ case ESC_W:+ prop = ESC_P;+ PCRE2_FALLTHROUGH /* 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;+}++++/*************************************************+* Maximum size of parsed_pattern for given input *+*************************************************/++/* This function is called from parse_regex() below, to determine the amount+of memory to allocate for parsed_pattern. It is also called to check whether+the amount of data written respects the amount of memory allocated.++Arguments:+ ptr points to the start of the pattern+ ptrend points to the end of the pattern+ utf TRUE in UTF mode+ options the options bits++Returns: the number of uint32_t units for parsed_pattern+*/+static ptrdiff_t+max_parsed_pattern(PCRE2_SPTR ptr, PCRE2_SPTR ptrend, BOOL utf,+ uint32_t options)+{+PCRE2_SIZE big32count = 0;+ptrdiff_t parsed_size_needed;++/* When PCRE2_AUTO_CALLOUT is not set, in all but one case the number of+unsigned 32-bit ints written out to the parsed pattern is bounded by the length+of the pattern. 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 < ptrend; p++) if (*p >= META_END) big32count++;+ }+#else+(void)utf; /* Avoid compiler warning */+#endif++parsed_size_needed = (ptrend - ptr) + big32count;++/* When PCRE2_AUTO_CALLOUT is set we have to assume a numerical callout (4+elements) for each character. This is overkill, but memory is plentiful these+days. */++if ((options & PCRE2_AUTO_CALLOUT) != 0)+ parsed_size_needed += (ptrend - ptr) * 4;++return parsed_size_needed;+}++++/*************************************************+* 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, /* State after '[' (initial), or '[a-z'; hyphen is literal */+ RANGE_STARTED, /* State after '[1-'; last-emitted code is META_RANGE_XYZ */+ RANGE_FORBID_NO, /* State after '[\d'; '-]' is allowed but not '-1]' */+ RANGE_FORBID_STARTED, /* State after '[\d-'*/+ RANGE_OK_ESCAPED, /* State after '[\1'; hyphen may be a range */+ RANGE_OK_LITERAL /* State after '[1'; hyphen may be a range */+};++/* States used for analyzing operators and operands in extended character+classes. */++enum {+ CLASS_OP_EMPTY, /* At start of an expression; empty previous contents */+ CLASS_OP_OPERAND, /* Have preceding operand; after "z" a "--" can follow */+ CLASS_OP_OPERATOR /* Have preceding operator; after "--" operand must follow */+};++/* States used for determining the parse mode in character classes. The two+PERL_EXT values must be last. */++enum {+ CLASS_MODE_NORMAL, /* Ordinary PCRE2 '[...]' class. */+ CLASS_MODE_ALT_EXT, /* UTS#18-style extended '[...]' class. */+ CLASS_MODE_PERL_EXT, /* Perl extended '(?[...])' class. */+ CLASS_MODE_PERL_EXT_LEAF /* Leaf within extended '(?[ [...] ])' class. */+};++/* 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, uint32_t xoptions,+ BOOL *has_lookbehind, compile_block *cb)+{+uint32_t c;+uint32_t delimiter;+uint32_t namelen;+uint32_t class_range_state;+uint32_t class_op_state;+uint32_t class_mode_state;+uint32_t *class_start;+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;+uint16_t nest_depth = 0;+int16_t class_depth_m1 = -1; /* The m1 means minus 1. */+int16_t class_maxdepth_m1 = -1;+uint16_t hash;+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 is_dupname;+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 */+PCRE2_SPTR class_range_forbid_ptr = NULL;+named_group *ng;+nest_save *top_nest, *end_nests;+#ifdef PCRE2_DEBUG+uint32_t *parsed_pattern_check;+ptrdiff_t parsed_pattern_extra = 0;+ptrdiff_t parsed_pattern_extra_check = 0;+PCRE2_SPTR ptr_check;+#endif++PCRE2_ASSERT(parsed_pattern != NULL);++/* 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;+ }++#ifdef PCRE2_DEBUG+parsed_pattern_check = parsed_pattern;+ptr_check = ptr;+#endif++/* 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)+ {+ /* LCOV_EXCL_START */+ if (parsed_pattern >= parsed_pattern_end)+ {+ PCRE2_DEBUG_UNREACHABLE();+ errorcode = ERR63; /* Internal error (parsed pattern overflow) */+ goto FAILED;+ }+ /* LCOV_EXCL_STOP */++ 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 (nest_depth > cb->cx->parens_nest_limit)+ {+ errorcode = ERR19;+ goto FAILED; /* Parentheses too deeply nested */+ }++ /* Check that we haven't emitted too much into parsed_pattern. We allocate+ a suitably-sized buffer upfront, then do unchecked writes to it. If we only+ write a little bit too much, everything will appear to be OK, because the+ upfront size is an overestimate... but a malicious pattern could end up+ forcing a write past the buffer end. We must catch this during+ development. */++#ifdef PCRE2_DEBUG+ /* Strong post-write check. Won't help in release builds - at this point+ the write has already occurred so it's too late. However, should stop us+ committing unsafe code. */+ PCRE2_ASSERT((parsed_pattern - parsed_pattern_check) ++ (parsed_pattern_extra - parsed_pattern_extra_check) <=+ max_parsed_pattern(ptr_check, ptr, utf, options));+ parsed_pattern_check = parsed_pattern;+ parsed_pattern_extra_check = parsed_pattern_extra;+ ptr_check = ptr;+#endif++ /* LCOV_EXCL_START */+ if (parsed_pattern >= parsed_pattern_end)+ {+ /* Weak pre-write check; only ensures parsed_pattern[0] is writeable+ (but the code below can write many chars). Better than nothing. */+ PCRE2_DEBUG_UNREACHABLE();+ errorcode = ERR63; /* Internal error (parsed pattern overflow) */+ goto FAILED;+ }+ /* LCOV_EXCL_STOP */++ /* 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 (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, cb->bracount, 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)+ {+ /* A literal inside a \Q...\E is not allowed if we are expecting a+ conditional assertion, but an empty \Q\E sequence is OK. */+ if (expect_cond_assert > 0 && *ptr == CHAR_Q &&+ !(ptrend - ptr >= 3 && ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E))+ {+ ptr--;+ errorcode = ERR28;+ goto FAILED;+ }+ 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)+ {+ errorcode = ERR28;+ if (expect_cond_assert == 2) goto FAILED;+ goto FAILED_BACK;+ }+ }++ /* 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, cb->bracount, 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);+ escape = -escape - 1;+ *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, utf, &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 numerical 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)+ {+ ptr = p;+ errorcode = ERR119; /* Missing terminator for number */+ goto ESCAPE_FAILED;+ }+ ptr = p + 1;+ 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;+ }++ /* 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;++#ifdef PCRE2_DEBUG+ PCRE2_ASSERT(parsed_pattern_extra >= 2);+ parsed_pattern_extra -= 2;+#endif+ }++ /* 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:++ /* 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;+ okquantifier = TRUE;+ 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;+ ptr = tempptr + 2;+ goto FAILED;+ }++ class_mode_state = ((options & PCRE2_ALT_EXTENDED_CLASS) != 0)?+ CLASS_MODE_ALT_EXT : CLASS_MODE_NORMAL;++ /* Jump here from '(?[...])'. That jump must initialize class_mode_state,+ set c to the '[' character, and ptr to just after the '['. */++ FROM_PERL_EXTENDED_CLASS:+ okquantifier = TRUE;++ /* 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. Classes may be nested, if+ PCRE2_ALT_EXTENDED_CLASS is set, or the class is of the form (?[...]). */++ /* c is still set to '[' so the loop will handle the start of the class. */++ class_depth_m1 = -1;+ class_maxdepth_m1 = -1;+ class_range_state = RANGE_NO;+ class_op_state = CLASS_OP_EMPTY;+ class_start = NULL;++ 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;+ }++ /* Surprisingly, you cannot use \Q..\E to escape a character inside a+ Perl extended class. However, empty \Q\E sequences are allowed, so here+ were're only giving an error if the \Q..\E is non-empty. */++ if (class_mode_state == CLASS_MODE_PERL_EXT)+ {+ errorcode = ERR116;+ goto FAILED;+ }++ goto CLASS_LITERAL;+ }++ /* Skip over space and tab (only) in extended-more mode, or anywhere+ inside a Perl extended class (which implies /xx). */++ if ((c == CHAR_SPACE || c == CHAR_HT) &&+ ((options & PCRE2_EXTENDED_MORE) != 0 ||+ class_mode_state >= CLASS_MODE_PERL_EXT))+ 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 (class_depth_m1 >= 0 &&+ 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)+ {+ ptr = tempptr + 2;+ errorcode = ERR50;+ goto FAILED;+ }++ /* 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.++ Roll back to the hyphen for the error position. */++ if (class_range_state == RANGE_FORBID_STARTED)+ {+ ptr = class_range_forbid_ptr;+ errorcode = ERR50;+ goto FAILED;+ }++ /* Disallow implicit union in Perl extended classes. */++ if (class_op_state == CLASS_OP_OPERAND &&+ class_mode_state == CLASS_MODE_PERL_EXT)+ {+ ptr = tempptr + 2;+ errorcode = ERR113;+ goto FAILED;+ }++ if (*ptr != CHAR_COLON)+ {+ ptr = tempptr + 2;+ errorcode = ERR13;+ goto FAILED;+ }++ if (*(++ptr) == CHAR_CIRCUMFLEX_ACCENT)+ {+ posix_negate = TRUE;+ ptr++;+ }++ posix_class = check_posix_name(ptr, (int)(tempptr - ptr));+ ptr = tempptr + 2;+ if (posix_class < 0)+ {+ errorcode = ERR30;+ goto FAILED;+ }++ /* Set "a hyphen is forbidden to be the start of a range". For the '-]'+ case, the hyphen is treated as a literal, but for '-1' it is disallowed+ (because it would be interpreted as range). */++ class_range_state = RANGE_FORBID_NO;+ class_op_state = CLASS_OP_OPERAND;++ /* 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;+ }++ /* Check for the start of the outermost class, or the start of a nested class. */++ else if ((c == CHAR_LEFT_SQUARE_BRACKET &&+ (class_depth_m1 < 0 || class_mode_state == CLASS_MODE_ALT_EXT ||+ class_mode_state == CLASS_MODE_PERL_EXT)) ||+ (c == CHAR_LEFT_PARENTHESIS &&+ class_mode_state == CLASS_MODE_PERL_EXT))+ {+ uint32_t start_c = c;+ uint32_t new_class_mode_state;++ /* Update the class mode, if moving into a 'leaf' inside a Perl extended+ class. */++ if (start_c == CHAR_LEFT_SQUARE_BRACKET &&+ class_mode_state == CLASS_MODE_PERL_EXT && class_depth_m1 >= 0)+ new_class_mode_state = CLASS_MODE_PERL_EXT_LEAF;+ else+ new_class_mode_state = class_mode_state;++ /* Tidy up the other class before starting the nested class. */+ /* -[ beginning a nested class is a literal '-' */++ if (class_range_state == RANGE_STARTED)+ parsed_pattern[-1] = CHAR_MINUS;++ /* Disallow implicit union in Perl extended classes. */++ if (class_op_state == CLASS_OP_OPERAND &&+ class_mode_state == CLASS_MODE_PERL_EXT)+ {+ errorcode = ERR113;+ goto FAILED;+ }++ /* Validate nesting depth */+ if (class_depth_m1 >= ECLASS_NEST_LIMIT - 1)+ {+ ptr--; /* Point rightwards at the paren, same as ERR19. */+ errorcode = ERR107; /* Classes too deeply nested */+ goto FAILED;+ }++ /* Process the character class start. 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;+ for (;;)+ {+ if (ptr >= ptrend)+ {+ if (start_c == CHAR_LEFT_PARENTHESIS)+ errorcode = ERR14; /* Missing terminating ')' */+ else+ errorcode = ERR6; /* Missing terminating ']' */+ goto FAILED;+ }++ GETCHARINCTEST(c, ptr);+ if (new_class_mode_state == CLASS_MODE_PERL_EXT) break;+ else 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 ((c == CHAR_SPACE || c == CHAR_HT) && /* Note: just these two */+ ((options & PCRE2_EXTENDED_MORE) != 0 ||+ new_class_mode_state >= CLASS_MODE_PERL_EXT))+ 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, and if it's not+ a Perl-extended class. */++ if (c == CHAR_RIGHT_SQUARE_BRACKET &&+ (cb->external_options & PCRE2_ALLOW_EMPTY_CLASS) != 0 &&+ new_class_mode_state < CLASS_MODE_PERL_EXT)+ {+ PCRE2_ASSERT(start_c == CHAR_LEFT_SQUARE_BRACKET);++ if (class_start != NULL)+ {+ PCRE2_ASSERT(class_depth_m1 >= 0);+ /* Represents that the class is an extended class. */+ *class_start |= CLASS_IS_ECLASS;+ class_start = NULL;+ }++ *parsed_pattern++ = negate_class? META_CLASS_EMPTY_NOT : META_CLASS_EMPTY;++ /* Leave nesting depth unchanged; but check for zero depth to handle the+ very first (top-level) class being empty. */+ if (class_depth_m1 < 0) break;++ class_range_state = RANGE_NO; /* for processing the containing class */+ class_op_state = CLASS_OP_OPERAND;+ goto CLASS_CONTINUE;+ }++ /* Enter a non-empty class. */++ if (class_start != NULL)+ {+ PCRE2_ASSERT(class_depth_m1 >= 0);+ /* Represents that the class is an extended class. */+ *class_start |= CLASS_IS_ECLASS;+ class_start = NULL;+ }++ class_start = parsed_pattern;+ *parsed_pattern++ = negate_class? META_CLASS_NOT : META_CLASS;+ class_range_state = RANGE_NO;+ class_op_state = CLASS_OP_EMPTY;+ class_mode_state = new_class_mode_state;+ ++class_depth_m1;+ if (class_maxdepth_m1 < class_depth_m1)+ class_maxdepth_m1 = class_depth_m1;+ /* Reset; no op seen yet at new depth. */+ cb->class_op_used[class_depth_m1] = 0;++ /* Implement the special start-of-class literal meaning of ']'. */+ if (c == CHAR_RIGHT_SQUARE_BRACKET &&+ new_class_mode_state != CLASS_MODE_PERL_EXT)+ {+ class_range_state = RANGE_OK_LITERAL;+ class_op_state = CLASS_OP_OPERAND;+ PARSED_LITERAL(c, parsed_pattern);+ goto CLASS_CONTINUE;+ }++ continue; /* We have already loaded c with the next character */+ }++ /* Check for the end of the class. */++ else if (c == CHAR_RIGHT_SQUARE_BRACKET ||+ (c == CHAR_RIGHT_PARENTHESIS && class_mode_state == CLASS_MODE_PERL_EXT))+ {+ /* In Perl extended mode, the ']' can only be used to match the+ opening '[', and ')' must match an opening parenthesis. */+ if (class_mode_state == CLASS_MODE_PERL_EXT)+ {+ if (c == CHAR_RIGHT_SQUARE_BRACKET && class_depth_m1 != 0)+ {+ errorcode = ERR14;+ ptr--; /* Correct the offset */+ goto FAILED;+ }+ if (c == CHAR_RIGHT_PARENTHESIS && class_depth_m1 < 1)+ {+ errorcode = ERR22;+ goto FAILED;+ }+ }++ /* Check no trailing operator. */+ if (class_op_state == CLASS_OP_OPERATOR)+ {+ errorcode = ERR110;+ goto FAILED;+ }++ /* Check no empty expression for Perl extended expressions. */+ if (class_mode_state == CLASS_MODE_PERL_EXT &&+ class_op_state == CLASS_OP_EMPTY)+ {+ errorcode = ERR114;+ goto FAILED;+ }++ /* -] at the end of a class is a literal '-' */+ if (class_range_state == RANGE_STARTED)+ parsed_pattern[-1] = CHAR_MINUS;++ *parsed_pattern++ = META_CLASS_END;++ if (--class_depth_m1 < 0)+ {+ /* Check for and consume ')' after '(?[...]'. */+ PCRE2_ASSERT(class_mode_state != CLASS_MODE_PERL_EXT_LEAF);+ if (class_mode_state == CLASS_MODE_PERL_EXT)+ {+ if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)+ {+ errorcode = ERR115;+ goto FAILED;+ }++ ptr++;+ }++ break;+ }++ class_range_state = RANGE_NO; /* for processing the containing class */+ class_op_state = CLASS_OP_OPERAND;+ if (class_mode_state == CLASS_MODE_PERL_EXT_LEAF)+ class_mode_state = CLASS_MODE_PERL_EXT;+ /* The extended class flag has already+ been set for the parent class. */+ class_start = NULL;+ }++ /* Handle a Perl set binary operator */++ else if (class_mode_state == CLASS_MODE_PERL_EXT &&+ (c == CHAR_PLUS || c == CHAR_VERTICAL_LINE || c == CHAR_MINUS ||+ c == CHAR_AMPERSAND || c == CHAR_CIRCUMFLEX_ACCENT))+ {+ /* Check that there was a preceding operand. */+ if (class_op_state != CLASS_OP_OPERAND)+ {+ errorcode = ERR109;+ goto FAILED;+ }++ if (class_start != NULL)+ {+ PCRE2_ASSERT(class_depth_m1 >= 0);+ /* Represents that the class is an extended class. */+ *class_start |= CLASS_IS_ECLASS;+ class_start = NULL;+ }++ PCRE2_ASSERT(class_range_state != RANGE_STARTED &&+ class_range_state != RANGE_FORBID_STARTED);++ *parsed_pattern++ = c == CHAR_PLUS? META_ECLASS_OR :+ c == CHAR_VERTICAL_LINE? META_ECLASS_OR :+ c == CHAR_MINUS? META_ECLASS_SUB :+ c == CHAR_AMPERSAND? META_ECLASS_AND :+ META_ECLASS_XOR;+ class_range_state = RANGE_NO;+ class_op_state = CLASS_OP_OPERATOR;+ }++ /* Handle a Perl set unary operator */++ else if (class_mode_state == CLASS_MODE_PERL_EXT &&+ c == CHAR_EXCLAMATION_MARK)+ {+ /* Check that the "!" has not got a preceding operand (i.e. it's the+ start of the class, or follows an operator). */+ if (class_op_state == CLASS_OP_OPERAND)+ {+ errorcode = ERR113;+ goto FAILED;+ }++ if (class_start != NULL)+ {+ PCRE2_ASSERT(class_depth_m1 >= 0);+ /* Represents that the class is an extended class. */+ *class_start |= CLASS_IS_ECLASS;+ class_start = NULL;+ }++ PCRE2_ASSERT(class_range_state != RANGE_STARTED &&+ class_range_state != RANGE_FORBID_STARTED);++ *parsed_pattern++ = META_ECLASS_NOT;+ class_range_state = RANGE_NO;+ class_op_state = CLASS_OP_OPERATOR;+ }++ /* Handle a UTS#18 set operator */++ else if (class_mode_state == CLASS_MODE_ALT_EXT &&+ (c == CHAR_VERTICAL_LINE || c == CHAR_MINUS ||+ c == CHAR_AMPERSAND || c == CHAR_TILDE) &&+ ptr < ptrend && *ptr == c)+ {+ ++ptr;++ /* Check there isn't a triple-repetition. */+ if (ptr < ptrend && *ptr == c)+ {+ while (ptr < ptrend && *ptr == c) ++ptr; /* Improve error offset. */+ errorcode = ERR108;+ goto FAILED;+ }++ /* Check for a preceding operand. */+ if (class_op_state != CLASS_OP_OPERAND)+ {+ errorcode = ERR109;+ goto FAILED;+ }++ /* Check for mixed precedence. Forbid [A--B&&C]. */+ if (cb->class_op_used[class_depth_m1] != 0 &&+ cb->class_op_used[class_depth_m1] != (uint8_t)c)+ {+ errorcode = ERR111;+ goto FAILED;+ }++ if (class_start != NULL)+ {+ PCRE2_ASSERT(class_depth_m1 >= 0);+ /* Represents that the class is an extended class. */+ *class_start |= CLASS_IS_ECLASS;+ class_start = NULL;+ }++ /* Dangling '-' before an operator is a literal */+ if (class_range_state == RANGE_STARTED)+ parsed_pattern[-1] = CHAR_MINUS;++ *parsed_pattern++ = c == CHAR_VERTICAL_LINE? META_ECLASS_OR :+ c == CHAR_MINUS? META_ECLASS_SUB :+ c == CHAR_AMPERSAND? META_ECLASS_AND :+ META_ECLASS_XOR;+ class_range_state = RANGE_NO;+ class_op_state = CLASS_OP_OPERATOR;+ cb->class_op_used[class_depth_m1] = (uint8_t)c;+ }++ /* Handle escapes in a class */++ else if (c == CHAR_BACKSLASH)+ {+ tempptr = ptr;+ escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode, options,+ xoptions, cb->bracount, TRUE, cb);++ if (errorcode != 0)+ {+ if ((xoptions & PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL) == 0 ||+ class_mode_state >= CLASS_MODE_PERL_EXT)+ 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_k:+ c = CHAR_k; /* \k is not special in a class, just like \g */+ 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;+ goto FAILED;++ case ESC_N: /* Not permitted by Perl either */+ 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, utf, &negated, &ptype, &pdata, &errorcode, cb))+ goto FAILED;++ /* In caseless matching, particular characteristics Lu, Ll, and Lt+ get converted to the general characteristic L&. That is, upper,+ lower, and title case letters are all conflated. */++ if ((options & PCRE2_CASELESS) != 0 && ptype == PT_PC &&+ (pdata == ucp_Lu || pdata == ucp_Ll || pdata == ucp_Lt))+ {+ ptype = PT_LAMP;+ pdata = 0;+ }++ 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 */++ /* All others are not allowed in a class */++ /* LCOV_EXCL_START */+ default:+ PCRE2_DEBUG_UNREACHABLE();+ PCRE2_FALLTHROUGH /* Fall through */+ /* LCOV_EXCL_STOP */++ case ESC_A:+ case ESC_Z:+ case ESC_z:+ case ESC_G:+ case ESC_K:+ case ESC_C:+ errorcode = ERR7;+ goto FAILED;+ }++ /* All the switch-cases above which end in "break" describe a set+ of characters. None may start a range. */++ /* 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;+ }++ /* Perl gives a warning unless the hyphen following a multi-character+ escape is the last character in the class. PCRE throws an error. */++ if (class_range_state == RANGE_FORBID_STARTED)+ {+ ptr = class_range_forbid_ptr;+ errorcode = ERR50;+ goto FAILED;+ }++ /* Disallow implicit union in Perl extended classes. */++ if (class_op_state == CLASS_OP_OPERAND &&+ class_mode_state == CLASS_MODE_PERL_EXT)+ {+ errorcode = ERR113;+ goto FAILED;+ }++ class_range_state = RANGE_FORBID_NO;+ class_op_state = CLASS_OP_OPERAND;+ }++ /* Forbid unescaped literals, and the special meaning of '-', inside a+ Perl extended class. */++ else if (class_mode_state == CLASS_MODE_PERL_EXT)+ {+ errorcode = ERR116;+ goto FAILED;+ }++ /* 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 forbidden start of range */++ else if (c == CHAR_MINUS && class_range_state == RANGE_FORBID_NO)+ {+ *parsed_pattern++ = CHAR_MINUS;+ class_range_state = RANGE_FORBID_STARTED;+ class_range_forbid_ptr = ptr;+ }++ /* Handle a literal character */++ else+ {+ CLASS_LITERAL:++ /* Disallow implicit union in Perl extended classes. */++ if (class_op_state == CLASS_OP_OPERAND &&+ class_mode_state == CLASS_MODE_PERL_EXT)+ {+ errorcode = ERR113;+ goto FAILED;+ }++ 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;+ }+ 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;+ class_op_state = CLASS_OP_OPERAND;+ }+ else if (class_range_state == RANGE_FORBID_STARTED)+ {+ ptr = class_range_forbid_ptr;+ errorcode = ERR50;+ goto FAILED;+ }+ else /* Potential start of range */+ {+ class_range_state = char_is_literal?+ RANGE_OK_LITERAL : RANGE_OK_ESCAPED;+ class_op_state = CLASS_OP_OPERAND;+ PARSED_LITERAL(c, parsed_pattern);+ }+ }++ /* Proceed to next thing in the class. */++ CLASS_CONTINUE:+ if (ptr >= ptrend)+ {+ if (class_mode_state == CLASS_MODE_PERL_EXT && class_depth_m1 > 0)+ errorcode = ERR14; /* Missing terminating ')' */+ if (class_mode_state == CLASS_MODE_ALT_EXT &&+ class_depth_m1 == 0 && class_maxdepth_m1 == 1)+ errorcode = ERR112; /* Missing terminating ']', but we saw '[ [ ]...' */+ else+ errorcode = ERR6; /* Missing terminating ']' */+ goto FAILED;+ }+ GETCHARINCTEST(c, ptr);+ } /* End of class-processing loop */++ 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) goto UNCLOSED_PARENTHESIS;+ if (*ptr != CHAR_COLON)+ {+ errorcode = ERR95; /* Malformed */+ goto FAILED_FORWARD;+ }++ /* 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 = 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)+ {+ /* LCOV_EXCL_START */+ default:+ PCRE2_DEBUG_UNREACHABLE();+ errorcode = ERR89; /* Unknown code; should never occur because */+ goto FAILED; /* the meta values come from a table above. */+ /* LCOV_EXCL_STOP */++ 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_SCS:+ ptr++;+ *parsed_pattern++ = META_SCS;++ parsed_pattern = parse_capture_list(&ptr, ptrend, utf, parsed_pattern,+ 0, &errorcode, cb);+ if (parsed_pattern == NULL) goto FAILED;+ goto POST_ASSERTION;++ 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;++#ifdef PCRE2_DEBUG+ /* We'll write out two META_KETs for a single ")" in the input+ pattern, so we reserve space for that in our bounds check. */+ parsed_pattern_extra++;+#endif+ }+ 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);+#ifdef PCRE2_DEBUG+ /* Reserve space in our bounds check for optionally wrapping the (*ACCEPT)+ with a non-capturing bracket, if there is a following quantifier. */+ if (okquantifier) parsed_pattern_extra += 2;+#endif++ /* 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;+ 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;+ 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_FORWARD;+ }+ 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 && *ptr != CHAR_LEFT_PARENTHESIS))+ {+ errorcode = ERR58;+ goto FAILED;+ }+ terminator = CHAR_NUL;+ 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 (ptr + 1 >= ptrend)+ {+ ++ptr;+ goto UNCLOSED_PARENTHESIS;+ }+ if (!IS_DIGIT(ptr[1]))+ {+ errorcode = ERR29; /* Missing number */+ ++ptr;+ goto FAILED_FORWARD;+ }+ PCRE2_FALLTHROUGH /* 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;+ PCRE2_ASSERT(i >= 0); /* NB (?0) is permitted, represented by i=0 */+ terminator = CHAR_NUL;++ SET_RECURSION:+ *parsed_pattern++ = META_RECURSE | (uint32_t)i;+ offset = (PCRE2_SIZE)(ptr - cb->start_pattern);+ /* End of recursive call by number handling */+ goto READ_RECURSION_ARGUMENTS;+++ /* ---- Recursion/subroutine calls by name ---- */++ case CHAR_AMPERSAND:+ RECURSE_BY_NAME:+ if (!read_name(&ptr, ptrend, utf, 0, &offset, &name,+ &namelen, &errorcode, cb)) goto FAILED;+ *parsed_pattern++ = META_RECURSE_BYNAME;+ *parsed_pattern++ = namelen;+ terminator = CHAR_NUL;++ READ_RECURSION_ARGUMENTS:+ PUTOFFSET(offset, parsed_pattern);+ okquantifier = TRUE;++ /* Arguments are not supported for \g construct. */+ if (terminator != CHAR_NUL) break;++ if (ptr < ptrend && *ptr == CHAR_LEFT_PARENTHESIS)+ {+ parsed_pattern = parse_capture_list(&ptr, ptrend, utf, parsed_pattern,+ offset, &errorcode, cb);+ if (parsed_pattern == NULL) goto FAILED;+ }++ if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)+ goto UNCLOSED_PARENTHESIS;++ ptr++;+ break;++ /* ---- Callout with numerical or string argument ---- */++ case CHAR_C:+ if ((xoptions & PCRE2_EXTRA_NEVER_CALLOUT) != 0)+ {+ ptr++;+ errorcode = ERR103;+ goto FAILED;+ }++ 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_FORWARD;+ }++ *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))+ {+ PCRE2_ASSERT(i >= 0);+ 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)))+ {+ errorcode = ERR79;+ if (!ge) goto FAILED_FORWARD;+ goto FAILED;+ }++ if (!read_number(&ptr, ptrend, -1, 1000, ERR79, &major, &errorcode))+ goto FAILED;++ if (ptr < ptrend && *ptr == CHAR_DOT)+ {+ if (++ptr >= ptrend || !IS_DIGIT(*ptr))+ {+ errorcode = ERR79;+ if (ptr < ptrend) goto FAILED_FORWARD;+ goto FAILED;+ }+ if (!read_number(&ptr, ptrend, -1, 1000, ERR79, &minor, &errorcode))+ goto FAILED;+ }+ if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)+ {+ errorcode = ERR79;+ if (ptr < ptrend) goto FAILED_FORWARD;+ goto FAILED;+ }++ *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 (*napla: */+ *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. */++ is_dupname = FALSE;+ hash = PRIV(compile_get_hash_from_name)(name, namelen);+ ng = cb->named_groups;+ for (i = 0; i < cb->names_found; i++, ng++)+ {+ if (namelen == ng->length && hash == NAMED_GROUP_GET_HASH(ng) &&+ PRIV(strncmp)(name, ng->name, (PCRE2_SIZE)namelen) == 0)+ {+ /* When a bracket is referenced by the same name multiple+ times, is not considered as a duplicate and ignored. */+ if (ng->number == cb->bracount) break;+ if ((options & PCRE2_DUPNAMES) == 0)+ {+ errorcode = ERR43;+ goto FAILED;+ }++ ng->hash_dup |= NAMED_GROUP_IS_DUPNAME;+ is_dupname = TRUE; /* Mark as a duplicate */+ cb->dupnames = TRUE; /* Duplicate names exist */++ /* The entry represents a duplicate. */+ name = ng->name;+ namelen = 0;++ /* Even duplicated names may refer to the same+ capture index. These references are also ignored. */+ for (; i < cb->names_found; i++, ng++)+ if (ng->name == name && ng->number == cb->bracount)+ break;+ break;+ }+ else if (ng->number == cb->bracount)+ {+ errorcode = ERR65;+ goto FAILED;+ }+ }++ /* Ignore duplicate with same number. */+ if (i < cb->names_found) break;++ /* 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 */+ if (is_dupname)+ hash |= NAMED_GROUP_IS_DUPNAME;++ 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].hash_dup = hash;+ cb->names_found++;+ break;+++ /* ---- Perl extended character class ---- */++ /* These are of the form '(?[...])'. We handle these via the same parser+ that consumes ordinary '[...]' classes, but with a flag set to activate+ the extended behaviour. */++ case CHAR_LEFT_SQUARE_BRACKET:+ class_mode_state = CLASS_MODE_PERL_EXT;+ c = *ptr++;+ goto FROM_PERL_EXTENDED_CLASS;+ } /* 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;++#ifdef PCRE2_DEBUG+ PCRE2_ASSERT(parsed_pattern_extra > 0);+ parsed_pattern_extra--;+#endif+ }++ 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;+ }+ 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;+ }+++PARSED_END:++PCRE2_ASSERT((parsed_pattern - parsed_pattern_check) ++ (parsed_pattern_extra - parsed_pattern_extra_check) <=+ max_parsed_pattern(ptr_check, ptr, utf, options));++/* Manage callout for the final item */++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. */++/* LCOV_EXCL_START */+if (parsed_pattern >= parsed_pattern_end)+ {+ PCRE2_DEBUG_UNREACHABLE();+ errorcode = ERR63; /* Internal error (parsed pattern overflow) */+ goto FAILED;+ }+/* LCOV_EXCL_STOP */++*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--;+#ifdef SUPPORT_UNICODE+if (utf) BACKCHAR(ptr);+#endif+goto FAILED;++/* Some errors need to indicate the next character. */++FAILED_FORWARD:+ptr++;+#ifdef SUPPORT_UNICODE+if (utf) FORWARDCHARTEST(ptr, ptrend);+#endif+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;+ PCRE2_FALLTHROUGH /* 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;+ }+ }++/* LCOV_EXCL_START */+PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */+/* LCOV_EXCL_STOP */+}++++/*************************************************+* 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 *pptr = *pptrptr;+uint32_t meta, meta_arg;+uint32_t firstcuflags, reqcuflags;+uint32_t zeroreqcuflags, zerofirstcuflags;+uint32_t req_caseopt, reqvary, tempreqvary;+/* Some opcodes, such as META_CAPTURE_NUMBER or META_CAPTURE_NAME,+depends on the previous value of offset. */+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;++/* 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++/* 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++)+ {+ BOOL possessive_quantifier;+ BOOL note_group_empty;+ 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)+ {+ /* LCOV_EXCL_START */+ if (code >= cb->start_workspace + cb->workspace_size)+ {+ PCRE2_DEBUG_UNREACHABLE();+ *errorcodeptr = ERR52; /* Over-ran workspace - internal error */+ cb->erroroffset = 0;+ return 0;+ }+ /* LCOV_EXCL_STOP */++ if (code > cb->start_workspace + cb->workspace_size -+ WORK_SIZE_SAFETY_MARGIN) /* Check for overrun */+ {+ *errorcodeptr = ERR86; /* Pattern too complicated */+ cb->erroroffset = 0;+ 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 */+ cb->erroroffset = 0;+ return 0;+ }+ *lengthptr += (PCRE2_SIZE)(code - orig_code);+ if (*lengthptr > MAX_PATTERN_SIZE)+ {+ *errorcodeptr = ERR20; /* Pattern is too large */+ cb->erroroffset = 0;+ 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 generate an empty class - we have no dedicated opcode+ to optimise the representation, but it's a rare case (the '(*FAIL)'+ construct would be a clearer way for a pattern author to represent a+ non-matching branch, but it does have different semantics to '[]' if both+ are followed by a quantifier). The empty-negated [^] matches any character,+ so is useful: generate OP_ALLANY for this. */++ case META_CLASS_EMPTY:+ case META_CLASS_EMPTY_NOT:+ matched_char = TRUE;+ if (meta == META_CLASS_EMPTY_NOT) *code++ = OP_ALLANY;+ else+ {+ *code++ = OP_CLASS;+ memset(code, 0, 32);+ code += 32 / sizeof(PCRE2_UCHAR);+ }++ 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;++ /* Check for complex extended classes and handle them separately. */++ if ((*pptr & CLASS_IS_ECLASS) != 0)+ {+ if (!PRIV(compile_class_nested)(options, xoptions, &pptr, &code,+ errorcodeptr, cb, lengthptr))+ return 0;+ goto CLASS_END_PROCESSING;+ }++ /* 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)+ {+ 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. If the character is+ affected by the special Turkish rules, hardcode the not-matching+ characters using a caseset. */++#ifdef SUPPORT_UNICODE+ if ((utf||ucp) && (options & PCRE2_CASELESS) != 0)+ {+ uint32_t caseset;++ if ((xoptions & (PCRE2_EXTRA_TURKISH_CASING|PCRE2_EXTRA_CASELESS_RESTRICT)) ==+ PCRE2_EXTRA_TURKISH_CASING &&+ UCD_ANY_I(c))+ {+ caseset = PRIV(ucd_turkish_dotted_i_caseset) + (UCD_DOTTED_I(c)? 0 : 3);+ }+ else if ((caseset = UCD_CASESET(c)) != 0 &&+ (xoptions & PCRE2_EXTRA_CASELESS_RESTRICT) != 0 &&+ PRIV(ucd_caseless_sets)[caseset] < 128)+ {+ caseset = 0; /* Ignore the caseless set if it's restricted. */+ }++ if (caseset != 0)+ {+ *code++ = OP_NOTPROP;+ *code++ = PT_CLIST;+ *code++ = caseset;+ 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. When Turkish casing applies, an 'i' does not match its normal+ Unicode "othercase". */++ 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)) &&+ !((xoptions & (PCRE2_EXTRA_TURKISH_CASING|PCRE2_EXTRA_CASELESS_RESTRICT)) ==+ PCRE2_EXTRA_TURKISH_CASING &&+ UCD_ANY_I(c)))+#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;+ }+ }+ }++ /* Now emit the OP_CLASS/OP_NCLASS/OP_XCLASS/OP_ALLANY opcode. */++ pptr = PRIV(compile_class_not_nested)(options, xoptions, pptr + 1,+ &code, meta == META_CLASS_NOT, NULL,+ errorcodeptr, cb, lengthptr);+ if (pptr == NULL) return 0;+ PCRE2_ASSERT(*pptr == META_CLASS_END);++ CLASS_END_PROCESSING:++ /* 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;+ 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;+ PCRE2_FALLTHROUGH /* 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;+ PCRE2_FALLTHROUGH /* 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 scan substring. Scan substring assertion starts with META_SCS,+ which recursively calls compile_branch. The first opcode processed by+ this recursive call is always META_OFFSET. */++ case META_OFFSET:+ if (lengthptr != NULL)+ {+ pptr = PRIV(compile_parse_scan_substr_args)(pptr, errorcodeptr, cb, lengthptr);+ if (pptr == NULL)+ return 0;+ break;+ }++ while (TRUE)+ {+ int count, index;+ named_group *ng;++ switch (META_CODE(*pptr))+ {+ case META_OFFSET:+ pptr++;+ SKIPOFFSET(pptr);+ continue;++ case META_CAPTURE_NAME:+ ng = cb->named_groups + pptr[1];+ pptr += 2;+ count = 0;+ index = 0;++ if (!PRIV(compile_find_dupname_details)(ng->name, ng->length, &index,+ &count, errorcodeptr, cb)) return 0;++ code[0] = OP_DNCREF;+ PUT2(code, 1, index);+ PUT2(code, 1 + IMM2_SIZE, count);+ code += 1 + 2 * IMM2_SIZE;+ continue;++ case META_CAPTURE_NUMBER:+ pptr += 2;+ if (pptr[-1] == 0) continue;++ code[0] = OP_CREF;+ PUT2(code, 1, pptr[-1]);+ code += 1 + IMM2_SIZE;+ continue;++ default:+ break;+ }++ break;+ }+ --pptr;+ break;++ case META_SCS:+ bravalue = OP_ASSERT_SCS;+ cb->assert_depth += 1;+ goto GROUP_PROCESS;+++ /* ===================================================================*/+ /* 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;++ if (lengthptr != NULL)+ {+ uint32_t i;+ PCRE2_SPTR name;+ named_group *ng;+ uint32_t *start_pptr = pptr;+ 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. */++ ng = PRIV(compile_find_named_group)(name, length, cb);++ if (ng == NULL)+ {+ /* 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. */++ 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;+ PCRE2_ASSERT(start_pptr[0] == META_COND_RNUMBER);+ start_pptr[1] = groupnumber;+ skipunits = 1+IMM2_SIZE;+ goto GROUP_PROCESS_NOTE_EMPTY;+ }++ /* From here on, we know we have a name (not a number),+ so treat META_COND_RNUMBER the same as META_COND_NAME. */+ if (meta == META_COND_RNUMBER) meta = META_COND_NAME;++ if ((ng->hash_dup & NAMED_GROUP_IS_DUPNAME) == 0)+ {+ /* Found a non-duplicated name. Since it is a global,+ it is enough to update it in the pre-processing phase. */+ if (ng->number > cb->top_backref) cb->top_backref = ng->number;++ start_pptr[0] = meta;+ start_pptr[1] = ng->number;++ skipunits = 1 + IMM2_SIZE;+ goto GROUP_PROCESS_NOTE_EMPTY;+ }++ /* 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. */++ start_pptr[0] = meta | 1;+ start_pptr[1] = (uint32_t)(ng - cb->named_groups);++ /* 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. */+ skipunits = 1 + 2 * IMM2_SIZE;+ }+ else+ {+ /* Otherwise lengthptr equals to NULL,+ which is the second phase of compilation. */+ int count, index;+ named_group *ng;++ /* Generate code using the data+ collected in the pre-processing phase. */++ if (meta == META_COND_RNUMBER)+ {+ code[1+LINK_SIZE] = OP_RREF;+ PUT2(code, 2 + LINK_SIZE, pptr[1]);+ skipunits = 1 + IMM2_SIZE;+ pptr += 1 + SIZEOFFSET;+ goto GROUP_PROCESS_NOTE_EMPTY;+ }++ if (meta_arg == 0)+ {+ code[1+LINK_SIZE] = (meta == META_COND_RNAME)? OP_RREF : OP_CREF;+ PUT2(code, 2 + LINK_SIZE, pptr[1]);+ skipunits = 1 + IMM2_SIZE;+ pptr += 1 + SIZEOFFSET;+ goto GROUP_PROCESS_NOTE_EMPTY;+ }++ ng = cb->named_groups + pptr[1];+ count = 0; /* Values for first pass (avoids compiler warning) */+ index = 0;++ /* The failed case is an internal error. */+ if (!PRIV(compile_find_dupname_details)(ng->name, ng->length, &index,+ &count, errorcodeptr, cb)) return 0;++ /* 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_DNRREF : OP_DNCREF;++ /* Insert appropriate data values. */+ PUT2(code, 2 + LINK_SIZE, index);+ PUT2(code, 2 + LINK_SIZE + IMM2_SIZE, count);+ skipunits = 1 + 2 * IMM2_SIZE;+ pptr += 1 + SIZEOFFSET;+ }++ PCRE2_ASSERT(meta != META_CAPTURE_NAME);+ 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;++ /* Point at initial ( for too many branches error */+ offset -= 2;+ 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_ASSERT_SCS)+ 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;+ named_group *ng;+ 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. */++ ng = PRIV(compile_find_named_group)(name, length, cb);++ if (ng == NULL)+ {+ /* If the name was not found we have a bad reference. */+ *errorcodeptr = ERR15;+ cb->erroroffset = offset;+ return 0;+ }++ 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 a back reference name is not duplicated, we can handle it as+ a numerical reference. */++ if ((ng->hash_dup & NAMED_GROUP_IS_DUPNAME) == 0)+ {+ 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 && !PRIV(compile_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);+ if ((options & PCRE2_CASELESS) != 0)+ *code++ = (((xoptions & PCRE2_EXTRA_CASELESS_RESTRICT) != 0)?+ REFI_FLAG_CASELESS_RESTRICT : 0) |+ (((xoptions & PCRE2_EXTRA_TURKISH_CASING) != 0)?+ REFI_FLAG_TURKISH_CASING : 0);+ }+ 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;++ /* 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. */++ PCRE2_ASSERT(previous != NULL);+ 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:+ case OP_ECLASS:+#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;++ /* 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, (int)length_prevgroup) ||+ OFLOW_MAX - *lengthptr < delta)+ {+ *errorcodeptr = ERR20;+ return 0;+ }+ *lengthptr += delta;+ }+ else for (int i = 0; i < replicate; i++)+ {+ memcpy(code, previous, CU2BYTES(length_prevgroup));+ previous = code;+ code += length_prevgroup;+ }++ /* 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. */+ {+ PCRE2_SIZE length = (lengthptr != NULL) ? 1 + LINK_SIZE : length_prevgroup;++ (void)memmove(previous + 1 + LINK_SIZE, previous, CU2BYTES(length));+ op_previous = *previous = OP_BRA;+ PUT(previous, 1, 1 + LINK_SIZE + length);+ previous[1 + LINK_SIZE + length] = OP_KET;+ PUT(previous, 2 + LINK_SIZE + length, 1 + LINK_SIZE + length);+ }+ code += 2 + 2 * LINK_SIZE;+ length_prevgroup += 2 + 2 * LINK_SIZE;+ group_return = -1; /* Set "may match empty string" */++ /* Now treat as a repeated OP_BRA. */+ PCRE2_FALLTHROUGH /* 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_ASSERT_SCS:+ 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:++ /* LCOV_EXCL_START */+ if (op_previous >= OP_EODN || op_previous <= OP_WORD_BOUNDARY)+ {+ PCRE2_DEBUG_UNREACHABLE();+ *errorcodeptr = ERR10; /* Not a character type - internal error */+ return 0;+ }+ /* LCOV_EXCL_STOP */++ {+ 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.+ You must also set op_type before the jump. */+ 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:+ case OP_ECLASS:+ 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);+ if ((options & PCRE2_CASELESS) != 0)+ *code++ = (((xoptions & PCRE2_EXTRA_CASELESS_RESTRICT) != 0)?+ REFI_FLAG_CASELESS_RESTRICT : 0) |+ (((xoptions & PCRE2_EXTRA_TURKISH_CASING) != 0)?+ REFI_FLAG_TURKISH_CASING : 0);++ /* 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;+ /* Repeat processing requires this information to+ determine the real length in pre-compile phase. */+ length_prevgroup = 1 + LINK_SIZE;++ if (META_CODE(pptr[1]) == META_OFFSET ||+ META_CODE(pptr[1]) == META_CAPTURE_NAME ||+ META_CODE(pptr[1]) == META_CAPTURE_NUMBER)+ {+ recurse_arguments *args;++ if (lengthptr != NULL)+ {+ if (!PRIV(compile_parse_recurse_args)(pptr, offset, errorcodeptr, cb))+ return 0;++ args = (recurse_arguments*)cb->last_data;+ length_prevgroup += (args->size * (1 + IMM2_SIZE));+ *lengthptr += (args->size * (1 + IMM2_SIZE));+ pptr += args->skip_size;+ }+ else+ {+ uint16_t *current, *end;++ args = (recurse_arguments*)cb->first_data;+ PCRE2_ASSERT(args != NULL && args->header.type == CDATA_RECURSE_ARGS);++ current = (uint16_t*)(args + 1);+ end = current + args->size;+ PCRE2_ASSERT(end > current);++ do+ {+ code[0] = OP_CREF;+ PUT2(code, 1, *current);+ code += 1 + IMM2_SIZE;+ }+ while (++current < end);++ length_prevgroup += (args->size * (1 + IMM2_SIZE));+ pptr += args->skip_size;+ cb->first_data = args->header.next;+ cb->cx->memctl.free(args, cb->cx->memctl.memory_data);+ }+ }++ 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;++ /* In caseless matching, particular characteristics Lu, Ll, and Lt get+ converted to the general characteristic L&. That is, upper, lower, and+ title case letters are all conflated. */++ if ((options & PCRE2_CASELESS) != 0 && ptype == PT_PC &&+ (pdata == ucp_Lu || pdata == ucp_Ll || pdata == ucp_Lt))+ {+ ptype = PT_LAMP;+ pdata = 0;+ }++ /* The special case of \p{Any} is compiled to OP_ALLANY and \P{Any}+ is compiled to [] so as to benefit from the auto-anchoring code. */++ if (ptype == PT_ANY)+ {+ if (meta_arg == ESC_P)+ {+ *code++ = OP_CLASS;+ memset(code, 0, 32);+ code += 32 / sizeof(PCRE2_UCHAR);+ }+ else+ *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;+ (void)utf; /* Avoid compiler warning. */+#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;+ PCRE2_FALLTHROUGH /* Fall through */++ case ESC_A:+ if (cb->max_lookbehind == 0) cb->max_lookbehind = 1;+ break;++ case ESC_K:+ cb->external_flags |= PCRE2_HASBSK; /* Record */+ 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:+ /* LCOV_EXCL_START */+ if (meta >= META_END)+ {+ PCRE2_DEBUG_UNREACHABLE();+ *errorcodeptr = ERR89; /* Internal error - unrecognized. */+ return 0;+ }+ /* LCOV_EXCL_STOP */++ /* 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. If the character is affected by the special Turkish rules,+ hardcode the matching characters using a caseset. */++#ifdef SUPPORT_UNICODE+ if ((utf||ucp) && (options & PCRE2_CASELESS) != 0)+ {+ uint32_t caseset;++ if ((xoptions & (PCRE2_EXTRA_TURKISH_CASING|PCRE2_EXTRA_CASELESS_RESTRICT)) ==+ PCRE2_EXTRA_TURKISH_CASING &&+ UCD_ANY_I(meta))+ {+ caseset = PRIV(ucd_turkish_dotted_i_caseset) + (UCD_DOTTED_I(meta)? 0 : 3);+ }+ else if ((caseset = UCD_CASESET(meta)) != 0 &&+ (xoptions & PCRE2_EXTRA_CASELESS_RESTRICT) != 0 &&+ PRIV(ucd_caseless_sets)[caseset] < 128)+ {+ caseset = 0; /* Ignore the caseless set if it's restricted. */+ }++ 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 */++/* LCOV_EXCL_START */+PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */+return 0; /* Avoid compiler warnings */+/* LCOV_EXCL_STOP */+}++++/*************************************************+* 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;+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;+ cb->erroroffset = 0;+ 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;+ uint32_t branchfirstcu = 0, branchreqcu = 0;+ uint32_t branchfirstcuflags = REQ_UNSET, branchreqcuflags = REQ_UNSET;++ /* Insert OP_REVERSE or OP_VREVERSE if this is a lookbehind assertion. There+ is only a single minimum length for the whole assertion. When the minimum+ 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)+ {+ uint32_t branch_length = (uint32_t)(code - last_branch);+ do+ {+ uint32_t 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, (uint32_t)(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++;+ }++/* LCOV_EXCL_START */+PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */+return 0; /* Avoid compiler warnings */+/* LCOV_EXCL_STOP */+}++++/*************************************************+* 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+ dotstar_anchor TRUE if automatic anchoring optimization is enabled++Returns: TRUE or FALSE+*/++static BOOL+is_anchored(PCRE2_SPTR code, uint32_t bracket_map, compile_block *cb,+ int atomcount, BOOL inassert, BOOL dotstar_anchor)+{+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, dotstar_anchor))+ 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, dotstar_anchor)) return FALSE;+ }++ /* Positive forward assertion */++ else if (op == OP_ASSERT || op == OP_ASSERT_NA)+ {+ if (!is_anchored(scode, bracket_map, cb, atomcount, TRUE, dotstar_anchor)) 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, dotstar_anchor))+ return FALSE;+ }++ /* Atomic groups */++ else if (op == OP_ONCE)+ {+ if (!is_anchored(scode, bracket_map, cb, atomcount + 1, inassert, dotstar_anchor))+ 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 || !dotstar_anchor)+ 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+ dotstar_anchor TRUE if automatic anchoring optimization is enabled++Returns: TRUE or FALSE+*/++static BOOL+is_startline(PCRE2_SPTR code, unsigned int bracket_map, compile_block *cb,+ int atomcount, BOOL inassert, BOOL dotstar_anchor)+{+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, dotstar_anchor))+ 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, dotstar_anchor))+ 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, dotstar_anchor))+ return FALSE;+ }++ /* Positive forward assertions */++ else if (op == OP_ASSERT || op == OP_ASSERT_NA)+ {+ if (!is_startline(scode, bracket_map, cb, atomcount, TRUE, dotstar_anchor))+ return FALSE;+ }++ /* Atomic brackets */++ else if (op == OP_ONCE)+ {+ if (!is_startline(scode, bracket_map, cb, atomcount + 1, inassert, dotstar_anchor))+ 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 || !dotstar_anchor)+ 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_UCHAR *+find_recurse(PCRE2_UCHAR *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. ECLASS is used for+ classes that use set operations internally. CALLOUT_STR is used for+ callouts with string arguments. In each case the length in the table is+ zero; the actual length is stored in the compiled code. */++ if (c == OP_XCLASS || c == OP_ECLASS) 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;+ PCRE2_FALLTHROUGH /* 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;+ PCRE2_FALLTHROUGH /* 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;+}++++/*************************************************+* 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;++ /* The parsed regex is malformed; we have reached the end and did+ not find the end of the construct which we are skipping over. */++ /* LCOV_EXCL_START */+ case META_END:+ PCRE2_DEBUG_UNREACHABLE();+ return NULL;+ /* LCOV_EXCL_STOP */++ /* 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:+ if (*pptr - META_ESCAPE == ESC_P || *pptr - META_ESCAPE == ESC_p)+ pptr += 1; /* Skip prop data */+ 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_SCS:+ 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];+ }++/* LCOV_EXCL_START */+PCRE2_UNREACHABLE(); /* Control never reaches here */+/* LCOV_EXCL_STOP */+}++++/*************************************************+* 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 min, max;+ uint32_t group = 0;+ uint32_t itemlength = 0;+ uint32_t itemminlength = 0;++ 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:+ case META_SCS:+ *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. Note that+ set_lookbehind_lengths() updates pptr, leaving it pointing to the final ket+ of the group, so no need to update it here. */++ 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;+ PCRE2_FALLTHROUGH /* Fall through */++ case META_RECURSE_BYNAME:+ {+ PCRE2_SPTR name;+ BOOL is_dupname = FALSE;+ named_group *ng;+ uint32_t meta_code = META_CODE(*pptr);+ uint32_t length = *(++pptr);++ GETPLUSOFFSET(offset, pptr);+ name = cb->start_pattern + offset;+ ng = PRIV(compile_find_named_group)(name, length, cb);++ if (ng == NULL)+ {+ *errcodeptr = ERR15; /* Non-existent subpattern */+ cb->erroroffset = offset;+ return -1;+ }++ group = ng->number;+ is_dupname = (ng->hash_dup & NAMED_GROUP_IS_DUPNAME) != 0;++ /* 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;+ }++ PCRE2_FALLTHROUGH /* 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);+ PCRE2_FALLTHROUGH /* 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;+ }+ PCRE2_FALLTHROUGH /* 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;++/* LCOV_EXCL_START */+PARSED_SKIP_FAILED:+PCRE2_DEBUG_UNREACHABLE();+*errcodeptr = ERR90; /* Unhandled META code - internal error */+return -1;+/* LCOV_EXCL_STOP */+}++++/*************************************************+* 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 ((PCRE2_SIZE)maxlength > cb->max_varlookbehind)+ {+ *errcodeptr = ERR100;+ cb->erroroffset = offset;+ return FALSE;+ }+ }+else gbptr[1] = 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))+ {+ /* The following erroroffset is a bogus but safe value. This branch should+ be avoided by providing a proper implementation for all supported cases+ below. */++ /* LCOV_EXCL_START */+ default:+ PCRE2_DEBUG_UNREACHABLE();+ cb->erroroffset = 0;+ return ERR70; /* Unrecognized meta code */+ /* LCOV_EXCL_STOP */++ case META_ESCAPE:+ if (*pptr - META_ESCAPE == ESC_P || *pptr - META_ESCAPE == ESC_p)+ pptr += 1; /* Skip prop data */+ 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_SCS:+ 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_OFFSET:+ 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:+ case META_CAPTURE_NAME:+ case META_CAPTURE_NUMBER:+ 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;++ /* Note that set_lookbehind_lengths() updates pptr, leaving it pointing to+ the final ket of the group, so no need to update it here. */++ 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 null_str[1] = { 0xcd }; /* Dummy for handling null inputs */+PCRE2_UCHAR *code; /* Current pointer in compiled code */+PCRE2_UCHAR *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 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 xoptions; /* Flags from context, modified */++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 */++/* Enable all optimizations by default. */+uint32_t optim_flags = ccontext != NULL ? ccontext->optimization_flags :+ PCRE2_OPTIMIZATION_ALL;++/* 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)+ {+ if (erroroffset != NULL) *erroroffset = 0;+ return NULL;+ }+if (erroroffset == NULL)+ {+ if (errorptr != NULL) *errorptr = ERR120;+ 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 = null_str;+ 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);+(void)zero_terminated; /* Silence compiler; only used if Valgrind enabled */++if (patlen > ccontext->max_pattern_length)+ {+ *errorptr = ERR88;+ return NULL;+ }++/* Optimization flags in 'options' can override those in the compile context.+This is because some options to disable optimizations were added before the+optimization flags word existed, and we need to continue supporting them+for backwards compatibility. */++if ((options & PCRE2_NO_AUTO_POSSESS) != 0)+ optim_flags &= ~PCRE2_OPTIM_AUTO_POSSESS;+if ((options & PCRE2_NO_DOTSTAR_ANCHOR) != 0)+ optim_flags &= ~PCRE2_OPTIM_DOTSTAR_ANCHOR;+if ((options & PCRE2_NO_START_OPTIMIZE) != 0)+ optim_flags &= ~PCRE2_OPTIM_START_OPTIMIZE;++/* 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;+cb.first_data = NULL;+cb.last_data = NULL;+#ifdef SUPPORT_WIDE_CHARS+cb.char_lists_size = 0;+#endif++/* 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++xoptions = ccontext->extra_options;+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++)+ {+ const pso *p = pso_list + i;++ if (patlen - skipatstart - 2 >= p->length &&+ PRIV(strncmp_c8)(ptr + skipatstart + 2, p->name, p->length) == 0)+ {+ uint32_t c, pp;++ skipatstart += p->length + 2;+ switch(p->type)+ {+ case PSO_OPT:+ cb.external_options |= p->value;+ break;++ case PSO_XOPT:+ xoptions |= 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;+ while (pp < patlen && IS_DIGIT(ptr[pp]))+ {+ if (c > UINT32_MAX / 10 - 1) break; /* Integer overflow */+ c = c*10 + (ptr[pp++] - CHAR_0);+ }+ if (pp >= patlen || pp == skipatstart || ptr[pp] != CHAR_RIGHT_PARENTHESIS)+ {+ errorcode = ERR60;+ ptr += pp;+ utf = FALSE; /* Used by HAD_EARLY_ERROR */+ 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;+ break;++ case PSO_OPTMZ:+ optim_flags &= ~(p->value);++ /* For backward compatibility the three original VERBs to disable+ optimizations need to also update the corresponding bit in the+ external options. */++ switch(p->value)+ {+ case PCRE2_OPTIM_AUTO_POSSESS:+ cb.external_options |= PCRE2_NO_AUTO_POSSESS;+ break;++ case PCRE2_OPTIM_DOTSTAR_ANCHOR:+ cb.external_options |= PCRE2_NO_DOTSTAR_ANCHOR;+ break;++ case PCRE2_OPTIM_START_OPTIMIZE:+ cb.external_options |= PCRE2_NO_START_OPTIMIZE;+ break;+ }++ break;++ /* LCOV_EXCL_START */+ default:+ /* All values in the enum need an explicit entry for this switch+ but until a better way to prevent coding mistakes is invented keep+ a catch all that triggers a debug build assert as a failsafe */+ PCRE2_DEBUG_UNREACHABLE();+ /* LCOV_EXCL_STOP */+ }+ break; /* Out of the table scan loop */+ }+ }+ if (i >= sizeof(pso_list)/sizeof(pso)) break; /* Out of pso loop */+ }+ PCRE2_ASSERT(skipatstart <= patlen);+ }++/* 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;+ }++/* PCRE2_EXTRA_TURKISH_CASING checks */++if ((xoptions & PCRE2_EXTRA_TURKISH_CASING) != 0)+ {+ if (!utf && !ucp)+ {+ errorcode = ERR104;+ goto HAD_EARLY_ERROR;+ }++#if PCRE2_CODE_UNIT_WIDTH == 8+ if (!utf)+ {+ errorcode = ERR105;+ goto HAD_EARLY_ERROR;+ }+#endif++ if ((xoptions & PCRE2_EXTRA_CASELESS_RESTRICT) != 0)+ {+ errorcode = ERR106;+ 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;++ /* LCOV_EXCL_START */+ default:+ PCRE2_DEBUG_UNREACHABLE();+ errorcode = ERR56;+ goto HAD_EARLY_ERROR;+ /* LCOV_EXCL_STOP */+ }++/* 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). */++/* Ensure that the parsed pattern buffer is big enough. For many smaller+patterns the vector on the stack (which was set up above) can be used. */++parsed_size_needed = max_parsed_pattern(ptr, cb.end_pattern, utf, options);++/* Allow for 2x uint32_t at the start and 2 at the end, for+PCRE2_EXTRA_MATCH_WORD or PCRE2_EXTRA_MATCH_LINE (which are exclusive). */++if ((ccontext->extra_options &+ (PCRE2_EXTRA_MATCH_WORD|PCRE2_EXTRA_MATCH_LINE)) != 0)+ parsed_size_needed += 4;++/* When PCRE2_AUTO_CALLOUT is set we allow for one callout at the end. */++if ((options & PCRE2_AUTO_CALLOUT) != 0)+ parsed_size_needed += 4;++parsed_size_needed += 1; /* For the final META_END */++if (parsed_size_needed > PARSED_PATTERN_DEFAULT_SIZE)+ {+ uint32_t *heap_parsed_pattern = ccontext->memctl.malloc(+ parsed_size_needed * 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;++/* Do the parsing scan. */++errorcode = parse_regex(ptr, cb.external_options, xoptions, &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, xoptions, &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 defined SUPPORT_WIDE_CHARS+PCRE2_ASSERT((cb.char_lists_size & 0x3) == 0);+if (length > MAX_PATTERN_SIZE ||+ MAX_PATTERN_SIZE - length < (cb.char_lists_size / sizeof(PCRE2_UCHAR)))+#else+if (length > MAX_PATTERN_SIZE)+#endif+ {+ errorcode = ERR20;+ cb.erroroffset = 0;+ 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 =+ CU2BYTES((PCRE2_SIZE)cb.names_found * (PCRE2_SIZE)cb.name_entry_size);++#if defined SUPPORT_WIDE_CHARS+if (cb.char_lists_size != 0)+ {+#if PCRE2_CODE_UNIT_WIDTH != 32+ /* Align to 32 bit first. This ensures the+ allocated area will also be 32 bit aligned. */+ re_blocksize = (PCRE2_SIZE)CLIST_ALIGN_TO(re_blocksize, sizeof(uint32_t));+#endif+ re_blocksize += cb.char_lists_size;+ }+#endif++re_blocksize += CU2BYTES(length);++if (re_blocksize > ccontext->max_pattern_compiled_length)+ {+ errorcode = ERR101;+ cb.erroroffset = 0;+ goto HAD_CB_ERROR;+ }++re_blocksize += sizeof(pcre2_real_code);+re = (pcre2_real_code *)+ ccontext->memctl.malloc(re_blocksize, ccontext->memctl.memory_data);+if (re == NULL)+ {+ errorcode = ERR21;+ cb.erroroffset = 0;+ 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->code_start = re_blocksize - CU2BYTES(length);+re->magic_number = MAGIC_NUMBER;+re->compile_options = options;+re->overall_options = cb.external_options;+re->extra_options = xoptions;+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;+re->optimization_flags = optim_flags;++/* The basic block is immediately followed by the name table, and the compiled+code follows after that. */++codestart = (PCRE2_UCHAR *)((uint8_t *)re + re->code_start);++/* 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;+#ifdef SUPPORT_WIDE_CHARS+cb.char_lists_size = 0;+#endif+++/* 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;+ uint32_t tablecount = 0;++ /* Length 0 represents duplicates, and they have already been handled. */+ for (i = 0; i < cb.names_found; i++, ng++)+ if (ng->length > 0)+ tablecount = PRIV(compile_add_name_to_table)(&cb, ng, tablecount);++ PCRE2_ASSERT(tablecount == cb.names_found);+ }++/* 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, re->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;+/* LCOV_EXCL_START */+if (usedlength > length)+ {+ PCRE2_DEBUG_UNREACHABLE();+ errorcode = ERR23; /* Overflow of code block - internal error */+ cb.erroroffset = 0;+ goto HAD_CB_ERROR;+ }+/* LCOV_EXCL_STOP */++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 = find_recurse(codestart, utf);+ rcode != NULL;+ rcode = 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);+ /* LCOV_EXCL_START */+ if (rgroup == NULL)+ {+ PCRE2_DEBUG_UNREACHABLE();+ errorcode = ERR53;+ break;+ }+ /* LCOV_EXCL_STOP */++ 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, (uint32_t)(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 && (optim_flags & PCRE2_OPTIM_AUTO_POSSESS) != 0)+ {+ PCRE2_UCHAR *temp = (PCRE2_UCHAR *)codestart;+ int possessify_rc = PRIV(auto_possessify)(temp, &cb);+ /* LCOV_EXCL_START */+ if (possessify_rc != 0)+ {+ PCRE2_DEBUG_UNREACHABLE();+ errorcode = ERR80;+ cb.erroroffset = 0;+ }+ /* LCOV_EXCL_STOP */+ }++/* 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)+ {+ BOOL dotstar_anchor = ((optim_flags & PCRE2_OPTIM_DOTSTAR_ANCHOR) != 0);+ if (is_anchored(codestart, 0, &cb, 0, FALSE, dotstar_anchor))+ 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_OPTIM_START_OPTIMIZE+is disabled, 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 ((optim_flags & PCRE2_OPTIM_START_OPTIMIZE) != 0)+ {+ int minminlength = 0; /* For minimal minlength from first/required CU */+ int study_rc;++ /* 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) {+ uint32_t assertedcuflags = 0;+ uint32_t assertedcu = find_firstassertedcu(codestart, &assertedcuflags, 0);+ /* It would be wrong to use the asserted first code unit as `firstcu` for+ * regexes which are able to match a 1-character string (e.g. /(?=a)b?a/)+ * For that example, if we set both firstcu and reqcu to 'a', it would mean+ * the subject string needs to be at least 2 characters long, which is wrong.+ * With more analysis, we would be able to set firstcu in more cases. */+ if (assertedcuflags < REQ_NONE && assertedcu != reqcu) {+ firstcu = assertedcu;+ firstcuflags = assertedcuflags;+ }+ }++ /* 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, code units in the range 128-255 are introductory code+ units 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)+ {+ BOOL dotstar_anchor = ((optim_flags & PCRE2_OPTIM_DOTSTAR_ANCHOR) != 0);+ if (is_startline(codestart, 0, &cb, 0, FALSE, dotstar_anchor))+ 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. */++ study_rc = PRIV(study)(re);+ /* LCOV_EXCL_START */+ if (study_rc != 0)+ {+ PCRE2_DEBUG_UNREACHABLE();+ errorcode = ERR31;+ cb.erroroffset = 0;+ goto HAD_CB_ERROR;+ }+ /* LCOV_EXCL_STOP */++ /* 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. */++#ifdef SUPPORT_UNICODE+/* All items must be freed. */+PCRE2_ASSERT(cb.first_data == NULL);+#endif++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:+/* Ensure we don't return out-of-range erroroffset. */+PCRE2_ASSERT(ptr >= pattern);+PCRE2_ASSERT(ptr <= (pattern + patlen));+/* Ensure that the erroroffset never slices a UTF-encoded character in half.+If the input is invalid, then we return an offset just before the first invalid+character, so the text to the left of the offset must always be valid. */+#if defined PCRE2_DEBUG && defined SUPPORT_UNICODE+if (ptr > pattern && utf)+ {+ PCRE2_SPTR prev = ptr - 1;+ PCRE2_SIZE dummyoffset;+ BACKCHAR(prev);+ PCRE2_ASSERT(prev >= pattern);+ PCRE2_ASSERT(PRIV(valid_utf)(prev, ptr - prev, &dummyoffset) == 0);+ }+#endif+*erroroffset = ptr - pattern;++HAD_ERROR:+*errorptr = errorcode;+pcre2_code_free(re);+re = NULL;++if (cb.first_data != NULL)+ {+ compile_data* current_data = cb.first_data;+ do+ {+ compile_data* next_data = current_data->next;+ cb.cx->memctl.free(current_data, cb.cx->memctl.memory_data);+ current_data = next_data;+ }+ while (current_data != NULL);+ }+ goto EXIT; }
+ src/c/pcre2/src/pcre2_compile.h view
@@ -0,0 +1,356 @@+/*************************************************+* Perl-Compatible Regular Expressions *+*************************************************/++/* PCRE2 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+ Original API code Copyright (c) 1997-2012 University of Cambridge+ 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.+-----------------------------------------------------------------------------+*/++#ifndef PCRE2_COMPILE_H_IDEMPOTENT_GUARD+#define PCRE2_COMPILE_H_IDEMPOTENT_GUARD++#include "pcre2_internal.h"++/* 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, ERR102, ERR103, ERR104, ERR105, ERR106, ERR107, ERR108, ERR109, ERR110,+ ERR111, ERR112, ERR113, ERR114, ERR115, ERR116, ERR117, ERR118, ERR119, ERR120 };++/* 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) 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_OFFSET 0x80160000u /* Setting offset for various META+ codes (e.g. META_CAPTURE_NAME) */+#define META_SCS 0x80170000u /* (*scan_substring:... */+#define META_CAPTURE_NAME 0x80180000u /* Next <name> in capture lists */+#define META_CAPTURE_NUMBER 0x80190000u /* Next digits in capture lists */+#define META_DOLLAR 0x801a0000u /* $ metacharacter */+#define META_DOT 0x801b0000u /* . metacharacter */+#define META_ESCAPE 0x801c0000u /* \d and friends */+#define META_KET 0x801d0000u /* closing parenthesis */+#define META_NOCAPTURE 0x801e0000u /* no capture parens */+#define META_OPTIONS 0x801f0000u /* (?i) and friends */+#define META_POSIX 0x80200000u /* POSIX class item */+#define META_POSIX_NEG 0x80210000u /* negative POSIX class item */+#define META_RANGE_ESCAPED 0x80220000u /* range with at least one escape */+#define META_RANGE_LITERAL 0x80230000u /* range defined literally */+#define META_RECURSE 0x80240000u /* Recursion */+#define META_RECURSE_BYNAME 0x80250000u /* (?&name) */+#define META_SCRIPT_RUN 0x80260000u /* (*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 0x80270000u /* (?= */+#define META_LOOKAHEADNOT 0x80280000u /* (?! */+#define META_LOOKBEHIND 0x80290000u /* (?<= */+#define META_LOOKBEHINDNOT 0x802a0000u /* (?<! */++/* These cannot be conditions */++#define META_LOOKAHEAD_NA 0x802b0000u /* (*napla: */+#define META_LOOKBEHIND_NA 0x802c0000u /* (*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 0x802d0000u /* (*MARK) */+#define META_ACCEPT 0x802e0000u /* (*ACCEPT) */+#define META_FAIL 0x802f0000u /* (*FAIL) */+#define META_COMMIT 0x80300000u /* These */+#define META_COMMIT_ARG 0x80310000u /* pairs */+#define META_PRUNE 0x80320000u /* must */+#define META_PRUNE_ARG 0x80330000u /* be */+#define META_SKIP 0x80340000u /* kept */+#define META_SKIP_ARG 0x80350000u /* in */+#define META_THEN 0x80360000u /* this */+#define META_THEN_ARG 0x80370000u /* order */++/* These must be kept in groups of adjacent 3 values, and all together. */++#define META_ASTERISK 0x80380000u /* * */+#define META_ASTERISK_PLUS 0x80390000u /* *+ */+#define META_ASTERISK_QUERY 0x803a0000u /* *? */+#define META_PLUS 0x803b0000u /* + */+#define META_PLUS_PLUS 0x803c0000u /* ++ */+#define META_PLUS_QUERY 0x803d0000u /* +? */+#define META_QUERY 0x803e0000u /* ? */+#define META_QUERY_PLUS 0x803f0000u /* ?+ */+#define META_QUERY_QUERY 0x80400000u /* ?? */+#define META_MINMAX 0x80410000u /* {n,m} repeat */+#define META_MINMAX_PLUS 0x80420000u /* {n,m}+ repeat */+#define META_MINMAX_QUERY 0x80430000u /* {n,m}? repeat */++/* These meta codes must be kept in a group, with the OR/SUB/XOR in+this order, and AND/NOT at the start/end. */++#define META_ECLASS_AND 0x80440000u /* && (or &) in a class */+#define META_ECLASS_OR 0x80450000u /* || (or |, +) in a class */+#define META_ECLASS_SUB 0x80460000u /* -- (or -) in a class */+#define META_ECLASS_XOR 0x80470000u /* ~~ (or ^) in a class */+#define META_ECLASS_NOT 0x80480000u /* ! in a class */++/* Convenience aliases. */++#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 alphabetic 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++/* 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)++/* 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++#ifdef PCRE2_DEBUG+/* Compile data types. */+#define CDATA_RECURSE_ARGS 0 /* Argument list for recurse */+#define CDATA_CRANGE 1 /* Character range list */+#endif++/* Extended class management flags. */++#define CLASS_IS_ECLASS 0x1++/* Macro for the highest character value. */++#if PCRE2_CODE_UNIT_WIDTH == 8+#define MAX_UCHAR_VALUE 0xffu+#elif PCRE2_CODE_UNIT_WIDTH == 16+#define MAX_UCHAR_VALUE 0xffffu+#else+#define MAX_UCHAR_VALUE 0xffffffffu+#endif++#define GET_MAX_CHAR_VALUE(utf) \+ ((utf) ? MAX_UTF_CODE_POINT : MAX_UCHAR_VALUE)++/* Macro for setting individual bits in class bitmaps. */++#define SETBIT(a,b) a[(b) >> 3] |= (uint8_t)(1u << ((b) & 0x7))++/* Macro for 8 bit specific checks. */+#if PCRE2_CODE_UNIT_WIDTH == 8+#define SELECT_VALUE8(value8, value) (value8)+#else+#define SELECT_VALUE8(value8, value) (value)+#endif++/* Macro for aligning data. */+#define CLIST_ALIGN_TO(base, align) \+ ((base + ((size_t)(align) - 1)) & ~((size_t)(align) - 1))++/* Structure for holding information about an OP_ECLASS internal operand.+An "operand" here could be just a single OP_[X]CLASS, or it could be some+complex expression; but it's some sequence of ECL_* codes which pushes one+value to the stack. */+typedef struct {+ /* The position of the operand - or NULL if (lengthptr != NULL). */+ PCRE2_UCHAR *code_start;+ PCRE2_SIZE length;+ /* The operand's type if it is a single code (ECL_XCLASS, ECL_ANY, ECL_NONE);+ otherwise zero if the operand is not atomic. */+ uint8_t op_single_type;+ /* Regardless of whether it's a single code or not, we fully constant-fold+ the bitmap for code points < 256. */+ class_bits_storage bits;+} eclass_op_info;++/* Macros for the definitions below, to prevent name collisions. */++#define _pcre2_posix_class_maps PCRE2_SUFFIX(_pcre2_posix_class_maps)+#define _pcre2_update_classbits PCRE2_SUFFIX(_pcre2_update_classbits_)+#define _pcre2_compile_class_nested PCRE2_SUFFIX(_pcre2_compile_class_nested_)+#define _pcre2_compile_class_not_nested PCRE2_SUFFIX(_pcre2_compile_class_not_nested_)+#define _pcre2_compile_get_hash_from_name PCRE2_SUFFIX(_pcre2_compile_get_hash_from_name)+#define _pcre2_compile_find_named_group PCRE2_SUFFIX(_pcre2_compile_find_named_group)+#define _pcre2_compile_find_dupname_details PCRE2_SUFFIX(_pcre2_compile_find_dupname_details)+#define _pcre2_compile_add_name_to_table PCRE2_SUFFIX(_pcre2_compile_add_name_to_table)+#define _pcre2_compile_parse_scan_substr_args PCRE2_SUFFIX(_pcre2_compile_parse_scan_substr_args)+#define _pcre2_compile_parse_recurse_args PCRE2_SUFFIX(_pcre2_compile_parse_recurse_args)+++/* Indices of the POSIX classes in posix_names, posix_name_lengths,+posix_class_maps, and posix_substitutes. They must be kept in sync. */++#define PC_DIGIT 7+#define PC_GRAPH 8+#define PC_PRINT 9+#define PC_PUNCT 10+#define PC_XDIGIT 13++extern const int PRIV(posix_class_maps)[];++/* Defines for hash_dup member in named_group structure. */++#define NAMED_GROUP_HASH_MASK ((uint16_t)0x7fff)+#define NAMED_GROUP_IS_DUPNAME ((uint16_t)0x8000)++#define NAMED_GROUP_GET_HASH(ng) ((ng)->hash_dup & NAMED_GROUP_HASH_MASK)++/* Exported functions from pcre2_compile_class.c file: */++/* Set bits in classbits according to the property type */++void PRIV(update_classbits)(uint32_t ptype, uint32_t pdata, BOOL negated,+ uint8_t *classbits);++/* Compile the META codes from start_ptr...end_ptr, writing a single OP_CLASS+OP_CLASS, OP_NCLASS, OP_XCLASS, or OP_ALLANY into pcode. */++uint32_t *PRIV(compile_class_not_nested)(uint32_t options, uint32_t xoptions,+ uint32_t *start_ptr, PCRE2_UCHAR **pcode, BOOL negate_class, BOOL* has_bitmap,+ int *errorcodeptr, compile_block *cb, PCRE2_SIZE *lengthptr);++/* Compile the META codes in pptr into opcodes written to pcode. The pptr must+start at a META_CLASS or META_CLASS_NOT.++The pptr will be left pointing at the matching META_CLASS_END. */++BOOL PRIV(compile_class_nested)(uint32_t options, uint32_t xoptions,+ uint32_t **pptr, PCRE2_UCHAR **pcode, int *errorcodeptr,+ compile_block *cb, PCRE2_SIZE *lengthptr);++/* Exported functions from pcre2_compile_cgroup.c file: */++/* Compute hash from a capture name. */++uint16_t PRIV(compile_get_hash_from_name)(PCRE2_SPTR name, uint32_t length);++/* Get the descriptor of a known named capture. */++named_group *PRIV(compile_find_named_group)(PCRE2_SPTR name,+ uint32_t length, compile_block *cb);++/* Add entires to name table in alphabetical order. */++uint32_t PRIV(compile_add_name_to_table)(compile_block *cb,+ named_group *ng, uint32_t tablecount);++/* Searches the properties of duplicated names, and returns them+in indexptr and countptr. */++BOOL PRIV(compile_find_dupname_details)(PCRE2_SPTR name, uint32_t length,+ int *indexptr, int *countptr, int *errorcodeptr, compile_block *cb);++/* Parse the arguments of recurse operations. */++uint32_t * PRIV(compile_parse_scan_substr_args)(uint32_t *pptr,+ int *errorcodeptr, compile_block *cb, PCRE2_SIZE *lengthptr);++/* Parse the arguments of recurse operations. */++BOOL PRIV(compile_parse_recurse_args)(uint32_t *pptr_start,+ PCRE2_SIZE offset, int *errorcodeptr, compile_block *cb);++#endif /* PCRE2_COMPILE_H_IDEMPOTENT_GUARD */++/* End of pcre2_compile.h */
+ src/c/pcre2/src/pcre2_compile_cgroup.c view
@@ -0,0 +1,632 @@+/*************************************************+* 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+ Original API code Copyright (c) 1997-2012 University of Cambridge+ 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.+-----------------------------------------------------------------------------+*/+++#include "pcre2_compile.h"++/*************************************************+* Compute the hash code from a capture name *+*************************************************/++/* This function returns with a simple hash code+computed from the name of a capture group.++Arguments:+ name name of the capture group+ length the length of the name++Returns: hash code+*/++uint16_t+PRIV(compile_get_hash_from_name)(PCRE2_SPTR name, uint32_t length)+{+uint16_t hash;++PCRE2_ASSERT(length > 0);++hash = (uint16_t)((name[0] & 0x7f) | ((name[length - 1] & 0xff) << 7));+PCRE2_ASSERT(hash <= NAMED_GROUP_HASH_MASK);+return hash;+}+++/*************************************************+* Get the descriptor of a known named capture *+*************************************************/++/* This function returns the descriptor in the+named group list of a known capture group.++Arguments:+ name name of the capture group+ length the length of the name++Returns: pointer to the descriptor when found,+ NULL otherwise+ */++named_group *+PRIV(compile_find_named_group)(PCRE2_SPTR name,+ uint32_t length, compile_block *cb)+{+uint16_t hash = PRIV(compile_get_hash_from_name)(name, length);+named_group *ng;+named_group *end = cb->named_groups + cb->names_found;++for (ng = cb->named_groups; ng < end; ng++)+ if (length == ng->length && hash == NAMED_GROUP_GET_HASH(ng) &&+ PRIV(strncmp)(name, ng->name, length) == 0) return ng;++return NULL;+}+++/*************************************************+* 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+ nb named group entry+ tablecount the count of names in the table so far++Returns: new tablecount+*/++uint32_t+PRIV(compile_add_name_to_table)(compile_block *cb,+ named_group *ng, uint32_t tablecount)+{+uint32_t i;+PCRE2_SPTR name = ng->name;+int length = ng->length;+uint32_t duplicate_count = 1;++PCRE2_UCHAR *slot = cb->name_table;++PCRE2_ASSERT(length > 0);++if ((ng->hash_dup & NAMED_GROUP_IS_DUPNAME) != 0)+ {+ named_group *ng_it;+ named_group *end = cb->named_groups + cb->names_found;++ for (ng_it = ng + 1; ng_it < end; ng_it++)+ if (ng_it->name == name) duplicate_count++;+ }++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 * duplicate_count, slot,+ CU2BYTES((tablecount - i) * cb->name_entry_size));+ break;+ }++ /* Continue the loop for a later or duplicate name */++ slot += cb->name_entry_size;+ }++tablecount += duplicate_count;++while (TRUE)+ {+ PUT2(slot, 0, ng->number);+ 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));++ if (--duplicate_count == 0) break;++ while (TRUE)+ {+ ++ng;+ if (ng->name == name) break;+ }++ slot += cb->name_entry_size;+ }++return tablecount;+}+++/*************************************************+* 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+*/++BOOL+PRIV(compile_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. */++/* LCOV_EXCL_START */+if (i >= cb->names_found)+ {+ PCRE2_DEBUG_UNREACHABLE();+ *errorcodeptr = ERR53;+ cb->erroroffset = name - cb->start_pattern;+ return FALSE;+ }+/* LCOV_EXCL_STOP */++/* 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;+}+++/* Process the capture list of scan substring and recurse+operations. Since at least one argument must be present,+a 0 return value represents error. */++static size_t+PRIV(compile_process_capture_list)(uint32_t *pptr, PCRE2_SIZE offset,+ int *errorcodeptr, compile_block *cb)+{+size_t i, size = 0;+named_group *ng;+PCRE2_SPTR name;+uint32_t length;+named_group *end = cb->named_groups + cb->names_found;++while (TRUE)+ {+ ++pptr;++ switch (META_CODE(*pptr))+ {+ case META_OFFSET:+ GETPLUSOFFSET(offset, pptr);+ continue;++ case META_CAPTURE_NAME:+ offset += META_DATA(*pptr);+ length = *(++pptr);+ name = cb->start_pattern + offset;++ ng = PRIV(compile_find_named_group)(name, length, cb);++ if (ng == NULL)+ {+ *errorcodeptr = ERR15;+ cb->erroroffset = offset;+ return 0;+ }++ if ((ng->hash_dup & NAMED_GROUP_IS_DUPNAME) == 0)+ {+ pptr[-1] = META_CAPTURE_NUMBER;+ pptr[0] = ng->number;+ size++;+ continue;+ }++ /* Remains only for duplicated names. */+ pptr[-1] = META_CAPTURE_NAME;+ pptr[0] = (uint32_t)(ng - cb->named_groups);+ size++;+ name = ng->name;++ while (++ng < end)+ if (ng->name == name) size++;+ continue;++ case META_CAPTURE_NUMBER:+ offset += META_DATA(*pptr);++ i = *(++pptr);+ if (i > cb->bracount)+ {+ *errorcodeptr = ERR15;+ cb->erroroffset = offset;+ return 0;+ }+ if (i > cb->top_backref) cb->top_backref = (uint16_t)i;+ size++;+ continue;++ default:+ break;+ }++ PCRE2_ASSERT(size > 0);+ return size;+ }+}+++/*******************************************************+* Parse the arguments of scan substring operations *+********************************************************/++/* This function parses the arguments of scan substring operations.++Arguments:+ pptr_start points to the current parsed pattern pointer+ offset argument starting offset in the pattern+ errorcodeptr where to put an error code+ cb the compile block+ lengthptr NULL during the real compile phase+ points to length accumulator during pre-compile phase++Returns: TRUE if OK, FALSE if not, error code set+*/++uint32_t *+PRIV(compile_parse_scan_substr_args)(uint32_t *pptr,+ int *errorcodeptr, compile_block *cb, PCRE2_SIZE *lengthptr)+{+uint8_t *captures;+uint8_t *capture_ptr;+uint8_t bit;+PCRE2_SPTR name;+named_group *ng;+named_group *end = cb->named_groups + cb->names_found;+BOOL all_found;+size_t size;++PCRE2_ASSERT(*pptr == META_OFFSET);+if (PRIV(compile_process_capture_list)(pptr - 1, 0, errorcodeptr, cb) == 0)+ return NULL;++/* Align to bytes. Since the highest capture can+be equal to bracount, +1 is added before the aligning. */+size = (cb->bracount + 1 + 7) >> 3;+captures = (uint8_t*)cb->cx->memctl.malloc(size, cb->cx->memctl.memory_data);+if (captures == NULL)+ {+ *errorcodeptr = ERR21;+ READPLUSOFFSET(cb->erroroffset, pptr);+ return NULL;+ }++memset(captures, 0, size);++while (TRUE)+ {+ switch (META_CODE(*pptr))+ {+ case META_OFFSET:+ pptr++;+ SKIPOFFSET(pptr);+ continue;++ case META_CAPTURE_NAME:+ ng = cb->named_groups + pptr[1];+ PCRE2_ASSERT((ng->hash_dup & NAMED_GROUP_IS_DUPNAME) != 0);+ pptr += 2;+ name = ng->name;++ all_found = TRUE;+ do+ {+ if (ng->name != name) continue;++ capture_ptr = captures + (ng->number >> 3);+ PCRE2_ASSERT(capture_ptr < captures + size);+ bit = (uint8_t)(1 << (ng->number & 0x7));++ if ((*capture_ptr & bit) == 0)+ {+ *capture_ptr |= bit;+ all_found = FALSE;+ }+ }+ while (++ng < end);++ if (!all_found)+ {+ *lengthptr += 1 + 2 * IMM2_SIZE;+ continue;+ }++ pptr[-2] = META_CAPTURE_NUMBER;+ pptr[-1] = 0;+ continue;++ case META_CAPTURE_NUMBER:+ pptr += 2;++ capture_ptr = captures + (pptr[-1] >> 3);+ PCRE2_ASSERT(capture_ptr < captures + size);+ bit = (uint8_t)(1 << (pptr[-1] & 0x7));++ if ((*capture_ptr & bit) != 0)+ {+ pptr[-1] = 0;+ continue;+ }++ *capture_ptr |= bit;+ *lengthptr += 1 + IMM2_SIZE;+ continue;++ default:+ break;+ }++ break;+ }++cb->cx->memctl.free(captures, cb->cx->memctl.memory_data);+return pptr - 1;+}+++/* Implement heapsort heapify algorithm. */++static void do_heapify_u16(uint16_t *captures, size_t size, size_t i)+{+size_t max;+size_t left;+size_t right;+uint16_t tmp;++while (TRUE)+ {+ max = i;+ left = (i << 1) + 1;+ right = left + 1;++ if (left < size && captures[left] > captures[max]) max = left;+ if (right < size && captures[right] > captures[max]) max = right;+ if (i == max) return;++ tmp = captures[i];+ captures[i] = captures[max];+ captures[max] = tmp;+ i = max;+ }+}+++/*************************************************+* Parse the arguments of recurse operations *+*************************************************/++/* This function parses the arguments of recurse operations.++Arguments:+ pptr_start the current parsed pattern pointer+ offset argument starting offset in the pattern+ errorcodeptr where to put an error code+ cb the compile block+ lengthptr NULL during the real compile phase+ points to length accumulator during pre-compile phase++Returns: TRUE if OK, FALSE if not, error code set+*/++BOOL+PRIV(compile_parse_recurse_args)(uint32_t *pptr_start,+ PCRE2_SIZE offset, int *errorcodeptr, compile_block *cb)+{+uint32_t *pptr = pptr_start;+size_t i, size;+PCRE2_SPTR name;+named_group *ng;+named_group *end = cb->named_groups + cb->names_found;+recurse_arguments *args;+uint16_t *captures;+uint16_t *current;+uint16_t *captures_end;+uint16_t tmp;++/* Process all arguments, compute the required size. */++size = PRIV(compile_process_capture_list)(pptr, offset, errorcodeptr, cb);+if (size == 0) return FALSE;++args = cb->cx->memctl.malloc(+ sizeof(recurse_arguments) + size * sizeof(uint16_t), cb->cx->memctl.memory_data);++if (args == NULL)+ {+ *errorcodeptr = ERR21;+ cb->erroroffset = offset;+ return FALSE;+ }++args->header.next = NULL;+#ifdef PCRE2_DEBUG+args->header.type = CDATA_RECURSE_ARGS;+#endif+args->size = size;++/* Caching the pre-processed capture list. */+if (cb->last_data != NULL)+ cb->last_data->next = &args->header;+else+ cb->first_data = &args->header;++cb->last_data = &args->header;++/* Create the capture list size. */++captures = (uint16_t*)(args + 1);++while (TRUE)+ {+ ++pptr;++ switch (META_CODE(*pptr))+ {+ case META_OFFSET:+ SKIPOFFSET(pptr);+ continue;++ case META_CAPTURE_NAME:+ ng = cb->named_groups + *(++pptr);+ PCRE2_ASSERT((ng->hash_dup & NAMED_GROUP_IS_DUPNAME) != 0);+ *captures++ = (uint16_t)(ng->number);++ name = ng->name;++ while (++ng < end)+ if (ng->name == name) *captures++ = (uint16_t)(ng->number);+ continue;++ case META_CAPTURE_NUMBER:+ *captures++ = *(++pptr);+ continue;++ default:+ break;+ }++ break;+ }++PCRE2_ASSERT(size == (size_t)(captures - (uint16_t*)(args + 1)));+args->skip_size = (size_t)(pptr - pptr_start) - 1;++if (size == 1) return TRUE;++/* Sort captures. */++captures = (uint16_t*)(args + 1);+i = (size >> 1) - 1;+while (TRUE)+ {+ do_heapify_u16(captures, size, i);+ if (i == 0) break;+ i--;+ }++for (i = size - 1; i > 0; i--)+ {+ tmp = captures[0];+ captures[0] = captures[i];+ captures[i] = tmp;++ do_heapify_u16(captures, i, 0);+ }++/* Remove duplicates. */++captures_end = captures + size;+tmp = *captures++;+current = captures;++while (current < captures_end)+ {+ if (*current != tmp)+ {+ tmp = *current;+ *captures++ = tmp;+ }++ current++;+ }++args->size = (size_t)(captures - (uint16_t*)(args + 1));+return TRUE;+}++/* End of pcre2_compile_cgroup.c */
+ src/c/pcre2/src/pcre2_compile_class.c view
@@ -0,0 +1,2769 @@+/*************************************************+* 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+ Original API code Copyright (c) 1997-2012 University of Cambridge+ 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.+-----------------------------------------------------------------------------+*/+++#include "pcre2_compile.h"++++typedef struct {+ /* Option bits for eclass. */+ uint32_t options;+ uint32_t xoptions;+ /* Rarely used members. */+ int *errorcodeptr;+ compile_block *cb;+ /* Bitmap is needed. */+ BOOL needs_bitmap;+} eclass_context;++/* Checks the allowed tokens at the end of a class structure in debug mode.+When a new token is not processed by all loops, and the token is equals to+a) one of the cases here:+ the compiler will complain about a duplicated case value.+b) none of the cases here:+ the loop without the handler will stop with an assertion failure. */++#ifdef PCRE2_DEBUG+#define CLASS_END_CASES(meta) \+ default: \+ PCRE2_ASSERT((meta) <= META_END); \+ PCRE2_FALLTHROUGH /* Fall through */ \+ case META_CLASS: \+ case META_CLASS_NOT: \+ case META_CLASS_EMPTY: \+ case META_CLASS_EMPTY_NOT: \+ case META_CLASS_END: \+ case META_ECLASS_AND: \+ case META_ECLASS_OR: \+ case META_ECLASS_SUB: \+ case META_ECLASS_XOR: \+ case META_ECLASS_NOT:+#else+#define CLASS_END_CASES(meta) \+ default:+#endif++#ifdef SUPPORT_WIDE_CHARS++/* Heapsort algorithm. */++static void do_heapify(uint32_t *buffer, size_t size, size_t i)+{+size_t max;+size_t left;+size_t right;+uint32_t tmp1, tmp2;++while (TRUE)+ {+ max = i;+ left = (i << 1) + 2;+ right = left + 2;++ if (left < size && buffer[left] > buffer[max]) max = left;+ if (right < size && buffer[right] > buffer[max]) max = right;+ if (i == max) return;++ /* Swap items. */+ tmp1 = buffer[i];+ tmp2 = buffer[i + 1];+ buffer[i] = buffer[max];+ buffer[i + 1] = buffer[max + 1];+ buffer[max] = tmp1;+ buffer[max + 1] = tmp2;+ i = max;+ }+}++#ifdef SUPPORT_UNICODE++#define PARSE_CLASS_UTF 0x1+#define PARSE_CLASS_CASELESS_UTF 0x2+#define PARSE_CLASS_RESTRICTED_UTF 0x4+#define PARSE_CLASS_TURKISH_UTF 0x8++/* Get the range of nocase characters which includes the+'c' character passed as argument, or directly follows 'c'. */++static const uint32_t*+get_nocase_range(uint32_t c)+{+uint32_t left = 0;+uint32_t right = PRIV(ucd_nocase_ranges_size);+uint32_t middle;++if (c > MAX_UTF_CODE_POINT) return PRIV(ucd_nocase_ranges) + right;++while (TRUE)+ {+ /* Range end of the middle element. */+ middle = ((left + right) >> 1) | 0x1;++ if (PRIV(ucd_nocase_ranges)[middle] <= c)+ left = middle + 1;+ else if (middle > 1 && PRIV(ucd_nocase_ranges)[middle - 2] > c)+ right = middle - 1;+ else+ return PRIV(ucd_nocase_ranges) + (middle - 1);+ }+}++/* Get the list of othercase characters, which belongs to the passed range.+Create ranges from these characters, and append them to the buffer argument. */++static size_t+utf_caseless_extend(uint32_t start, uint32_t end, uint32_t options,+ uint32_t *buffer)+{+uint32_t new_start = start;+uint32_t new_end = end;+uint32_t c = start;+const uint32_t *list;+uint32_t tmp[3];+size_t result = 2;+const uint32_t *skip_range = get_nocase_range(c);+uint32_t skip_start = skip_range[0];++#if PCRE2_CODE_UNIT_WIDTH == 8+PCRE2_ASSERT(options & PARSE_CLASS_UTF);+#endif++#if PCRE2_CODE_UNIT_WIDTH == 32+if (end > MAX_UTF_CODE_POINT) end = MAX_UTF_CODE_POINT;+#endif++while (c <= end)+ {+ uint32_t co;++ if (c > skip_start)+ {+ c = skip_range[1];+ skip_range += 2;+ skip_start = skip_range[0];+ continue;+ }++ /* Compute caseless set. */++ if ((options & (PARSE_CLASS_TURKISH_UTF|PARSE_CLASS_RESTRICTED_UTF)) ==+ PARSE_CLASS_TURKISH_UTF &&+ UCD_ANY_I(c))+ {+ co = PRIV(ucd_turkish_dotted_i_caseset) + (UCD_DOTTED_I(c)? 0 : 3);+ }+ else if ((co = UCD_CASESET(c)) != 0 &&+ (options & PARSE_CLASS_RESTRICTED_UTF) != 0 &&+ PRIV(ucd_caseless_sets)[co] < 128)+ {+ co = 0; /* Ignore the caseless set if it's restricted. */+ }++ if (co != 0)+ list = PRIV(ucd_caseless_sets) + co;+ else+ {+ co = UCD_OTHERCASE(c);+ list = tmp;+ tmp[0] = c;+ tmp[1] = NOTACHAR;++ if (co != c)+ {+ tmp[1] = co;+ tmp[2] = NOTACHAR;+ }+ }+ c++;++ /* Add characters. */+ do+ {+#if PCRE2_CODE_UNIT_WIDTH == 16+ if (!(options & PARSE_CLASS_UTF) && *list > 0xffff) continue;+#endif++ if (*list < new_start)+ {+ if (*list + 1 == new_start)+ {+ new_start--;+ continue;+ }+ }+ else if (*list > new_end)+ {+ if (*list - 1 == new_end)+ {+ new_end++;+ continue;+ }+ }+ else continue;++ result += 2;+ if (buffer != NULL)+ {+ buffer[0] = *list;+ buffer[1] = *list;+ buffer += 2;+ }+ }+ while (*(++list) != NOTACHAR);+ }++ if (buffer != NULL)+ {+ buffer[0] = new_start;+ buffer[1] = new_end;+ buffer += 2;+ (void)buffer;+ }+ return result;+}++#endif++/* Add a character list to a buffer. */++static size_t+append_char_list(const uint32_t *p, uint32_t *buffer)+{+const uint32_t *n;+size_t result = 0;++while (*p != NOTACHAR)+ {+ n = p;+ while (n[0] == n[1] - 1) n++;++ PCRE2_ASSERT(*p < 0xffff);++ if (buffer != NULL)+ {+ buffer[0] = *p;+ buffer[1] = *n;+ buffer += 2;+ }++ result += 2;+ p = n + 1;+ }++ return result;+}++static uint32_t+get_highest_char(uint32_t options)+{+(void)options; /* Avoid compiler warning. */++#if PCRE2_CODE_UNIT_WIDTH == 8+return MAX_UTF_CODE_POINT;+#else+#ifdef SUPPORT_UNICODE+return GET_MAX_CHAR_VALUE((options & PARSE_CLASS_UTF) != 0);+#else+return MAX_UCHAR_VALUE;+#endif+#endif+}++/* Add a negated character list to a buffer. */+static size_t+append_negated_char_list(const uint32_t *p, uint32_t options, uint32_t *buffer)+{+const uint32_t *n;+uint32_t start = 0;+size_t result = 2;++PCRE2_ASSERT(*p > 0);++while (*p != NOTACHAR)+ {+ n = p;+ while (n[0] == n[1] - 1) n++;++ PCRE2_ASSERT(*p < 0xffff);++ if (buffer != NULL)+ {+ buffer[0] = start;+ buffer[1] = *p - 1;+ buffer += 2;+ }++ result += 2;+ start = *n + 1;+ p = n + 1;+ }++ if (buffer != NULL)+ {+ buffer[0] = start;+ buffer[1] = get_highest_char(options);+ buffer += 2;+ (void)buffer;+ }++ return result;+}++static uint32_t *+append_non_ascii_range(uint32_t options, uint32_t *buffer)+{+ if (buffer == NULL) return NULL;++ buffer[0] = 0x100;+ buffer[1] = get_highest_char(options);+ return buffer + 2;+}++static size_t+parse_class(uint32_t *ptr, uint32_t options, uint32_t *buffer)+{+size_t total_size = 0;+size_t size;+uint32_t meta_arg;+uint32_t start_char;++while (TRUE)+ {+ switch (META_CODE(*ptr))+ {+ case META_ESCAPE:+ meta_arg = META_DATA(*ptr);+ switch (meta_arg)+ {+ case ESC_D:+ case ESC_W:+ case ESC_S:+ buffer = append_non_ascii_range(options, buffer);+ total_size += 2;+ break;++ case ESC_h:+ size = append_char_list(PRIV(hspace_list), buffer);+ total_size += size;+ if (buffer != NULL) buffer += size;+ break;++ case ESC_H:+ size = append_negated_char_list(PRIV(hspace_list), options, buffer);+ total_size += size;+ if (buffer != NULL) buffer += size;+ break;++ case ESC_v:+ size = append_char_list(PRIV(vspace_list), buffer);+ total_size += size;+ if (buffer != NULL) buffer += size;+ break;++ case ESC_V:+ size = append_negated_char_list(PRIV(vspace_list), options, buffer);+ total_size += size;+ if (buffer != NULL) buffer += size;+ break;++ case ESC_p:+ case ESC_P:+ ptr++;+ if (meta_arg == ESC_p && (*ptr >> 16) == PT_ANY)+ {+ if (buffer != NULL)+ {+ buffer[0] = 0;+ buffer[1] = get_highest_char(options);+ buffer += 2;+ }+ total_size += 2;+ }+ break;+ }+ ptr++;+ continue;+ case META_POSIX_NEG:+ buffer = append_non_ascii_range(options, buffer);+ total_size += 2;+ ptr += 2;+ continue;+ case META_POSIX:+ ptr += 2;+ continue;+ case META_BIGVALUE:+ /* Character literal */+ ptr++;+ break;+ CLASS_END_CASES(*ptr)+ if (*ptr >= META_END) return total_size;+ break;+ }++ start_char = *ptr;++ if (ptr[1] == META_RANGE_LITERAL || ptr[1] == META_RANGE_ESCAPED)+ {+ ptr += 2;+ PCRE2_ASSERT(*ptr < META_END || *ptr == META_BIGVALUE);++ if (*ptr == META_BIGVALUE) ptr++;++#ifdef EBCDIC+#error "Missing EBCDIC support"+#endif+ }++#ifdef SUPPORT_UNICODE+ if (options & PARSE_CLASS_CASELESS_UTF)+ {+ size = utf_caseless_extend(start_char, *ptr++, options, buffer);+ if (buffer != NULL) buffer += size;+ total_size += size;+ continue;+ }+#endif++ if (buffer != NULL)+ {+ buffer[0] = start_char;+ buffer[1] = *ptr;+ buffer += 2;+ }++ ptr++;+ total_size += 2;+ }++ return total_size;+}++/* Extra uint32_t values for storing the lengths of range lists in+the worst case. Two uint32_t lengths and a range end for a range+starting before 255 */+#define CHAR_LIST_EXTRA_SIZE 3++/* Starting character values for each character list. */++static const uint32_t char_list_starts[] = {+#if PCRE2_CODE_UNIT_WIDTH == 32+ XCL_CHAR_LIST_HIGH_32_START,+#endif+#if PCRE2_CODE_UNIT_WIDTH == 32 || defined SUPPORT_UNICODE+ XCL_CHAR_LIST_LOW_32_START,+#endif+ XCL_CHAR_LIST_HIGH_16_START,+ /* Must be terminated by XCL_CHAR_LIST_LOW_16_START,+ which also represents the end of the bitset. */+ XCL_CHAR_LIST_LOW_16_START,+};++static class_ranges *+compile_optimize_class(uint32_t *start_ptr, uint32_t options,+ uint32_t xoptions, compile_block *cb)+{+class_ranges* cranges;+uint32_t *ptr;+uint32_t *buffer;+uint32_t *dst;+uint32_t class_options = 0;+size_t range_list_size = 0, total_size, i;+uint32_t tmp1, tmp2;+const uint32_t *char_list_next;+uint16_t *next_char;+uint32_t char_list_start, char_list_end;+uint32_t range_start, range_end;++#ifdef SUPPORT_UNICODE+if (options & PCRE2_UTF)+ class_options |= PARSE_CLASS_UTF;++if ((options & PCRE2_CASELESS) && (options & (PCRE2_UTF|PCRE2_UCP)))+ class_options |= PARSE_CLASS_CASELESS_UTF;++if (xoptions & PCRE2_EXTRA_CASELESS_RESTRICT)+ class_options |= PARSE_CLASS_RESTRICTED_UTF;++if (xoptions & PCRE2_EXTRA_TURKISH_CASING)+ class_options |= PARSE_CLASS_TURKISH_UTF;+#else+(void)options; /* Avoid compiler warning. */+(void)xoptions; /* Avoid compiler warning. */+#endif++/* Compute required space for the range. */++range_list_size = parse_class(start_ptr, class_options, NULL);+PCRE2_ASSERT((range_list_size & 0x1) == 0);++/* Allocate buffer. The total_size also represents the end of the buffer. */++total_size = range_list_size ++ ((range_list_size >= 2) ? CHAR_LIST_EXTRA_SIZE : 0);++cranges = cb->cx->memctl.malloc(+ sizeof(class_ranges) + total_size * sizeof(uint32_t),+ cb->cx->memctl.memory_data);++if (cranges == NULL) return NULL;++cranges->header.next = NULL;+#ifdef PCRE2_DEBUG+cranges->header.type = CDATA_CRANGE;+#endif+cranges->range_list_size = (uint16_t)range_list_size;+cranges->char_lists_types = 0;+cranges->char_lists_size = 0;+cranges->char_lists_start = 0;++if (range_list_size == 0) return cranges;++buffer = (uint32_t*)(cranges + 1);+parse_class(start_ptr, class_options, buffer);++/* Using <= instead of == to help static analysis. */+if (range_list_size <= 2) return cranges;++/* In-place sorting of ranges. */++i = (((range_list_size >> 2) - 1) << 1);+while (TRUE)+ {+ do_heapify(buffer, range_list_size, i);+ if (i == 0) break;+ i -= 2;+ }++i = range_list_size - 2;+while (TRUE)+ {+ tmp1 = buffer[i];+ tmp2 = buffer[i + 1];+ buffer[i] = buffer[0];+ buffer[i + 1] = buffer[1];+ buffer[0] = tmp1;+ buffer[1] = tmp2;++ do_heapify(buffer, i, 0);+ if (i == 0) break;+ i -= 2;+ }++/* Merge ranges whenever possible. */+dst = buffer;+ptr = buffer + 2;+range_list_size -= 2;++/* The second condition is a very rare corner case, where the end of the last+range is the maximum character. This range cannot be extended further. */++while (range_list_size > 0 && dst[1] != ~(uint32_t)0)+ {+ if (dst[1] + 1 < ptr[0])+ {+ dst += 2;+ dst[0] = ptr[0];+ dst[1] = ptr[1];+ }+ else if (dst[1] < ptr[1]) dst[1] = ptr[1];++ ptr += 2;+ range_list_size -= 2;+ }++PCRE2_ASSERT(dst[1] <= get_highest_char(class_options));++/* When the number of ranges are less than six,+they are not converted to range lists. */++ptr = buffer;+while (ptr < dst && ptr[1] < 0x100) ptr += 2;+if (dst - ptr < (2 * (6 - 1)))+ {+ cranges->range_list_size = (uint16_t)(dst + 2 - buffer);+ return cranges;+ }++/* Compute character lists structures. */++char_list_next = char_list_starts;+char_list_start = *char_list_next++;+#if PCRE2_CODE_UNIT_WIDTH == 32+char_list_end = XCL_CHAR_LIST_HIGH_32_END;+#elif defined SUPPORT_UNICODE+char_list_end = XCL_CHAR_LIST_LOW_32_END;+#else+char_list_end = XCL_CHAR_LIST_HIGH_16_END;+#endif+next_char = (uint16_t*)(buffer + total_size);++tmp1 = 0;+tmp2 = ((sizeof(char_list_starts) / sizeof(uint32_t)) - 1) * XCL_TYPE_BIT_LEN;+PCRE2_ASSERT(tmp2 <= 3 * XCL_TYPE_BIT_LEN && tmp2 >= XCL_TYPE_BIT_LEN);+range_start = dst[0];+range_end = dst[1];++while (TRUE)+ {+ if (range_start >= char_list_start)+ {+ if (range_start == range_end || range_end < char_list_end)+ {+ tmp1++;+ next_char--;++ if (char_list_start < XCL_CHAR_LIST_LOW_32_START)+ *next_char = (uint16_t)((range_end << XCL_CHAR_SHIFT) | XCL_CHAR_END);+ else+ *(uint32_t*)(--next_char) =+ (range_end << XCL_CHAR_SHIFT) | XCL_CHAR_END;+ }++ if (range_start < range_end)+ {+ if (range_start > char_list_start)+ {+ tmp1++;+ next_char--;++ if (char_list_start < XCL_CHAR_LIST_LOW_32_START)+ *next_char = (uint16_t)(range_start << XCL_CHAR_SHIFT);+ else+ *(uint32_t*)(--next_char) = (range_start << XCL_CHAR_SHIFT);+ }+ else+ cranges->char_lists_types |= XCL_BEGIN_WITH_RANGE << tmp2;+ }++ PCRE2_ASSERT((uint32_t*)next_char >= dst + 2);++ if (dst > buffer)+ {+ dst -= 2;+ range_start = dst[0];+ range_end = dst[1];+ continue;+ }++ range_start = 0;+ range_end = 0;+ }++ if (range_end >= char_list_start)+ {+ PCRE2_ASSERT(range_start < char_list_start);++ if (range_end < char_list_end)+ {+ tmp1++;+ next_char--;++ if (char_list_start < XCL_CHAR_LIST_LOW_32_START)+ *next_char = (uint16_t)((range_end << XCL_CHAR_SHIFT) | XCL_CHAR_END);+ else+ *(uint32_t*)(--next_char) =+ (range_end << XCL_CHAR_SHIFT) | XCL_CHAR_END;++ PCRE2_ASSERT((uint32_t*)next_char >= dst + 2);+ }++ cranges->char_lists_types |= XCL_BEGIN_WITH_RANGE << tmp2;+ }++ if (tmp1 >= XCL_ITEM_COUNT_MASK)+ {+ cranges->char_lists_types |= XCL_ITEM_COUNT_MASK << tmp2;+ next_char--;++ if (char_list_start < XCL_CHAR_LIST_LOW_32_START)+ *next_char = (uint16_t)tmp1;+ else+ *(uint32_t*)(--next_char) = tmp1;+ }+ else+ cranges->char_lists_types |= tmp1 << tmp2;++ if (range_start < XCL_CHAR_LIST_LOW_16_START) break;++ PCRE2_ASSERT(tmp2 >= XCL_TYPE_BIT_LEN);+ char_list_end = char_list_start - 1;+ char_list_start = *char_list_next++;+ tmp1 = 0;+ tmp2 -= XCL_TYPE_BIT_LEN;+ }++if (dst[0] < XCL_CHAR_LIST_LOW_16_START) dst += 2;+PCRE2_ASSERT((uint16_t*)dst <= next_char);++cranges->char_lists_size =+ (size_t)((uint8_t*)(buffer + total_size) - (uint8_t*)next_char);+cranges->char_lists_start = (size_t)((uint8_t*)next_char - (uint8_t*)buffer);+cranges->range_list_size = (uint16_t)(dst - buffer);+return cranges;+}++#endif /* SUPPORT_WIDE_CHARS */++#ifdef SUPPORT_UNICODE++void PRIV(update_classbits)(uint32_t ptype, uint32_t pdata, BOOL negated,+ uint8_t *classbits)+{+/* Update PRIV(xclass) when this function is changed. */+int c, chartype;+const ucd_record *prop;+uint32_t gentype;+BOOL set_bit;++if (ptype == PT_ANY)+ {+ if (!negated) memset(classbits, 0xff, 32);+ return;+ }++for (c = 0; c < 256; c++)+ {+ prop = GET_UCD(c);+ set_bit = FALSE;+ (void)set_bit;++ switch (ptype)+ {+ case PT_LAMP:+ chartype = prop->chartype;+ set_bit = (chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt);+ break;++ case PT_GC:+ set_bit = (PRIV(ucp_gentype)[prop->chartype] == pdata);+ break;++ case PT_PC:+ set_bit = (prop->chartype == pdata);+ break;++ case PT_SC:+ set_bit = (prop->script == pdata);+ break;++ case PT_SCX:+ set_bit = (prop->script == pdata ||+ MAPBIT(PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(prop), pdata) != 0);+ break;++ case PT_ALNUM:+ gentype = PRIV(ucp_gentype)[prop->chartype];+ set_bit = (gentype == ucp_L || gentype == ucp_N);+ break;++ case PT_SPACE: /* Perl space */+ case PT_PXSPACE: /* POSIX space */+ switch(c)+ {+ HSPACE_BYTE_CASES:+ VSPACE_BYTE_CASES:+ set_bit = TRUE;+ break;++ default:+ set_bit = (PRIV(ucp_gentype)[prop->chartype] == ucp_Z);+ break;+ }+ break;++ case PT_WORD:+ chartype = prop->chartype;+ gentype = PRIV(ucp_gentype)[chartype];+ set_bit = (gentype == ucp_L || gentype == ucp_N ||+ chartype == ucp_Mn || chartype == ucp_Pc);+ break;++ case PT_UCNC:+ set_bit = (c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||+ c == CHAR_GRAVE_ACCENT || c >= 0xa0);+ break;++ case PT_BIDICL:+ set_bit = (UCD_BIDICLASS_PROP(prop) == pdata);+ break;++ case PT_BOOL:+ set_bit = MAPBIT(PRIV(ucd_boolprop_sets) ++ UCD_BPROPS_PROP(prop), pdata) != 0;+ break;++ case PT_PXGRAPH:+ chartype = prop->chartype;+ gentype = PRIV(ucp_gentype)[chartype];+ set_bit = (gentype != ucp_Z && (gentype != ucp_C || chartype == ucp_Cf));+ break;++ case PT_PXPRINT:+ chartype = prop->chartype;+ set_bit = (chartype != ucp_Zl && chartype != ucp_Zp &&+ (PRIV(ucp_gentype)[chartype] != ucp_C || chartype == ucp_Cf));+ break;++ case PT_PXPUNCT:+ gentype = PRIV(ucp_gentype)[prop->chartype];+ set_bit = (gentype == ucp_P || (c < 128 && gentype == ucp_S));+ break;++ default:+ PCRE2_ASSERT(ptype == PT_PXXDIGIT);+ set_bit = (c >= CHAR_0 && c <= CHAR_9) ||+ (c >= CHAR_A && c <= CHAR_F) ||+ (c >= CHAR_a && c <= CHAR_f);+ break;+ }++ if (negated) set_bit = !set_bit;+ if (set_bit) *classbits |= (uint8_t)(1 << (c & 0x7));+ if ((c & 0x7) == 0x7) classbits++;+ }+}++#endif /* SUPPORT_UNICODE */++++#ifdef SUPPORT_WIDE_CHARS++/*************************************************+* XClass related properties *+*************************************************/++/* XClass needs to be generated. */+#define XCLASS_REQUIRED 0x1+/* XClass has 8 bit character. */+#define XCLASS_HAS_8BIT_CHARS 0x2+/* XClass has properties. */+#define XCLASS_HAS_PROPS 0x4+/* XClass has character lists. */+#define XCLASS_HAS_CHAR_LISTS 0x8+/* XClass matches to all >= 256 characters. */+#define XCLASS_HIGH_ANY 0x10++#endif+++/*************************************************+* Internal entry point for add range to class *+*************************************************/++/* This function sets the overall range for characters < 256.+It also handles non-utf case folding.++Arguments:+ options the options bits+ xoptions the extra options bits+ cb compile data+ start start of range character+ end end of range character++Returns: cb->classbits is updated+*/++static void+add_to_class(uint32_t options, uint32_t xoptions, compile_block *cb,+ uint32_t start, uint32_t end)+{+uint8_t *classbits = cb->classbits.classbits;+uint32_t c, byte_start, byte_end;+uint32_t classbits_end = (end <= 0xff ? end : 0xff);++#ifndef SUPPORT_UNICODE+(void)xoptions; /* Avoid compiler warning. */+#endif++/* 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+ /* UTF mode. This branch is taken if we don't support wide characters (e.g.+ 8-bit library, without UTF), but we do treat those characters as Unicode+ (if UCP flag is set). In this case, we only need to expand the character class+ set to include the case pairs which are in the 0-255 codepoint range. */+ if ((options & (PCRE2_UTF|PCRE2_UCP)) != 0)+ {+ BOOL turkish_i = (xoptions & (PCRE2_EXTRA_TURKISH_CASING|PCRE2_EXTRA_CASELESS_RESTRICT)) ==+ PCRE2_EXTRA_TURKISH_CASING;+ if (start < 128)+ {+ uint32_t lo_end = (classbits_end < 127 ? classbits_end : 127);+ for (c = start; c <= lo_end; c++)+ {+ if (turkish_i && UCD_ANY_I(c)) continue;+ SETBIT(classbits, cb->fcc[c]);+ }+ }+ if (classbits_end >= 128)+ {+ uint32_t hi_start = (start > 128 ? start : 128);+ for (c = hi_start; c <= classbits_end; c++)+ {+ uint32_t co = UCD_OTHERCASE(c);+ if (co <= 0xff) SETBIT(classbits, co);+ }+ }+ }++ else+#endif /* SUPPORT_UNICODE */++ /* Not UTF mode */+ {+ for (c = start; c <= classbits_end; c++)+ SETBIT(classbits, cb->fcc[c]);+ }+ }++/* Use the bitmap for characters < 256. Otherwise use extra data. */++byte_start = (start + 7) >> 3;+byte_end = (classbits_end + 1) >> 3;++if (byte_start >= byte_end)+ {+ for (c = start; c <= classbits_end; c++)+ /* Regardless of start, c will always be <= 255. */+ SETBIT(classbits, c);+ return;+ }++for (c = byte_start; c < byte_end; c++)+ classbits[c] = 0xff;++byte_start <<= 3;+byte_end <<= 3;++for (c = start; c < byte_start; c++)+ SETBIT(classbits, c);++for (c = byte_end; c <= classbits_end; c++)+ SETBIT(classbits, c);+}+++#if PCRE2_CODE_UNIT_WIDTH == 8+/*************************************************+* Internal 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:+ 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: cb->classbits is updated+*/++static void+add_list_to_class(uint32_t options, uint32_t xoptions, compile_block *cb,+ const uint32_t *p)+{+while (p[0] < 256)+ {+ unsigned int n = 0;++ while(p[n+1] == p[0] + n + 1) n++;+ add_to_class(options, xoptions, cb, p[0], p[n]);++ p += n + 1;+ }+}++++/*************************************************+* 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:+ 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: cb->classbits is updated+*/++static void+add_not_list_to_class(uint32_t options, uint32_t xoptions, compile_block *cb,+ const uint32_t *p)+{+if (p[0] > 0)+ add_to_class(options, xoptions, cb, 0, p[0] - 1);+while (p[0] < 256)+ {+ while (p[1] == p[0] + 1) p++;+ add_to_class(options, xoptions, cb, p[0] + 1, (p[1] > 255) ? 255 : p[1] - 1);+ p++;+ }+}+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */++++/*************************************************+* Main entry-point to compile a character class *+*************************************************/++/* This function consumes a "leaf", which is a set of characters that will+become a single OP_CLASS OP_NCLASS, OP_XCLASS, or OP_ALLANY. */++uint32_t *+PRIV(compile_class_not_nested)(uint32_t options, uint32_t xoptions,+ uint32_t *start_ptr, PCRE2_UCHAR **pcode, BOOL negate_class, BOOL* has_bitmap,+ int *errorcodeptr, compile_block *cb, PCRE2_SIZE *lengthptr)+{+uint32_t *pptr = start_ptr;+PCRE2_UCHAR *code = *pcode;+BOOL should_flip_negation;+const uint8_t *cbits = cb->cbits;+/* Some functions such as add_to_class() or eclass processing+expects that the bitset is stored in cb->classbits.classbits. */+uint8_t *const classbits = cb->classbits.classbits;++#ifdef SUPPORT_UNICODE+BOOL utf = (options & PCRE2_UTF) != 0;+#else /* No Unicode support */+BOOL utf = FALSE;+#endif++/* Helper variables for OP_XCLASS opcode (for characters > 255). */++#ifdef SUPPORT_WIDE_CHARS+uint32_t xclass_props;+PCRE2_UCHAR *class_uchardata;+class_ranges* cranges;+#else+(void)has_bitmap; /* Avoid compiler warning. */+(void)errorcodeptr; /* Avoid compiler warning. */+(void)lengthptr; /* Avoid compiler warning. */+#endif++/* If an XClass 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 XClass may need to insert specific+matching or non-matching code for wide characters.+*/++should_flip_negation = FALSE;++/* XClass will be used when characters > 255 might match. */++#ifdef SUPPORT_WIDE_CHARS+xclass_props = 0;++#if PCRE2_CODE_UNIT_WIDTH == 8+cranges = NULL;++if (utf)+#endif+ {+ if (lengthptr != NULL)+ {+ cranges = compile_optimize_class(pptr, options, xoptions, cb);++ if (cranges == NULL)+ {+ *errorcodeptr = ERR21;+ return NULL;+ }++ /* Caching the pre-processed character ranges. */+ if (cb->last_data != NULL)+ cb->last_data->next = &cranges->header;+ else+ cb->first_data = &cranges->header;++ cb->last_data = &cranges->header;+ }+ else+ {+ /* Reuse the pre-processed character ranges. */+ cranges = (class_ranges*)cb->first_data;+ PCRE2_ASSERT(cranges != NULL && cranges->header.type == CDATA_CRANGE);+ cb->first_data = cranges->header.next;+ }++ if (cranges->range_list_size > 0)+ {+ const uint32_t *ranges = (const uint32_t*)(cranges + 1);++ if (ranges[0] <= 255)+ xclass_props |= XCLASS_HAS_8BIT_CHARS;++ if (ranges[cranges->range_list_size - 1] == GET_MAX_CHAR_VALUE(utf) &&+ ranges[cranges->range_list_size - 2] <= 256)+ xclass_props |= XCLASS_HIGH_ANY;+ }+ }++class_uchardata = code + LINK_SIZE + 2; /* For XCLASS items */+#endif /* SUPPORT_WIDE_CHARS */++/* 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);++/* Process items until end_ptr is reached. */++while (TRUE)+ {+ uint32_t meta = *(pptr++);+ BOOL local_negate;+ int posix_class;+ int taboffset, tabopt;+ class_bits_storage pbits;+ uint32_t escape, c;++ /* Handle POSIX classes such as [:alpha:] etc. */+ switch (META_CODE(meta))+ {+ case META_POSIX:+ case META_POSIX_NEG:++ local_negate = (meta == META_POSIX_NEG);+ posix_class = *(pptr++);++ if (local_negate) should_flip_negation = TRUE; /* 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+ /* TODO This entire block of code here appears to be unreachable!? I simply+ can't see how it can be hit, given that the frontend parser doesn't emit+ META_POSIX for GRAPH/PRINT/PUNCT when UCP is set. */+ if ((options & PCRE2_UCP) != 0 &&+ (xoptions & PCRE2_EXTRA_ASCII_POSIX) == 0)+ {+ uint32_t ptype;++ switch(posix_class)+ {+ case PC_GRAPH:+ case PC_PRINT:+ case PC_PUNCT:+ ptype = (posix_class == PC_GRAPH)? PT_PXGRAPH :+ (posix_class == PC_PRINT)? PT_PXPRINT : PT_PXPUNCT;++ PRIV(update_classbits)(ptype, 0, local_negate, classbits);++ if ((xclass_props & XCLASS_HIGH_ANY) == 0)+ {+ if (lengthptr != NULL)+ *lengthptr += 3;+ else+ {+ *class_uchardata++ = local_negate? XCL_NOTPROP : XCL_PROP;+ *class_uchardata++ = (PCRE2_UCHAR)ptype;+ *class_uchardata++ = 0;+ }+ xclass_props |= XCLASS_REQUIRED | XCLASS_HAS_PROPS;+ }+ continue;++ /* 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:+ 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.classbits, cbits + PRIV(posix_class_maps)[posix_class], 32);++ /* If there is a second table, add or remove it as required. */++ taboffset = PRIV(posix_class_maps)[posix_class + 1];+ tabopt = PRIV(posix_class_maps)[posix_class + 2];++ if (taboffset >= 0)+ {+ if (tabopt >= 0)+ for (int i = 0; i < 32; i++)+ pbits.classbits[i] |= cbits[i + taboffset];+ else+ for (int i = 0; i < 32; i++)+ pbits.classbits[i] &= (uint8_t)(~cbits[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;+#ifdef EBCDIC+ {+ uint8_t posix_vertical[4] = { CHAR_LF, CHAR_VT, CHAR_FF, CHAR_CR };+ uint8_t posix_underscore = CHAR_UNDERSCORE;+ uint8_t *chars = NULL;+ int n = 0;++ if (tabopt == 1) { chars = posix_vertical; n = 4; }+ else if (tabopt == 2) { chars = &posix_underscore; n = 1; }++ for (; n > 0; ++chars, --n)+ pbits.classbits[*chars/8] &= ~(1u << (*chars&7));+ }+#else+ if (tabopt == 1) pbits.classbits[1] &= ~0x3c;+ else if (tabopt == 2) pbits.classbits[11] &= 0x7f;+#endif++ /* Add the POSIX table or its complement into the main table that is+ being built and we are done. */++ {+ uint32_t *classwords = cb->classbits.classwords;++ if (local_negate)+ for (int i = 0; i < 8; i++)+ classwords[i] |= (uint32_t)(~pbits.classwords[i]);+ else+ for (int i = 0; i < 8; i++)+ classwords[i] |= pbits.classwords[i];+ }++#ifdef SUPPORT_WIDE_CHARS+ /* Every class contains at least one < 256 character. */+ xclass_props |= XCLASS_HAS_8BIT_CHARS;+#endif+ continue; /* End of POSIX handling */++ /* Other than POSIX classes, the only items we should encounter are+ \d-type escapes and literal characters (possibly as ranges). */+ case META_BIGVALUE:+ meta = *(pptr++);+ break;++ case META_ESCAPE:+ escape = META_DATA(meta);++ 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:+#if PCRE2_CODE_UNIT_WIDTH == 8+#ifdef SUPPORT_UNICODE+ if (cranges != NULL) break;+#endif+ add_list_to_class(options & ~PCRE2_CASELESS, xoptions,+ cb, PRIV(hspace_list));+#else+ PCRE2_ASSERT(cranges != NULL);+#endif+ break;++ case ESC_H:+#if PCRE2_CODE_UNIT_WIDTH == 8+#ifdef SUPPORT_UNICODE+ if (cranges != NULL) break;+#endif+ add_not_list_to_class(options & ~PCRE2_CASELESS, xoptions,+ cb, PRIV(hspace_list));+#else+ PCRE2_ASSERT(cranges != NULL);+#endif+ break;++ case ESC_v:+#if PCRE2_CODE_UNIT_WIDTH == 8+#ifdef SUPPORT_UNICODE+ if (cranges != NULL) break;+#endif+ add_list_to_class(options & ~PCRE2_CASELESS, xoptions,+ cb, PRIV(vspace_list));+#else+ PCRE2_ASSERT(cranges != NULL);+#endif+ break;++ case ESC_V:+#if PCRE2_CODE_UNIT_WIDTH == 8+#ifdef SUPPORT_UNICODE+ if (cranges != NULL) break;+#endif+ add_not_list_to_class(options & ~PCRE2_CASELESS, xoptions,+ cb, PRIV(vspace_list));+#else+ PCRE2_ASSERT(cranges != NULL);+#endif+ 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;++ /* The "Any" is processed by PRIV(update_classbits)(). */+ if (ptype == PT_ANY)+ {+#if PCRE2_CODE_UNIT_WIDTH == 8+ if (!utf && escape == ESC_p) memset(classbits, 0xff, 32);+#endif+ continue;+ }++ PRIV(update_classbits)(ptype, pdata, (escape == ESC_P), classbits);++ if ((xclass_props & XCLASS_HIGH_ANY) == 0)+ {+ if (lengthptr != NULL)+ *lengthptr += 3;+ else+ {+ *class_uchardata++ = (escape == ESC_p)? XCL_PROP : XCL_NOTPROP;+ *class_uchardata++ = ptype;+ *class_uchardata++ = pdata;+ }+ xclass_props |= XCLASS_REQUIRED | XCLASS_HAS_PROPS;+ }+ }+ continue;+#endif+ }++#ifdef SUPPORT_WIDE_CHARS+ /* Every non-property class contains at least one < 256 character. */+ xclass_props |= XCLASS_HAS_8BIT_CHARS;+#endif+ /* End handling \d-type escapes */+ continue;++ CLASS_END_CASES(meta)+ /* Literals. */+ if (meta < META_END) break;+ /* Non-literals: end of class contents. */+ goto END_PROCESSING;+ }++ /* 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. */++ c = 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 == META_RANGE_LITERAL || *pptr == META_RANGE_ESCAPED)+ {+ uint32_t d;++#ifdef EBCDIC+ BOOL range_is_literal = (*pptr == META_RANGE_LITERAL);+#endif+ ++pptr;+ 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;++#if PCRE2_CODE_UNIT_WIDTH == 8+#ifdef SUPPORT_UNICODE+ if (cranges != NULL) continue;+ xclass_props |= XCLASS_HAS_8BIT_CHARS;+#endif++ /* 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)+ {+ add_to_class(options, xoptions, cb, C + uc,+ ((D < CHAR_i)? D : CHAR_i) + uc);+ C = CHAR_j;+ }++ if (C <= D && C <= CHAR_r)+ {+ add_to_class(options, xoptions, cb, C + uc,+ ((D < CHAR_r)? D : CHAR_r) + uc);+ C = CHAR_s;+ }++ if (C <= D)+ add_to_class(options, xoptions, cb, C + uc, D + uc);+ }+ else+#endif+ /* Not an EBCDIC special range */++ add_to_class(options, xoptions, cb, c, d);+#else+ PCRE2_ASSERT(cranges != NULL);+#endif+ continue;+ } /* End of range handling */++ /* Character ranges are ignored when class_ranges is present. */+#if PCRE2_CODE_UNIT_WIDTH == 8+#ifdef SUPPORT_UNICODE+ if (cranges != NULL) continue;+ xclass_props |= XCLASS_HAS_8BIT_CHARS;+#endif+ /* Handle a single character. */++ add_to_class(options, xoptions, cb, meta, meta);+#else+ PCRE2_ASSERT(cranges != NULL);+#endif+ } /* End of main class-processing loop */++END_PROCESSING:++#ifdef SUPPORT_WIDE_CHARS+PCRE2_ASSERT((xclass_props & XCLASS_HAS_PROPS) == 0 ||+ (xclass_props & XCLASS_HIGH_ANY) == 0);++if (cranges != NULL)+ {+ uint32_t *range = (uint32_t*)(cranges + 1);+ uint32_t *end = range + cranges->range_list_size;++ while (range < end && range[0] < 256)+ {+ PCRE2_ASSERT((xclass_props & XCLASS_HAS_8BIT_CHARS) != 0);+ /* Add range to bitset. If we are in UTF or UCP mode, then clear the+ caseless bit, because the cranges handle caselessness (only) in this+ condition; see the condition for PARSE_CLASS_CASELESS_UTF in+ compile_optimize_class(). */+ add_to_class(((options & (PCRE2_UTF|PCRE2_UCP)) != 0)?+ (options & ~PCRE2_CASELESS) : options, xoptions, cb, range[0], range[1]);++ if (range[1] > 255) break;+ range += 2;+ }++ if (cranges->char_lists_size > 0)+ {+ /* The cranges structure is still used and freed later. */+ PCRE2_ASSERT((xclass_props & XCLASS_HIGH_ANY) == 0);+ xclass_props |= XCLASS_REQUIRED | XCLASS_HAS_CHAR_LISTS;+ }+ else+ {+ if ((xclass_props & XCLASS_HIGH_ANY) != 0)+ {+ PCRE2_ASSERT(range + 2 == end && range[0] <= 256 &&+ range[1] >= GET_MAX_CHAR_VALUE(utf));+ should_flip_negation = TRUE;+ range = end;+ }++ while (range < end)+ {+ uint32_t range_start = range[0];+ uint32_t range_end = range[1];++ range += 2;+ xclass_props |= XCLASS_REQUIRED;++ if (range_start < 256) range_start = 256;++ if (lengthptr != NULL)+ {+#ifdef SUPPORT_UNICODE+ if (utf)+ {+ *lengthptr += 1;++ if (range_start < range_end)+ *lengthptr += PRIV(ord2utf)(range_start, class_uchardata);++ *lengthptr += PRIV(ord2utf)(range_end, class_uchardata);+ continue;+ }+#endif /* SUPPORT_UNICODE */++ *lengthptr += range_start < range_end ? 3 : 2;+ continue;+ }++#ifdef SUPPORT_UNICODE+ if (utf)+ {+ if (range_start < range_end)+ {+ *class_uchardata++ = XCL_RANGE;+ class_uchardata += PRIV(ord2utf)(range_start, class_uchardata);+ }+ else+ *class_uchardata++ = XCL_SINGLE;++ class_uchardata += PRIV(ord2utf)(range_end, class_uchardata);+ continue;+ }+#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+ if (range_start < range_end)+ {+ *class_uchardata++ = XCL_RANGE;+ *class_uchardata++ = range_start;+ }+ else+ *class_uchardata++ = XCL_SINGLE;++ *class_uchardata++ = range_end;+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */+ }++ if (lengthptr == NULL)+ cb->cx->memctl.free(cranges, cb->cx->memctl.memory_data);+ }+ }+#endif /* SUPPORT_WIDE_CHARS */++/* 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_props & XCLASS_REQUIRED) != 0)+ {+ PCRE2_UCHAR *previous = code;++ if ((xclass_props & XCLASS_HAS_CHAR_LISTS) == 0)+ *class_uchardata++ = XCL_END; /* Marks the end of extra data */+ *code++ = OP_XCLASS;+ code += LINK_SIZE;+ *code = negate_class? XCL_NOT:0;+ if ((xclass_props & XCLASS_HAS_PROPS) != 0) *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 ((xclass_props & XCLASS_HAS_8BIT_CHARS) != 0 || has_bitmap != NULL)+ {+ if (negate_class)+ {+ uint32_t *classwords = cb->classbits.classwords;+ for (int i = 0; i < 8; i++) classwords[i] = ~classwords[i];+ }++ if (has_bitmap == NULL)+ {+ *code++ |= XCL_MAP;+ (void)memmove(code + (32 / sizeof(PCRE2_UCHAR)), code,+ CU2BYTES(class_uchardata - code));+ memcpy(code, classbits, 32);+ code = class_uchardata + (32 / sizeof(PCRE2_UCHAR));+ }+ else+ {+ code = class_uchardata;+ if ((xclass_props & XCLASS_HAS_8BIT_CHARS) != 0)+ *has_bitmap = TRUE;+ }+ }+ else code = class_uchardata;++ if ((xclass_props & XCLASS_HAS_CHAR_LISTS) != 0)+ {+ /* Char lists size is an even number, because all items are 16 or 32+ bit values. The character list data is always aligned to 32 bits. */+ size_t char_lists_size = cranges->char_lists_size;+ PCRE2_ASSERT((char_lists_size & 0x1) == 0 &&+ (cb->char_lists_size & 0x3) == 0);++ if (lengthptr != NULL)+ {+ char_lists_size = CLIST_ALIGN_TO(char_lists_size, sizeof(uint32_t));++#if PCRE2_CODE_UNIT_WIDTH == 8+ *lengthptr += 2 + LINK_SIZE;+#else+ *lengthptr += 1 + LINK_SIZE;+#endif++ cb->char_lists_size += char_lists_size;++ char_lists_size /= sizeof(PCRE2_UCHAR);++ /* Storage space for character lists is included+ in the maximum pattern size. */+ if (*lengthptr > MAX_PATTERN_SIZE ||+ MAX_PATTERN_SIZE - *lengthptr < char_lists_size)+ {+ *errorcodeptr = ERR20; /* Pattern is too large */+ return NULL;+ }+ }+ else+ {+ uint8_t *data;++ PCRE2_ASSERT(cranges->char_lists_types <= XCL_TYPE_MASK);+#if PCRE2_CODE_UNIT_WIDTH == 8+ /* Encode as high / low bytes. */+ code[0] = (uint8_t)(XCL_LIST |+ (cranges->char_lists_types >> 8));+ code[1] = (uint8_t)cranges->char_lists_types;+ code += 2;+#else+ *code++ = (PCRE2_UCHAR)(XCL_LIST | cranges->char_lists_types);+#endif++ /* Character lists are stored in backwards direction from+ byte code start. The non-dfa/dfa matchers can access these+ lists using the byte code start stored in match blocks.+ Each list is aligned to 32 bit with an optional unused+ 16 bit value at the beginning of the character list. */++ cb->char_lists_size += char_lists_size;+ data = (uint8_t*)cb->start_code - cb->char_lists_size;++ memcpy(data, (uint8_t*)(cranges + 1) + cranges->char_lists_start,+ char_lists_size);++ /* Since character lists total size is less than MAX_PATTERN_SIZE,+ their starting offset fits into a value which size is LINK_SIZE. */++ char_lists_size = cb->char_lists_size;+ PUT(code, 0, (uint32_t)(char_lists_size >> 1));+ code += LINK_SIZE;++#if defined PCRE2_DEBUG || defined SUPPORT_VALGRIND+ if ((char_lists_size & 0x2) != 0)+ {+ /* In debug the unused 16 bit value is set+ to a fixed value and marked unused. */+ ((uint16_t*)data)[-1] = 0x5555;+#ifdef SUPPORT_VALGRIND+ VALGRIND_MAKE_MEM_NOACCESS(data - 2, 2);+#endif+ }+#endif++ cb->char_lists_size =+ CLIST_ALIGN_TO(char_lists_size, sizeof(uint32_t));++ cb->cx->memctl.free(cranges, cb->cx->memctl.memory_data);+ }+ }++ /* Now fill in the complete length of the item */++ PUT(previous, 1, (int)(code - previous));+ goto DONE; /* 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. */++if (negate_class)+ {+ uint32_t *classwords = cb->classbits.classwords;++ for (int i = 0; i < 8; i++) classwords[i] = ~classwords[i];+ }++if ((SELECT_VALUE8(!utf, 0) || negate_class != should_flip_negation) &&+ cb->classbits.classwords[0] == ~(uint32_t)0)+ {+ const uint32_t *classwords = cb->classbits.classwords;+ int i;++ for (i = 0; i < 8; i++)+ if (classwords[i] != ~(uint32_t)0) break;++ if (i == 8)+ {+ *code++ = OP_ALLANY;+ goto DONE; /* End of class handling */+ }+ }++*code++ = (negate_class == should_flip_negation) ? OP_CLASS : OP_NCLASS;+memcpy(code, classbits, 32);+code += 32 / sizeof(PCRE2_UCHAR);++DONE:+*pcode = code;+return pptr - 1;+}++++/* ===================================================================*/+/* Here follows a block of ECLASS-compiling functions. You may well want to+read them from top to bottom; they are ordered from leafmost (at the top) to+outermost parser (at the bottom of the file). */++/* This function folds one operand using the negation operator.+The new, combined chunk of stack code is written out to *pop_info. */++static void+fold_negation(eclass_op_info *pop_info, PCRE2_SIZE *lengthptr,+ BOOL preserve_classbits)+{+/* If the chunk of stack code is already composed of multiple ops, we won't+descend in and try and propagate the negation down the tree. (That would lead+to O(n^2) compile-time, which could be exploitable with a malicious regex -+although maybe that's not really too much of a worry in a library that offers+an exponential-time matching function!) */++if (pop_info->op_single_type == 0)+ {+ if (lengthptr != NULL)+ *lengthptr += 1;+ else+ pop_info->code_start[pop_info->length] = ECL_NOT;+ pop_info->length += 1;+ }++/* Otherwise, it's a nice single-op item, so we can easily fold in the negation+without needing to produce an ECL_NOT. */++else if (pop_info->op_single_type == ECL_ANY ||+ pop_info->op_single_type == ECL_NONE)+ {+ pop_info->op_single_type = (pop_info->op_single_type == ECL_NONE)?+ ECL_ANY : ECL_NONE;+ if (lengthptr == NULL)+ *(pop_info->code_start) = pop_info->op_single_type;+ }+else+ {+ PCRE2_ASSERT(pop_info->op_single_type == ECL_XCLASS &&+ pop_info->length >= 1 + LINK_SIZE + 1);+ if (lengthptr == NULL)+ pop_info->code_start[1 + LINK_SIZE] ^= XCL_NOT;+ }++if (!preserve_classbits)+ {+ for (int i = 0; i < 8; i++)+ pop_info->bits.classwords[i] = ~pop_info->bits.classwords[i];+ }+}++++/* This function folds together two operands using a binary operator.+The new, combined chunk of stack code is written out to *lhs_op_info. */++static void+fold_binary(int op, eclass_op_info *lhs_op_info, eclass_op_info *rhs_op_info,+ PCRE2_SIZE *lengthptr)+{+switch (op)+ {+ /* ECL_AND truth table:++ LHS RHS RESULT+ ----------------+ ANY * RHS+ * ANY LHS+ NONE * NONE+ * NONE NONE+ X Y X & Y+ */++ case ECL_AND:+ if (rhs_op_info->op_single_type == ECL_ANY)+ {+ /* no-op: drop the RHS */+ }+ else if (lhs_op_info->op_single_type == ECL_ANY)+ {+ /* no-op: drop the LHS, and memmove the RHS into its place */+ if (lengthptr == NULL)+ memmove(lhs_op_info->code_start, rhs_op_info->code_start,+ CU2BYTES(rhs_op_info->length));+ lhs_op_info->length = rhs_op_info->length;+ lhs_op_info->op_single_type = rhs_op_info->op_single_type;+ }+ else if (rhs_op_info->op_single_type == ECL_NONE)+ {+ /* the result is ECL_NONE: write into the LHS */+ if (lengthptr == NULL)+ lhs_op_info->code_start[0] = ECL_NONE;+ lhs_op_info->length = 1;+ lhs_op_info->op_single_type = ECL_NONE;+ }+ else if (lhs_op_info->op_single_type == ECL_NONE)+ {+ /* the result is ECL_NONE: drop the RHS */+ }+ else+ {+ /* Both of LHS & RHS are either ECL_XCLASS, or compound operations. */+ if (lengthptr != NULL)+ *lengthptr += 1;+ else+ {+ PCRE2_ASSERT(rhs_op_info->code_start ==+ lhs_op_info->code_start + lhs_op_info->length);+ rhs_op_info->code_start[rhs_op_info->length] = ECL_AND;+ }+ lhs_op_info->length += rhs_op_info->length + 1;+ lhs_op_info->op_single_type = 0;+ }++ for (int i = 0; i < 8; i++)+ lhs_op_info->bits.classwords[i] &= rhs_op_info->bits.classwords[i];+ break;++ /* ECL_OR truth table:++ LHS RHS RESULT+ ----------------+ ANY * ANY+ * ANY ANY+ NONE * RHS+ * NONE LHS+ X Y X | Y+ */++ case ECL_OR:+ if (rhs_op_info->op_single_type == ECL_NONE)+ {+ /* no-op: drop the RHS */+ }+ else if (lhs_op_info->op_single_type == ECL_NONE)+ {+ /* no-op: drop the LHS, and memmove the RHS into its place */+ if (lengthptr == NULL)+ memmove(lhs_op_info->code_start, rhs_op_info->code_start,+ CU2BYTES(rhs_op_info->length));+ lhs_op_info->length = rhs_op_info->length;+ lhs_op_info->op_single_type = rhs_op_info->op_single_type;+ }+ else if (rhs_op_info->op_single_type == ECL_ANY)+ {+ /* the result is ECL_ANY: write into the LHS */+ if (lengthptr == NULL)+ lhs_op_info->code_start[0] = ECL_ANY;+ lhs_op_info->length = 1;+ lhs_op_info->op_single_type = ECL_ANY;+ }+ else if (lhs_op_info->op_single_type == ECL_ANY)+ {+ /* the result is ECL_ANY: drop the RHS */+ }+ else+ {+ /* Both of LHS & RHS are either ECL_XCLASS, or compound operations. */+ if (lengthptr != NULL)+ *lengthptr += 1;+ else+ {+ PCRE2_ASSERT(rhs_op_info->code_start ==+ lhs_op_info->code_start + lhs_op_info->length);+ rhs_op_info->code_start[rhs_op_info->length] = ECL_OR;+ }+ lhs_op_info->length += rhs_op_info->length + 1;+ lhs_op_info->op_single_type = 0;+ }++ for (int i = 0; i < 8; i++)+ lhs_op_info->bits.classwords[i] |= rhs_op_info->bits.classwords[i];+ break;++ /* ECL_XOR truth table:++ LHS RHS RESULT+ ----------------+ ANY * !RHS+ * ANY !LHS+ NONE * RHS+ * NONE LHS+ X Y X ^ Y+ */++ case ECL_XOR:+ if (rhs_op_info->op_single_type == ECL_NONE)+ {+ /* no-op: drop the RHS */+ }+ else if (lhs_op_info->op_single_type == ECL_NONE)+ {+ /* no-op: drop the LHS, and memmove the RHS into its place */+ if (lengthptr == NULL)+ memmove(lhs_op_info->code_start, rhs_op_info->code_start,+ CU2BYTES(rhs_op_info->length));+ lhs_op_info->length = rhs_op_info->length;+ lhs_op_info->op_single_type = rhs_op_info->op_single_type;+ }+ else if (rhs_op_info->op_single_type == ECL_ANY)+ {+ /* the result is !LHS: fold in the negation, and drop the RHS */+ /* Preserve the classbits, because we promise to deal with them later. */+ fold_negation(lhs_op_info, lengthptr, TRUE);+ }+ else if (lhs_op_info->op_single_type == ECL_ANY)+ {+ /* the result is !RHS: drop the LHS, memmove the RHS into its place, and+ fold in the negation */+ if (lengthptr == NULL)+ memmove(lhs_op_info->code_start, rhs_op_info->code_start,+ CU2BYTES(rhs_op_info->length));+ lhs_op_info->length = rhs_op_info->length;+ lhs_op_info->op_single_type = rhs_op_info->op_single_type;++ /* Preserve the classbits, because we promise to deal with them later. */+ fold_negation(lhs_op_info, lengthptr, TRUE);+ }+ else+ {+ /* Both of LHS & RHS are either ECL_XCLASS, or compound operations. */+ if (lengthptr != NULL)+ *lengthptr += 1;+ else+ {+ PCRE2_ASSERT(rhs_op_info->code_start ==+ lhs_op_info->code_start + lhs_op_info->length);+ rhs_op_info->code_start[rhs_op_info->length] = ECL_XOR;+ }+ lhs_op_info->length += rhs_op_info->length + 1;+ lhs_op_info->op_single_type = 0;+ }++ for (int i = 0; i < 8; i++)+ lhs_op_info->bits.classwords[i] ^= rhs_op_info->bits.classwords[i];+ break;++ /* LCOV_EXCL_START */+ default:+ PCRE2_DEBUG_UNREACHABLE();+ break;+ /* LCOV_EXCL_STOP */+ }+}++++static BOOL+compile_eclass_nested(eclass_context *context, BOOL negated,+ uint32_t **pptr, PCRE2_UCHAR **pcode,+ eclass_op_info *pop_info, PCRE2_SIZE *lengthptr);++/* This function consumes a group of implicitly-unioned class elements.+These can be characters, ranges, properties, or nested classes, as long+as they are all joined by being placed adjacently. */++static BOOL+compile_class_operand(eclass_context *context, BOOL negated,+ uint32_t **pptr, PCRE2_UCHAR **pcode, eclass_op_info *pop_info,+ PCRE2_SIZE *lengthptr)+{+uint32_t *ptr = *pptr;+uint32_t *prev_ptr;+PCRE2_UCHAR *code = *pcode;+PCRE2_UCHAR *code_start = code;+PCRE2_SIZE prev_length = (lengthptr != NULL)? *lengthptr : 0;+PCRE2_SIZE extra_length;+uint32_t meta = META_CODE(*ptr);++switch (meta)+ {+ case META_CLASS_EMPTY_NOT:+ case META_CLASS_EMPTY:+ ++ptr;+ pop_info->length = 1;+ if ((meta == META_CLASS_EMPTY) == negated)+ {+ *code++ = pop_info->op_single_type = ECL_ANY;+ memset(pop_info->bits.classbits, 0xff, 32);+ }+ else+ {+ *code++ = pop_info->op_single_type = ECL_NONE;+ memset(pop_info->bits.classbits, 0, 32);+ }+ break;++ case META_CLASS:+ case META_CLASS_NOT:+ if ((*ptr & CLASS_IS_ECLASS) != 0)+ {+ if (!compile_eclass_nested(context, negated, &ptr, &code,+ pop_info, lengthptr))+ return FALSE;++ PCRE2_ASSERT(*ptr == META_CLASS_END);+ ptr++;+ goto DONE;+ }++ ptr++;+ PCRE2_FALLTHROUGH /* Fall through */++ default:+ /* Scan forward characters, ranges, and properties.+ For example: inside [a-z_ -- m] we don't have brackets around "a-z_" but+ we still need to collect that fragment up into a "leaf" OP_CLASS. */++ prev_ptr = ptr;+ ptr = PRIV(compile_class_not_nested)(+ context->options, context->xoptions, ptr, &code,+ (meta != META_CLASS_NOT) == negated, &context->needs_bitmap,+ context->errorcodeptr, context->cb, lengthptr);+ if (ptr == NULL) return FALSE;++ /* We must have a 100% guarantee that ptr increases when+ compile_class_operand() returns, even on Release builds, so that we can+ statically prove our loops terminate. */+ /* LCOV_EXCL_START */+ if (ptr <= prev_ptr)+ {+ PCRE2_DEBUG_UNREACHABLE();+ return FALSE;+ }+ /* LCOV_EXCL_STOP */++ /* If we fell through above, consume the closing ']'. */+ if (meta == META_CLASS || meta == META_CLASS_NOT)+ {+ PCRE2_ASSERT(*ptr == META_CLASS_END);+ ptr++;+ }++ /* Regardless of whether (lengthptr == NULL), some data will still be written+ out to *pcode, which we need: we have to peek at it, to transform the opcode+ into the ECLASS version (since we need to hoist up the bitmaps). */+ PCRE2_ASSERT(code > code_start);+ extra_length = (lengthptr != NULL)? *lengthptr - prev_length : 0;++ /* Easiest case: convert OP_ALLANY to ECL_ANY */++ if (*code_start == OP_ALLANY)+ {+ PCRE2_ASSERT(code - code_start == 1 && extra_length == 0);+ pop_info->length = 1;+ *code_start = pop_info->op_single_type = ECL_ANY;+ memset(pop_info->bits.classbits, 0xff, 32);+ }++ /* For OP_CLASS and OP_NCLASS, we hoist out the bitmap and convert to+ ECL_NONE / ECL_ANY respectively. */++ else if (*code_start == OP_CLASS || *code_start == OP_NCLASS)+ {+ PCRE2_ASSERT(code - code_start == 1 + 32 / sizeof(PCRE2_UCHAR) &&+ extra_length == 0);+ pop_info->length = 1;+ *code_start = pop_info->op_single_type =+ (*code_start == OP_CLASS)? ECL_NONE : ECL_ANY;+ memcpy(pop_info->bits.classbits, code_start + 1, 32);+ /* Rewind the code pointer, but make sure we adjust *lengthptr, because we+ do need to reserve that space (even though we only use it temporarily). */+ if (lengthptr != NULL)+ *lengthptr += code - (code_start + 1);+ code = code_start + 1;++ if (!context->needs_bitmap && *code_start == ECL_NONE)+ {+ uint32_t *classwords = pop_info->bits.classwords;++ for (int i = 0; i < 8; i++)+ if (classwords[i] != 0)+ {+ context->needs_bitmap = TRUE;+ break;+ }+ }+ else+ context->needs_bitmap = TRUE;+ }++ /* Finally, for OP_XCLASS we hoist out the bitmap (if any), and convert to+ ECL_XCLASS. */++ else+ {+ PCRE2_ASSERT(*code_start == OP_XCLASS);+ *code_start = pop_info->op_single_type = ECL_XCLASS;++ PCRE2_ASSERT(code - code_start >= 1 + LINK_SIZE + 1);++ memcpy(pop_info->bits.classbits, context->cb->classbits.classbits, 32);+ pop_info->length = (code - code_start) + extra_length;+ }++ break;+ } /* End of switch(meta) */++pop_info->code_start = (lengthptr == NULL)? code_start : NULL;++if (lengthptr != NULL)+ {+ *lengthptr += code - code_start;+ code = code_start;+ }++DONE:+PCRE2_ASSERT(lengthptr == NULL || (code == code_start));++*pptr = ptr;+*pcode = code;+return TRUE;+}++++/* This function consumes a group of implicitly-unioned class elements.+These can be characters, ranges, properties, or nested classes, as long+as they are all joined by being placed adjacently. */++static BOOL+compile_class_juxtaposition(eclass_context *context, BOOL negated,+ uint32_t **pptr, PCRE2_UCHAR **pcode, eclass_op_info *pop_info,+ PCRE2_SIZE *lengthptr)+{+uint32_t *ptr = *pptr;+PCRE2_UCHAR *code = *pcode;+#ifdef PCRE2_DEBUG+PCRE2_UCHAR *start_code = *pcode;+#endif++/* See compile_class_binary_loose() for comments on compile-time folding of+the "negated" flag. */++/* Because it's a non-empty class, there must be an operand at the start. */+if (!compile_class_operand(context, negated, &ptr, &code, pop_info, lengthptr))+ return FALSE;++while (*ptr != META_CLASS_END &&+ !(*ptr >= META_ECLASS_AND && *ptr <= META_ECLASS_NOT))+ {+ uint32_t op;+ BOOL rhs_negated;+ eclass_op_info rhs_op_info;++ if (negated)+ {+ /* !(A juxtapose B) -> !A && !B */+ op = ECL_AND;+ rhs_negated = TRUE;+ }+ else+ {+ /* A juxtapose B -> A || B */+ op = ECL_OR;+ rhs_negated = FALSE;+ }++ /* An operand must follow the operator. */+ if (!compile_class_operand(context, rhs_negated, &ptr, &code,+ &rhs_op_info, lengthptr))+ return FALSE;++ /* Convert infix to postfix (RPN). */+ fold_binary(op, pop_info, &rhs_op_info, lengthptr);+ if (lengthptr == NULL)+ code = pop_info->code_start + pop_info->length;+ }++PCRE2_ASSERT(lengthptr == NULL || code == start_code);++*pptr = ptr;+*pcode = code;+return TRUE;+}++++/* This function consumes unary prefix operators. */++static BOOL+compile_class_unary(eclass_context *context, BOOL negated,+ uint32_t **pptr, PCRE2_UCHAR **pcode, eclass_op_info *pop_info,+ PCRE2_SIZE *lengthptr)+{+uint32_t *ptr = *pptr;+#ifdef PCRE2_DEBUG+PCRE2_UCHAR *start_code = *pcode;+#endif++while (*ptr == META_ECLASS_NOT)+ {+ ++ptr;+ negated = !negated;+ }++*pptr = ptr;+/* Because it's a non-empty class, there must be an operand. */+if (!compile_class_juxtaposition(context, negated, pptr, pcode,+ pop_info, lengthptr))+ return FALSE;++PCRE2_ASSERT(lengthptr == NULL || *pcode == start_code);+return TRUE;+}++++/* This function consumes tightly-binding binary operators. */++static BOOL+compile_class_binary_tight(eclass_context *context, BOOL negated,+ uint32_t **pptr, PCRE2_UCHAR **pcode, eclass_op_info *pop_info,+ PCRE2_SIZE *lengthptr)+{+uint32_t *ptr = *pptr;+PCRE2_UCHAR *code = *pcode;+#ifdef PCRE2_DEBUG+PCRE2_UCHAR *start_code = *pcode;+#endif++/* See compile_class_binary_loose() for comments on compile-time folding of+the "negated" flag. */++/* Because it's a non-empty class, there must be an operand at the start. */+if (!compile_class_unary(context, negated, &ptr, &code, pop_info, lengthptr))+ return FALSE;++while (*ptr == META_ECLASS_AND)+ {+ uint32_t op;+ BOOL rhs_negated;+ eclass_op_info rhs_op_info;++ if (negated)+ {+ /* !(A && B) -> !A || !B */+ op = ECL_OR;+ rhs_negated = TRUE;+ }+ else+ {+ /* A && B -> A && B */+ op = ECL_AND;+ rhs_negated = FALSE;+ }++ ++ptr;++ /* An operand must follow the operator. */+ if (!compile_class_unary(context, rhs_negated, &ptr, &code,+ &rhs_op_info, lengthptr))+ return FALSE;++ /* Convert infix to postfix (RPN). */+ fold_binary(op, pop_info, &rhs_op_info, lengthptr);+ if (lengthptr == NULL)+ code = pop_info->code_start + pop_info->length;+ }++PCRE2_ASSERT(lengthptr == NULL || code == start_code);++*pptr = ptr;+*pcode = code;+return TRUE;+}++++/* This function consumes loosely-binding binary operators. */++static BOOL+compile_class_binary_loose(eclass_context *context, BOOL negated,+ uint32_t **pptr, PCRE2_UCHAR **pcode, eclass_op_info *pop_info,+ PCRE2_SIZE *lengthptr)+{+uint32_t *ptr = *pptr;+PCRE2_UCHAR *code = *pcode;+#ifdef PCRE2_DEBUG+PCRE2_UCHAR *start_code = *pcode;+#endif++/* We really want to fold the negation operator, if at all possible, so that+simple cases can be reduced down. In particular, in 8-bit no-UTF mode, we want+to produce a fully-folded expression, so that we can guarantee not to emit any+OP_ECLASS codes (in the same way that we never emit OP_XCLASS in this mode).++This has the consequence that with a little ingenuity, we can in fact avoid+emitting (nearly...) all cases of the "NOT" operator. Imagine that we have:+ !(A ...+We have parsed the preceding "!", and we are about to parse the "A" operand. We+don't know yet whether there will even be a following binary operand! Both of+these are possibilities for what follows:+ !(A && B)+ !(A)+However, we can still fold the "!" into the "A" operand, because no matter what+the following binary operator will be, we can produce an expression which is+equivalent. */++/* Because it's a non-empty class, there must be an operand at the start. */+if (!compile_class_binary_tight(context, negated, &ptr, &code,+ pop_info, lengthptr))+ return FALSE;++while (*ptr >= META_ECLASS_OR && *ptr <= META_ECLASS_XOR)+ {+ uint32_t op;+ BOOL op_neg;+ BOOL rhs_negated;+ eclass_op_info rhs_op_info;++ if (negated)+ {+ /* The whole expression is being negated; we respond by unconditionally+ negating the LHS A, before seeing what follows. And hooray! We can recover,+ no matter what follows. */+ /* !(A || B) -> !A && !B */+ /* !(A -- B) -> !(A && !B) -> !A || B */+ /* !(A XOR B) -> !(!A XOR !B) -> !A XNOR !B */+ op = (*ptr == META_ECLASS_OR )? ECL_AND :+ (*ptr == META_ECLASS_SUB)? ECL_OR :+ /*ptr == META_ECLASS_XOR*/ ECL_XOR;+ op_neg = (*ptr == META_ECLASS_XOR);+ rhs_negated = *ptr != META_ECLASS_SUB;+ }+ else+ {+ /* A || B -> A || B */+ /* A -- B -> A && !B */+ /* A XOR B -> A XOR B */+ op = (*ptr == META_ECLASS_OR )? ECL_OR :+ (*ptr == META_ECLASS_SUB)? ECL_AND :+ /*ptr == META_ECLASS_XOR*/ ECL_XOR;+ op_neg = FALSE;+ rhs_negated = *ptr == META_ECLASS_SUB;+ }++ ++ptr;++ /* An operand must follow the operator. */+ if (!compile_class_binary_tight(context, rhs_negated, &ptr, &code,+ &rhs_op_info, lengthptr))+ return FALSE;++ /* Convert infix to postfix (RPN). */+ fold_binary(op, pop_info, &rhs_op_info, lengthptr);+ if (op_neg) fold_negation(pop_info, lengthptr, FALSE);+ if (lengthptr == NULL)+ code = pop_info->code_start + pop_info->length;+ }++PCRE2_ASSERT(lengthptr == NULL || code == start_code);++*pptr = ptr;+*pcode = code;+return TRUE;+}++++/* This function converts the META codes in pptr into opcodes written to+pcode. The pptr must start at a META_CLASS or META_CLASS_NOT.++The class is compiled as a left-associative sequence of operator+applications.++The pptr will be left pointing at the matching META_CLASS_END. */++static BOOL+compile_eclass_nested(eclass_context *context, BOOL negated,+ uint32_t **pptr, PCRE2_UCHAR **pcode,+ eclass_op_info *pop_info, PCRE2_SIZE *lengthptr)+{+uint32_t *ptr = *pptr;+#ifdef PCRE2_DEBUG+PCRE2_UCHAR *start_code = *pcode;+#endif++/* The CLASS_IS_ECLASS bit must be set since it is a nested class. */+PCRE2_ASSERT(*ptr == (META_CLASS | CLASS_IS_ECLASS) ||+ *ptr == (META_CLASS_NOT | CLASS_IS_ECLASS));++if (*ptr++ == (META_CLASS_NOT | CLASS_IS_ECLASS))+ negated = !negated;++(*pptr)++;++/* Because it's a non-empty class, there must be an operand at the start. */+if (!compile_class_binary_loose(context, negated, pptr, pcode,+ pop_info, lengthptr))+ return FALSE;++PCRE2_ASSERT(**pptr == META_CLASS_END);+PCRE2_ASSERT(lengthptr == NULL || *pcode == start_code);+return TRUE;+}++BOOL+PRIV(compile_class_nested)(uint32_t options, uint32_t xoptions,+ uint32_t **pptr, PCRE2_UCHAR **pcode, int *errorcodeptr,+ compile_block *cb, PCRE2_SIZE *lengthptr)+{+eclass_context context;+eclass_op_info op_info;+PCRE2_SIZE previous_length = (lengthptr != NULL)? *lengthptr : 0;+PCRE2_UCHAR *code = *pcode;+PCRE2_UCHAR *previous;+BOOL allbitsone = TRUE;++context.needs_bitmap = FALSE;+context.options = options;+context.xoptions = xoptions;+context.errorcodeptr = errorcodeptr;+context.cb = cb;++previous = code;+*code++ = OP_ECLASS;+code += LINK_SIZE;+*code++ = 0; /* Flags, currently zero. */+if (!compile_eclass_nested(&context, FALSE, pptr, &code, &op_info, lengthptr))+ return FALSE;++if (lengthptr != NULL)+ {+ *lengthptr += code - previous;+ code = previous;+ /* (*lengthptr - previous_length) now holds the amount of buffer that+ we require to make the call to compile_class_nested() with+ lengthptr = NULL, and including the (1+LINK_SIZE+1) that we write out+ before that call. */+ }++/* Do some useful counting of what's in the bitmap. */+for (int i = 0; i < 8; i++)+ if (op_info.bits.classwords[i] != 0xffffffff)+ {+ allbitsone = FALSE;+ break;+ }++/* After constant-folding the extended class syntax, it may turn out to be+a simple class after all. In that case, we can unwrap it from the+OP_ECLASS container - and in fact, we must do so, because in 8-bit+no-Unicode mode the matcher is compiled without support for OP_ECLASS. */++#ifndef SUPPORT_WIDE_CHARS+PCRE2_ASSERT(op_info.op_single_type != 0);+#else+if (op_info.op_single_type != 0)+#endif+ {+ /* Rewind back over the OP_ECLASS. */+ code = previous;++ /* If the bits are all ones, and the "high characters" are all matched+ too, we use a special-cased encoding of OP_ALLANY. */++ if (op_info.op_single_type == ECL_ANY && allbitsone)+ {+ /* Advancing code means rewinding lengthptr, at this point. */+ if (lengthptr != NULL) *lengthptr -= 1;+ *code++ = OP_ALLANY;+ }++ /* If the high bits are all matched / all not-matched, then we emit an+ OP_NCLASS/OP_CLASS respectively. */++ else if (op_info.op_single_type == ECL_ANY ||+ op_info.op_single_type == ECL_NONE)+ {+ PCRE2_SIZE required_len = 1 + (32 / sizeof(PCRE2_UCHAR));++ if (lengthptr != NULL)+ {+ if (required_len > (*lengthptr - previous_length))+ *lengthptr = previous_length + required_len;+ }++ /* Advancing code means rewinding lengthptr, at this point. */+ if (lengthptr != NULL) *lengthptr -= required_len;+ *code++ = (op_info.op_single_type == ECL_ANY)? OP_NCLASS : OP_CLASS;+ memcpy(code, op_info.bits.classbits, 32);+ code += 32 / sizeof(PCRE2_UCHAR);+ }++ /* Otherwise, we have an ECL_XCLASS, so we have the OP_XCLASS data+ there, but, we pulled out its bitmap into op_info, so now we have to+ put that back into the OP_XCLASS. */++ else+ {+#ifndef SUPPORT_WIDE_CHARS+ PCRE2_DEBUG_UNREACHABLE();+#else+ BOOL need_map = context.needs_bitmap;+ PCRE2_SIZE required_len;++ PCRE2_ASSERT(op_info.op_single_type == ECL_XCLASS);+ required_len = op_info.length + (need_map? 32/sizeof(PCRE2_UCHAR) : 0);++ if (lengthptr != NULL)+ {+ /* Don't unconditionally request all the space we need - we may+ already have asked for more during processing of the ECLASS. */+ if (required_len > (*lengthptr - previous_length))+ *lengthptr = previous_length + required_len;++ /* The code we write out here won't be ignored, even during the+ (lengthptr != NULL) phase, because if there's a following quantifier+ it will peek backwards. So we do have to write out a (truncated)+ OP_XCLASS, even on this branch. */+ *lengthptr -= 1 + LINK_SIZE + 1;+ *code++ = OP_XCLASS;+ PUT(code, 0, 1 + LINK_SIZE + 1);+ code += LINK_SIZE;+ *code++ = 0;+ }+ else+ {+ PCRE2_UCHAR *rest;+ PCRE2_SIZE rest_len;+ PCRE2_UCHAR flags;++ /* 1 unit: OP_XCLASS | LINK_SIZE units | 1 unit: flags | ...rest */+ PCRE2_ASSERT(op_info.length >= 1 + LINK_SIZE + 1);+ rest = op_info.code_start + 1 + LINK_SIZE + 1;+ rest_len = (op_info.code_start + op_info.length) - rest;++ /* First read any data we use, before memmove splats it. */+ flags = op_info.code_start[1 + LINK_SIZE];+ PCRE2_ASSERT((flags & XCL_MAP) == 0);++ /* Next do the memmove before any writes. */+ memmove(code + 1 + LINK_SIZE + 1 + (need_map? 32/sizeof(PCRE2_UCHAR) : 0),+ rest, CU2BYTES(rest_len));++ /* Finally write the header data. */+ *code++ = OP_XCLASS;+ PUT(code, 0, (int)required_len);+ code += LINK_SIZE;+ *code++ = flags | (need_map? XCL_MAP : 0);+ if (need_map)+ {+ memcpy(code, op_info.bits.classbits, 32);+ code += 32 / sizeof(PCRE2_UCHAR);+ }+ code += rest_len;+ }+#endif /* SUPPORT_WIDE_CHARS */+ }+ }++/* Otherwise, we're going to keep the OP_ECLASS. However, again we need+to do some adjustment to insert the bitmap if we have one. */++#ifdef SUPPORT_WIDE_CHARS+else+ {+ BOOL need_map = context.needs_bitmap;+ PCRE2_SIZE required_len =+ 1 + LINK_SIZE + 1 + (need_map? 32/sizeof(PCRE2_UCHAR) : 0) + op_info.length;++ if (lengthptr != NULL)+ {+ if (required_len > (*lengthptr - previous_length))+ *lengthptr = previous_length + required_len;++ /* As for the XCLASS branch above, we do have to write out a dummy+ OP_ECLASS, because of the backwards peek by the quantifier code. Write+ out a (truncated) OP_ECLASS, even on this branch. */+ *lengthptr -= 1 + LINK_SIZE + 1;+ *code++ = OP_ECLASS;+ PUT(code, 0, 1 + LINK_SIZE + 1);+ code += LINK_SIZE;+ *code++ = 0;+ }+ else+ {+ if (need_map)+ {+ PCRE2_UCHAR *map_start = previous + 1 + LINK_SIZE + 1;+ previous[1 + LINK_SIZE] |= ECL_MAP;+ memmove(map_start + 32/sizeof(PCRE2_UCHAR), map_start,+ CU2BYTES(code - map_start));+ memcpy(map_start, op_info.bits.classbits, 32);+ code += 32 / sizeof(PCRE2_UCHAR);+ }+ PUT(previous, 1, (int)(code - previous));+ }+ }+#endif /* SUPPORT_WIDE_CHARS */++*pcode = code;+return TRUE;+}++/* End of pcre2_compile_class.c */
src/c/pcre2/src/pcre2_config.c view
@@ -38,17 +38,10 @@ ----------------------------------------------------------------------------- */ -#ifdef HAVE_CONFIG_H-#include "config.h"-#endif -/* Save the configured link size, which is in bytes. In 16-bit and 32-bit modes-its value gets changed by pcre2_intmodedep.h (included by pcre2_internal.h) to-be in code units. */+#include "pcre2_internal.h" -static int configured_link_size = LINK_SIZE; -#include "pcre2_internal.h" /* These macros are the standard way of turning unquoted text into C strings. They allow macros like PCRE2_MAJOR to be defined without quotes, which is@@ -79,7 +72,7 @@ { if (where == NULL) /* Requests a length */ {- switch(what)+ switch (what) { default: return PCRE2_ERROR_BADOPTION;@@ -87,6 +80,7 @@ case PCRE2_CONFIG_BSR: case PCRE2_CONFIG_COMPILED_WIDTHS: case PCRE2_CONFIG_DEPTHLIMIT:+ case PCRE2_CONFIG_EFFECTIVE_LINKSIZE: case PCRE2_CONFIG_HEAPLIMIT: case PCRE2_CONFIG_JIT: case PCRE2_CONFIG_LINKSIZE:@@ -124,13 +118,13 @@ case PCRE2_CONFIG_COMPILED_WIDTHS: *((uint32_t *)where) = 0 #ifdef SUPPORT_PCRE2_8- + 1+ + (1 << 0) #endif #ifdef SUPPORT_PCRE2_16- + 2+ + (1 << 1) #endif #ifdef SUPPORT_PCRE2_32- + 4+ + (1 << 2) #endif ; break;@@ -139,6 +133,10 @@ *((uint32_t *)where) = MATCH_LIMIT_DEPTH; break; + case PCRE2_CONFIG_EFFECTIVE_LINKSIZE:+ *((uint32_t *)where) = LINK_SIZE * sizeof(PCRE2_UCHAR);+ break;+ case PCRE2_CONFIG_HEAPLIMIT: *((uint32_t *)where) = HEAP_LIMIT; break;@@ -163,7 +161,7 @@ #endif case PCRE2_CONFIG_LINKSIZE:- *((uint32_t *)where) = (uint32_t)configured_link_size;+ *((uint32_t *)where) = (uint32_t)CONFIGURED_LINK_SIZE; break; case PCRE2_CONFIG_MATCHLIMIT:@@ -206,8 +204,7 @@ #endif return (int)(1 + ((where == NULL)? strlen(v) : PRIV(strcpy_c8)((PCRE2_UCHAR *)where, v)));- }- break;+ } case PCRE2_CONFIG_UNICODE: #if defined SUPPORT_UNICODE@@ -224,8 +221,8 @@ XSTRING when PCRE2_PRERELEASE is not empty, an unwanted space is inserted. There are problems using an "obvious" approach like this: - XSTRING(PCRE2_MAJOR) "." XSTRING(PCRE_MINOR)- XSTRING(PCRE2_PRERELEASE) " " XSTRING(PCRE_DATE)+ XSTRING(PCRE2_MAJOR) "." XSTRING(PCRE2_MINOR)+ XSTRING(PCRE2_PRERELEASE) " " XSTRING(PCRE2_DATE) because, when PCRE2_PRERELEASE is empty, this leads to an attempted expansion of STRING(). The C standard states: "If (before argument substitution) any@@ -244,6 +241,7 @@ return (int)(1 + ((where == NULL)? strlen(v) : PRIV(strcpy_c8)((PCRE2_UCHAR *)where, v))); }+ } return 0;
src/c/pcre2/src/pcre2_context.c view
@@ -39,10 +39,6 @@ */ -#ifdef HAVE_CONFIG_H-#include "config.h"-#endif- #include "pcre2_internal.h" @@ -130,7 +126,7 @@ /* A default compile context is set up to save having to initialize at run time when no context is supplied to the compile function. */ -const pcre2_compile_context PRIV(default_compile_context) = {+pcre2_compile_context PRIV(default_compile_context) = { { default_malloc, default_free, NULL }, /* Default memory handling */ NULL, /* Stack guard */ NULL, /* Stack guard data */@@ -141,7 +137,8 @@ NEWLINE_DEFAULT, /* Newline convention */ PARENS_NEST_LIMIT, /* As it says */ 0, /* Extra options */- MAX_VARLOOKBEHIND /* As it says */+ MAX_VARLOOKBEHIND, /* As it says */+ PCRE2_OPTIMIZATION_ALL /* All optimizations enabled */ }; /* The create function copies the default into the new memory, but must@@ -163,7 +160,7 @@ /* A default match context is set up to save having to initialize at run time when no context is supplied to a match function. */ -const pcre2_match_context PRIV(default_match_context) = {+pcre2_match_context PRIV(default_match_context) = { { default_malloc, default_free, NULL }, #ifdef SUPPORT_JIT NULL, /* JIT callback */@@ -173,6 +170,8 @@ NULL, /* Callout data */ NULL, /* Substitute callout function */ NULL, /* Substitute callout data */+ NULL, /* Substitute case callout function */+ NULL, /* Substitute case callout data */ PCRE2_UNSET, /* Offset limit */ HEAP_LIMIT, MATCH_LIMIT,@@ -197,7 +196,7 @@ /* A default convert context is set up to save having to initialize at run time when no context is supplied to the convert function. */ -const pcre2_convert_context PRIV(default_convert_context) = {+pcre2_convert_context PRIV(default_convert_context) = { { default_malloc, default_free, NULL }, /* Default memory handling */ #ifdef _WIN32 CHAR_BACKSLASH, /* Default path separator */@@ -409,7 +408,39 @@ return 0; } +PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_set_optimize(pcre2_compile_context *ccontext, uint32_t directive)+{+if (ccontext == NULL)+ return PCRE2_ERROR_NULL; +switch (directive)+ {+ case PCRE2_OPTIMIZATION_NONE:+ ccontext->optimization_flags = 0;+ break;++ case PCRE2_OPTIMIZATION_FULL:+ ccontext->optimization_flags = PCRE2_OPTIMIZATION_ALL;+ break;++ default:+ if (directive >= PCRE2_AUTO_POSSESS && directive <= PCRE2_START_OPTIMIZE_OFF)+ {+ /* Even directive numbers starting from 64 switch a bit on;+ * Odd directive numbers starting from 65 switch a bit off */+ if ((directive & 1) != 0)+ ccontext->optimization_flags &= ~(1u << ((directive >> 1) - 32));+ else+ ccontext->optimization_flags |= 1u << ((directive >> 1) - 32);+ return 0;+ }+ return PCRE2_ERROR_BADOPTION;+ }++return 0;+}+ /* ------------ Match context ------------ */ PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION@@ -424,7 +455,7 @@ PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION pcre2_set_substitute_callout(pcre2_match_context *mcontext, int (*substitute_callout)(pcre2_substitute_callout_block *, void *),- void *substitute_callout_data)+ void *substitute_callout_data) { mcontext->substitute_callout = substitute_callout; mcontext->substitute_callout_data = substitute_callout_data;@@ -432,6 +463,17 @@ } PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_set_substitute_case_callout(pcre2_match_context *mcontext,+ PCRE2_SIZE (*substitute_case_callout)(PCRE2_SPTR, PCRE2_SIZE, PCRE2_UCHAR *,+ PCRE2_SIZE, int, void *),+ void *substitute_case_callout_data)+{+mcontext->substitute_case_callout = substitute_case_callout;+mcontext->substitute_case_callout_data = substitute_case_callout_data;+return 0;+}++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION pcre2_set_heap_limit(pcre2_match_context *mcontext, uint32_t limit) { mcontext->heap_limit = limit;@@ -460,10 +502,7 @@ } /* 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 */+synonym for backwards compatibility. The second now does nothing. */ PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION pcre2_set_recursion_limit(pcre2_match_context *mcontext, uint32_t limit)@@ -483,9 +522,7 @@ return 0; } -/* LCOV_EXCL_STOP */ - /* ------------ Convert context ------------ */ PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION@@ -497,10 +534,20 @@ return 0; } +static const char *globpunct =+ STR_EXCLAMATION_MARK STR_QUOTATION_MARK STR_NUMBER_SIGN STR_DOLLAR_SIGN+ STR_PERCENT_SIGN STR_AMPERSAND STR_APOSTROPHE STR_LEFT_PARENTHESIS+ STR_RIGHT_PARENTHESIS STR_ASTERISK STR_PLUS STR_COMMA STR_MINUS STR_DOT+ STR_SLASH STR_COLON STR_SEMICOLON STR_LESS_THAN_SIGN STR_EQUALS_SIGN+ STR_GREATER_THAN_SIGN STR_QUESTION_MARK STR_COMMERCIAL_AT+ STR_LEFT_SQUARE_BRACKET STR_BACKSLASH STR_RIGHT_SQUARE_BRACKET+ STR_CIRCUMFLEX_ACCENT STR_UNDERSCORE STR_GRAVE_ACCENT STR_LEFT_CURLY_BRACKET+ STR_VERTICAL_LINE STR_RIGHT_CURLY_BRACKET STR_TILDE;+ PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION pcre2_set_glob_escape(pcre2_convert_context *ccontext, uint32_t escape) {-if (escape > 255 || (escape != 0 && !ispunct(escape)))+if (escape > 255 || (escape != 0 && strchr(globpunct, escape) == NULL)) return PCRE2_ERROR_BADDATA; ccontext->glob_escape = escape; return 0;
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-2022 University of Cambridge+ New API code Copyright (c) 2016-2024 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -39,12 +39,10 @@ */ -#ifdef HAVE_CONFIG_H-#include "config.h"-#endif- #include "pcre2_internal.h" ++ #define TYPE_OPTIONS (PCRE2_CONVERT_GLOB| \ PCRE2_CONVERT_POSIX_BASIC|PCRE2_CONVERT_POSIX_EXTENDED) @@ -74,13 +72,23 @@ #define PUTCHARS(string) \ { \- for (s = (char *)(string); *s != 0; s++) \+ for (const char *s = string; *s != 0; s++) \ { \ if (p >= endp) return PCRE2_ERROR_NOMEMORY; \ *p++ = *s; \ } \ } +/* Macro to check for lowercase characters. */++#ifdef EBCDIC+#define ISLOWER(c) (((c) >= CHAR_a && (c) <= CHAR_i) || \+ ((c) >= CHAR_j && (c) <= CHAR_r) || \+ ((c) >= CHAR_s && (c) <= CHAR_z))+#else+#define ISLOWER(c) ((c) >= CHAR_a && (c) <= CHAR_z)+#endif+ /* Literals that must be escaped: \ ? * + | . ^ $ { } [ ] ( ) */ static const char *pcre2_escaped_literals =@@ -97,8 +105,26 @@ STR_LEFT_CURLY_BRACKET STR_RIGHT_CURLY_BRACKET STR_1 STR_2 STR_3 STR_4 STR_5 STR_6 STR_7 STR_8 STR_9; +/* Recognized POSIX classes, colon-separated. */ +static const char *posix_classes =+ STR_a STR_l STR_p STR_h STR_a STR_COLON+ STR_l STR_o STR_w STR_e STR_r STR_COLON+ STR_u STR_p STR_p STR_e STR_r STR_COLON+ STR_a STR_l STR_n STR_u STR_m STR_COLON+ STR_a STR_s STR_c STR_i STR_i STR_COLON+ STR_b STR_l STR_a STR_n STR_k STR_COLON+ STR_c STR_n STR_t STR_r STR_l STR_COLON+ STR_d STR_i STR_g STR_i STR_t STR_COLON+ STR_g STR_r STR_a STR_p STR_h STR_COLON+ STR_p STR_r STR_i STR_n STR_t STR_COLON+ STR_p STR_u STR_n STR_c STR_t STR_COLON+ STR_s STR_p STR_a STR_c STR_e STR_COLON+ STR_w STR_o STR_r STR_d STR_COLON+ STR_x STR_d STR_i STR_g STR_i STR_t STR_COLON; ++ /************************************************* * Convert a POSIX pattern * *************************************************/@@ -125,7 +151,6 @@ BOOL utf, PCRE2_UCHAR *use_buffer, PCRE2_SIZE use_length, PCRE2_SIZE *bufflenptr, BOOL dummyrun, pcre2_convert_context *ccontext) {-char *s; PCRE2_SPTR posix = pattern; PCRE2_UCHAR *p = use_buffer; PCRE2_UCHAR *pp = p;@@ -191,7 +216,7 @@ switch (posix_state) { case POSIX_CLASS_STARTED:- if (c <= 127 && islower(c)) break; /* Remain in started state */+ if (ISLOWER(c)) break; /* Remain in started state */ posix_state = POSIX_CLASS_NOT_STARTED; if (c == CHAR_COLON && plength > 0 && *posix == CHAR_RIGHT_SQUARE_BRACKET)@@ -201,7 +226,7 @@ posix++; continue; /* With next character after :] */ }- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case POSIX_CLASS_NOT_STARTED: if (c == CHAR_LEFT_SQUARE_BRACKET)@@ -278,9 +303,9 @@ if (plength == 0) return PCRE2_ERROR_END_BACKSLASH; if (extended) nextisliteral = TRUE; else {- if (*posix < 127 && strchr(posix_meta_escapes, *posix) != NULL)+ if (*posix < 255 && strchr(posix_meta_escapes, *posix) != NULL) {- if (isdigit(*posix)) PUTCHARS(STR_BACKSLASH);+ if (*posix >= CHAR_0 && *posix <= CHAR_9) PUTCHARS(STR_BACKSLASH); if (p + 1 > endp) return PCRE2_ERROR_NOMEMORY; lastspecial = *p++ = *posix++; plength--;@@ -296,7 +321,7 @@ case CHAR_LEFT_PARENTHESIS: bracount++;- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case CHAR_QUESTION_MARK: case CHAR_PLUS:@@ -304,7 +329,7 @@ case CHAR_RIGHT_CURLY_BRACKET: case CHAR_VERTICAL_LINE: if (!extended) goto ESCAPE_LITERAL;- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case CHAR_DOT: case CHAR_DOLLAR_SIGN:@@ -333,10 +358,10 @@ posix_state = POSIX_ANCHORED; goto COPY_SPECIAL; }- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ default:- if (c < 128 && strchr(pcre2_escaped_literals, c) != NULL)+ if (c < 255 && strchr(pcre2_escaped_literals, c) != NULL) { ESCAPE_LITERAL: PUTCHARS(STR_BACKSLASH);@@ -475,8 +500,6 @@ convert_glob_parse_class(PCRE2_SPTR *from, PCRE2_SPTR pattern_end, pcre2_output_context *out) {-static const char *posix_classes = "alnum:alpha:ascii:blank:cntrl:digit:"- "graph:lower:print:punct:space:upper:word:xdigit:"; PCRE2_SPTR start = *from + 1; PCRE2_SPTR pattern = start; const char *class_ptr;@@ -501,7 +524,7 @@ while (TRUE) {- if (*class_ptr == CHAR_NUL) return 0;+ if (*class_ptr == 0) return 0; pattern = start; @@ -540,31 +563,61 @@ static BOOL convert_glob_char_in_class(int class_index, PCRE2_UCHAR c) {+const uint8_t *cbits = PRIV(default_tables) + cbits_offset;+int cbit;+ #if PCRE2_CODE_UNIT_WIDTH != 8 if (c > 0xff) {- /* ctype functions are not sane for c > 0xff */- return 0;+ /* Can't access the character tables for c > 0xff */+ return FALSE; } #endif +/* See posix_class_maps. This is a small local clone of that.+Note that we don't know exactly what character tables will be used at+match time, but, for the purposes of pattern conversion, it should be+sufficient to use PCRE2's built-in default tables. */+ switch (class_index) {- case 1: return isalnum(c);- case 2: return isalpha(c);- case 3: return 1;- case 4: return c == CHAR_HT || c == CHAR_SPACE;- case 5: return iscntrl(c);- case 6: return isdigit(c);- case 7: return isgraph(c);- case 8: return islower(c);- case 9: return isprint(c);- case 10: return ispunct(c);- case 11: return isspace(c);- case 12: return isupper(c);- case 13: return isalnum(c) || c == CHAR_UNDERSCORE;- default: return isxdigit(c);+ case 1: /* alpha */+ if (c == CHAR_UNDERSCORE) return FALSE;+ if (((cbits + cbit_digit)[c/8] & (1u << (c&7))) != 0) return FALSE;+ cbit = cbit_word;+ break;++ case 2: cbit = cbit_lower; break; /* lower */+ case 3: cbit = cbit_upper; break; /* upper */++ case 4: /* alnum */+ if (c == CHAR_UNDERSCORE) return FALSE;+ cbit = cbit_word;+ break;++ case 5: /* ascii */+ if (((cbits + cbit_cntrl)[c/8] & (1u << (c&7))) != 0) return TRUE;+ cbit = cbit_print;+ break;++ case 6: /* blank */+ if (c == CHAR_LF || c == CHAR_VT || c == CHAR_FF || c == CHAR_CR)+ return FALSE;+ cbit = cbit_space;+ break;++ case 7: cbit = cbit_cntrl; break; /* cntrl */+ case 8: cbit = cbit_digit; break; /* digit */+ case 9: cbit = cbit_graph; break; /* graph */+ case 10: cbit = cbit_print; break; /* print */+ case 11: cbit = cbit_punct; break; /* punct */+ case 12: cbit = cbit_space; break; /* space */+ case 13: cbit = cbit_word; break; /* word */+ case 14: cbit = cbit_xdigit; break; /* xdigit */+ default: return FALSE; }++return ((cbits + cbit)[c/8] & (1u << (c&7))) != 0; } /* Parse a range of characters.@@ -1006,7 +1059,7 @@ c = *pattern++; } - if (c < 128 && strchr(pcre2_escaped_literals, c) != NULL)+ if (c < 255 && strchr(pcre2_escaped_literals, c) != NULL) convert_glob_write(&out, CHAR_BACKSLASH); convert_glob_write(&out, c);@@ -1065,15 +1118,23 @@ PCRE2_UCHAR **buffptr, PCRE2_SIZE *bufflenptr, pcre2_convert_context *ccontext) {-int i, rc;+int rc;+PCRE2_UCHAR null_str[1] = { 0xcd }; PCRE2_UCHAR dummy_buffer[DUMMY_BUFFER_SIZE]; PCRE2_UCHAR *use_buffer = dummy_buffer; PCRE2_SIZE use_length = DUMMY_BUFFER_SIZE; BOOL utf = (options & PCRE2_CONVERT_UTF) != 0; uint32_t pattype = options & TYPE_OPTIONS; -if (pattern == NULL || bufflenptr == NULL) return PCRE2_ERROR_NULL;+if (pattern == NULL && plength == 0)+ pattern = null_str; +if (pattern == NULL || bufflenptr == NULL)+ {+ if (bufflenptr != NULL) *bufflenptr = 0; /* Error offset */+ return PCRE2_ERROR_NULL;+ }+ if ((options & ~ALL_OPTIONS) != 0 || /* Undefined bit set */ (pattype & (~pattype+1)) != pattype || /* More than one type set */ pattype == 0) /* No type set */@@ -1119,7 +1180,7 @@ /* Call an individual converter, either just once (if a buffer was provided or just the length is needed), or twice (if a memory allocation is required). */ -for (i = 0; i < 2; i++)+for (int i = 0; i < 2; i++) { PCRE2_UCHAR *allocated; BOOL dummyrun = buffptr == NULL || *buffptr == NULL;@@ -1137,9 +1198,13 @@ bufflenptr, dummyrun, ccontext); break; + /* We have already validated pattype. */+ /* LCOV_EXCL_START */ default:+ PCRE2_DEBUG_UNREACHABLE(); *bufflenptr = 0; /* Error offset */ return PCRE2_ERROR_INTERNAL;+ /* LCOV_EXCL_STOP */ } if (rc != 0 || /* Error */@@ -1152,16 +1217,23 @@ allocated = PRIV(memctl_malloc)(sizeof(pcre2_memctl) + (*bufflenptr + 1)*PCRE2_CODE_UNIT_WIDTH, (pcre2_memctl *)ccontext);- if (allocated == NULL) return PCRE2_ERROR_NOMEMORY;+ if (allocated == NULL)+ {+ *bufflenptr = 0; /* Error offset */+ return PCRE2_ERROR_NOMEMORY;+ } *buffptr = (PCRE2_UCHAR *)(((char *)allocated) + sizeof(pcre2_memctl)); use_buffer = *buffptr; use_length = *bufflenptr + 1; } -/* Control should never get here. */-+/* Running the loop above ought to have succeeded the second time. */+/* LCOV_EXCL_START */+PCRE2_DEBUG_UNREACHABLE();+*bufflenptr = 0; /* Error offset */ return PCRE2_ERROR_INTERNAL;+/* LCOV_EXCL_STOP */ }
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-2023 University of Cambridge+ New API code Copyright (c) 2016-2024 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -72,16 +72,14 @@ in others, so I abandoned this code. */ -#ifdef HAVE_CONFIG_H-#include "config.h"-#endif+#include "pcre2_internal.h" ++ #define NLBLOCK mb /* Block containing newline information */ #define PSSTART start_subject /* Field containing processed string start */ #define PSEND end_subject /* Field containing processed string end */ -#include "pcre2_internal.h"- #define PUBLIC_DFA_MATCH_OPTIONS \ (PCRE2_ANCHORED|PCRE2_ENDANCHORED|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY| \ PCRE2_NOTEMPTY_ATSTART|PCRE2_NO_UTF_CHECK|PCRE2_PARTIAL_HARD| \@@ -156,6 +154,7 @@ 0, /* CLASS */ 0, /* NCLASS */ 0, /* XCLASS - variable length */+ 0, /* ECLASS - variable length */ 0, /* REF */ 0, /* REFI */ 0, /* DNREF */@@ -175,6 +174,7 @@ 0, /* Assert behind not */ 0, /* NA assert */ 0, /* NA assert behind */+ 0, /* Assert scan substring */ 0, /* ONCE */ 0, /* SCRIPT_RUN */ 0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */@@ -188,7 +188,7 @@ 0, 0, /* COMMIT, COMMIT_ARG */ 0, 0, 0, /* FAIL, ACCEPT, ASSERT_ACCEPT */ 0, 0, 0, /* CLOSE, SKIPZERO, DEFINE */- 0, 0 /* \B and \b in UCP mode */+ 0, 0, /* \B and \b in UCP mode */ }; /* This table identifies those opcodes that inspect a character. It is used to@@ -234,6 +234,7 @@ 1, /* CLASS */ 1, /* NCLASS */ 1, /* XCLASS - variable length */+ 1, /* ECLASS - variable length */ 0, /* REF */ 0, /* REFI */ 0, /* DNREF */@@ -253,6 +254,7 @@ 0, /* Assert behind not */ 0, /* NA assert */ 0, /* NA assert behind */+ 0, /* Assert scan substring */ 0, /* ONCE */ 0, /* SCRIPT_RUN */ 0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */@@ -266,9 +268,13 @@ 0, 0, /* COMMIT, COMMIT_ARG */ 0, 0, 0, /* FAIL, ACCEPT, ASSERT_ACCEPT */ 0, 0, 0, /* CLOSE, SKIPZERO, DEFINE */- 1, 1 /* \B and \b in UCP mode */+ 1, 1, /* \B and \b in UCP mode */ }; +/* Compile-time check that these tables have the correct size. */+STATIC_ASSERT(sizeof(coptable) == OP_TABLE_LENGTH, coptable);+STATIC_ASSERT(sizeof(poptable) == OP_TABLE_LENGTH, poptable);+ /* These 2 tables allow for compact code for testing for \D, \d, \S, \s, \W, and \w */ @@ -695,7 +701,6 @@ int i, j; int clen, dlen; uint32_t c, d;- int forced_fail = 0; BOOL partial_newline = FALSE; BOOL could_continue = reset_could_continue; reset_could_continue = FALSE;@@ -842,19 +847,6 @@ switch (codevalue) { /* ========================================================================== */- /* These cases are never obeyed. This is a fudge that causes a compile-- time error if the vectors coptable or poptable, which are indexed by- opcode, are not the correct length. It seems to be the only way to do- such a check at compile time, as the sizeof() operator does not work- in the C preprocessor. */-- case OP_TABLE_LENGTH:- case OP_TABLE_LENGTH +- ((sizeof(coptable) == OP_TABLE_LENGTH) &&- (sizeof(poptable) == OP_TABLE_LENGTH)):- return 0;--/* ========================================================================== */ /* Reached a closing bracket. If not at the end of the pattern, carry on with the next opcode. For repeating opcodes, also add the repeat state. Note that KETRPOS will always be encountered at the end of the@@ -1179,10 +1171,6 @@ const ucd_record * prop = GET_UCD(c); switch(code[1]) {- case PT_ANY:- OK = TRUE;- break;- case PT_LAMP: chartype = prop->chartype; OK = chartype == ucp_Lu || chartype == ucp_Ll ||@@ -1462,10 +1450,6 @@ const ucd_record * prop = GET_UCD(c); switch(code[2]) {- case PT_ANY:- OK = TRUE;- break;- case PT_LAMP: chartype = prop->chartype; OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt;@@ -1727,10 +1711,6 @@ const ucd_record * prop = GET_UCD(c); switch(code[2]) {- case PT_ANY:- OK = TRUE;- break;- case PT_LAMP: chartype = prop->chartype; OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt;@@ -2017,10 +1997,6 @@ const ucd_record * prop = GET_UCD(c); switch(code[1 + IMM2_SIZE + 1]) {- case PT_ANY:- OK = TRUE;- break;- case PT_LAMP: chartype = prop->chartype; OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt;@@ -2352,7 +2328,7 @@ case 0x2029: #endif /* Not EBCDIC */ if (mb->bsr_convention == PCRE2_BSR_ANYCRLF) break;- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case CHAR_LF: ADD_NEW(state_offset + 1, 0);@@ -2464,7 +2440,7 @@ caseless = TRUE; codevalue -= OP_STARI - OP_STAR; - /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case OP_PLUS: case OP_MINPLUS: case OP_POSPLUS:@@ -2508,7 +2484,7 @@ case OP_NOTPOSQUERYI: caseless = TRUE; codevalue -= OP_STARI - OP_STAR;- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case OP_QUERY: case OP_MINQUERY: case OP_POSQUERY:@@ -2549,7 +2525,7 @@ case OP_NOTPOSSTARI: caseless = TRUE; codevalue -= OP_STARI - OP_STAR;- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case OP_STAR: case OP_MINSTAR: case OP_POSSTAR:@@ -2586,7 +2562,7 @@ case OP_NOTEXACTI: caseless = TRUE; codevalue -= OP_STARI - OP_STAR;- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case OP_EXACT: case OP_NOTEXACT: count = current_state->count; /* Number already matched */@@ -2621,7 +2597,7 @@ case OP_NOTPOSUPTOI: caseless = TRUE; codevalue -= OP_STARI - OP_STAR;- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case OP_UPTO: case OP_MINUPTO: case OP_POSUPTO:@@ -2663,35 +2639,54 @@ case OP_CLASS: case OP_NCLASS:+#ifdef SUPPORT_WIDE_CHARS case OP_XCLASS:+ case OP_ECLASS:+#endif { BOOL isinclass = FALSE; int next_state_offset; PCRE2_SPTR ecode; +#ifdef SUPPORT_WIDE_CHARS+ /* An extended class may have a table or a list of single characters,+ ranges, or both, and it may be positive or negative. There's a+ function that sorts all this out. */++ if (codevalue == OP_XCLASS)+ {+ ecode = code + GET(code, 1);+ if (clen > 0)+ isinclass = PRIV(xclass)(c, code + 1 + LINK_SIZE,+ (const uint8_t*)mb->start_code, utf);+ }++ /* A nested set-based class has internal opcodes for performing+ set operations. */++ else if (codevalue == OP_ECLASS)+ {+ ecode = code + GET(code, 1);+ if (clen > 0)+ isinclass = PRIV(eclass)(c, code + 1 + LINK_SIZE, ecode,+ (const uint8_t*)mb->start_code, utf);+ }++ else+#endif /* SUPPORT_WIDE_CHARS */+ /* For a simple class, there is always just a 32-byte table, and we can set isinclass from it. */ - if (codevalue != OP_XCLASS) { ecode = code + 1 + (32 / sizeof(PCRE2_UCHAR)); if (clen > 0) { isinclass = (c > 255)? (codevalue == OP_NCLASS) :- ((((uint8_t *)(code + 1))[c/8] & (1u << (c&7))) != 0);+ ((((const uint8_t *)(code + 1))[c/8] & (1u << (c&7))) != 0); } } - /* An extended class may have a table or a list of single characters,- ranges, or both, and it may be positive or negative. There's a- function that sorts all this out. */-- else- {- ecode = code + GET(code, 1);- if (clen > 0) isinclass = PRIV(xclass)(c, code + 1 + LINK_SIZE, utf);- }- /* At this point, isinclass is set for all kinds of class, and ecode points to the byte after the end of the class. If there is a quantifier, this is where it will be. */@@ -2784,7 +2779,6 @@ though the other "backtracking verbs" are not supported. */ case OP_FAIL:- forced_fail++; /* Count FAILs for multiple states */ break; case OP_ASSERT:@@ -2945,6 +2939,9 @@ uint32_t recno = (callpat == mb->start_code)? 0 : GET2(callpat, 1 + LINK_SIZE); + /* Argument list has not been supported yet. */+ if (code[1 + LINK_SIZE] == OP_CREF) return PCRE2_ERROR_DFA_UITEM;+ if (rws->free < RWS_RSIZE + RWS_OVEC_RSIZE) { rc = more_workspace(&rws, RWS_OVEC_RSIZE, mb);@@ -3058,7 +3055,7 @@ if (codevalue == OP_BRAPOSZERO) { allow_zero = TRUE;- codevalue = *(++code); /* Codevalue will be one of above BRAs */+ ++code; /* The following opcode will be one of the above BRAs */ } else allow_zero = FALSE; @@ -3271,18 +3268,12 @@ matches that we are going to find. If partial matching has been requested, check for appropriate conditions. - The "forced_ fail" variable counts the number of (*F) encountered for the- character. If it is equal to the original active_count (saved in- workspace[1]) it means that (*F) was found on every active state. In this- case we don't want to give a partial match.- The "could_continue" variable is true if a state could have continued but for the fact that the end of the subject was reached. */ if (new_count <= 0) { if (could_continue && /* Some could go on, and */- forced_fail != workspace[1] && /* Not all forced fail & */ ( /* either... */ (mb->moptions & PCRE2_PARTIAL_HARD) != 0 /* Hard partial */ || /* or... */@@ -3351,10 +3342,12 @@ pcre2_match_context *mcontext, int *workspace, PCRE2_SIZE wscount) { int rc;-int was_zero_terminated = 0; const pcre2_real_code *re = (const pcre2_real_code *)code;+uint32_t original_options = options; +PCRE2_UCHAR null_str[1] = { 0xcd };+PCRE2_SPTR original_subject = subject; PCRE2_SPTR start_match; PCRE2_SPTR end_subject; PCRE2_SPTR bumpalong_limit;@@ -3396,49 +3389,51 @@ /* Recognize NULL, length 0 as an empty string. */ -if (subject == NULL && length == 0) subject = (PCRE2_SPTR)"";+if (subject == NULL && length == 0) subject = null_str; /* Plausibility checks */ -if ((options & ~PUBLIC_DFA_MATCH_OPTIONS) != 0) return PCRE2_ERROR_BADOPTION;-if (re == NULL || subject == NULL || workspace == NULL || match_data == NULL)- return PCRE2_ERROR_NULL;+if (match_data == NULL) return PCRE2_ERROR_NULL;+if (re == NULL || subject == NULL || workspace == NULL)+ { rc = PCRE2_ERROR_NULL; goto EXIT; }+if ((options & ~PUBLIC_DFA_MATCH_OPTIONS) != 0)+ { rc = PCRE2_ERROR_BADOPTION; goto EXIT; } if (length == PCRE2_ZERO_TERMINATED) { length = PRIV(strlen)(subject);- was_zero_terminated = 1; } -if (wscount < 20) return PCRE2_ERROR_DFA_WSSIZE;-if (start_offset > length) return PCRE2_ERROR_BADOFFSET;+if (wscount < 20) { rc = PCRE2_ERROR_DFA_WSSIZE; goto EXIT; }+if (start_offset > length) { rc = PCRE2_ERROR_BADOFFSET; goto EXIT; } /* Partial matching and PCRE2_ENDANCHORED are currently not allowed at the same time. */ if ((options & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) != 0 && ((re->overall_options | options) & PCRE2_ENDANCHORED) != 0)- return PCRE2_ERROR_BADOPTION;+ { rc = PCRE2_ERROR_BADOPTION; goto EXIT; } /* Invalid UTF support is not available for DFA matching. */ if ((re->overall_options & PCRE2_MATCH_INVALID_UTF) != 0)- return PCRE2_ERROR_DFA_UINVALID_UTF;+ { rc = PCRE2_ERROR_DFA_UINVALID_UTF; goto EXIT; } /* Check that the first field in the block is the magic number. If it is not, return with PCRE2_ERROR_BADMAGIC. */ -if (re->magic_number != MAGIC_NUMBER) return PCRE2_ERROR_BADMAGIC;+if (re->magic_number != MAGIC_NUMBER)+ { rc = PCRE2_ERROR_BADMAGIC; goto EXIT; } /* Check the code unit width. */ if ((re->flags & PCRE2_MODE_MASK) != PCRE2_CODE_UNIT_WIDTH/8)- return PCRE2_ERROR_BADMODE;+ { rc = PCRE2_ERROR_BADMODE; goto EXIT; } /* PCRE2_NOTEMPTY and PCRE2_NOTEMPTY_ATSTART are match-time flags in the options variable for this function. Users of PCRE2 who are not calling the function directly would like to have a way of setting these flags, in the same-way that they can set pcre2_compile() flags like PCRE2_NO_AUTOPOSSESS with+way that they can set pcre2_compile() flags like PCRE2_NO_AUTO_POSSESS with constructions like (*NO_AUTOPOSSESS). To enable this, (*NOTEMPTY) and (*NOTEMPTY_ATSTART) set bits in the pattern's "flag" function which can now be transferred to the options for this function. The bits are guaranteed to be@@ -3459,8 +3454,8 @@ if ((options & PCRE2_DFA_RESTART) != 0) { if ((workspace[0] & (-2)) != 0 || workspace[1] < 1 ||- workspace[1] > (int)((wscount - 2)/INTS_PER_STATEBLOCK))- return PCRE2_ERROR_DFA_BADRESTART;+ workspace[1] > (int)((wscount - 2)/INTS_PER_STATEBLOCK))+ { rc = PCRE2_ERROR_DFA_BADRESTART; goto EXIT; } } /* Set some local values */@@ -3508,7 +3503,7 @@ if (mcontext->offset_limit != PCRE2_UNSET) { if ((re->overall_options & PCRE2_USE_OFFSET_LIMIT) == 0)- return PCRE2_ERROR_BADOFFSETLIMIT;+ { rc = PCRE2_ERROR_BADOFFSETLIMIT; goto EXIT; } bumpalong_limit = subject + mcontext->offset_limit; } mb->callout = mcontext->callout;@@ -3528,8 +3523,7 @@ if (mb->heap_limit > re->limit_heap) mb->heap_limit = re->limit_heap; -mb->start_code = (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code)) +- re->name_count * re->name_entry_size;+mb->start_code = (PCRE2_SPTR)((const uint8_t *)re + re->code_start); mb->tables = re->tables; mb->start_subject = subject; mb->end_subject = end_subject;@@ -3576,7 +3570,12 @@ mb->nltype = NLTYPE_ANYCRLF; break; - default: return PCRE2_ERROR_INTERNAL;+ /* LCOV_EXCL_START */+ default:+ PCRE2_DEBUG_UNREACHABLE();+ rc = PCRE2_ERROR_INTERNAL;+ goto EXIT;+ /* LCOV_EXCL_STOP */ } /* Check a UTF string for validity if required. For 8-bit and 16-bit strings,@@ -3597,7 +3596,7 @@ #if PCRE2_CODE_UNIT_WIDTH != 32 unsigned int i; if (start_match < end_subject && NOT_FIRSTCU(*start_match))- return PCRE2_ERROR_BADUTFOFFSET;+ { rc = PCRE2_ERROR_BADUTFOFFSET; goto EXIT; } for (i = re->max_lookbehind; i > 0 && check_subject > subject; i--) { check_subject--;@@ -3618,12 +3617,12 @@ /* Validate the relevant portion of the subject. After an error, adjust the offset to be an absolute offset in the whole string. */ - match_data->rc = PRIV(valid_utf)(check_subject,+ rc = PRIV(valid_utf)(check_subject, length - (PCRE2_SIZE)(check_subject - subject), &(match_data->startchar));- if (match_data->rc != 0)+ if (rc != 0) { match_data->startchar += (PCRE2_SIZE)(check_subject - subject);- return match_data->rc;+ goto EXIT; } } #endif /* SUPPORT_UNICODE */@@ -3687,9 +3686,10 @@ /* Fill in fields that are always returned in the match data. */ match_data->code = re;-match_data->subject = NULL; /* Default for no match */+match_data->subject = NULL; /* Default for match error */ match_data->mark = NULL; match_data->matchedby = PCRE2_MATCHEDBY_DFA_INTERPRETER;+match_data->options = original_options; /* Call the main matching function, looping for a non-anchored regex after a failed match. If not restarting, perform certain optimizations at the start of@@ -3705,7 +3705,7 @@ these, for testing and for ensuring that all callouts do actually occur. The optimizations must also be avoided when restarting a DFA match. */ - if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0 &&+ if ((re->optimization_flags & PCRE2_OPTIM_START_OPTIMIZE) != 0 && (options & PCRE2_DFA_RESTART) == 0) { /* If firstline is TRUE, the start of the match is constrained to the first@@ -4041,29 +4041,40 @@ if (rc != PCRE2_ERROR_NOMATCH || anchored) {+ if (rc == PCRE2_ERROR_NOMATCH) goto NOMATCH_EXIT;+ if (rc == PCRE2_ERROR_PARTIAL && match_data->oveccount > 0) { 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->startchar = (PCRE2_SIZE)(start_match - subject);- match_data->rc = rc; - if (rc >= 0 &&(options & PCRE2_COPY_MATCHED_SUBJECT) != 0)+ if (rc >= 0 || rc == PCRE2_ERROR_PARTIAL) {- length = CU2BYTES(length + was_zero_terminated);- match_data->subject = match_data->memctl.malloc(length,- match_data->memctl.memory_data);- if (match_data->subject == NULL) return PCRE2_ERROR_NOMEMORY;- memcpy((void *)match_data->subject, subject, length);+ match_data->subject_length = length;+ match_data->start_offset = start_offset;+ match_data->leftchar = (PCRE2_SIZE)(mb->start_used_ptr - subject);+ match_data->rightchar = (PCRE2_SIZE)(mb->last_used_ptr - subject);+ match_data->startchar = (PCRE2_SIZE)(start_match - subject);+ }++ if (rc >= 0 && (options & PCRE2_COPY_MATCHED_SUBJECT) != 0)+ {+ if (length != 0)+ {+ match_data->subject = match_data->memctl.malloc(CU2BYTES(length),+ match_data->memctl.memory_data);+ if (match_data->subject == NULL)+ { rc = PCRE2_ERROR_NOMEMORY; goto EXIT; }+ memcpy((void *)match_data->subject, subject, CU2BYTES(length));+ }+ else+ match_data->subject = NULL; match_data->flags |= PCRE2_MD_COPIED_SUBJECT; }- else+ else if (rc >= 0 || rc == PCRE2_ERROR_PARTIAL) {- if (rc >= 0 || rc == PCRE2_ERROR_PARTIAL) match_data->subject = subject;+ match_data->subject = original_subject; } goto EXIT; }@@ -4097,6 +4108,9 @@ } /* "Bumpalong" loop */ NOMATCH_EXIT:+match_data->subject = original_subject;+match_data->subject_length = length;+match_data->start_offset = start_offset; rc = PCRE2_ERROR_NOMATCH; EXIT:@@ -4107,6 +4121,7 @@ mb->memctl.free(next, mb->memctl.memory_data); } +match_data->rc = rc; return rc; }
src/c/pcre2/src/pcre2_dftables.c view
@@ -47,21 +47,23 @@ variable. By default, the tables are written in source form, but if -b is given, they are written in binary. */ -#ifdef HAVE_CONFIG_H-#include "config.h"-#endif + #include <ctype.h> #include <stdio.h> #include <string.h> #include <locale.h> -#define PCRE2_DFTABLES /* for pcre2_internal.h, pcre2_maketables.c */+/* For pcre2_internal.h, pcre2_maketables.c, pcre2_tables.c */+#define PCRE2_DFTABLES+/* For pcre2_tables.c */+#define PRIV(name) name #define PCRE2_CODE_UNIT_WIDTH 0 /* Must be set, but not relevant here */ #include "pcre2_internal.h" #include "pcre2_maketables.c"+#include "pcre2_tables.c" static const char *classlist[] =@@ -70,8 +72,25 @@ "word", "graph", "print", "punct", "cntrl" }; +static int identity(int c) { return c; } +#ifdef EBCDIC+static int ebcdic_to_unicode(int c)+{+if (c < 0 || c > 255) abort(); +return ebcdic_1047_to_ascii[c];+}++static int unicode_to_ebcdic(int c)+{+if (c < 0 || c > 255) abort();++return ascii_to_ebcdic_1047[c];+}+#endif++ /************************************************* * Usage * *************************************************/@@ -83,6 +102,9 @@ "Usage: pcre2_dftables [options] <output file>\n" " -b Write output in binary (default is source code)\n" " -L Use locale from LC_ALL (default is \"C\" locale)\n"+#ifdef EBCDIC+ " -E Use EBCDIC 1047 via locale C.UTF-8\n"+#endif ); } @@ -101,6 +123,8 @@ char *env = (char *)"C"; const uint8_t *tables; const uint8_t *base_of_tables;+int (*charfn_to)(int) = identity;+int (*charfn_from)(int) = identity; /* Process options */ @@ -125,6 +149,24 @@ env = getenv("LC_ALL"); } +#ifdef EBCDIC+ else if (strcmp(arg, "-E") == 0)+ {+ if (setlocale(LC_ALL, "C.UTF-8") == NULL)+ {+ (void)fprintf(stderr, "pcre2_dftables: setlocale() failed\n");+ return 1;+ }+#ifdef EBCDIC_NL25+ env = "EBCDIC 1047 (NL 0x25)";+#else+ env = "EBCDIC 1047 (NL 0x15)";+#endif+ charfn_to = ebcdic_to_unicode;+ charfn_from = unicode_to_ebcdic;+ }+#endif+ else if (strcmp(arg, "-b") == 0) binary = TRUE; @@ -143,7 +185,7 @@ /* Make the tables */ -tables = maketables();+tables = maketables(charfn_to, charfn_from); base_of_tables = tables; f = fopen(argv[i], "wb");@@ -197,20 +239,7 @@ "pcre2_dftables manually with the -L option to build tables using the LC_ALL\n" "locale. */\n\n"); -/* Force config.h in z/OS */--#if defined NATIVE_ZOS (void)fprintf(f,- "/* For z/OS, config.h is forced */\n"- "#ifndef HAVE_CONFIG_H\n"- "#define HAVE_CONFIG_H 1\n"- "#endif\n\n");-#endif--(void)fprintf(f,- "#ifdef HAVE_CONFIG_H\n"- "#include \"config.h\"\n"- "#endif\n\n" "#include \"pcre2_internal.h\"\n\n"); (void)fprintf(f,
src/c/pcre2/src/pcre2_error.c view
@@ -39,12 +39,10 @@ */ -#ifdef HAVE_CONFIG_H-#include "config.h"-#endif- #include "pcre2_internal.h" ++ #define STRING(a) # a #define XSTRING(s) STRING(s) @@ -96,8 +94,8 @@ "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"- "digit expected after (?+ or (?-\0"+ "atomic assertion expected after (?( or (?(?C)\0"+ "digit expected after (?+\0" /* 30 */ "unknown POSIX class name\0" "internal error in pcre2_study(): should not occur\0"@@ -148,7 +146,7 @@ #ifndef EBCDIC "\\c must be followed by a printable ASCII character\0" #else- "\\c must be followed by a letter or one of [\\]^_?\0"+ "\\c must be followed by a letter or one of @[\\]^_?\0" #endif "\\k is not followed by a braced, angle-bracketed, or quoted name\0" /* 70 */@@ -161,7 +159,7 @@ "using UCP is disabled by the application\0" "name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN)\0" "character code point value in \\u.... sequence is too large\0"- "digits missing in \\x{} or \\o{} or \\N{U+}\0"+ "digits missing after \\x or in \\x{} or \\o{} or \\N{U+}\0" "syntax error or number too big in (?(VERSION condition\0" /* 80 */ "internal error: unknown opcode in auto_possessify()\0"@@ -185,11 +183,34 @@ "(*alpha_assertion) not recognized\0" "script runs require Unicode support, which this version of PCRE2 does not have\0" "too many capturing groups (maximum 65535)\0"- "atomic assertion expected after (?( or (?(?C)\0"+ "octal digit missing after \\0 (PCRE2_EXTRA_NO_BS0 is set)\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"+ "octal value given by \\ddd is greater than \\377 (forbidden by PCRE2_EXTRA_PYTHON_OCTAL)\0"+ "using callouts is disabled by the application\0"+ "PCRE2_EXTRA_TURKISH_CASING require Unicode (UTF or UCP) mode\0"+ /* 105 */+ "PCRE2_EXTRA_TURKISH_CASING requires UTF in 8-bit mode\0"+ "PCRE2_EXTRA_TURKISH_CASING and PCRE2_EXTRA_CASELESS_RESTRICT are not compatible\0"+ "extended character class nesting is too deep\0"+ "invalid operator in extended character class\0"+ "unexpected operator in extended character class (no preceding operand)\0"+ /* 110 */+ "expected operand after operator in extended character class\0"+ "square brackets needed to clarify operator precedence in extended character class\0"+ "missing terminating ] for extended character class (note '[' must be escaped under PCRE2_ALT_EXTENDED_CLASS)\0"+ "unexpected expression in extended character class (no preceding operator)\0"+ "empty expression in extended character class\0"+ /* 115 */+ "terminating ] with no following closing parenthesis in (?[...]\0"+ "unexpected character in (?[...]) extended character class\0"+ "expected capture group number or name\0"+ "missing opening parenthesis\0"+ "syntax error in subpattern number (missing terminator?)\0"+ /* 120 */+ "erroroffset passed as NULL\0" ; /* Match-time and UTF error texts are in the same format. */@@ -273,9 +294,18 @@ "heap limit exceeded\0" "invalid syntax\0" /* 65 */- "internal error - duplicate substitution match\0"+ "internal error: duplicate substitution match\0" "PCRE2_MATCH_INVALID_UTF is not supported for DFA matching\0"- "INTERNAL ERROR: invalid substring offset\0"+ "internal error: invalid substring offset\0"+ "feature is not supported by the JIT compiler\0"+ "error performing replacement case transformation\0"+ /* 70 */+ "replacement too large (longer than PCRE2_SIZE)\0"+ "substitute pattern differs from prior match call\0"+ "substitute subject differs from prior match call\0"+ "substitute start offset differs from prior match call\0"+ "substitute options differ from prior match call\0"+ "disallowed use of \\K in lookaround\0" ; @@ -302,7 +332,7 @@ { const unsigned char *message; PCRE2_SIZE i;-int n;+int n, rc = 0; if (size == 0) return PCRE2_ERROR_NOMEMORY; @@ -318,13 +348,13 @@ } else /* Invalid error number */ {- message = (unsigned char *)"\0"; /* Empty message list */+ message = (const unsigned char *)"\0"; /* Empty message list */ n = 1; } for (; n > 0; n--) {- while (*message++ != CHAR_NUL) {};+ while (*message++ != CHAR_NUL) {} if (*message == CHAR_NUL) return PCRE2_ERROR_BADDATA; } @@ -332,14 +362,23 @@ { if (i >= size - 1) {- buffer[i] = 0; /* Terminate partial message */- return PCRE2_ERROR_NOMEMORY;+ rc = PCRE2_ERROR_NOMEMORY;+ break; } buffer[i] = *message++; } -buffer[i] = 0;-return (int)i;+#if defined EBCDIC && 'a' != 0x81+/* If compiling for EBCDIC, but the compiler's string literals are not EBCDIC,+then we are in the "force EBCDIC 1047" mode. I have chosen to add a few lines+here to translate the error strings on the fly, rather than require the string+literals above to be written out arduously using the "STR_XYZ" macros. */+for (PCRE2_SIZE j = 0; j < i; ++j)+ buffer[j] = PRIV(ascii_to_ebcdic_1047)[buffer[j]];+#endif++buffer[i] = 0; /* Terminate message, even if truncated. */+return rc? rc : (int)i; } /* End of pcre2_error.c */
src/c/pcre2/src/pcre2_extuni.c view
@@ -38,19 +38,16 @@ ----------------------------------------------------------------------------- */ + /* This module contains an internal function that is used to match a Unicode extended grapheme sequence. It is used by both pcre2_match() and-pcre2_def_match(). However, it is called only when Unicode support is being+pcre2_dfa_match(). However, it is called only when Unicode support is being compiled. Nevertheless, we provide a dummy function when there is no Unicode support, because some compilers do not like functionless source files. */ -#ifdef HAVE_CONFIG_H-#include "config.h"-#endif-- #include "pcre2_internal.h"+ /* Dummy function */
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-2023 University of Cambridge+ New API code Copyright (c) 2016-2024 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -46,13 +46,10 @@ finding the minimum matching length. */ -#ifdef HAVE_CONFIG_H-#include "config.h"-#endif- #include "pcre2_internal.h" + /************************************************* * Scan compiled regex for specific bracket * *************************************************/@@ -76,18 +73,19 @@ if (c == OP_END) return NULL; /* 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+ This includes negated single high-valued characters. ECLASS is used for+ classes that use set operations internally. CALLOUT_STR is used for+ callouts with string arguments. In each case 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);+ if (c == OP_XCLASS || c == OP_ECLASS) code += GET(code, 1);+ else if (c == OP_CALLOUT_STR) code += GET(code, 1 + 2*LINK_SIZE); /* Handle lookbehind */ else if (c == OP_REVERSE || c == OP_VREVERSE) {- if (number < 0) return (PCRE2_UCHAR *)code;+ if (number < 0) return code; code += PRIV(OP_lengths)[c]; } @@ -97,7 +95,7 @@ c == OP_CBRAPOS || c == OP_SCBRAPOS) { int n = (int)GET2(code, 1+LINK_SIZE);- if (n == number) return (PCRE2_UCHAR *)code;+ if (n == number) return code; code += PRIV(OP_lengths)[c]; }
src/c/pcre2/src/pcre2_fuzzsupport.c view
@@ -1,3 +1,44 @@+/*************************************************+* 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+ Original API code Copyright (c) 1997-2012 University of Cambridge+ New API code Copyright (c) 2016-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.+-----------------------------------------------------------------------------+*/++ /*************************************************************************** Fuzzer driver for PCRE2. Given an arbitrary string of bytes and a length, it tries to compile and match it, deriving options from the string itself. If@@ -11,6 +52,7 @@ Further updates March/April/May 2024 by PH ***************************************************************************/ + #include <errno.h> #include <stdarg.h> #include <stdio.h>@@ -29,8 +71,6 @@ #define PCRE2_CODE_UNIT_WIDTH 8 #endif -#include "config.h"-#include "pcre2.h" #include "pcre2_internal.h" #define MAX_MATCH_SIZE 1000@@ -42,7 +82,8 @@ #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_ALT_EXTENDED_CLASS|PCRE2_ALT_VERBNAMES|PCRE2_AUTO_CALLOUT| \+ PCRE2_CASELESS|PCRE2_DOLLAR_ENDONLY| \ PCRE2_DOTALL|PCRE2_DUPNAMES|PCRE2_ENDANCHORED|PCRE2_EXTENDED| \ PCRE2_EXTENDED_MORE|PCRE2_FIRSTLINE| \ PCRE2_MATCH_UNSET_BACKREF|PCRE2_MULTILINE|PCRE2_NEVER_BACKSLASH_C| \@@ -67,9 +108,10 @@ (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",+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%s\n", ((compile_options & PCRE2_ALT_BSUX) != 0)? " alt_bsux" : "", ((compile_options & PCRE2_ALT_CIRCUMFLEX) != 0)? " alt_circumflex" : "",+ ((compile_options & PCRE2_ALT_EXTENDED_CLASS) != 0)? "alt_extended_class" : "", ((compile_options & PCRE2_ALT_VERBNAMES) != 0)? " alt_verbnames" : "", ((compile_options & PCRE2_ALLOW_EMPTY_CLASS) != 0)? " allow_empty_class" : "", ((compile_options & PCRE2_ANCHORED) != 0)? " anchored" : "",@@ -169,8 +211,8 @@ static void describe_failure( const char *task,- const unsigned char *data,- size_t size,+ const PCRE2_UCHAR *data,+ PCRE2_SIZE size, uint32_t compile_options, uint32_t match_options, int errorcode,@@ -257,7 +299,7 @@ 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");+ fprintf(stderr, "Hard stack size limit is too small\n"); _exit(1); } rc = setrlimit(RLIMIT_STACK, &rlim);@@ -328,8 +370,8 @@ continue; i++; /* Points to '{' */ - /* Loop for two values a quantifier. Offset i points to brace or comma at the- start of the loop.*/+ /* Loop for two values in a quantifier. Offset i points to brace or comma+ at the start of the loop. */ for (int ii = 0; ii < 2; ii++) {@@ -337,7 +379,7 @@ if (i >= size - 1) goto END_QSCAN; /* Can happen for , */ - /* Ignore leading spaces */+ /* Ignore leading spaces. */ while (wdata[i+1] == ' ' || wdata[i+1] == '\t') {@@ -345,7 +387,16 @@ if (i >= size - 1) goto END_QSCAN; } - /* Scan for a number ending in brace or comma in the first iteration,+ /* Ignore non-significant leading zeros. */++ while (wdata[i+1] == '0' && i+2 < size && wdata[i+2] >= '0' &&+ wdata[i+2] <= '9')+ {+ 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++)@@ -358,18 +409,19 @@ 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';+ 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. */+ /* 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; @@ -700,8 +752,8 @@ 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+free(newwdata); if (match_context != NULL) pcre2_match_context_free(match_context); if (compile_context != NULL) pcre2_compile_context_free(compile_context); return 0;
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-2023 University of Cambridge+ New API code Copyright (c) 2016-2024 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -41,6 +41,15 @@ #ifndef PCRE2_INTERNAL_H_IDEMPOTENT_GUARD #define PCRE2_INTERNAL_H_IDEMPOTENT_GUARD +/* We do not assume that the config.h file has an idempotent include guard,+since it may well be written by clients. The standard Autoheader config.h does+not have an include guard (although we could customise that). */++#if defined HAVE_CONFIG_H && !defined PCRE2_CONFIG_H_IDEMPOTENT_GUARD+#define PCRE2_CONFIG_H_IDEMPOTENT_GUARD+#include "config.h"+#endif+ /* We do not support both EBCDIC and Unicode at the same time. The "configure" script prevents both being selected, but not everybody uses "configure". EBCDIC is only supported for the 8-bit library, but the check for this has to be later@@ -59,13 +68,12 @@ 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) && \+#if (!defined PCRE2_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 @@ -88,6 +96,12 @@ #define TRUE 1 #endif +/* Helper macro for static (compile-time) assertions. Can be used inside+functions, or at the top-level of a file. */+#define STATIC_ASSERT_JOIN(a,b) a ## b+#define STATIC_ASSERT(cond, msg) \+ typedef int STATIC_ASSERT_JOIN(static_assertion_,msg)[(cond)?1:-1]+ /* Valgrind (memcheck) support */ #ifdef SUPPORT_VALGRIND@@ -114,14 +128,13 @@ #endif /* When compiling a DLL for Windows, the exported symbols have to be declared-using some MS magic. I found some useful information on this web page:-http://msdn2.microsoft.com/en-us/library/y4h7bcy6(VS.80).aspx. According to the-information there, using __declspec(dllexport) without "extern" we have a-definition; with "extern" we have a declaration. The settings here override the-setting in pcre2.h (which is included below); it defines only PCRE2_EXP_DECL,-which is all that is needed for applications (they just import the symbols). We-use:+using some MS magic, as documented here:+https://learn.microsoft.com/en-us/cpp/build/exporting-from-a-dll-using-declspec-dllexport +In pcre2.h (which is included below), we define only PCRE2_EXP_DECL,+which is all that is needed for applications (they just import the symbols). To+compile the library, we use:+ PCRE2_EXP_DECL for declarations PCRE2_EXP_DEFN for definitions @@ -134,46 +147,32 @@ exported symbols. That's why, in the non-Windows case, we set PCRE2_EXP_DEFN only if it is not already set. */ +#if defined __cplusplus+#error This project uses C99. C++ is not supported.+#endif+ #ifndef PCRE2_EXP_DECL-# ifdef _WIN32-# ifndef PCRE2_STATIC-# define PCRE2_EXP_DECL extern __declspec(dllexport)-# define PCRE2_EXP_DEFN __declspec(dllexport)-# else-# define PCRE2_EXP_DECL extern PCRE2_EXPORT-# define PCRE2_EXP_DEFN-# endif+# if defined(_WIN32) && !defined(PCRE2_STATIC)+# define PCRE2_EXP_DECL extern __declspec(dllexport) # else-# ifdef __cplusplus-# define PCRE2_EXP_DECL extern "C" PCRE2_EXPORT-# else-# define PCRE2_EXP_DECL extern PCRE2_EXPORT-# endif-# ifndef PCRE2_EXP_DEFN-# define PCRE2_EXP_DEFN PCRE2_EXP_DECL-# endif+# define PCRE2_EXP_DECL extern PCRE2_EXPORT # endif #endif +#ifndef PCRE2_EXP_DEFN+# if defined(_WIN32) && !defined(PCRE2_STATIC)+# define PCRE2_EXP_DEFN extern __declspec(dllexport)+# else+# define PCRE2_EXP_DEFN extern PCRE2_EXPORT+# endif+#endif+ /* Include the public PCRE2 header and the definitions of UCP character property values. This must follow the setting of PCRE2_EXP_DECL above. */ #include "pcre2.h" #include "pcre2_ucp.h" -/* When PCRE2 is compiled as a C++ library, the subject pointer can be replaced-with a custom type. This makes it possible, for example, to allow pcre2_match()-to process subject strings that are discontinuous by using a smart pointer-class. It must always be possible to inspect all of the subject string in-pcre2_match() because of the way it backtracks. */--/* WARNING: This is as yet untested for PCRE2. */--#ifdef CUSTOM_SUBJECT_PTR-#undef PCRE2_SPTR-#define PCRE2_SPTR CUSTOM_SUBJECT_PTR-#endif- /* 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@@ -195,28 +194,6 @@ #define PRIV(name) _pcre2_##name #endif -/* When compiling for use with the Virtual Pascal compiler, these functions-need to have their names changed. PCRE2 must be compiled with the -DVPCOMPAT-option on the command line. */--#ifdef VPCOMPAT-#define strlen(s) _strlen(s)-#define strncmp(s1,s2,m) _strncmp(s1,s2,m)-#define memcmp(s,c,n) _memcmp(s,c,n)-#define memcpy(d,s,n) _memcpy(d,s,n)-#define memmove(d,s,n) _memmove(d,s,n)-#define memset(s,c,n) _memset(s,c,n)-#else /* VPCOMPAT */--/* Otherwise, to cope with SunOS4 and other systems that lack memmove(), define-a macro that calls an emulating function. */--#ifndef HAVE_MEMMOVE-#undef memmove /* Some systems may have a macro */-#define memmove(a, b, c) PRIV(memmove)(a, b, c)-#endif /* not HAVE_MEMMOVE */-#endif /* not VPCOMPAT */- /* This is an unsigned int value that no UTF character can ever have, as Unicode doesn't go beyond 0x0010ffff. */ @@ -400,7 +377,7 @@ #define HSPACE_LIST \ CHAR_HT, CHAR_SPACE, CHAR_NBSP, \ 0x1680, 0x180e, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, \- 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202f, 0x205f, 0x3000, \+ 0x2006, 0x2007, 0x2008, 0x2009, 0x200a, 0x202f, 0x205f, 0x3000, \ NOTACHAR #define HSPACE_MULTIBYTE_CASES \@@ -416,7 +393,7 @@ case 0x2007: /* FIGURE SPACE */ \ case 0x2008: /* PUNCTUATION SPACE */ \ case 0x2009: /* THIN SPACE */ \- case 0x200A: /* HAIR SPACE */ \+ case 0x200a: /* HAIR SPACE */ \ case 0x202f: /* NARROW NO-BREAK SPACE */ \ case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ \ case 0x3000 /* IDEOGRAPHIC SPACE */@@ -523,29 +500,30 @@ three must not be changed, because whichever is set is actually the number of bytes in a code unit in that mode. */ -#define PCRE2_MODE8 0x00000001 /* compiled in 8 bit mode */-#define PCRE2_MODE16 0x00000002 /* compiled in 16 bit mode */-#define PCRE2_MODE32 0x00000004 /* compiled in 32 bit mode */-#define PCRE2_FIRSTSET 0x00000010 /* first_code unit is set */-#define PCRE2_FIRSTCASELESS 0x00000020 /* caseless first code unit */-#define PCRE2_FIRSTMAPSET 0x00000040 /* bitmap of first code units is set */-#define PCRE2_LASTSET 0x00000080 /* last code unit is set */-#define PCRE2_LASTCASELESS 0x00000100 /* caseless last code unit */-#define PCRE2_STARTLINE 0x00000200 /* start after \n for multiline */-#define PCRE2_JCHANGED 0x00000400 /* j option used in pattern */-#define PCRE2_HASCRORLF 0x00000800 /* explicit \r or \n in pattern */-#define PCRE2_HASTHEN 0x00001000 /* pattern contains (*THEN) */-#define PCRE2_MATCH_EMPTY 0x00002000 /* pattern can match empty string */-#define PCRE2_BSR_SET 0x00004000 /* BSR was set in the pattern */-#define PCRE2_NL_SET 0x00008000 /* newline was set in the pattern */-#define PCRE2_NOTEMPTY_SET 0x00010000 /* (*NOTEMPTY) used ) keep */-#define PCRE2_NE_ATST_SET 0x00020000 /* (*NOTEMPTY_ATSTART) used) together */-#define PCRE2_DEREF_TABLES 0x00040000 /* release character tables */-#define PCRE2_NOJIT 0x00080000 /* (*NOJIT) used */-#define PCRE2_HASBKPORX 0x00100000 /* contains \P, \p, or \X */-#define PCRE2_DUPCAPUSED 0x00200000 /* contains (?| */-#define PCRE2_HASBKC 0x00400000 /* contains \C */-#define PCRE2_HASACCEPT 0x00800000 /* contains (*ACCEPT) */+#define PCRE2_MODE8 0x00000001u /* compiled in 8 bit mode */+#define PCRE2_MODE16 0x00000002u /* compiled in 16 bit mode */+#define PCRE2_MODE32 0x00000004u /* compiled in 32 bit mode */+#define PCRE2_FIRSTSET 0x00000010u /* first_code unit is set */+#define PCRE2_FIRSTCASELESS 0x00000020u /* caseless first code unit */+#define PCRE2_FIRSTMAPSET 0x00000040u /* bitmap of first code units is set */+#define PCRE2_LASTSET 0x00000080u /* last code unit is set */+#define PCRE2_LASTCASELESS 0x00000100u /* caseless last code unit */+#define PCRE2_STARTLINE 0x00000200u /* start after \n for multiline */+#define PCRE2_JCHANGED 0x00000400u /* j option used in pattern */+#define PCRE2_HASCRORLF 0x00000800u /* explicit \r or \n in pattern */+#define PCRE2_HASTHEN 0x00001000u /* pattern contains (*THEN) */+#define PCRE2_MATCH_EMPTY 0x00002000u /* pattern can match empty string */+#define PCRE2_BSR_SET 0x00004000u /* BSR was set in the pattern */+#define PCRE2_NL_SET 0x00008000u /* newline was set in the pattern */+#define PCRE2_NOTEMPTY_SET 0x00010000u /* (*NOTEMPTY) used ) keep */+#define PCRE2_NE_ATST_SET 0x00020000u /* (*NOTEMPTY_ATSTART) used) together */+#define PCRE2_DEREF_TABLES 0x00040000u /* release character tables */+#define PCRE2_NOJIT 0x00080000u /* (*NOJIT) used */+#define PCRE2_HASBKPORX 0x00100000u /* contains \P, \p, or \X */+#define PCRE2_DUPCAPUSED 0x00200000u /* contains (?| */+#define PCRE2_HASBKC 0x00400000u /* contains \C */+#define PCRE2_HASACCEPT 0x00800000u /* contains (*ACCEPT) */+#define PCRE2_HASBSK 0x01000000u /* contains \K */ #define PCRE2_MODE_MASK (PCRE2_MODE8 | PCRE2_MODE16 | PCRE2_MODE32) @@ -574,6 +552,16 @@ #define REQ_CU_MAX 2000 #endif +/* The maximum nesting depth for Unicode character class sets.+Currently fixed. Warning: the interpreter relies on this so it can encode+the operand stack in a uint32_t. A nesting limit of 15 implies (15*2+1)=31+stack operands required, due to the fact that we have two (and only two)+levels of operator precedence. In the UTS#18 syntax, you can write 'x&&y[z]'+and in Perl syntax you can write '(?[ x - y & (z) ])', both of which imply+pushing the match results for x & y to the stack. */++#define ECLASS_NEST_LIMIT 15+ /* Offsets for the bitmap tables in the cbits set of tables. Each table contains a set of bits for a class map. Some classes are built by combining these tables. */@@ -609,7 +597,14 @@ #define ctypes_offset (cbits_offset + cbit_length) /* Character types */ #define TABLES_LENGTH (ctypes_offset + 256) +/* Private flags used in compile_context.optimization_flags */ +#define PCRE2_OPTIM_AUTO_POSSESS 0x00000001u+#define PCRE2_OPTIM_DOTSTAR_ANCHOR 0x00000002u+#define PCRE2_OPTIM_START_OPTIMIZE 0x00000004u++#define PCRE2_OPTIMIZATION_ALL 0x00000007u+ /* -------------------- Character and string names ------------------------ */ /* If PCRE2 is to support UTF-8 on EBCDIC platforms, we cannot use normal@@ -675,6 +670,10 @@ compatibility. NEL is the Unicode newline character; make sure it is a positive value. */ +#if '\n' != 0x0a+#error "ASCII character '\n' is not 0x0a"+#endif+ #define CHAR_LF '\n' #define CHAR_NL CHAR_LF #define CHAR_NEL ((unsigned char)'\x85')@@ -690,8 +689,233 @@ #endif /* EBCDIC */ -/* The remaining definitions work in both environments. */+/* When we want to use EBCDIC with an ASCII compiler, for testing EBCDIC on+ASCII platforms, then we can hardcode an EBCDIC codepage (IBM-1047). */ +#ifdef EBCDIC_IGNORING_COMPILER++#define CHAR_NUL '\000'+#define CHAR_HT '\005'+#define CHAR_VT '\013'+#define CHAR_FF '\014'+#define CHAR_CR '\015'+#define CHAR_BS '\026'+#define CHAR_BEL '\057'++#define CHAR_SPACE '\100'+#define CHAR_EXCLAMATION_MARK '\132'+#define CHAR_QUOTATION_MARK '\177'+#define CHAR_NUMBER_SIGN '\173'+#define CHAR_DOLLAR_SIGN '\133'+#define CHAR_PERCENT_SIGN '\154'+#define CHAR_AMPERSAND '\120'+#define CHAR_APOSTROPHE '\175'+#define CHAR_LEFT_PARENTHESIS '\115'+#define CHAR_RIGHT_PARENTHESIS '\135'+#define CHAR_ASTERISK '\134'+#define CHAR_PLUS '\116'+#define CHAR_COMMA '\153'+#define CHAR_MINUS '\140'+#define CHAR_DOT '\113'+#define CHAR_SLASH '\141'+#define CHAR_0 ((unsigned char)'\xf0')+#define CHAR_1 ((unsigned char)'\xf1')+#define CHAR_2 ((unsigned char)'\xf2')+#define CHAR_3 ((unsigned char)'\xf3')+#define CHAR_4 ((unsigned char)'\xf4')+#define CHAR_5 ((unsigned char)'\xf5')+#define CHAR_6 ((unsigned char)'\xf6')+#define CHAR_7 ((unsigned char)'\xf7')+#define CHAR_8 ((unsigned char)'\xf8')+#define CHAR_9 ((unsigned char)'\xf9')+#define CHAR_COLON '\172'+#define CHAR_SEMICOLON '\136'+#define CHAR_LESS_THAN_SIGN '\114'+#define CHAR_EQUALS_SIGN '\176'+#define CHAR_GREATER_THAN_SIGN '\156'+#define CHAR_QUESTION_MARK '\157'+#define CHAR_COMMERCIAL_AT '\174'+#define CHAR_A ((unsigned char)'\xc1')+#define CHAR_B ((unsigned char)'\xc2')+#define CHAR_C ((unsigned char)'\xc3')+#define CHAR_D ((unsigned char)'\xc4')+#define CHAR_E ((unsigned char)'\xc5')+#define CHAR_F ((unsigned char)'\xc6')+#define CHAR_G ((unsigned char)'\xc7')+#define CHAR_H ((unsigned char)'\xc8')+#define CHAR_I ((unsigned char)'\xc9')+#define CHAR_J ((unsigned char)'\xd1')+#define CHAR_K ((unsigned char)'\xd2')+#define CHAR_L ((unsigned char)'\xd3')+#define CHAR_M ((unsigned char)'\xd4')+#define CHAR_N ((unsigned char)'\xd5')+#define CHAR_O ((unsigned char)'\xd6')+#define CHAR_P ((unsigned char)'\xd7')+#define CHAR_Q ((unsigned char)'\xd8')+#define CHAR_R ((unsigned char)'\xd9')+#define CHAR_S ((unsigned char)'\xe2')+#define CHAR_T ((unsigned char)'\xe3')+#define CHAR_U ((unsigned char)'\xe4')+#define CHAR_V ((unsigned char)'\xe5')+#define CHAR_W ((unsigned char)'\xe6')+#define CHAR_X ((unsigned char)'\xe7')+#define CHAR_Y ((unsigned char)'\xe8')+#define CHAR_Z ((unsigned char)'\xe9')+#define CHAR_LEFT_SQUARE_BRACKET ((unsigned char)'\xad')+#define CHAR_BACKSLASH ((unsigned char)'\xe0')+#define CHAR_RIGHT_SQUARE_BRACKET ((unsigned char)'\xbd')+#define CHAR_CIRCUMFLEX_ACCENT '\137'+#define CHAR_UNDERSCORE '\155'+#define CHAR_GRAVE_ACCENT '\171'+#define CHAR_a ((unsigned char)'\x81')+#define CHAR_b ((unsigned char)'\x82')+#define CHAR_c ((unsigned char)'\x83')+#define CHAR_d ((unsigned char)'\x84')+#define CHAR_e ((unsigned char)'\x85')+#define CHAR_f ((unsigned char)'\x86')+#define CHAR_g ((unsigned char)'\x87')+#define CHAR_h ((unsigned char)'\x88')+#define CHAR_i ((unsigned char)'\x89')+#define CHAR_j ((unsigned char)'\x91')+#define CHAR_k ((unsigned char)'\x92')+#define CHAR_l ((unsigned char)'\x93')+#define CHAR_m ((unsigned char)'\x94')+#define CHAR_n ((unsigned char)'\x95')+#define CHAR_o ((unsigned char)'\x96')+#define CHAR_p ((unsigned char)'\x97')+#define CHAR_q ((unsigned char)'\x98')+#define CHAR_r ((unsigned char)'\x99')+#define CHAR_s ((unsigned char)'\xa2')+#define CHAR_t ((unsigned char)'\xa3')+#define CHAR_u ((unsigned char)'\xa4')+#define CHAR_v ((unsigned char)'\xa5')+#define CHAR_w ((unsigned char)'\xa6')+#define CHAR_x ((unsigned char)'\xa7')+#define CHAR_y ((unsigned char)'\xa8')+#define CHAR_z ((unsigned char)'\xa9')+#define CHAR_LEFT_CURLY_BRACKET ((unsigned char)'\xc0')+#define CHAR_VERTICAL_LINE '\117'+#define CHAR_RIGHT_CURLY_BRACKET ((unsigned char)'\xd0')+#define CHAR_TILDE ((unsigned char)'\xa1')++#define STR_HT "\005"+#define STR_VT "\013"+#define STR_FF "\014"+#define STR_CR "\015"+#define STR_BS "\026"+#define STR_BEL "\057"++#define STR_SPACE "\100"+#define STR_EXCLAMATION_MARK "\132"+#define STR_QUOTATION_MARK "\177"+#define STR_NUMBER_SIGN "\173"+#define STR_DOLLAR_SIGN "\133"+#define STR_PERCENT_SIGN "\154"+#define STR_AMPERSAND "\120"+#define STR_APOSTROPHE "\175"+#define STR_LEFT_PARENTHESIS "\115"+#define STR_RIGHT_PARENTHESIS "\135"+#define STR_ASTERISK "\134"+#define STR_PLUS "\116"+#define STR_COMMA "\153"+#define STR_MINUS "\140"+#define STR_DOT "\113"+#define STR_SLASH "\141"+#define STR_0 "\360"+#define STR_1 "\361"+#define STR_2 "\362"+#define STR_3 "\363"+#define STR_4 "\364"+#define STR_5 "\365"+#define STR_6 "\366"+#define STR_7 "\367"+#define STR_8 "\370"+#define STR_9 "\371"+#define STR_COLON "\172"+#define STR_SEMICOLON "\136"+#define STR_LESS_THAN_SIGN "\114"+#define STR_EQUALS_SIGN "\176"+#define STR_GREATER_THAN_SIGN "\156"+#define STR_QUESTION_MARK "\157"+#define STR_COMMERCIAL_AT "\174"+#define STR_A "\301"+#define STR_B "\302"+#define STR_C "\303"+#define STR_D "\304"+#define STR_E "\305"+#define STR_F "\306"+#define STR_G "\307"+#define STR_H "\310"+#define STR_I "\311"+#define STR_J "\321"+#define STR_K "\322"+#define STR_L "\323"+#define STR_M "\324"+#define STR_N "\325"+#define STR_O "\326"+#define STR_P "\327"+#define STR_Q "\330"+#define STR_R "\331"+#define STR_S "\342"+#define STR_T "\343"+#define STR_U "\344"+#define STR_V "\345"+#define STR_W "\346"+#define STR_X "\347"+#define STR_Y "\350"+#define STR_Z "\351"+#define STR_LEFT_SQUARE_BRACKET "\255"+#define STR_BACKSLASH "\340"+#define STR_RIGHT_SQUARE_BRACKET "\275"+#define STR_CIRCUMFLEX_ACCENT "\137"+#define STR_UNDERSCORE "\155"+#define STR_GRAVE_ACCENT "\171"+#define STR_a "\201"+#define STR_b "\202"+#define STR_c "\203"+#define STR_d "\204"+#define STR_e "\205"+#define STR_f "\206"+#define STR_g "\207"+#define STR_h "\210"+#define STR_i "\211"+#define STR_j "\221"+#define STR_k "\222"+#define STR_l "\223"+#define STR_m "\224"+#define STR_n "\225"+#define STR_o "\226"+#define STR_p "\227"+#define STR_q "\230"+#define STR_r "\231"+#define STR_s "\242"+#define STR_t "\243"+#define STR_u "\244"+#define STR_v "\245"+#define STR_w "\246"+#define STR_x "\247"+#define STR_y "\250"+#define STR_z "\251"+#define STR_LEFT_CURLY_BRACKET "\300"+#define STR_VERTICAL_LINE "\117"+#define STR_RIGHT_CURLY_BRACKET "\320"+#define STR_TILDE "\241"++#else /* EBCDIC_IGNORING_COMPILER */++/* Otherwise, on a real EBCDIC compiler or an ASCII compiler, we can use simple+string and character literals. */++#ifdef EBCDIC+#if 'a' != 0x81+#error "EBCDIC character 'a' is not 0x81"+#endif+#else+#if 'a' != 0x61+#error "ASCII character 'a' is not 0x61"+#endif+#endif+ #define CHAR_NUL '\0' #define CHAR_HT '\t' #define CHAR_VT '\v'@@ -899,84 +1123,7 @@ #define STR_RIGHT_CURLY_BRACKET "}" #define STR_TILDE "~" -#define STRING_ACCEPT0 "ACCEPT\0"-#define STRING_COMMIT0 "COMMIT\0"-#define STRING_F0 "F\0"-#define STRING_FAIL0 "FAIL\0"-#define STRING_MARK0 "MARK\0"-#define STRING_PRUNE0 "PRUNE\0"-#define STRING_SKIP0 "SKIP\0"-#define STRING_THEN "THEN"--#define STRING_atomic0 "atomic\0"-#define STRING_pla0 "pla\0"-#define STRING_plb0 "plb\0"-#define STRING_napla0 "napla\0"-#define STRING_naplb0 "naplb\0"-#define STRING_nla0 "nla\0"-#define STRING_nlb0 "nlb\0"-#define STRING_sr0 "sr\0"-#define STRING_asr0 "asr\0"-#define STRING_positive_lookahead0 "positive_lookahead\0"-#define STRING_positive_lookbehind0 "positive_lookbehind\0"-#define STRING_non_atomic_positive_lookahead0 "non_atomic_positive_lookahead\0"-#define STRING_non_atomic_positive_lookbehind0 "non_atomic_positive_lookbehind\0"-#define STRING_negative_lookahead0 "negative_lookahead\0"-#define STRING_negative_lookbehind0 "negative_lookbehind\0"-#define STRING_script_run0 "script_run\0"-#define STRING_atomic_script_run "atomic_script_run"--#define STRING_alpha0 "alpha\0"-#define STRING_lower0 "lower\0"-#define STRING_upper0 "upper\0"-#define STRING_alnum0 "alnum\0"-#define STRING_ascii0 "ascii\0"-#define STRING_blank0 "blank\0"-#define STRING_cntrl0 "cntrl\0"-#define STRING_digit0 "digit\0"-#define STRING_graph0 "graph\0"-#define STRING_print0 "print\0"-#define STRING_punct0 "punct\0"-#define STRING_space0 "space\0"-#define STRING_word0 "word\0"-#define STRING_xdigit "xdigit"--#define STRING_DEFINE "DEFINE"-#define STRING_VERSION "VERSION"-#define STRING_WEIRD_STARTWORD "[:<:]]"-#define STRING_WEIRD_ENDWORD "[:>:]]"--#define STRING_CR_RIGHTPAR "CR)"-#define STRING_LF_RIGHTPAR "LF)"-#define STRING_CRLF_RIGHTPAR "CRLF)"-#define STRING_ANY_RIGHTPAR "ANY)"-#define STRING_ANYCRLF_RIGHTPAR "ANYCRLF)"-#define STRING_NUL_RIGHTPAR "NUL)"-#define STRING_BSR_ANYCRLF_RIGHTPAR "BSR_ANYCRLF)"-#define STRING_BSR_UNICODE_RIGHTPAR "BSR_UNICODE)"-#define STRING_UTF8_RIGHTPAR "UTF8)"-#define STRING_UTF16_RIGHTPAR "UTF16)"-#define STRING_UTF32_RIGHTPAR "UTF32)"-#define STRING_UTF_RIGHTPAR "UTF)"-#define STRING_UCP_RIGHTPAR "UCP)"-#define STRING_NO_AUTO_POSSESS_RIGHTPAR "NO_AUTO_POSSESS)"-#define STRING_NO_DOTSTAR_ANCHOR_RIGHTPAR "NO_DOTSTAR_ANCHOR)"-#define STRING_NO_JIT_RIGHTPAR "NO_JIT)"-#define STRING_NO_START_OPT_RIGHTPAR "NO_START_OPT)"-#define STRING_NOTEMPTY_RIGHTPAR "NOTEMPTY)"-#define STRING_NOTEMPTY_ATSTART_RIGHTPAR "NOTEMPTY_ATSTART)"-#define STRING_LIMIT_HEAP_EQ "LIMIT_HEAP="-#define STRING_LIMIT_MATCH_EQ "LIMIT_MATCH="-#define STRING_LIMIT_DEPTH_EQ "LIMIT_DEPTH="-#define STRING_LIMIT_RECURSION_EQ "LIMIT_RECURSION="-#define STRING_MARK "MARK"--#define STRING_bc "bc"-#define STRING_bidiclass "bidiclass"-#define STRING_sc "sc"-#define STRING_script "script"-#define STRING_scriptextensions "scriptextensions"-#define STRING_scx "scx"+#endif /* EBCDIC_WITH_ASCII_COMPILER */ #else /* SUPPORT_UNICODE */ @@ -1200,6 +1347,9 @@ #define STR_RIGHT_CURLY_BRACKET "\175" #define STR_TILDE "\176" +#endif /* SUPPORT_UNICODE */++ #define STRING_ACCEPT0 STR_A STR_C STR_C STR_E STR_P STR_T "\0" #define STRING_COMMIT0 STR_C STR_O STR_M STR_M STR_I STR_T "\0" #define STRING_F0 STR_F "\0"@@ -1216,6 +1366,7 @@ #define STRING_naplb0 STR_n STR_a STR_p STR_l STR_b "\0" #define STRING_nla0 STR_n STR_l STR_a "\0" #define STRING_nlb0 STR_n STR_l STR_b "\0"+#define STRING_scs0 STR_s STR_c STR_s "\0" #define STRING_sr0 STR_s STR_r "\0" #define STRING_asr0 STR_a STR_s STR_r "\0" #define STRING_positive_lookahead0 STR_p STR_o STR_s STR_i STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_a STR_h STR_e STR_a STR_d "\0"@@ -1226,6 +1377,7 @@ #define STRING_negative_lookbehind0 STR_n STR_e STR_g STR_a STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_b STR_e STR_h STR_i STR_n STR_d "\0" #define STRING_script_run0 STR_s STR_c STR_r STR_i STR_p STR_t STR_UNDERSCORE STR_r STR_u STR_n "\0" #define STRING_atomic_script_run STR_a STR_t STR_o STR_m STR_i STR_c STR_UNDERSCORE STR_s STR_c STR_r STR_i STR_p STR_t STR_UNDERSCORE STR_r STR_u STR_n+#define STRING_scan_substring0 STR_s STR_c STR_a STR_n STR_UNDERSCORE STR_s STR_u STR_b STR_s STR_t STR_r STR_i STR_n STR_g "\0" #define STRING_alpha0 STR_a STR_l STR_p STR_h STR_a "\0" #define STRING_lower0 STR_l STR_o STR_w STR_e STR_r "\0"@@ -1266,6 +1418,8 @@ #define STRING_NO_START_OPT_RIGHTPAR STR_N STR_O STR_UNDERSCORE STR_S STR_T STR_A STR_R STR_T STR_UNDERSCORE STR_O STR_P STR_T STR_RIGHT_PARENTHESIS #define STRING_NOTEMPTY_RIGHTPAR STR_N STR_O STR_T STR_E STR_M STR_P STR_T STR_Y STR_RIGHT_PARENTHESIS #define STRING_NOTEMPTY_ATSTART_RIGHTPAR STR_N STR_O STR_T STR_E STR_M STR_P STR_T STR_Y STR_UNDERSCORE STR_A STR_T STR_S STR_T STR_A STR_R STR_T STR_RIGHT_PARENTHESIS+#define STRING_CASELESS_RESTRICT_RIGHTPAR STR_C STR_A STR_S STR_E STR_L STR_E STR_S STR_S STR_UNDERSCORE STR_R STR_E STR_S STR_T STR_R STR_I STR_C STR_T STR_RIGHT_PARENTHESIS+#define STRING_TURKISH_CASING_RIGHTPAR STR_T STR_U STR_R STR_K STR_I STR_S STR_H STR_UNDERSCORE STR_C STR_A STR_S STR_I STR_N STR_G STR_RIGHT_PARENTHESIS #define STRING_LIMIT_HEAP_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_H STR_E STR_A STR_P STR_EQUALS_SIGN #define STRING_LIMIT_MATCH_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_M STR_A STR_T STR_C STR_H STR_EQUALS_SIGN #define STRING_LIMIT_DEPTH_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_D STR_E STR_P STR_T STR_H STR_EQUALS_SIGN@@ -1280,8 +1434,6 @@ #define STRING_scx STR_s STR_c STR_x -#endif /* SUPPORT_UNICODE */- /* -------------------- End of character and string names -------------------*/ /* -------------------- Definitions for compiled patterns -------------------*/@@ -1290,21 +1442,22 @@ changed, the autopossessifying table in pcre2_auto_possess.c must be updated to match. */ -#define PT_ANY 0 /* Any property - matches all chars */-#define PT_LAMP 1 /* L& - the union of Lu, Ll, Lt */-#define PT_GC 2 /* Specified general characteristic (e.g. L) */-#define PT_PC 3 /* Specified particular characteristic (e.g. Lu) */-#define PT_SC 4 /* Script only (e.g. Han) */-#define PT_SCX 5 /* Script extensions (includes SC) */-#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, 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 */-#define PT_BOOL 13 /* Boolean property */-#define PT_TABSIZE 14 /* Size of square table for autopossessify tests */+#define PT_LAMP 0 /* L& - the union of Lu, Ll, Lt */+#define PT_GC 1 /* Specified general characteristic (e.g. L) */+#define PT_PC 2 /* Specified particular characteristic (e.g. Lu) */+#define PT_SC 3 /* Script only (e.g. Han) */+#define PT_SCX 4 /* Script extensions (includes SC) */+#define PT_ALNUM 5 /* Alphanumeric - the union of L and N */+#define PT_SPACE 6 /* Perl space - general category Z plus 9,10,12,13 */+#define PT_PXSPACE 7 /* POSIX space - Z plus 9,10,11,12,13 */+#define PT_WORD 8 /* Word - L, N, Mn, or Pc */+#define PT_CLIST 9 /* Pseudo-property: match character list */+#define PT_UCNC 10 /* Universal Character nameable character */+#define PT_BIDICL 11 /* Specified bidi class */+#define PT_BOOL 12 /* Boolean property */+#define PT_ANY 13 /* Must be the last entry!+ Any property - matches all chars */+#define PT_TABSIZE PT_ANY /* Size of square table for autopossessify tests */ /* The following special properties are used only in XCLASS items, when POSIX classes are specified and PCRE2_UCP is set - in other words, for Unicode@@ -1334,7 +1487,95 @@ #define XCL_RANGE 2 /* A range (two multibyte chars) follows */ #define XCL_PROP 3 /* Unicode property (2-byte property code follows) */ #define XCL_NOTPROP 4 /* Unicode inverted property (ditto) */+/* This value represents the beginning of character lists. The value+is 16 bit long, and stored as a high and low byte pair in 8 bit mode.+The lower 12 bit contains information about character lists (see later). */+#define XCL_LIST (sizeof(PCRE2_UCHAR) == 1 ? 0x10 : 0x1000) +/* When a character class contains many characters/ranges,+they are stored in character lists. There are four character+lists which contain characters/ranges within a given range.++The name, character range and item size for each list:+Low16 [0x100 - 0x7fff] 16 bit items+High16 [0x8000 - 0xffff] 16 bit items+Low32 [0x10000 - 0x7fffffff] 32 bit items+High32 [0x80000000 - 0xffffffff] 32 bit items++The Low32 character list is used only when utf encoding or 32 bit+character width is enabled, and the High32 character is used only+when 32 bit character width is enabled.++Each character list contain items. The lowest bit represents that+an item is the beginning of a range (bit is cleared), or not (bit+is set). The other bits represent the character shifted left by+one, so its highest bit is discarded. Due to the layout of character+lists, the highest bit of a character is always known:++Low16 and Low32: the highest bit is always zero+High16 and High32: the highest bit is always one++The items are ordered in increasing order, so binary search can be+used to find the lower bound of an input character. The lower bound+is the highest item, which value is less or equal than the input+character. If the lower bit of the item is cleard, or the character+stored in the item equals to the input character, the input+character is in the character list. */++/* Character list constants. */+#define XCL_CHAR_LIST_LOW_16_START 0x100+#define XCL_CHAR_LIST_LOW_16_END 0x7fff+#define XCL_CHAR_LIST_LOW_16_ADD 0x0++#define XCL_CHAR_LIST_HIGH_16_START 0x8000+#define XCL_CHAR_LIST_HIGH_16_END 0xffff+#define XCL_CHAR_LIST_HIGH_16_ADD 0x8000++#define XCL_CHAR_LIST_LOW_32_START 0x10000+#define XCL_CHAR_LIST_LOW_32_END 0x7fffffff+#define XCL_CHAR_LIST_LOW_32_ADD 0x0++#define XCL_CHAR_LIST_HIGH_32_START 0x80000000+#define XCL_CHAR_LIST_HIGH_32_END 0xffffffff+#define XCL_CHAR_LIST_HIGH_32_ADD 0x80000000++/* Mask for getting the descriptors of character list ranges.+Each descriptor has XCL_TYPE_BIT_LEN bits, and can be processed+by XCL_BEGIN_WITH_RANGE and XCL_ITEM_COUNT_MASK macros. */+#define XCL_TYPE_MASK 0xfff+#define XCL_TYPE_BIT_LEN 3+/* If this bit is set, the first item of the character list is the+end of a range, which started before the starting character of the+character list. */+#define XCL_BEGIN_WITH_RANGE 0x4+/* Number of items in the character list: 0, 1, or 2. The value 3+represents that the item count is stored at the begining of the+character list. The item count has the same width as the items+in the character list (e.g. 16 bit for Low16 and High16 lists). */+#define XCL_ITEM_COUNT_MASK 0x3+/* Shift and flag for constructing character list items. The XCL_CHAR_END+is set, when the item is not the beginning of a range. The XCL_CHAR_SHIFT+can be used to encode / decode the character value stored in an item. */+#define XCL_CHAR_END 0x1+#define XCL_CHAR_SHIFT 1++/* Flag bits for an extended class (OP_ECLASS), which is used for complex+character matches such as [\p{Greek} && \p{Ll}]. */++#define ECL_MAP 0x01 /* Flag: a 32-byte map is present */++/* Type tags for the items stored in an extended class (OP_ECLASS). These items+follow the OP_ECLASS's flag char and bitmap, and represent a Reverse Polish+Notation list of operands and operators manipulating a stack of bits. */++#define ECL_AND 1 /* Pop two from the stack, AND, and push result. */+#define ECL_OR 2 /* Pop two from the stack, OR, and push result. */+#define ECL_XOR 3 /* Pop two from the stack, XOR, and push result. */+#define ECL_NOT 4 /* Pop one from the stack, NOT, and push result. */+#define ECL_XCLASS 5 /* XCLASS nested within ECLASS; match and push result. */+#define ECL_ANY 6 /* Temporary, only used during compilation. */+#define ECL_NONE 7 /* Temporary, only used during compilation. */+ /* These are escaped items that aren't just an encoding of a particular data value such as \n. They must have non-zero values, as check_escape() returns 0 for a data character. In the escapes[] table in pcre2_compile.c their values@@ -1555,102 +1796,105 @@ character > 255 is encountered. */ OP_XCLASS, /* 112 Extended class for handling > 255 chars within the class. This does both positive and negative. */- OP_REF, /* 113 Match a back reference, casefully */- OP_REFI, /* 114 Match a back reference, caselessly */- OP_DNREF, /* 115 Match a duplicate name backref, casefully */- OP_DNREFI, /* 116 Match a duplicate name backref, caselessly */- OP_RECURSE, /* 117 Match a numbered subpattern (possibly recursive) */- OP_CALLOUT, /* 118 Call out to external function if provided */- OP_CALLOUT_STR, /* 119 Call out with string argument */+ OP_ECLASS, /* 113 Really-extended class, for handling logical+ expressions computed over characters. */+ OP_REF, /* 114 Match a back reference, casefully */+ OP_REFI, /* 115 Match a back reference, caselessly */+ OP_DNREF, /* 116 Match a duplicate name backref, casefully */+ OP_DNREFI, /* 117 Match a duplicate name backref, caselessly */+ OP_RECURSE, /* 118 Match a numbered subpattern (possibly recursive) */+ OP_CALLOUT, /* 119 Call out to external function if provided */+ OP_CALLOUT_STR, /* 120 Call out with string argument */ - OP_ALT, /* 120 Start of alternation */- OP_KET, /* 121 End of group that doesn't have an unbounded repeat */- OP_KETRMAX, /* 122 These two must remain together and in this */- OP_KETRMIN, /* 123 order. They are for groups the repeat for ever. */- OP_KETRPOS, /* 124 Possessive unlimited repeat. */+ OP_ALT, /* 121 Start of alternation */+ OP_KET, /* 122 End of group that doesn't have an unbounded repeat */+ OP_KETRMAX, /* 123 These two must remain together and in this */+ OP_KETRMIN, /* 124 order. They are for groups the repeat for ever. */+ OP_KETRPOS, /* 125 Possessive unlimited repeat. */ /* The assertions must come before BRA, CBRA, ONCE, and COND. */ - OP_REVERSE, /* 125 Move pointer back - used in lookbehind assertions */- 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 */+ OP_REVERSE, /* 126 Move pointer back - used in lookbehind assertions */+ OP_VREVERSE, /* 127 Move pointer back - variable */+ OP_ASSERT, /* 128 Positive lookahead */+ OP_ASSERT_NOT, /* 129 Negative lookahead */+ OP_ASSERTBACK, /* 130 Positive lookbehind */+ OP_ASSERTBACK_NOT, /* 131 Negative lookbehind */+ OP_ASSERT_NA, /* 132 Positive non-atomic lookahead */+ OP_ASSERTBACK_NA, /* 133 Positive non-atomic lookbehind */+ OP_ASSERT_SCS, /* 134 Scan substring */ /* 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, /* 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 */+ OP_ONCE, /* 135 Atomic group, contains captures */+ OP_SCRIPT_RUN, /* 136 Non-capture, but check characters' scripts */+ OP_BRA, /* 137 Start of non-capturing bracket */+ OP_BRAPOS, /* 138 Ditto, with unlimited, possessive repeat */+ OP_CBRA, /* 139 Start of capturing bracket */+ OP_CBRAPOS, /* 140 Ditto, with unlimited, possessive repeat */+ OP_COND, /* 141 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, /* 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 */+ OP_SBRA, /* 142 Start of non-capturing bracket, check empty */+ OP_SBRAPOS, /* 143 Ditto, with unlimited, possessive repeat */+ OP_SCBRA, /* 144 Start of capturing bracket, check empty */+ OP_SCBRAPOS, /* 145 Ditto, with unlimited, possessive repeat */+ OP_SCOND, /* 146 Conditional group, check empty */ /* The next two pairs must (respectively) be kept together. */ - 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_CREF, /* 147 Used to hold a capture number as condition */+ OP_DNCREF, /* 148 Used to point to duplicate names as a condition */+ OP_RREF, /* 149 Used to hold a recursion number as condition */+ OP_DNRREF, /* 150 Used to point to duplicate names as a condition */+ OP_FALSE, /* 151 Always false (used by DEFINE and VERSION) */+ OP_TRUE, /* 152 Always true (used by VERSION) */ - OP_BRAZERO, /* 151 These two must remain together and in this */- OP_BRAMINZERO, /* 152 order. */- OP_BRAPOSZERO, /* 153 */+ OP_BRAZERO, /* 153 These two must remain together and in this */+ OP_BRAMINZERO, /* 154 order. */+ OP_BRAPOSZERO, /* 155 */ /* These are backtracking control verbs */ - 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 */+ OP_MARK, /* 156 always has an argument */+ OP_PRUNE, /* 157 */+ OP_PRUNE_ARG, /* 158 same, but with argument */+ OP_SKIP, /* 159 */+ OP_SKIP_ARG, /* 160 same, but with argument */+ OP_THEN, /* 161 */+ OP_THEN_ARG, /* 162 same, but with argument */+ OP_COMMIT, /* 163 */+ OP_COMMIT_ARG, /* 164 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, /* 163 */- OP_ACCEPT, /* 164 */- OP_ASSERT_ACCEPT, /* 165 Used inside assertions */- OP_CLOSE, /* 166 Used before OP_ACCEPT to close open captures */+ OP_FAIL, /* 165 */+ OP_ACCEPT, /* 166 */+ OP_ASSERT_ACCEPT, /* 167 Used inside assertions */+ OP_CLOSE, /* 168 Used before OP_ACCEPT to close open captures */ /* This is used to skip a subpattern with a {0} quantifier */ - OP_SKIPZERO, /* 167 */+ OP_SKIPZERO, /* 169 */ /* 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, /* 168 */+ OP_DEFINE, /* 170 */ /* 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 */+ OP_NOT_UCP_WORD_BOUNDARY, /* 171 */+ OP_UCP_WORD_BOUNDARY, /* 172 */ /* 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@@ -1668,7 +1912,7 @@ /* This macro defines textual names for all the opcodes. These are used only for debugging, and some of them are only partial names. The macro is referenced-only in pcre2_printint.c, which fills out the full names in many cases (and in+only in pcre2_printint_inc.h, which fills out the full names in many cases (and in some cases doesn't actually use these names at all). */ #define OP_NAME_LIST \@@ -1693,19 +1937,21 @@ "*+","++", "?+", "{", \ "*", "*?", "+", "+?", "?", "??", "{", "{", \ "*+","++", "?+", "{", \- "class", "nclass", "xclass", "Ref", "Refi", "DnRef", "DnRefi", \+ "class", "nclass", "xclass", "eclass", \+ "Ref", "Refi", "DnRef", "DnRefi", \ "Recurse", "Callout", "CalloutStr", \ "Alt", "Ket", "KetRmax", "KetRmin", "KetRpos", \ "Reverse", "VReverse", "Assert", "Assert not", \ "Assert back", "Assert back not", \ "Non-atomic assert", "Non-atomic assert back", \+ "Scan substring", \ "Once", \ "Script run", \ "Bra", "BraPos", "CBra", "CBraPos", \ "Cond", \ "SBra", "SBraPos", "SCBra", "SCBraPos", \ "SCond", \- "Cond ref", "Cond dnref", "Cond rec", "Cond dnrec", \+ "Capture ref", "Capture dnref", "Cond rec", "Cond dnrec", \ "Cond false", "Cond true", \ "Brazero", "Braminzero", "Braposzero", \ "*MARK", "*PRUNE", "*PRUNE", "*SKIP", "*SKIP", \@@ -1766,10 +2012,11 @@ 1+(32/sizeof(PCRE2_UCHAR)), /* CLASS */ \ 1+(32/sizeof(PCRE2_UCHAR)), /* NCLASS */ \ 0, /* XCLASS - variable length */ \+ 0, /* ECLASS - variable length */ \ 1+IMM2_SIZE, /* REF */ \- 1+IMM2_SIZE, /* REFI */ \+ 1+IMM2_SIZE+1, /* REFI */ \ 1+2*IMM2_SIZE, /* DNREF */ \- 1+2*IMM2_SIZE, /* DNREFI */ \+ 1+2*IMM2_SIZE+1, /* DNREFI */ \ 1+LINK_SIZE, /* RECURSE */ \ 1+2*LINK_SIZE+1, /* CALLOUT */ \ 0, /* CALLOUT_STR - variable length */ \@@ -1786,6 +2033,7 @@ 1+LINK_SIZE, /* Assert behind not */ \ 1+LINK_SIZE, /* NA Assert */ \ 1+LINK_SIZE, /* NA Assert behind */ \+ 1+LINK_SIZE, /* Scan substring */ \ 1+LINK_SIZE, /* ONCE */ \ 1+LINK_SIZE, /* SCRIPT_RUN */ \ 1+LINK_SIZE, /* BRA */ \@@ -1815,7 +2063,12 @@ #define RREF_ANY 0xffff +/* Constants used by OP_REFI and OP_DNREFI to control matching behaviour. */ +#define REFI_FLAG_CASELESS_RESTRICT 0x1+#define REFI_FLAG_TURKISH_CASING 0x2++ /* ---------- Private structures that are mode-independent. ---------- */ /* Structure to hold data for custom memory management. */@@ -1890,6 +2143,14 @@ #define UCD_SCRIPTX(ch) UCD_SCRIPTX_PROP(GET_UCD(ch)) #define UCD_BPROPS(ch) UCD_BPROPS_PROP(GET_UCD(ch)) #define UCD_BIDICLASS(ch) UCD_BIDICLASS_PROP(GET_UCD(ch))+#define UCD_ANY_I(ch) \+ /* match any of the four characters 'i', 'I', U+0130, U+0131 */ \+ (((uint32_t)(ch) | 0x20u) == 0x69u || ((uint32_t)(ch) | 1u) == 0x0131u)+#define UCD_DOTTED_I(ch) \+ ((uint32_t)(ch) == 0x69u || (uint32_t)(ch) == 0x0130u)+#define UCD_FOLD_I_TURKISH(ch) \+ ((uint32_t)(ch) == 0x0130u ? 0x69u : \+ (uint32_t)(ch) == 0x49u ? 0x0131u : (uint32_t)(ch)) /* The "scriptx" and bprops fields contain offsets into vectors of 32-bit words that form a bitmap representing a list of scripts or boolean properties. These@@ -1935,7 +2196,7 @@ #if PCRE2_CODE_UNIT_WIDTH == 8 extern const int PRIV(utf8_table1)[];-extern const int PRIV(utf8_table1_size);+extern const unsigned PRIV(utf8_table1_size); extern const int PRIV(utf8_table2)[]; extern const int PRIV(utf8_table3)[]; extern const uint8_t PRIV(utf8_table4)[];@@ -1955,6 +2216,9 @@ #define _pcre2_vspace_list PCRE2_SUFFIX(_pcre2_vspace_list_) #define _pcre2_ucd_boolprop_sets PCRE2_SUFFIX(_pcre2_ucd_boolprop_sets_) #define _pcre2_ucd_caseless_sets PCRE2_SUFFIX(_pcre2_ucd_caseless_sets_)+#define _pcre2_ucd_turkish_dotted_i_caseset PCRE2_SUFFIX(_pcre2_ucd_turkish_dotted_i_caseset_)+#define _pcre2_ucd_nocase_ranges PCRE2_SUFFIX(_pcre2_ucd_nocase_ranges_)+#define _pcre2_ucd_nocase_ranges_size PCRE2_SUFFIX(_pcre2_ucd_nocase_ranges_size_) #define _pcre2_ucd_digit_sets PCRE2_SUFFIX(_pcre2_ucd_digit_sets_) #define _pcre2_ucd_script_sets PCRE2_SUFFIX(_pcre2_ucd_script_sets_) #define _pcre2_ucd_records PCRE2_SUFFIX(_pcre2_ucd_records_)@@ -1967,18 +2231,23 @@ #define _pcre2_utt PCRE2_SUFFIX(_pcre2_utt_) #define _pcre2_utt_names PCRE2_SUFFIX(_pcre2_utt_names_) #define _pcre2_utt_size PCRE2_SUFFIX(_pcre2_utt_size_)+#define _pcre2_ebcdic_1047_to_ascii PCRE2_SUFFIX(_pcre2_ebcdic_1047_to_ascii_)+#define _pcre2_ascii_to_ebcdic_1047 PCRE2_SUFFIX(_pcre2_ascii_to_ebcdic_1047_) extern const uint8_t PRIV(OP_lengths)[]; extern const uint32_t PRIV(callout_end_delims)[]; extern const uint32_t PRIV(callout_start_delims)[];-extern const pcre2_compile_context PRIV(default_compile_context);-extern const pcre2_convert_context PRIV(default_convert_context);-extern const pcre2_match_context PRIV(default_match_context);+extern pcre2_compile_context PRIV(default_compile_context);+extern pcre2_convert_context PRIV(default_convert_context);+extern pcre2_match_context PRIV(default_match_context); extern const uint8_t PRIV(default_tables)[]; extern const uint32_t PRIV(hspace_list)[]; extern const uint32_t PRIV(vspace_list)[]; extern const uint32_t PRIV(ucd_boolprop_sets)[]; extern const uint32_t PRIV(ucd_caseless_sets)[];+extern const uint32_t PRIV(ucd_turkish_dotted_i_caseset);+extern const uint32_t PRIV(ucd_nocase_ranges)[];+extern const uint32_t PRIV(ucd_nocase_ranges_size); extern const uint32_t PRIV(ucd_digit_sets)[]; extern const uint32_t PRIV(ucd_script_sets)[]; extern const ucd_record PRIV(ucd_records)[];@@ -1996,6 +2265,8 @@ extern const ucp_type_table PRIV(utt)[]; extern const char PRIV(utt_names)[]; extern const size_t PRIV(utt_size);+extern const uint8_t PRIV(ebcdic_1047_to_ascii)[];+extern const uint8_t PRIV(ascii_to_ebcdic_1047)[]; /* Mode-dependent macros and hidden and private structures are defined in a separate file so that pcre2test can include them at all supported widths. When@@ -2019,6 +2290,7 @@ #define _pcre2_auto_possessify PCRE2_SUFFIX(_pcre2_auto_possessify_) #define _pcre2_check_escape PCRE2_SUFFIX(_pcre2_check_escape_)+#define _pcre2_ckd_smul PCRE2_SUFFIX(_pcre2_ckd_smul_) #define _pcre2_extuni PCRE2_SUFFIX(_pcre2_extuni_) #define _pcre2_find_bracket PCRE2_SUFFIX(_pcre2_find_bracket_) #define _pcre2_is_newline PCRE2_SUFFIX(_pcre2_is_newline_)@@ -2039,11 +2311,13 @@ #define _pcre2_valid_utf PCRE2_SUFFIX(_pcre2_valid_utf_) #define _pcre2_was_newline PCRE2_SUFFIX(_pcre2_was_newline_) #define _pcre2_xclass PCRE2_SUFFIX(_pcre2_xclass_)+#define _pcre2_eclass PCRE2_SUFFIX(_pcre2_eclass_) extern int _pcre2_auto_possessify(PCRE2_UCHAR *, const compile_block *); extern int _pcre2_check_escape(PCRE2_SPTR *, PCRE2_SPTR, uint32_t *,- int *, uint32_t, uint32_t, BOOL, compile_block *);+ int *, uint32_t, uint32_t, uint32_t, BOOL, compile_block *);+extern BOOL _pcre2_ckd_smul(PCRE2_SIZE *, int, int); extern PCRE2_SPTR _pcre2_extuni(uint32_t, PCRE2_SPTR, PCRE2_SPTR, PCRE2_SPTR, BOOL, int *); extern PCRE2_SPTR _pcre2_find_bracket(PCRE2_SPTR, BOOL, int);@@ -2066,18 +2340,13 @@ extern int _pcre2_valid_utf(PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE *); extern BOOL _pcre2_was_newline(PCRE2_SPTR, uint32_t, PCRE2_SPTR, uint32_t *, BOOL);-extern BOOL _pcre2_xclass(uint32_t, PCRE2_SPTR, BOOL);--/* This function is needed only when memmove() is not available. */--#if !defined(VPCOMPAT) && !defined(HAVE_MEMMOVE)-#define _pcre2_memmove PCRE2_SUFFIX(_pcre2_memmove)-extern void * _pcre2_memmove(void *, const void *, size_t);-#endif+extern BOOL _pcre2_xclass(uint32_t, PCRE2_SPTR, const uint8_t *, BOOL);+extern BOOL _pcre2_eclass(uint32_t, PCRE2_SPTR, PCRE2_SPTR,+ const uint8_t *, BOOL); #endif /* PCRE2_CODE_UNIT_WIDTH */ -extern BOOL PRIV(ckd_smul)(PCRE2_SIZE *, int, int);+#include "pcre2_util.h" #endif /* PCRE2_INTERNAL_H_IDEMPOTENT_GUARD */
src/c/pcre2/src/pcre2_intmodedep.h view
@@ -47,10 +47,17 @@ Some of the mode-dependent macros are required at different widths for different parts of the pcre2test code (in particular, the included-pcre_printint.c file). We undefine them here so that they can be re-defined for-multiple inclusions. Not all of these are used in pcre2test, but it's easier-just to undefine them all. */+pcre2_printint_inc.h file). We undefine them here so that they can be re-defined+for multiple inclusions. Not all of these are used in pcre2test, but it's easier+just to undefine them all. +You can also include pcre2_intmodedep.h with PCRE2_CODE_UNIT_WIDTH defined to+zero in order to simply clear the previous macros. */++#ifndef PCRE2_CODE_UNIT_WIDTH+#error PCRE2_CODE_UNIT_WIDTH must be defined+#endif+ #undef ACROSSCHAR #undef BACKCHAR #undef BYTES2CU@@ -81,9 +88,14 @@ #undef PUTINC #undef TABLE_GET +/*************************************************+* MACROS *+*************************************************/ +/* Macros may be undefined and re-defined if the same file handles multiple+bit-widths. */ -/* -------------------------- MACROS ----------------------------- */+#if PCRE2_CODE_UNIT_WIDTH != 0 /* PCRE keeps offsets in its compiled code as at least 16-bit quantities (always stored in big-endian order in 8-bit mode) by default. These are used,@@ -97,11 +109,23 @@ The macros are controlled by the value of LINK_SIZE. This defaults to 2, but values of 3 or 4 are also supported. */ +#ifndef CONFIGURED_LINK_SIZE+#if LINK_SIZE == 2+#define CONFIGURED_LINK_SIZE 2+#elif LINK_SIZE == 3+#define CONFIGURED_LINK_SIZE 3+#elif LINK_SIZE == 4+#define CONFIGURED_LINK_SIZE 4+#else+#error LINK_SIZE must be 2, 3, or 4+#endif+#endif /* CONFIGURED_LINK_SIZE */+ /* ------------------- 8-bit support ------------------ */ #if PCRE2_CODE_UNIT_WIDTH == 8 -#if LINK_SIZE == 2+#if CONFIGURED_LINK_SIZE == 2 #define PUT(a,n,d) \ (a[n] = (PCRE2_UCHAR)((d) >> 8)), \ (a[(n)+1] = (PCRE2_UCHAR)((d) & 255))@@ -109,7 +133,7 @@ (unsigned int)(((a)[n] << 8) | (a)[(n)+1]) #define MAX_PATTERN_SIZE (1 << 16) -#elif LINK_SIZE == 3+#elif CONFIGURED_LINK_SIZE == 3 #define PUT(a,n,d) \ (a[n] = (PCRE2_UCHAR)((d) >> 16)), \ (a[(n)+1] = (PCRE2_UCHAR)((d) >> 8)), \@@ -118,7 +142,7 @@ (unsigned int)(((a)[n] << 16) | ((a)[(n)+1] << 8) | (a)[(n)+2]) #define MAX_PATTERN_SIZE (1 << 24) -#elif LINK_SIZE == 4+#elif CONFIGURED_LINK_SIZE == 4 #define PUT(a,n,d) \ (a[n] = (PCRE2_UCHAR)((d) >> 24)), \ (a[(n)+1] = (PCRE2_UCHAR)((d) >> 16)), \@@ -128,8 +152,6 @@ (unsigned int)(((a)[n] << 24) | ((a)[(n)+1] << 16) | ((a)[(n)+2] << 8) | (a)[(n)+3]) #define MAX_PATTERN_SIZE (1 << 30) /* Keep it positive */ -#else-#error LINK_SIZE must be 2, 3, or 4 #endif @@ -137,7 +159,7 @@ #elif PCRE2_CODE_UNIT_WIDTH == 16 -#if LINK_SIZE == 2+#if CONFIGURED_LINK_SIZE == 2 #undef LINK_SIZE #define LINK_SIZE 1 #define PUT(a,n,d) \@@ -146,7 +168,7 @@ (a[n]) #define MAX_PATTERN_SIZE (1 << 16) -#elif LINK_SIZE == 3 || LINK_SIZE == 4+#elif CONFIGURED_LINK_SIZE == 3 || CONFIGURED_LINK_SIZE == 4 #undef LINK_SIZE #define LINK_SIZE 2 #define PUT(a,n,d) \@@ -156,8 +178,6 @@ (unsigned int)(((a)[n] << 16) | (a)[(n)+1]) #define MAX_PATTERN_SIZE (1 << 30) /* Keep it positive */ -#else-#error LINK_SIZE must be 2, 3, or 4 #endif @@ -194,7 +214,7 @@ #define GET2(a,n) (unsigned int)(((a)[n] << 8) | (a)[(n)+1]) #define PUT2(a,n,d) a[n] = (d) >> 8, a[(n)+1] = (d) & 255 -#else /* Code units are 16 or 32 bits */+#elif PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32 #define IMM2_SIZE 1 #define GET2(a,n) a[n] #define PUT2(a,n,d) a[n] = d@@ -219,7 +239,7 @@ #define CHMAX_255(c) TRUE #endif /* SUPPORT_UNICODE */ -#else /* Code units are 16 or 32 bits */+#elif PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32 #define CHMAX_255(c) ((c) <= 255u) #define MAX_255(c) ((c) <= 255u) #define MAX_MARK ((1u << 16) - 1)@@ -285,7 +305,7 @@ #define HAS_EXTRALEN(c) HASUTF8EXTRALEN(c) -/* Returns with the additional number of characters if IS_MULTICHAR(c) is TRUE.+/* Returns with the additional number of characters if HAS_EXTRALEN(c) is TRUE. Otherwise it has an undefined behaviour. */ #define GET_EXTRALEN(c) (PRIV(utf8_table4)[(c) & 0x3fu])@@ -371,7 +391,7 @@ #define HAS_EXTRALEN(c) (((c) & 0xfc00u) == 0xd800u) -/* Returns with the additional number of characters if IS_MULTICHAR(c) is TRUE.+/* Returns with the additional number of characters if HAS_EXTRALEN(c) is TRUE. Otherwise it has an undefined behaviour. */ #define GET_EXTRALEN(c) 1@@ -435,7 +455,7 @@ c = *eptr; \ if ((c & 0xfc00u) == 0xd800u) GETUTF16LEN(c, eptr, len); -/* Get the next UTF-816character, testing for UTF-16 mode, not advancing the+/* Get the next UTF-16 character, testing for UTF-16 mode, not advancing the pointer, incrementing length if there is a low surrogate. This is called when we do not know if we are in UTF-16 mode. */ @@ -466,7 +486,7 @@ /* ------------------- 32-bit support ------------------ */ -#else+#elif PCRE2_CODE_UNIT_WIDTH == 32 /* These are trivial for the 32-bit library, since all UTF-32 characters fit into one PCRE2_UCHAR unit. */@@ -547,7 +567,33 @@ #define PUTINC(a,n,d) PUT(a,n,d), a += LINK_SIZE #define PUT2INC(a,n,d) PUT2(a,n,d), a += IMM2_SIZE +#endif /* PCRE2_CODE_UNIT_WIDTH != 0 */ +++/*************************************************+* STRUCTURES *+*************************************************/++/* We need a more complex include guard than usual, because the file can be+included once for each bit-width to define the various structures. */++#if PCRE2_CODE_UNIT_WIDTH == 8 && !defined PCRE2_INTMODEDEP_IDEMPOTENT_GUARD_8+#define PCRE2_INTMODEDEP_IDEMPOTENT_GUARD_8+#define PCRE2_INTMODEDEP_CAN_DEFINE+#endif+#if PCRE2_CODE_UNIT_WIDTH == 16 && !defined PCRE2_INTMODEDEP_IDEMPOTENT_GUARD_16+#define PCRE2_INTMODEDEP_IDEMPOTENT_GUARD_16+#define PCRE2_INTMODEDEP_CAN_DEFINE+#endif+#if PCRE2_CODE_UNIT_WIDTH == 32 && !defined PCRE2_INTMODEDEP_IDEMPOTENT_GUARD_32+#define PCRE2_INTMODEDEP_IDEMPOTENT_GUARD_32+#define PCRE2_INTMODEDEP_CAN_DEFINE+#endif++#ifdef PCRE2_INTMODEDEP_CAN_DEFINE+#undef PCRE2_INTMODEDEP_CAN_DEFINE+ /* ----------------------- HIDDEN STRUCTURES ----------------------------- */ /* NOTE: All these structures *must* start with a pcre2_memctl structure. The@@ -556,6 +602,11 @@ /* The real general context structure. At present it holds only data for custom memory control. */ +/* WARNING: if this is ever changed, code in pcre2_substitute.c will have to be+changed because it builds a general context "by hand" in order to avoid the+malloc() call in pcre2_general_context)_create(). There is also code in+pcre2_match.c that makes the same assumption. */+ typedef struct pcre2_real_general_context { pcre2_memctl memctl; } pcre2_real_general_context;@@ -574,6 +625,7 @@ uint32_t parens_nest_limit; uint32_t extra_options; uint32_t max_varlookbehind;+ uint32_t optimization_flags; } pcre2_real_compile_context; /* The real match context structure. */@@ -584,10 +636,13 @@ pcre2_jit_callback jit_callback; void *jit_callback_data; #endif- int (*callout)(pcre2_callout_block *, void *);- void *callout_data;- int (*substitute_callout)(pcre2_substitute_callout_block *, void *);- void *substitute_callout_data;+ int (*callout)(pcre2_callout_block *, void *);+ void *callout_data;+ int (*substitute_callout)(pcre2_substitute_callout_block *, void *);+ void *substitute_callout_data;+ PCRE2_SIZE (*substitute_case_callout)(PCRE2_SPTR, PCRE2_SIZE, PCRE2_UCHAR *,+ PCRE2_SIZE, int, void *);+ void *substitute_case_callout_data; PCRE2_SIZE offset_limit; uint32_t heap_limit; uint32_t match_limit;@@ -615,7 +670,7 @@ #define CODE_BLOCKSIZE_TYPE PCRE2_SIZE #undef LOOKBEHIND_MAX-#define LOOKBEHIND_MAX UINT16_MAX+#define LOOKBEHIND_MAX ((int)UINT16_MAX) typedef struct pcre2_real_code { pcre2_memctl memctl; /* Memory control fields */@@ -623,6 +678,7 @@ void *executable_jit; /* Pointer to JIT code */ uint8_t start_bitmap[32]; /* Bitmap for starting code unit < 256 */ CODE_BLOCKSIZE_TYPE blocksize; /* Total (bytes) that was malloc-ed */+ CODE_BLOCKSIZE_TYPE code_start; /* Byte code start offset */ uint32_t magic_number; /* Paranoid and endianness check */ uint32_t compile_options; /* Options passed to pcre2_compile() */ uint32_t overall_options; /* Options after processing the pattern */@@ -641,6 +697,7 @@ uint16_t top_backref; /* Highest numbered back reference */ uint16_t name_entry_size; /* Size (code units) of table entries */ uint16_t name_count; /* Number of name entries in the table */+ uint32_t optimization_flags; /* Optimizations enabled at compile time */ } pcre2_real_code; /* The real match data structure. Define ovector as large as it can ever@@ -661,12 +718,14 @@ struct heapframe *heapframes; /* Backtracking frames heap memory */ PCRE2_SIZE heapframes_size; /* Malloc-ed size */ PCRE2_SIZE subject_length; /* Subject length */+ PCRE2_SIZE start_offset; /* Offset to start of search */ 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 */+ uint32_t options; /* Options passed in to the match call */ int rc; /* The return code from the match */ PCRE2_SIZE ovector[131072]; /* Must be last in the structure */ } pcre2_real_match_data;@@ -707,15 +766,51 @@ } branch_chain; /* Structure for building a list of named groups during the first pass of-compiling. */+compiling. When a duplicate name is stored in the list, its name is set to+the name of the first entry with the same name, and its length is set to 0. */ typedef struct named_group { PCRE2_SPTR name; /* Points to the name in the pattern */ uint32_t number; /* Group number */ uint16_t length; /* Length of the name */- uint16_t isdup; /* TRUE if a duplicate */+ uint16_t hash_dup; /* A concatenation of a 15 bit hash code and+ a singe bit which represents duplication */ } named_group; +/* Structure for storing compile time data. */++typedef struct compile_data {+ struct compile_data *next; /* Next compile data */+#ifdef PCRE2_DEBUG+ uint8_t type; /* Debug only type of the data */+#endif+} compile_data;++/* Structure for caching sorted ranges. This improves the performance+of translating META code to byte code. */++typedef struct class_ranges {+ compile_data header; /* Common header */+ size_t char_lists_size; /* Total size of encoded char lists */+ size_t char_lists_start; /* Start offset of encoded char lists */+ uint16_t range_list_size; /* Size of ranges array */+ uint16_t char_lists_types; /* The XCL_LIST header of char lists */+ /* Followed by the list of ranges (start/end pairs) */+} class_ranges;++/* Structure for sorted recurse arguments. */++typedef struct recurse_arguments {+ compile_data header; /* Common header */+ size_t size; /* Total size */+ size_t skip_size; /* Space consumed by arguments */+} recurse_arguments;++typedef union class_bits_storage {+ uint8_t classbits[32];+ uint32_t classwords[8];+} class_bits_storage;+ /* Structure for passing "static" information around between the functions doing the compiling, so that they are thread-safe. */ @@ -725,14 +820,15 @@ const uint8_t *fcc; /* Points to case-flipping table */ const uint8_t *cbits; /* Points to character type table */ const uint8_t *ctypes; /* Points to table of type maps */- PCRE2_SPTR start_workspace; /* The start of working space */- PCRE2_SPTR start_code; /* The start of the compiled code */+ PCRE2_UCHAR *start_workspace; /* The start of working space */+ PCRE2_UCHAR *start_code; /* The start of the compiled code */ PCRE2_SPTR start_pattern; /* The start of the pattern */ PCRE2_SPTR end_pattern; /* The end of the pattern */ PCRE2_UCHAR *name_table; /* The name/number table */ PCRE2_SIZE workspace_size; /* Size of workspace */ PCRE2_SIZE small_ref_offset[10]; /* Offsets for \1 to \9 */ PCRE2_SIZE erroroffset; /* Offset of error in pattern */+ class_bits_storage classbits; /* Temporary store for classbits */ uint16_t names_found; /* Number of entries so far */ uint16_t name_entry_size; /* Size of each entry */ uint16_t parens_depth; /* Depth of nested parentheses */@@ -750,9 +846,9 @@ uint32_t backref_map; /* Bitmap of low back refs */ uint32_t nltype; /* Newline type */ uint32_t nllen; /* Newline string length */- uint32_t class_range_start; /* Overall class range start */- uint32_t class_range_end; /* Overall class range end */ PCRE2_UCHAR nl[4]; /* Newline string when fixed length */+ uint8_t class_op_used[ECLASS_NEST_LIMIT]; /* Operation used for+ extended classes */ uint32_t req_varyopt; /* "After variable item" flag for reqbyte */ uint32_t max_varlookbehind; /* Limit for variable lookbehinds */ int max_lookbehind; /* Maximum lookbehind encountered (characters) */@@ -760,6 +856,11 @@ BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */ BOOL had_recurse; /* Had a pattern recursion or subroutine call */ BOOL dupnames; /* Duplicate names exist */+ compile_data *first_data; /* First item in the compile data list */+ compile_data *last_data; /* Last item in the compile data list */+#ifdef SUPPORT_WIDE_CHARS+ size_t char_lists_size; /* Current size of character lists */+#endif } compile_block; /* Structure for keeping the properties of the in-memory stack used@@ -793,7 +894,7 @@ to RRMATCH(), but which do not need to be copied to new frames. */ PCRE2_SPTR ecode; /* The current position in the pattern */- PCRE2_SPTR temp_sptr[2]; /* Used for short-term PCRE_SPTR values */+ PCRE2_SPTR temp_sptr[2]; /* Used for short-term PCRE2_SPTR values */ 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 */@@ -841,11 +942,10 @@ 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-multiple of PCRE2_SIZE. See various comments above. */+/* Assert that the size of the heapframe structure is a multiple of PCRE2_SIZE.+See various comments above. */ -typedef char check_heapframe_size[- ((sizeof(heapframe) % sizeof(PCRE2_SIZE)) == 0)? (+1):(-1)];+STATIC_ASSERT((sizeof(heapframe) % sizeof(PCRE2_SIZE)) == 0, heapframe_size); /* Structure for computing the alignment of heapframe. */ @@ -869,7 +969,9 @@ uint32_t match_call_count; /* Number of times a new frame is created */ BOOL hitend; /* Hit the end of the subject at some point */ BOOL hasthen; /* Pattern contains (*THEN) */+ BOOL hasbsk; /* Pattern contains \K */ BOOL allowemptypartial; /* Allow empty hard partial */+ BOOL allowlookaroundbsk; /* Allow \K within lookarounds */ const uint8_t *lcc; /* Points to lower casing table */ const uint8_t *fcc; /* Points to case-flipping table */ const uint8_t *ctypes; /* Points to table of type maps */@@ -936,5 +1038,7 @@ } dfa_match_block; #endif /* PCRE2_PCRE2TEST */++#endif /* PCRE2_INTMODEDEP_CAN_DEFINE */ /* End of pcre2_intmodedep.h */
+ src/c/pcre2/src/pcre2_jit_char_inc.h view
@@ -0,0 +1,2280 @@+/*************************************************+* 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+ This module by Zoltan Herczeg+ Original API code Copyright (c) 1997-2012 University of Cambridge+ 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.+-----------------------------------------------------------------------------+*/++/* XClass matching code. */++#ifdef SUPPORT_WIDE_CHARS++#define ECLASS_CHAR_DATA STACK_TOP+#define ECLASS_STACK_DATA STACK_LIMIT++#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);++#define READ_FROM_CHAR_LIST(destination) \+ if (list_ind <= 1) \+ { \+ destination = *(const uint16_t*)next_char; \+ next_char += 2; \+ } \+ else \+ { \+ destination = *(const uint32_t*)next_char; \+ next_char += 4; \+ }++#define XCLASS_LOCAL_RANGES_SIZE 32+#define XCLASS_LOCAL_RANGES_LOG2_SIZE 5++typedef struct xclass_stack_item {+ sljit_u32 first_item;+ sljit_u32 last_item;+ struct sljit_jump *jump;+} xclass_stack_item;++typedef struct xclass_ranges {+ size_t range_count;+ /* Pointer to ranges. A stack area is provided when a small buffer is enough. */+ uint32_t *ranges;+ uint32_t local_ranges[XCLASS_LOCAL_RANGES_SIZE * 2];+ /* Stack size must be log2(ranges / 2). */+ xclass_stack_item *stack;+ xclass_stack_item local_stack[XCLASS_LOCAL_RANGES_LOG2_SIZE];+} xclass_ranges;++static void xclass_compute_ranges(compiler_common *common, PCRE2_SPTR cc, xclass_ranges *ranges)+{+DEFINE_COMPILER;+size_t range_count = 0, est_range_count;+size_t est_stack_size, tmp;+uint32_t type, list_ind;+uint32_t est_type;+uint32_t char_list_add, range_start, range_end;+const uint8_t *next_char;+const uint8_t *est_next_char;+#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] */++if (*cc == XCL_SINGLE || *cc == XCL_RANGE)+ {+ /* Only a few ranges are present. */+ do+ {+ type = *cc++;+ SLJIT_ASSERT(type == XCL_SINGLE || type == XCL_RANGE);+ GETCHARINCTEST(range_end, cc);+ ranges->ranges[range_count] = range_end;++ if (type == XCL_RANGE)+ {+ GETCHARINCTEST(range_end, cc);+ }++ ranges->ranges[range_count + 1] = range_end;+ range_count += 2;+ }+ while (*cc != XCL_END);++ SLJIT_ASSERT(range_count <= XCLASS_LOCAL_RANGES_SIZE);+ ranges->range_count = range_count;+ return;+ }++SLJIT_ASSERT(cc[0] >= XCL_LIST);+#if PCRE2_CODE_UNIT_WIDTH == 8+type = (uint32_t)(cc[0] << 8) | cc[1];+cc += 2;+#else+type = cc[0];+cc++;+#endif /* CODE_UNIT_WIDTH */++/* Align characters. */+next_char = (const uint8_t*)common->start - (GET(cc, 0) << 1);+type &= XCL_TYPE_MASK;++/* Estimate size. */+est_next_char = next_char;+est_type = type;+est_range_count = 0;+list_ind = 0;++while (est_type > 0)+ {+ uint32_t item_count = est_type & XCL_ITEM_COUNT_MASK;++ if (item_count == XCL_ITEM_COUNT_MASK)+ {+ if (list_ind <= 1)+ {+ item_count = *(const uint16_t*)est_next_char;+ est_next_char += 2;+ }+ else+ {+ item_count = *(const uint32_t*)est_next_char;+ est_next_char += 4;+ }+ }++ est_type >>= XCL_TYPE_BIT_LEN;+ est_next_char += (size_t)item_count << (list_ind <= 1 ? 1 : 2);+ list_ind++;+ est_range_count += item_count + 1;+ }++if (est_range_count > XCLASS_LOCAL_RANGES_SIZE)+ {+ est_stack_size = 0;+ tmp = est_range_count - 1;++ /* Compute log2(est_range_count) */+ while (tmp > 0)+ {+ est_stack_size++;+ tmp >>= 1;+ }++ ranges->stack = (xclass_stack_item*)SLJIT_MALLOC((sizeof(xclass_stack_item) * est_stack_size)+ + ((sizeof(uint32_t) << 1) * (size_t)est_range_count), compiler->allocator_data);++ if (ranges->stack == NULL)+ {+ sljit_set_compiler_memory_error(compiler);+ ranges->ranges = NULL;+ return;+ }++ ranges->ranges = (uint32_t*)(ranges->stack + est_stack_size);+ }++char_list_add = XCL_CHAR_LIST_LOW_16_ADD;+range_start = ~(uint32_t)0;+list_ind = 0;++if ((type & XCL_BEGIN_WITH_RANGE) != 0)+ range_start = XCL_CHAR_LIST_LOW_16_START;++while (type > 0)+ {+ uint32_t item_count = type & XCL_ITEM_COUNT_MASK;++ if (item_count == XCL_ITEM_COUNT_MASK)+ {+ READ_FROM_CHAR_LIST(item_count);+ SLJIT_ASSERT(item_count >= XCL_ITEM_COUNT_MASK);+ }++ while (item_count > 0)+ {+ READ_FROM_CHAR_LIST(range_end);++ if ((range_end & XCL_CHAR_END) != 0)+ {+ range_end = char_list_add + (range_end >> XCL_CHAR_SHIFT);++ if (range_start == ~(uint32_t)0)+ range_start = range_end;++ ranges->ranges[range_count] = range_start;+ ranges->ranges[range_count + 1] = range_end;+ range_count += 2;+ range_start = ~(uint32_t)0;+ }+ else+ range_start = char_list_add + (range_end >> XCL_CHAR_SHIFT);++ item_count--;+ }++ list_ind++;+ type >>= XCL_TYPE_BIT_LEN;++ if (range_start == ~(uint32_t)0)+ {+ if ((type & XCL_BEGIN_WITH_RANGE) != 0)+ {+ if (list_ind == 1) range_start = XCL_CHAR_LIST_HIGH_16_START;+#if PCRE2_CODE_UNIT_WIDTH == 32+ else if (list_ind == 2) range_start = XCL_CHAR_LIST_LOW_32_START;+ else range_start = XCL_CHAR_LIST_HIGH_32_START;+#else+ else range_start = XCL_CHAR_LIST_LOW_32_START;+#endif+ }+ }+ else if ((type & XCL_BEGIN_WITH_RANGE) == 0)+ {+ if (list_ind == 1) range_end = XCL_CHAR_LIST_LOW_16_END;+ else if (list_ind == 2) range_end = XCL_CHAR_LIST_HIGH_16_END;+#if PCRE2_CODE_UNIT_WIDTH == 32+ else if (list_ind == 3) range_end = XCL_CHAR_LIST_LOW_32_END;+ else range_end = XCL_CHAR_LIST_HIGH_32_END;+#else+ else range_end = XCL_CHAR_LIST_LOW_32_END;+#endif++ ranges->ranges[range_count] = range_start;+ ranges->ranges[range_count + 1] = range_end;+ range_count += 2;+ range_start = ~(uint32_t)0;+ }++ if (list_ind == 1) char_list_add = XCL_CHAR_LIST_HIGH_16_ADD;+#if PCRE2_CODE_UNIT_WIDTH == 32+ else if (list_ind == 2) char_list_add = XCL_CHAR_LIST_LOW_32_ADD;+ else char_list_add = XCL_CHAR_LIST_HIGH_32_ADD;+#else+ else char_list_add = XCL_CHAR_LIST_LOW_32_ADD;+#endif+ }++SLJIT_ASSERT(range_count > 0 && range_count <= (est_range_count << 1));+SLJIT_ASSERT(next_char <= (const uint8_t*)common->start);+ranges->range_count = range_count;+}++static void xclass_check_bitset(compiler_common *common, const sljit_u8 *bitset, jump_list **found, jump_list **backtracks)+{+DEFINE_COMPILER;+struct sljit_jump *jump;++jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);+if (!optimize_class(common, bitset, (bitset[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)bitset);+ 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);+}++#if defined SUPPORT_UNICODE && (PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16)++static void xclass_update_min_max(compiler_common *common, PCRE2_SPTR cc, sljit_u32 *min_ptr, sljit_u32 *max_ptr)+{+uint32_t type, list_ind, c;+sljit_u32 min = *min_ptr;+sljit_u32 max = *max_ptr;+uint32_t char_list_add;+const uint8_t *next_char;+BOOL utf = TRUE;++/* This function is pointless without utf 8/16. */+SLJIT_ASSERT(common->utf);+if (*cc == XCL_SINGLE || *cc == XCL_RANGE)+ {+ /* Only a few ranges are present. */+ do+ {+ type = *cc++;+ SLJIT_ASSERT(type == XCL_SINGLE || type == XCL_RANGE);+ GETCHARINCTEST(c, cc);++ if (c < min)+ min = c;++ if (type == XCL_RANGE)+ {+ GETCHARINCTEST(c, cc);+ }++ if (c > max)+ max = c;+ }+ while (*cc != XCL_END);++ SLJIT_ASSERT(min <= MAX_UTF_CODE_POINT && max <= MAX_UTF_CODE_POINT && min <= max);+ *min_ptr = min;+ *max_ptr = max;+ return;+ }++SLJIT_ASSERT(cc[0] >= XCL_LIST);+#if PCRE2_CODE_UNIT_WIDTH == 8+type = (uint32_t)(cc[0] << 8) | cc[1];+cc += 2;+#else+type = cc[0];+cc++;+#endif /* CODE_UNIT_WIDTH */++/* Align characters. */+next_char = (const uint8_t*)common->start - (GET(cc, 0) << 1);+type &= XCL_TYPE_MASK;++SLJIT_ASSERT(type != 0);++/* Detect minimum. */++/* Skip unused ranges. */+list_ind = 0;+while ((type & (XCL_BEGIN_WITH_RANGE | XCL_ITEM_COUNT_MASK)) == 0)+ {+ type >>= XCL_TYPE_BIT_LEN;+ list_ind++;+ }++SLJIT_ASSERT(list_ind <= 2);+switch (list_ind)+ {+ case 0:+ char_list_add = XCL_CHAR_LIST_LOW_16_ADD;+ c = XCL_CHAR_LIST_LOW_16_START;+ break;++ case 1:+ char_list_add = XCL_CHAR_LIST_HIGH_16_ADD;+ c = XCL_CHAR_LIST_HIGH_16_START;+ break;++ default:+ char_list_add = XCL_CHAR_LIST_LOW_32_ADD;+ c = XCL_CHAR_LIST_LOW_32_START;+ break;+ }++if ((type & XCL_BEGIN_WITH_RANGE) != 0)+ {+ if (c < min)+ min = c;+ }+else+ {+ if ((type & XCL_ITEM_COUNT_MASK) == XCL_ITEM_COUNT_MASK)+ {+ if (list_ind <= 1)+ c = *(const uint16_t*)(next_char + 2);+ else+ c = *(const uint32_t*)(next_char + 4);+ }+ else+ {+ if (list_ind <= 1)+ c = *(const uint16_t*)next_char;+ else+ c = *(const uint32_t*)next_char;+ }++ c = char_list_add + (c >> XCL_CHAR_SHIFT);+ if (c < min)+ min = c;+ }++/* Detect maximum. */++/* Skip intermediate ranges. */+while (TRUE)+ {+ if ((type & XCL_ITEM_COUNT_MASK) == XCL_ITEM_COUNT_MASK)+ {+ if (list_ind <= 1)+ {+ c = *(const uint16_t*)next_char;+ next_char += (c + 1) << 1;+ }+ else+ {+ c = *(const uint32_t*)next_char;+ next_char += (c + 1) << 2;+ }+ }+ else+ next_char += (type & XCL_ITEM_COUNT_MASK) << (list_ind <= 1 ? 1 : 2);++ if ((type >> XCL_TYPE_BIT_LEN) == 0)+ break;++ list_ind++;+ type >>= XCL_TYPE_BIT_LEN;+ }++SLJIT_ASSERT(list_ind <= 2 && type != 0);+switch (list_ind)+ {+ case 0:+ char_list_add = XCL_CHAR_LIST_LOW_16_ADD;+ c = XCL_CHAR_LIST_LOW_16_END;+ break;++ case 1:+ char_list_add = XCL_CHAR_LIST_HIGH_16_ADD;+ c = XCL_CHAR_LIST_HIGH_16_END;+ break;++ default:+ char_list_add = XCL_CHAR_LIST_LOW_32_ADD;+ c = XCL_CHAR_LIST_LOW_32_END;+ break;+ }++if ((type & XCL_ITEM_COUNT_MASK) != 0)+ {+ /* Type is reused as temporary. */+ if (list_ind <= 1)+ type = *(const uint16_t*)(next_char - 2);+ else+ type = *(const uint32_t*)(next_char - 4);++ if (type & XCL_CHAR_END)+ c = char_list_add + (type >> XCL_CHAR_SHIFT);+ }++if (c > max)+ max = c;++SLJIT_ASSERT(min <= MAX_UTF_CODE_POINT && max <= MAX_UTF_CODE_POINT && min <= max);+*min_ptr = min;+*max_ptr = max;+}++#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == [8|16] */++#define XCLASS_IS_ECLASS 0x001+#ifdef SUPPORT_UNICODE+#define XCLASS_SAVE_CHAR 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_LOCAL0 0x200+#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);++/* TMP3 must be preserved because it is used by compile_iterator_matchingpath. */+static void compile_xclass_matchingpath(compiler_common *common, PCRE2_SPTR cc, jump_list **backtracks, sljit_u32 status)+{+DEFINE_COMPILER;+jump_list *found = NULL;+jump_list *check_result = NULL;+jump_list **list = (cc[0] & XCL_NOT) == 0 ? &found : backtracks;+sljit_uw c, charoffset;+sljit_u32 max = READ_CHAR_MAX, min = 0;+struct sljit_jump *jump = NULL;+PCRE2_UCHAR flags;+PCRE2_SPTR ccbegin;+sljit_u32 compares, invertcmp, depth;+sljit_u32 first_item, last_item, mid_item;+sljit_u32 range_start, range_end;+xclass_ranges ranges;+BOOL has_cmov, last_range_set;++#ifdef SUPPORT_UNICODE+sljit_u32 category_list = 0;+sljit_u32 items;+int typereg = TMP1;+#else+(void)c; /* Avoid compiler warning. */+#endif /* SUPPORT_UNICODE */++SLJIT_ASSERT(common->locals_size >= SSIZE_OF(sw));+/* Scanning the necessary info. */+flags = *cc++;+ccbegin = cc;+compares = 0;++if (flags & XCL_MAP)+ cc += 32 / sizeof(PCRE2_UCHAR);++#ifdef SUPPORT_UNICODE+while (*cc == XCL_PROP || *cc == XCL_NOTPROP)+ {+ compares++;+ cc++;++ items = 0;++ switch(*cc)+ {+ 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:+ status |= XCLASS_HAS_SCRIPT_EXTENSION;+ if (cc[-1] == XCL_NOTPROP)+ {+ status |= XCLASS_SCRIPT_EXTENSION_NOTPROP;+ break;+ }+ compares++;+ PCRE2_FALLTHROUGH /* Fall through */++ case PT_SC:+ status |= XCLASS_HAS_SCRIPT;+ break;++ case PT_SPACE:+ case PT_PXSPACE:+ case PT_PXGRAPH:+ case PT_PXPRINT:+ case PT_PXPUNCT:+ status |= XCLASS_SAVE_CHAR | XCLASS_HAS_TYPE;+ break;++ case PT_UCNC:+ case PT_PXXDIGIT:+ status |= XCLASS_SAVE_CHAR;+ break;++ case PT_BOOL:+ status |= XCLASS_HAS_BOOL;+ break;++ case PT_BIDICL:+ status |= XCLASS_HAS_BIDICL;+ break;++ default:+ SLJIT_UNREACHABLE();+ break;+ }++ if (items > 0)+ {+ if (cc[-1] == XCL_NOTPROP)+ items ^= UCPCAT_ALL;+ category_list |= items;+ status |= XCLASS_HAS_TYPE;+ compares--;+ }++ cc += 2;+ }++if (category_list == UCPCAT_ALL)+ {+ /* All or no characters are accepted, same as dotall. */+ if (status & XCLASS_IS_ECLASS)+ {+ if (list != backtracks)+ OP2(SLJIT_OR, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1);+ return;+ }++ compile_char1_matchingpath(common, OP_ALLANY, cc, backtracks, FALSE);+ if (list == backtracks)+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));+ return;+ }++if (category_list != 0)+ compares++;+#endif++if (*cc != XCL_END)+ {+#if defined SUPPORT_UNICODE && (PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16)+ if (common->utf && compares == 0 && !(status & XCLASS_IS_ECLASS))+ {+ SLJIT_ASSERT(category_list == 0);+ max = 0;+ min = (flags & XCL_MAP) != 0 ? 0 : READ_CHAR_MAX;+ xclass_update_min_max(common, cc, &min, &max);+ }+#endif+ compares++;+#ifdef SUPPORT_UNICODE+ status |= XCLASS_SAVE_CHAR;+#endif /* SUPPORT_UNICODE */+ }++#ifdef SUPPORT_UNICODE+SLJIT_ASSERT(compares > 0 || category_list != 0);+#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 (!(status & XCLASS_IS_ECLASS))+ {+ if ((flags & XCL_NOT) != 0)+ read_char(common, min, max, backtracks, READ_CHAR_UPDATE_STR_PTR);+ else+ {+#ifdef SUPPORT_UNICODE+ read_char(common, min, max, (status & XCLASS_NEEDS_UCD) ? backtracks : NULL, 0);+#else /* !SUPPORT_UNICODE */+ read_char(common, min, max, NULL, 0);+#endif /* SUPPORT_UNICODE */+ }+ }++if ((flags & XCL_MAP) != 0)+ {+ SLJIT_ASSERT(!(status & XCLASS_IS_ECLASS));+ xclass_check_bitset(common, (const sljit_u8 *)cc, &found, backtracks);+ cc += 32 / sizeof(PCRE2_UCHAR);+ }++#ifdef SUPPORT_UNICODE+if (status & XCLASS_NEEDS_UCD)+ {+ if ((status & (XCLASS_SAVE_CHAR | XCLASS_IS_ECLASS)) == XCLASS_SAVE_CHAR)+ OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);++#if PCRE2_CODE_UNIT_WIDTH == 32+ if (!common->utf)+ {+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, MAX_UTF_CODE_POINT + 1);+ SELECT(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, UNASSIGNED_UTF_CHAR, TMP1);+ }+#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);+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM | SLJIT_SRC2_UNDEFINED, TMP1, 0, TMP1, 0, TMP2, 0, UCD_BLOCK_SHIFT);+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2));+ OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM | SLJIT_SRC2_UNDEFINED, TMP2, 0, TMP2, 0, TMP2, 0, 1);+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);++ ccbegin = cc;++ if (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_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 (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_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 (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_PROP || *cc == XCL_NOTPROP)+ {+ cc++;++ switch (*cc)+ {+ case PT_SCX:+ if (cc[-1] == XCL_NOTPROP)+ break;+ PCRE2_FALLTHROUGH /* 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 (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 (status & XCLASS_SCRIPT_EXTENSION_NOTPROP)+ {+ if (status & XCLASS_HAS_TYPE)+ {+ if ((status & (XCLASS_SAVE_CHAR | XCLASS_IS_ECLASS)) == XCLASS_SAVE_CHAR)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL0, TMP2, 0);+ status |= XCLASS_SCRIPT_EXTENSION_RESTORE_LOCAL0;+ }+ else+ {+ OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP2, 0);+ 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_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 (status & XCLASS_SCRIPT_EXTENSION_RESTORE_LOCAL0)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0);+ else if (status & XCLASS_SCRIPT_EXTENSION_RESTORE_RETURN_ADDR)+ OP1(SLJIT_MOV, TMP2, 0, RETURN_ADDR, 0);+ cc = ccbegin;+ }++ if (status & XCLASS_SAVE_CHAR)+ OP1(SLJIT_MOV, TMP1, 0, (status & XCLASS_IS_ECLASS) ? ECLASS_CHAR_DATA : RETURN_ADDR, 0);++ if (status & XCLASS_HAS_TYPE)+ {+ if (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;++#ifdef SUPPORT_UNICODE+while (*cc == XCL_PROP || *cc == XCL_NOTPROP)+ {+ compares--;+ invertcmp = (compares == 0 && list != backtracks);+ jump = NULL;++ if (*cc == XCL_NOTPROP)+ invertcmp ^= 0x1;+ cc++;+ switch(*cc)+ {+ 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_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;++ if (jump != NULL)+ add_jump(compiler, compares > 0 ? list : backtracks, jump);+ }++if (compares == 0)+ {+ if (found != NULL)+ set_jumps(found, LABEL());++ if (status & XCLASS_IS_ECLASS)+ OP2(SLJIT_OR, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1);+ return;+ }+#endif /* SUPPORT_UNICODE */++SLJIT_ASSERT(compares == 1);+ranges.range_count = 0;+ranges.ranges = ranges.local_ranges;+ranges.stack = ranges.local_stack;++xclass_compute_ranges(common, cc, &ranges);++/* Memory error is set for the compiler. */+if (ranges.stack == NULL)+ return;++#if (defined SLJIT_DEBUG && SLJIT_DEBUG) && \+ defined SUPPORT_UNICODE && (PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16)+if (common->utf)+ {+ min = READ_CHAR_MAX;+ max = 0;+ xclass_update_min_max(common, cc, &min, &max);+ SLJIT_ASSERT(ranges.ranges[0] == min && ranges.ranges[ranges.range_count - 1] == max);+ }+#endif /* SLJIT_DEBUG && SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == [8|16] */++invertcmp = (list != backtracks);++if (ranges.range_count == 2)+ {+ range_start = ranges.ranges[0];+ range_end = ranges.ranges[1];++ if (range_start < range_end)+ {+ SET_CHAR_OFFSET(range_start);+ jump = CMP(SLJIT_LESS_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(range_end - range_start));+ }+ else+ jump = CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(range_start - charoffset));++ add_jump(compiler, backtracks, jump);++ SLJIT_ASSERT(ranges.stack == ranges.local_stack);+ if (found != NULL)+ set_jumps(found, LABEL());++ if (status & XCLASS_IS_ECLASS)+ OP2(SLJIT_OR, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1);+ return;+ }++range_start = ranges.ranges[0];+SET_CHAR_OFFSET(range_start);+if (ranges.range_count >= 6)+ {+ /* Early fail. */+ range_end = ranges.ranges[ranges.range_count - 1];+ add_jump(compiler, (flags & XCL_NOT) == 0 ? backtracks : &found,+ CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, (sljit_sw)(range_end - range_start)));+ }++depth = 0;+first_item = 0;+last_item = (sljit_u32)(ranges.range_count - 2);+has_cmov = sljit_has_cpu_feature(SLJIT_HAS_CMOV) != 0;++while (TRUE)+ {+ /* At least two items are present. */+ SLJIT_ASSERT(first_item < last_item && charoffset == ranges.ranges[0]);+ last_range_set = FALSE;++ if (first_item + 6 <= last_item)+ {+ mid_item = ((first_item + last_item) >> 1) & ~(sljit_u32)1;+ SLJIT_ASSERT(last_item >= mid_item + 4);++ range_end = ranges.ranges[mid_item + 1];+ if (first_item + 6 > mid_item && ranges.ranges[mid_item] == range_end)+ {+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(range_end - charoffset));+ ranges.stack[depth].jump = JUMP(SLJIT_GREATER);+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);+ last_range_set = TRUE;+ }+ else+ ranges.stack[depth].jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, (sljit_sw)(range_end - charoffset));++ ranges.stack[depth].first_item = (sljit_u32)(mid_item + 2);+ ranges.stack[depth].last_item = (sljit_u32)last_item;++ depth++;+ SLJIT_ASSERT(ranges.stack == ranges.local_stack ?+ depth <= XCLASS_LOCAL_RANGES_LOG2_SIZE : (ranges.stack + depth) <= (xclass_stack_item*)ranges.ranges);++ last_item = mid_item;+ if (!last_range_set)+ continue;++ last_item -= 2;+ }++ if (!last_range_set)+ {+ range_start = ranges.ranges[first_item];+ range_end = ranges.ranges[first_item + 1];++ if (range_start < range_end)+ {+ SET_CHAR_OFFSET(range_start);+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, (sljit_sw)(range_end - range_start));+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);+ }+ else+ {+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(range_start - charoffset));+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);+ }+ first_item += 2;+ }++ SLJIT_ASSERT(first_item <= last_item);++ do+ {+ range_start = ranges.ranges[first_item];+ range_end = ranges.ranges[first_item + 1];++ if (range_start < range_end)+ {+ SET_CHAR_OFFSET(range_start);+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, (sljit_sw)(range_end - range_start));++ if (has_cmov)+ SELECT(SLJIT_LESS_EQUAL, TMP2, STR_END, 0, TMP2);+ else+ OP_FLAGS(SLJIT_OR | ((first_item == last_item) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_LESS_EQUAL);+ }+ else+ {+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(range_start - charoffset));++ if (has_cmov)+ SELECT(SLJIT_EQUAL, TMP2, STR_END, 0, TMP2);+ else+ OP_FLAGS(SLJIT_OR | ((first_item == last_item) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_EQUAL);+ }++ first_item += 2;+ }+ while (first_item <= last_item);++ if (depth == 0) break;++ add_jump(compiler, &check_result, JUMP(SLJIT_JUMP));++ /* The charoffset resets after the end of a branch is reached. */+ charoffset = ranges.ranges[0];+ depth--;+ first_item = ranges.stack[depth].first_item;+ last_item = ranges.stack[depth].last_item;+ JUMPHERE(ranges.stack[depth].jump);+ }++if (check_result != NULL)+ set_jumps(check_result, LABEL());++if (has_cmov)+ jump = CMP(SLJIT_NOT_EQUAL ^ invertcmp, TMP2, 0, SLJIT_IMM, 0);+else+ {+ sljit_set_current_flags(compiler, SLJIT_SET_Z);+ jump = JUMP(SLJIT_NOT_EQUAL ^ invertcmp);+ }++add_jump(compiler, backtracks, jump);++if (found != NULL)+ set_jumps(found, LABEL());++if (status & XCLASS_IS_ECLASS)+ OP2(SLJIT_OR, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1);++if (ranges.stack != ranges.local_stack)+ SLJIT_FREE(ranges.stack, compiler->allocator_data);+}++static PCRE2_SPTR compile_eclass_matchingpath(compiler_common *common, PCRE2_SPTR cc, jump_list **backtracks)+{+DEFINE_COMPILER;+PCRE2_SPTR end = cc + GET(cc, 0) - 1;+PCRE2_SPTR begin;+jump_list *not_found;+jump_list *found = NULL;++cc += LINK_SIZE;++/* Should be optimized later. */+read_char(common, 0, READ_CHAR_MAX, backtracks, 0);++if (((*cc++) & ECL_MAP) != 0)+ {+ xclass_check_bitset(common, (const sljit_u8 *)cc, &found, backtracks);+ cc += 32 / sizeof(PCRE2_UCHAR);+ }++begin = cc;++OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL0, ECLASS_CHAR_DATA, 0);+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL1, ECLASS_STACK_DATA, 0);+OP1(SLJIT_MOV, ECLASS_STACK_DATA, 0, SLJIT_IMM, 0);+OP1(SLJIT_MOV, ECLASS_CHAR_DATA, 0, TMP1, 0);++/* All eclass must start with an xclass. */+SLJIT_ASSERT(*cc == ECL_XCLASS);++while (cc < end)+ {+ switch (*cc)+ {+ case ECL_AND:+ ++cc;+ OP2(SLJIT_OR, TMP2, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, ~(sljit_sw)1);+ OP2(SLJIT_LSHR, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1);+ OP2(SLJIT_AND, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, TMP2, 0);+ break;++ case ECL_OR:+ ++cc;+ OP2(SLJIT_AND, TMP2, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1);+ OP2(SLJIT_LSHR, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1);+ OP2(SLJIT_OR, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, TMP2, 0);+ break;++ case ECL_XOR:+ ++cc;+ OP2(SLJIT_AND, TMP2, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1);+ OP2(SLJIT_LSHR, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1);+ OP2(SLJIT_XOR, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, TMP2, 0);+ break;++ case ECL_NOT:+ ++cc;+ OP2(SLJIT_XOR, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1);+ break;++ default:+ SLJIT_ASSERT(*cc == ECL_XCLASS);+ if (cc != begin)+ {+ OP1(SLJIT_MOV, TMP1, 0, ECLASS_CHAR_DATA, 0);+ OP2(SLJIT_SHL, ECLASS_STACK_DATA, 0, ECLASS_STACK_DATA, 0, SLJIT_IMM, 1);+ }++ not_found = NULL;+ compile_xclass_matchingpath(common, cc + 1 + LINK_SIZE, ¬_found, XCLASS_IS_ECLASS);+ set_jumps(not_found, LABEL());++ cc += GET(cc, 1);+ break;+ }+ }++OP2U(SLJIT_SUB | SLJIT_SET_Z, ECLASS_STACK_DATA, 0, SLJIT_IMM, 0);+OP1(SLJIT_MOV, ECLASS_CHAR_DATA, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0);+OP1(SLJIT_MOV, ECLASS_STACK_DATA, 0, SLJIT_MEM1(SLJIT_SP), LOCAL1);+add_jump(compiler, backtracks, JUMP(SLJIT_EQUAL));+set_jumps(found, LABEL());+return end;+}++/* Generic character matching code. */++#undef SET_CHAR_OFFSET+#undef READ_FROM_CHAR_LIST+#undef XCLASS_LOCAL_RANGES_SIZE+#undef XCLASS_LOCAL_RANGES_LOG2_SIZE++#endif /* SUPPORT_WIDE_CHARS */++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;+}++#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 = 0, 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 = 0, 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;+}++static void compile_clist(compiler_common *common, PCRE2_SPTR cc, jump_list **backtracks)+{+DEFINE_COMPILER;+const sljit_u32 *other_cases;+struct sljit_jump *jump;+sljit_u32 min = 0, max = READ_CHAR_MAX;+BOOL has_cmov = sljit_has_cpu_feature(SLJIT_HAS_CMOV) != 0;++SLJIT_ASSERT(cc[1] == PT_CLIST);++if (cc[0] == OP_PROP)+ {+ other_cases = PRIV(ucd_caseless_sets) + cc[2];++ min = *other_cases++;+ max = min;++ while (*other_cases != NOTACHAR)+ {+ if (*other_cases > max) max = *other_cases;+ if (*other_cases < min) min = *other_cases;+ other_cases++;+ }+ }++other_cases = PRIV(ucd_caseless_sets) + cc[2];+SLJIT_ASSERT(other_cases[0] != NOTACHAR && other_cases[1] != NOTACHAR);+/* The NOTACHAR is higher than any character. */+SLJIT_ASSERT(other_cases[0] < other_cases[1] && other_cases[1] < other_cases[2]);++read_char(common, min, max, backtracks, READ_CHAR_UPDATE_STR_PTR);++/* At least two characters are required.+ Otherwise this case would be handled by the normal code path. */+/* NOTACHAR is the unsigned maximum. */++/* Optimizing character pairs, if their difference is power of 2. */+if (is_powerof2(other_cases[1] ^ other_cases[0]))+ {+ OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(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]))+ {+ SLJIT_ASSERT(other_cases[2] != NOTACHAR);++ OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(other_cases[2] ^ other_cases[1]));+ 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]);++ if (has_cmov)+ SELECT(SLJIT_EQUAL, TMP2, STR_END, 0, TMP2);+ else+ 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++));+ 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++));++ if (has_cmov)+ SELECT(SLJIT_EQUAL, TMP2, STR_END, 0, TMP2);+ else+ OP_FLAGS(SLJIT_OR | ((*other_cases == NOTACHAR) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_EQUAL);+ }++if (has_cmov)+ jump = CMP(cc[0] == OP_PROP ? SLJIT_EQUAL : SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0);+else+ jump = JUMP(cc[0] == OP_PROP ? SLJIT_ZERO : SLJIT_NOT_ZERO);++add_jump(compiler, backtracks, jump);+}++#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:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);+ if (cc[0] == PT_CLIST)+ {+ compile_clist(common, cc - 1, backtracks);+ return cc + 2;+ }++ propdata[0] = 0;+ propdata[1] = type == OP_NOTPROP ? XCL_NOTPROP : XCL_PROP;+ propdata[2] = cc[0];+ propdata[3] = cc[1];+ propdata[4] = XCL_END;+ compile_xclass_matchingpath(common, propdata, backtracks, 0);+ 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);+ 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);+ jump[1] = JUMP(SLJIT_JUMP);+ JUMPHERE(jump[0]);+ check_newlinechar(common, common->bsr_nltype, backtracks, FALSE);+ set_jumps(end_list, LABEL());+ JUMPHERE(jump[1]);+ 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, 0x1, 0x3000, backtracks, READ_CHAR_UPDATE_STR_PTR);+ else+ read_char(common, 0x1, 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, 0x1, 0x2029, backtracks, READ_CHAR_UPDATE_STR_PTR);+ else+ read_char(common, 0x1, 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 occur. */+ 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, 0);+ return cc + GET(cc, 0) - 1;++ case OP_ECLASS:+ if (check_str_ptr)+ detect_partial_match(common, backtracks);+ return compile_eclass_matchingpath(common, cc, backtracks);+#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);+}++
src/c/pcre2/src/pcre2_jit_compile.c view
@@ -39,14934 +39,14276 @@ ----------------------------------------------------------------------------- */ -#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)- options |= PCRE2_JIT_INVALID_UTF;--if ((options & PCRE2_JIT_COMPLETE) != 0 && (functions == NULL- || functions->executable_funcs[0] == NULL)) {- uint32_t excluded_options = (PCRE2_JIT_PARTIAL_SOFT | PCRE2_JIT_PARTIAL_HARD);- int result = jit_compile(code, options & ~excluded_options);- if (result != 0)- return result;- }--if ((options & PCRE2_JIT_PARTIAL_SOFT) != 0 && (functions == NULL- || functions->executable_funcs[1] == NULL)) {- uint32_t excluded_options = (PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_HARD);- int result = jit_compile(code, options & ~excluded_options);- if (result != 0)- return result;- }--if ((options & PCRE2_JIT_PARTIAL_HARD) != 0 && (functions == NULL- || functions->executable_funcs[2] == NULL)) {- uint32_t excluded_options = (PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_SOFT);- int result = jit_compile(code, options & ~excluded_options);- if (result != 0)- return result;- }--return 0;--#endif /* SUPPORT_JIT */-}--/* JIT compiler uses an all-in-one approach. This improves security,- since the code generator functions are not exported. */--#define INCLUDED_FROM_PCRE2_JIT_COMPILE--#include "pcre2_jit_match.c"-#include "pcre2_jit_misc.c"+#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 "../deps/sljit/sljit_src/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, OP_ASSERT_SCS. */+ jump_list *no_capture;+ assert_backtrack *assert;+ /* For OP_ONCE. Less than 0 if not needed. */+ int framesize;+ } u;+ /* For brackets with >3 alternatives. */+ struct sljit_jump *matching_mov_addr;+ /* 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;+ /* Creating a range based on the next character. */+ struct {+ unsigned int othercasebit;+ PCRE2_UCHAR chr;+ BOOL charpos_enabled;+ } charpos;+} 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;+ /* Start of caller arguments. */+ PCRE2_SPTR arg_start;+ /* Size of caller arguments in bytes. */+ sljit_uw arg_size;+} 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;+ /* Bitset which tells which capture brackets can be optimized. */+ sljit_u8 *optimized_cbrackets;+ /* Bitset for tracking capture bracket status. */+ sljit_u8 *cbracket_bitset;+ /* 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;+#if defined SLJIT_DEBUG && SLJIT_DEBUG+ /* End offset of locals for assertions. */+ sljit_s32 locals_size;+#endif+ /* 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;+ /* The offset of the saved STR_END in the outermost+ scan substring block. Since scan substring restores+ STR_END after a match, it is enough to restore+ STR_END inside a scan substring block. */+ sljit_s32 restore_end_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;+ /* Byte length of optimized_cbrackets and cbracket_bitset. */+ sljit_u32 cbracket_bitset_length;+ /* 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. */+ 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. */+/* Max limit of recursions. */+#define LIMIT_MATCH (0 * sizeof(sljit_sw))+/* Local variables. Their number is computed by check_opcode_types. */+#define LOCAL0 (1 * sizeof(sljit_sw))+#define LOCAL1 (2 * sizeof(sljit_sw))+#define LOCAL2 (3 * sizeof(sljit_sw))+#define LOCAL3 (4 * sizeof(sljit_sw))+#define LOCAL4 (5 * 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 ((sljit_u32)0xffffffff)++#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_ASSERT_SCS) || (*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_ASSERT_SCS) || (*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_ASSERT_SCS:+ 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_ECLASS:+ case OP_XCLASS:+ SLJIT_COMPILE_ASSERT(OP_XCLASS + 1 == OP_ECLASS && OP_CLASS + 1 == OP_NCLASS && OP_NCLASS < OP_XCLASS, class_byte_code_order);+ 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 sljit_s32 ref_update_local_size(compiler_common *common, PCRE2_SPTR cc, sljit_s32 current_locals_size)+{+/* Depends on do_casefulcmp(), do_caselesscmp(), and compile_ref_matchingpath() */+int locals_size = 2 * SSIZE_OF(sw);+SLJIT_UNUSED_ARG(common);++#ifdef SUPPORT_UNICODE+if ((*cc == OP_REFI || *cc == OP_DNREFI) && (common->utf || common->ucp))+ locals_size = 3 * SSIZE_OF(sw);+#endif++cc += PRIV(OP_lengths)[*cc];+/* Although do_casefulcmp() uses only one local, the allocate_stack()+calls during the repeat destroys LOCAL1 variables. */+if (*cc >= OP_CRSTAR && *cc <= OP_CRPOSRANGE)+ locals_size += 2 * SSIZE_OF(sw);++return (current_locals_size >= locals_size) ? current_locals_size : locals_size;+}++static SLJIT_INLINE BOOL is_optimized_cbracket(compiler_common *common, sljit_s32 capture_index)+{+sljit_u8 bit = (sljit_u8)(1 << (capture_index & 0x7));+return (common->optimized_cbrackets[capture_index >> 3] & bit) != 0;+}++static SLJIT_INLINE void clear_optimized_cbracket(compiler_common *common, sljit_s32 capture_index)+{+sljit_u8 mask = (sljit_u8)~(1 << (capture_index & 0x7));+common->optimized_cbrackets[capture_index >> 3] &= mask;+}++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;+sljit_s32 locals_size = 2 * SSIZE_OF(sw);+BOOL set_recursive_head = FALSE;+BOOL set_capture_last = FALSE;+BOOL set_mark = FALSE;++/* 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_TYPEUPTO:+ case OP_TYPEEXACT:+ if (cc[1 + IMM2_SIZE] == OP_EXTUNI && locals_size <= 3 * SSIZE_OF(sw))+ locals_size = 3 * SSIZE_OF(sw);+ cc += (2 + IMM2_SIZE) - 1;+ break;++ case OP_TYPEPOSSTAR:+ case OP_TYPEPOSPLUS:+ case OP_TYPEPOSQUERY:+ if (cc[1] == OP_EXTUNI && locals_size <= 3 * SSIZE_OF(sw))+ locals_size = 3 * SSIZE_OF(sw);+ cc += 2 - 1;+ break;++ case OP_TYPEPOSUPTO:+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf && locals_size <= 3 * SSIZE_OF(sw))+ locals_size = 3 * SSIZE_OF(sw);+#endif+ if (cc[1 + IMM2_SIZE] == OP_EXTUNI && locals_size <= 3 * SSIZE_OF(sw))+ locals_size = 3 * SSIZE_OF(sw);+ cc += (2 + IMM2_SIZE) - 1;+ break;++ case OP_REFI:+ case OP_REF:+ locals_size = ref_update_local_size(common, cc, locals_size);+ clear_optimized_cbracket(common, GET2(cc, 1));+ cc += PRIV(OP_lengths)[*cc];+ break;++ case OP_ASSERT_NA:+ case OP_ASSERTBACK_NA:+ case OP_ASSERT_SCS:+ slot = bracketend(cc);+ if (slot > assert_na_end)+ assert_na_end = slot;+ cc += 1 + LINK_SIZE;+ break;++ case OP_CBRAPOS:+ case OP_SCBRAPOS:+ clear_optimized_cbracket(common, GET2(cc, 1 + LINK_SIZE));+ 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:+ clear_optimized_cbracket(common, GET2(cc, 1));+ cc += 1 + IMM2_SIZE;+ break;++ case OP_DNREFI:+ case OP_DNREF:+ locals_size = ref_update_local_size(common, cc, locals_size);+ PCRE2_FALLTHROUGH /* Fall through */+ case OP_DNCREF:+ count = GET2(cc, 1 + IMM2_SIZE);+ slot = common->name_table + GET2(cc, 1) * common->name_entry_size;+ while (count-- > 0)+ {+ clear_optimized_cbracket(common, GET2(slot, 0));+ slot += common->name_entry_size;+ }+ cc += PRIV(OP_lengths)[*cc];+ break;++ case OP_RECURSE:+ /* Set its value only once. */+ set_recursive_head = TRUE;+ cc += 1 + LINK_SIZE;+ while (*cc == OP_CREF)+ {+ clear_optimized_cbracket(common, GET2(cc, 1));+ cc += 1 + IMM2_SIZE;+ }+ break;++ case OP_CALLOUT:+ case OP_CALLOUT_STR:+ set_capture_last = TRUE;+ 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;+ PCRE2_FALLTHROUGH /* Fall through */++ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ case OP_MARK:+ set_mark = TRUE;+ 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;+ cc += 1;+ break;++ case OP_SKIP_ARG:+ common->control_head_ptr = 1;+ common->has_skip_arg = TRUE;+ if (cc < assert_back_end)+ common->has_skip_in_assert_back = TRUE;+ cc += 1 + 2 + cc[1];+ break;++ case OP_ASSERT_ACCEPT:+ if (cc < assert_na_end)+ return FALSE;+ cc++;+ break;++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ case OP_CRPOSRANGE:+ /* The second value can be 0 for infinite repeats. */+ if (common->utf && GET2(cc, 1) != GET2(cc, 1 + IMM2_SIZE) && locals_size <= 3 * SSIZE_OF(sw))+ locals_size = 3 * SSIZE_OF(sw);+ cc += 1 + 2 * IMM2_SIZE;+ break;++ case OP_POSUPTO:+ case OP_POSUPTOI:+ case OP_NOTPOSUPTO:+ case OP_NOTPOSUPTOI:+ if (common->utf && locals_size <= 3 * SSIZE_OF(sw))+ locals_size = 3 * SSIZE_OF(sw);+#endif+ PCRE2_FALLTHROUGH /* Fall through */+ default:+ cc = next_opcode(common, cc);+ if (cc == NULL)+ return FALSE;+ break;+ }+ }++SLJIT_ASSERT((locals_size & (SSIZE_OF(sw) - 1)) == 0);+#if defined SLJIT_DEBUG && SLJIT_DEBUG+common->locals_size = locals_size;+#endif++if (locals_size > 0)+ common->ovector_start += locals_size;++if (set_mark)+ {+ SLJIT_ASSERT(common->mark_ptr == 0);+ common->mark_ptr = common->ovector_start;+ common->ovector_start += sizeof(sljit_sw);+ }++if (set_recursive_head)+ {+ SLJIT_ASSERT(common->recursive_head_ptr == 0);+ common->recursive_head_ptr = common->ovector_start;+ common->ovector_start += sizeof(sljit_sw);+ }++if (set_capture_last)+ {+ SLJIT_ASSERT(common->capture_last_ptr == 0);+ common->capture_last_ptr = common->ovector_start;+ common->ovector_start += sizeof(sljit_sw);+ }++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 || is_optimized_cbracket(common, GET2(cc, 1 + LINK_SIZE)));+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;+ PCRE2_FALLTHROUGH /* 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;+ PCRE2_FALLTHROUGH /* 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;+ PCRE2_FALLTHROUGH /* 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;+ PCRE2_FALLTHROUGH /* 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:+ case OP_ECLASS:+ 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;+ PCRE2_FALLTHROUGH /* 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;+ PCRE2_FALLTHROUGH /* 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 && !is_optimized_cbracket(common, GET2(cc, 1 + LINK_SIZE))))+ 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 > (sljit_u32)(*cc == OP_CRRANGE ? 0 : 1))+ 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)+ {+ /* Patterns must fit into an int32 even for link-size=4. */+ common->private_data_ptrs[max_end - common->start - LINK_SIZE] = (sljit_s32)(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] = (sljit_s32)(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_ASSERT_SCS:+ common->private_data_ptrs[cc - common->start] = private_data_ptr;+ private_data_ptr += 2 * 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_EXTUNI)+ space = 2;+ break;++ case OP_TYPEUPTO:+ size = 1 + IMM2_SIZE;+ if (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:+ case OP_ECLASS:+ 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;+}++static SLJIT_INLINE BOOL is_cbracket_processed(compiler_common *common, sljit_s32 capture_index)+{+sljit_u8 bit = (sljit_u8)(1 << (capture_index & 0x7));+sljit_u8 *ptr = common->cbracket_bitset + (capture_index >> 3);+sljit_u8 value = *ptr;++*ptr |= bit;+return (value & bit) != 0;+}++/* 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;+int offset;+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++memset(common->cbracket_bitset, 0, common->cbracket_bitset_length);++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;+ while (*cc == OP_CREF)+ {+ offset = GET2(cc, 1);+ if (!is_cbracket_processed(common, offset))+ length += 3;+ cc += 1 + IMM2_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;+ }++ offset = GET2(cc, 1 + LINK_SIZE);+ if (!is_cbracket_processed(common, offset))+ 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;+ PCRE2_FALLTHROUGH /* 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_ECLASS:++ 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);++memset(common->cbracket_bitset, 0, common->cbracket_bitset_length);++stackpos = STACK(stackpos);+if (ccend == NULL)+ {+ ccend = bracketend(cc) - (1 + LINK_SIZE);+ if (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS)+ cc = next_opcode(common, cc);+ }++/* The data is restored by do_revertframes(). */+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;+ while (*cc == OP_CREF)+ {+ offset = GET2(cc, 1);+ if (!is_cbracket_processed(common, offset))+ {+ offset <<= 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 + IMM2_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);+ if (!is_cbracket_processed(common, offset))+ {+ offset <<= 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];+ sljit_s32 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_s32 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),+ recurse_flag_recurse_arg = (1 << 5),+};++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, cref;+uint32_t recurse_flags = 0;++memset(common->recurse_bitset, 0, common->recurse_bitset_size);++if (common->currententry->arg_size > 0)+ {+ cref = common->currententry->arg_start;++ do+ {+ offset = GET2(cref, 1);+ recurse_check_bit(common, OVECTOR(offset << 1));+ cref += 1 + IMM2_SIZE;+ }+ while (*cref == OP_CREF);+ }++#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;+ if (*cc == OP_CREF)+ recurse_flags |= recurse_flag_recurse_arg;+ 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_CREF:+ if ((recurse_flags & recurse_flag_recurse_arg) != 0)+ {+ offset = GET2(cc, 1);+ if (recurse_check_bit(common, OVECTOR(offset << 1)))+ {+ SLJIT_ASSERT(recurse_check_bit(common, OVECTOR((offset << 1) + 1)));+ length += 2;+ }++ if (cc[1 + IMM2_SIZE] != OP_CREF)+ recurse_flags &= ~(uint32_t)recurse_flag_recurse_arg;+ }+ cc += 1 + IMM2_SIZE;+ break;++ case OP_ASSERT_SCS:+ SLJIT_ASSERT(PRIVATE_DATA(cc) != 0);+ if (recurse_check_bit(common, PRIVATE_DATA(cc)))+ length += 2;+ 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 (!is_optimized_cbracket(common, offset) && 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:+ case OP_ECLASS:+ 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, cref;+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 (common->currententry->arg_size > 0)+ {+ cref = common->currententry->arg_start;++ do+ {+ offset = GET2(cref, 1);+ recurse_check_bit(common, OVECTOR(offset << 1));+ cref += 1 + IMM2_SIZE;+ }+ while (*cref == OP_CREF);+ }++#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;+ if (*cc == OP_CREF)+ recurse_flags |= recurse_flag_recurse_arg;+ 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_CREF:+ if ((recurse_flags & recurse_flag_recurse_arg) != 0)+ {+ offset = GET2(cc, 1);+ 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 (cc[1 + IMM2_SIZE] != OP_CREF)+ recurse_flags &= ~(uint32_t)recurse_flag_recurse_arg;+ }+ cc += 1 + IMM2_SIZE;+ break;++ case OP_ASSERT_SCS:+ private_srcw[0] = PRIVATE_DATA(cc);+ private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);+ if (recurse_check_bit(common, private_srcw[0]))+ private_count = 2;+ 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 (!is_optimized_cbracket(common, offset))+ {+ 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:+ case OP_ECLASS:+ 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, (sljit_s32)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, (sljit_s32)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, (sljit_s32)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 verb even if it has no alternatives. */+if (*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT)+ current_offset = NULL;+else if (*cc >= OP_ASSERT_NA && *cc <= OP_ASSERT_SCS)+ has_alternatives = TRUE;+/* Conditional block does never capture. */+else if (*cc == OP_COND || *cc == OP_SCOND)+ has_alternatives = FALSE;++cc = next_opcode(common, cc);++if (has_alternatives)+ {+ switch (*cc)+ {+ case OP_REVERSE:+ case OP_CREF:+ cc += 1 + IMM2_SIZE;+ break;+ case OP_VREVERSE:+ case OP_DNCREF:+ cc += 1 + 2 * IMM2_SIZE;+ break;+ }++ current_offset = common->then_offsets + (cc - common->start);+ }++while (cc < end)+ {+ if (*cc >= OP_ASSERT && *cc <= OP_SCOND)+ {+ cc = set_then_offsets(common, cc, current_offset);+ continue;+ }++ 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);+ }++cc = end - 1 - LINK_SIZE;++/* Ignore repeats. */+if (*cc == OP_KET && PRIVATE_DATA(cc) != 0)+ end += PRIVATE_DATA(cc + 1);++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, sljit_s32 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);+#if defined SLJIT_DEBUG && SLJIT_DEBUG+SLJIT_ASSERT(common->locals_size >= 2 * SSIZE_OF(sw));+/* These two are also used by the stackalloc calls. */+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL0, TMP1, 0);+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL1, TMP1, 0);+#endif+#endif+add_stub(common, CMP(SLJIT_LESS, STACK_TOP, 0, STACK_LIMIT, 0));+}++static SLJIT_INLINE void free_stack(compiler_common *common, sljit_s32 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;++#ifndef EBCDIC+/* Optimized for English alphabet. */+if (c <= 127 && bit == 0x20)+ return (0 << 8) | 0x20;+#endif++/* 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);+sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM | SLJIT_SRC2_UNDEFINED, TMP1, 0, TMP1, 0, TMP2, 0, UCD_BLOCK_SHIFT);+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);+sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM | SLJIT_SRC2_UNDEFINED, TMP1, 0, TMP1, 0, TMP2, 0, UCD_BLOCK_SHIFT);+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 + (TMP2 << 1)) << 2. */+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));+sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM | SLJIT_SRC2_UNDEFINED, TMP2, 0, TMP2, 0, TMP2, 0, 1);+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 2);++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++;+}++/* Value can be increased if needed. Patterns+such as /(a|){33}b/ can exhaust the stack.++Note: /(a|){29}b/ already stops scan_prefix()+because it reaches the maximum step_count. */+#define SCAN_PREFIX_STACK_END 32++/*+Scan prefix stores the prefix string in the chars array.+The elements of the chars array is either small character+sets or "any" (count is set to 255).++Examples (the chars array is represented by a simple regex):++/(abc|xbyd)/ prefix: /[ax]b[cy]/ (length: 3)+/a[a-z]b+c/ prefix: a.b (length: 3)+/ab?cd/ prefix: a[bc][cd] (length: 3)+/(ab|cd)|(ef|gh)/ prefix: [aceg][bdfh] (length: 2)++The length is returned by scan_prefix(). The length is+less than or equal than the minimum length of the pattern.+*/++static int scan_prefix(compiler_common *common, PCRE2_SPTR cc, fast_forward_char_data *chars)+{+fast_forward_char_data *chars_start = chars;+fast_forward_char_data *chars_end = chars + MAX_N_CHARS;+PCRE2_SPTR cc_stack[SCAN_PREFIX_STACK_END];+fast_forward_char_data *chars_stack[SCAN_PREFIX_STACK_END];+sljit_u8 next_alternative_stack[SCAN_PREFIX_STACK_END];+BOOL last, any, class, caseless;+int stack_ptr, step_count, repeat, len, len_save;+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;+stack_ptr = 0;+step_count = 10000;+while (TRUE)+ {+ if (--step_count == 0)+ return 0;++ SLJIT_ASSERT(chars <= chars_start + MAX_N_CHARS);++ if (chars >= chars_end)+ {+ if (stack_ptr == 0)+ return (int)(chars_end - chars_start);++ --stack_ptr;+ cc = cc_stack[stack_ptr];+ chars = chars_stack[stack_ptr];++ if (chars >= chars_end)+ continue;++ if (next_alternative_stack[stack_ptr] != 0)+ {+ /* When an alternative is processed, the+ next alternative is pushed onto the stack. */+ SLJIT_ASSERT(*cc == OP_ALT);+ alternative = cc + GET(cc, 1);+ if (*alternative == OP_ALT)+ {+ SLJIT_ASSERT(stack_ptr < SCAN_PREFIX_STACK_END);+ SLJIT_ASSERT(chars_stack[stack_ptr] == chars);+ SLJIT_ASSERT(next_alternative_stack[stack_ptr] == 1);+ cc_stack[stack_ptr] = alternative;+ stack_ptr++;+ }+ cc += 1 + LINK_SIZE;+ }+ }++ last = TRUE;+ any = FALSE;+ class = FALSE;+ caseless = FALSE;++ switch (*cc)+ {+ case OP_CHARI:+ caseless = TRUE;+ PCRE2_FALLTHROUGH /* 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:+ case OP_ASSERT_SCS:+ cc = bracketend(cc);+ continue;++ case OP_PLUSI:+ case OP_MINPLUSI:+ case OP_POSPLUSI:+ caseless = TRUE;+ PCRE2_FALLTHROUGH /* Fall through */+ case OP_PLUS:+ case OP_MINPLUS:+ case OP_POSPLUS:+ cc++;+ break;++ case OP_EXACTI:+ caseless = TRUE;+ PCRE2_FALLTHROUGH /* 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;+ PCRE2_FALLTHROUGH /* 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+ if (stack_ptr >= SCAN_PREFIX_STACK_END)+ {+ chars_end = chars;+ continue;+ }++ cc_stack[stack_ptr] = cc + len;+ chars_stack[stack_ptr] = chars;+ next_alternative_stack[stack_ptr] = 0;+ stack_ptr++;++ 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);+ if (*alternative == OP_ALT)+ {+ if (stack_ptr >= SCAN_PREFIX_STACK_END)+ {+ chars_end = chars;+ continue;+ }++ cc_stack[stack_ptr] = alternative;+ chars_stack[stack_ptr] = chars;+ next_alternative_stack[stack_ptr] = 1;+ stack_ptr++;+ }++ 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))+ {+ chars_end = chars;+ continue;+ }+#endif+ class = TRUE;+ break;++ case OP_NCLASS:+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf)+ {+ chars_end = chars;+ continue;+ }+#endif+ class = TRUE;+ break;++#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+ case OP_XCLASS:+ case OP_ECLASS:+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf)+ {+ chars_end = chars;+ continue;+ }+#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))+ {+ chars_end = chars;+ continue;+ }+#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))+ {+ chars_end = chars;+ continue;+ }+#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))+ {+ chars_end = chars;+ continue;+ }+#endif+ any = TRUE;+ cc++;+ break;++ case OP_NOT:+ case OP_NOTI:+ cc++;+ PCRE2_FALLTHROUGH /* 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)+ {+ chars_end = chars;+ continue;+ }+#endif+ any = TRUE;+ cc++;+ break;++#ifdef SUPPORT_UNICODE+ case OP_NOTPROP:+ case OP_PROP:+#if PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf)+ {+ chars_end = chars;+ continue;+ }+#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)+ {+ chars_end = chars;+ continue;+ }+#endif+ any = TRUE;+ repeat = GET2(cc, 1);+ cc += 1 + IMM2_SIZE + 1;+ break;++ default:+ chars_end = chars;+ continue;+ }++ SLJIT_ASSERT(chars < chars_end);++ if (any)+ {+ do+ {+ chars->count = 255;+ chars++;+ }+ while (--repeat > 0 && chars < chars_end);++ repeat = 1;+ continue;+ }++ if (class)+ {+ bytes = (sljit_u8*) (cc + 1);+ cc += 1 + 32 / sizeof(PCRE2_UCHAR);++ SLJIT_ASSERT(last == TRUE && repeat == 1);+ switch (*cc)+ {+ case OP_CRQUERY:+ case OP_CRMINQUERY:+ case OP_CRPOSQUERY:+ last = FALSE;+ PCRE2_FALLTHROUGH /* Fall through */+ case OP_CRSTAR:+ case OP_CRMINSTAR:+ case OP_CRPOSSTAR:+ if (stack_ptr >= SCAN_PREFIX_STACK_END)+ {+ chars_end = chars;+ continue;+ }++ cc_stack[stack_ptr] = ++cc;+ chars_stack[stack_ptr] = chars;+ next_alternative_stack[stack_ptr] = 0;+ stack_ptr++;+ 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)+ {+ chars_end = chars;+ continue;+ }++ last = (repeat != (int)GET2(cc, 1 + IMM2_SIZE));+ cc += 1 + 2 * IMM2_SIZE;+ 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;+ }++ chars++;+ }+ while (--repeat > 0 && chars < chars_end);++ repeat = 1;+ if (last)+ chars_end = chars;+ 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)+ {+ chars_end = chars;+ continue;+ }+ }+ 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--;++ chr = *cc;+ add_prefix_char(*cc, chars, len == 0);++ if (caseless)+ add_prefix_char(*oc, chars, len == 0);++ chars++;+ cc++;+ oc++;+ }+ while (len > 0 && chars < chars_end);++ if (--repeat == 0 || chars >= chars_end)+ break;++ len = len_save;+ cc = cc_save;+ }++ repeat = 1;+ if (last)+ chars_end = chars;+ }+}++#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;++for (i = 0; i < MAX_N_CHARS; i++)+ {+ chars[i].count = 0;+ chars[i].last_count = 0;+ }++max = scan_prefix(common, common->start, chars);++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, TMP1, 0, TMP2, 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_ASSERT(common->locals_size >= 2 * SSIZE_OF(sw));+sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), LOCAL0);+/* 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), LOCAL1, &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), LOCAL0);+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), LOCAL1, NULL);+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR, valid_utf);++ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0);+ 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), LOCAL0);+ 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);++#ifdef EBCDIC+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_LF);+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_VT);+OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_FF);+OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_CR);+OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_NEL);+#else+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, CHAR_LF);+OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR - CHAR_LF);+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_NEL - CHAR_LF);+#endif+#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 - CHAR_LF);+#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, CHAR_HT);+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_SPACE);+OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_NBSP);+#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);++#ifdef EBCDIC+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_LF);+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_VT);+OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_FF);+OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_CR);+OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_NEL);+#else+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, CHAR_LF);+OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR - CHAR_LF);+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_NEL - CHAR_LF);+#endif+#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 - CHAR_LF);+#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;+ }++/* Update ref_update_local_size() when this changes. */+SLJIT_ASSERT(common->locals_size >= SSIZE_OF(sw));+sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), LOCAL0);+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), LOCAL0);+ }+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), LOCAL0);+ 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), LOCAL0);+ }++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;++/* Update ref_update_local_size() when this changes. */+SLJIT_ASSERT(common->locals_size >= 2 * SSIZE_OF(sw));+sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), LOCAL0);+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);++OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL1, 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), LOCAL0);++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), LOCAL1);+OP_SRC(SLJIT_FAST_RETURN, TMP1, 0);+}++#include "pcre2_jit_char_inc.h"++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;+}++/* 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;+struct sljit_jump *turkish_ascii_i = NULL;+struct sljit_jump *turkish_non_ascii_i = NULL;+jump_list *no_match = NULL;+int source_reg = COUNT_MATCH;+int source_end_reg = ARGUMENTS;+int char1_reg = STACK_LIMIT;+PCRE2_UCHAR refi_flag = 0;++if (*cc == OP_REFI || *cc == OP_DNREFI)+ refi_flag = cc[PRIV(OP_lengths)[*cc] - 1];+#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 || common->ucp) && (*cc == OP_REFI || *cc == OP_DNREFI))+ {+ /* Update ref_update_local_size() when this changes. */+ SLJIT_ASSERT(common->locals_size >= 3 * SSIZE_OF(sw));++ 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), LOCAL0, source_reg, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL1, source_end_reg, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL2, 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);++ if ((refi_flag & (REFI_FLAG_TURKISH_CASING|REFI_FLAG_CASELESS_RESTRICT)) ==+ REFI_FLAG_TURKISH_CASING)+ {+ OP2(SLJIT_OR, SLJIT_TMP_DEST_REG, 0, char1_reg, 0, SLJIT_IMM, 0x20);+ turkish_ascii_i = CMP(SLJIT_EQUAL, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 0x69);++ OP2(SLJIT_OR, SLJIT_TMP_DEST_REG, 0, char1_reg, 0, SLJIT_IMM, 0x1);+ turkish_non_ascii_i = CMP(SLJIT_EQUAL, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 0x131);+ }++ 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));++ if (refi_flag & REFI_FLAG_CASELESS_RESTRICT)+ add_jump(compiler, &no_match, CMP(SLJIT_LESS | SLJIT_32, SLJIT_MEM1(TMP2), 0, SLJIT_IMM, 128));++ 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);++ if ((refi_flag & (REFI_FLAG_TURKISH_CASING|REFI_FLAG_CASELESS_RESTRICT)) ==+ REFI_FLAG_TURKISH_CASING)+ {+ add_jump(compiler, &no_match, JUMP(SLJIT_JUMP));+ JUMPHERE(turkish_ascii_i);++ OP2(SLJIT_LSHR, char1_reg, 0, char1_reg, 0, SLJIT_IMM, 5);+ OP2(SLJIT_AND, char1_reg, 0, char1_reg, 0, SLJIT_IMM, 1);+ OP2(SLJIT_XOR, char1_reg, 0, char1_reg, 0, SLJIT_IMM, 1);+ OP2(SLJIT_ADD, char1_reg, 0, char1_reg, 0, SLJIT_IMM, 0x130);+ CMPTO(SLJIT_EQUAL, TMP1, 0, char1_reg, 0, loop);++ add_jump(compiler, &no_match, JUMP(SLJIT_JUMP));+ JUMPHERE(turkish_non_ascii_i);++ OP2(SLJIT_AND, char1_reg, 0, char1_reg, 0, SLJIT_IMM, 1);+ OP2(SLJIT_XOR, char1_reg, 0, char1_reg, 0, SLJIT_IMM, 1);+ OP2(SLJIT_SHL, char1_reg, 0, char1_reg, 0, SLJIT_IMM, 5);+ OP2(SLJIT_ADD, char1_reg, 0, char1_reg, 0, SLJIT_IMM, 0x49);+ CMPTO(SLJIT_EQUAL, TMP1, 0, char1_reg, 0, loop);+ }++ set_jumps(no_match, LABEL());+ if (common->mode == PCRE2_JIT_COMPLETE)+ JUMPHERE(partial);++ OP1(SLJIT_MOV, source_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0);+ OP1(SLJIT_MOV, source_end_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCAL1);+ OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCAL2);+ 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), LOCAL0);+ OP1(SLJIT_MOV, source_end_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCAL1);+ OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCAL2);++ check_partial(common, FALSE);+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));+ }++ JUMPHERE(jump);+ OP1(SLJIT_MOV, source_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0);+ OP1(SLJIT_MOV, source_end_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCAL1);+ OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCAL2);+ 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 || *cc == OP_DNREF) ? &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 || *cc == OP_DNREF) ? &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 local_start = LOCAL2;+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;++if (*ccbegin == OP_REFI || *ccbegin == OP_DNREFI)+ {+ cc += 1;+#ifdef SUPPORT_UNICODE+ if (common->utf || common->ucp)+ local_start = LOCAL3;+#endif+ }++type = cc[1 + IMM2_SIZE];++SLJIT_COMPILE_ASSERT((OP_CRSTAR & 0x1) == 0, crstar_opcode_must_be_even);+/* Update ref_update_local_size() when this changes. */+SLJIT_ASSERT(local_start + 2 * SSIZE_OF(sw) <= (int)LOCAL0 + common->locals_size);+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), local_start + SSIZE_OF(sw), 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), local_start + SSIZE_OF(sw), 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), local_start, SLJIT_IMM, 0);++ label = LABEL();+ if (!ref)+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), local_start + SSIZE_OF(sw));+ compile_ref_matchingpath(common, ccbegin, &backtrack->own_backtracks, FALSE, FALSE);++ if (min > 1 || max > 1)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), local_start);+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), local_start, 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;+PCRE2_SPTR end;+sljit_sw start = GET(cc, 1);+sljit_uw arg_size;+PCRE2_SPTR start_cc;+BOOL needs_control_head;++end = cc + 1 + LINK_SIZE;++while (*end == OP_CREF)+ end += 1 + IMM2_SIZE;++PUSH_BACKTRACK(sizeof(recurse_backtrack), cc, end);++/* 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 end;+ }++cc += 1 + LINK_SIZE;+arg_size = (sljit_uw)IN_UCHARS(end - cc);+while (entry != NULL)+ {+ if (entry->start == start && entry->arg_size == arg_size+ && (arg_size == 0 || memcmp(cc, entry->arg_start, arg_size) == 0))+ 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 end;+ entry->next = NULL;+ entry->entry_label = NULL;+ entry->backtrack_label = NULL;+ entry->entry_calls = NULL;+ entry->backtrack_calls = NULL;+ entry->start = start;+ entry->arg_start = cc;+ entry->arg_size = arg_size;++ 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 end;+}++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_s32 callout_arg_size = (common->re->top_bracket + 1) * 2 * SSIZE_OF(sw); /* top_bracket is uint16 so maximum is 1MiB */++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. */+SLJIT_ASSERT(common->locals_size >= SSIZE_OF(sw));+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL0, 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), LOCAL0);+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, cc + 1 + 2 * IMM2_SIZE);++ 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;+sljit_s32 save_restore_end_ptr = common->restore_end_ptr;+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->restore_end_ptr = 0;+ 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->restore_end_ptr = save_restore_end_ptr;+ 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->restore_end_ptr = save_restore_end_ptr;+ 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);+ SLJIT_ASSERT(framesize != 0);+ 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->restore_end_ptr = save_restore_end_ptr;+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 (!is_optimized_cbracket(common, offset >> 1))+ {+ 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;+jump_list *jumplist;+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 (!is_optimized_cbracket(common, offset))+ {+ 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_ASSERT_SCS || 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 (is_optimized_cbracket(common, offset >> 1))+ {+ 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 (opcode == OP_ASSERT_SCS)+ {+ /* Nested scs blocks will not update this variable. */+ if (common->restore_end_ptr == 0)+ common->restore_end_ptr = private_data_ptr + sizeof(sljit_sw);++ if (*matchingpath == OP_CREF && (matchingpath[1 + IMM2_SIZE] != OP_CREF && matchingpath[1 + IMM2_SIZE] != OP_DNCREF))+ {+ /* Optimized case for a single capture reference. */+ i = OVECTOR(GET2(matchingpath, 1) << 1);++ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), i);++ add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.no_capture), CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)));+ matchingpath += 1 + IMM2_SIZE;++ allocate_stack(common, has_alternatives ? 3 : 2);++ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ OP1(SLJIT_MOV, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw), STR_END, 0);+ OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), i + sizeof(sljit_sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0);+ OP1(SLJIT_MOV, STR_PTR, 0, TMP2, 0);+ }+ else+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));+ jumplist = NULL;++ while (TRUE)+ {+ if (*matchingpath == OP_CREF)+ {+ sljit_get_local_base(compiler, TMP2, 0, OVECTOR(GET2(matchingpath, 1) << 1));+ matchingpath += 1 + IMM2_SIZE;+ }+ else+ {+ SLJIT_ASSERT(*matchingpath == OP_DNCREF);++ i = GET2(matchingpath, 1 + IMM2_SIZE);+ slot = common->name_table + GET2(matchingpath, 1) * common->name_entry_size;++ while (i-- > 1)+ {+ sljit_get_local_base(compiler, TMP2, 0, OVECTOR(GET2(slot, 0) << 1));+ add_jump(compiler, &jumplist, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(TMP2), 0, TMP1, 0));+ slot += common->name_entry_size;+ }++ sljit_get_local_base(compiler, TMP2, 0, OVECTOR(GET2(slot, 0) << 1));+ matchingpath += 1 + 2 * IMM2_SIZE;+ }++ if (*matchingpath != OP_CREF && *matchingpath != OP_DNCREF)+ break;++ add_jump(compiler, &jumplist, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(TMP2), 0, TMP1, 0));+ }++ add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.no_capture),+ CMP(SLJIT_EQUAL, SLJIT_MEM1(TMP2), 0, TMP1, 0));++ set_jumps(jumplist, LABEL());++ allocate_stack(common, has_alternatives ? 3 : 2);++ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ OP1(SLJIT_MOV, SLJIT_TMP_DEST_REG, 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, STR_PTR, 0, SLJIT_MEM1(TMP2), 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw), STR_END, 0);+ OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));+ }++ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_TMP_DEST_REG, 0);++ if (has_alternatives)+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), STR_PTR, 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.no_capture),+ 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.no_capture), 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.no_capture = 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);+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))+ return NULL;+ }+ }++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_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 (!is_optimized_cbracket(common, offset >> 1))+ 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)->matching_mov_addr = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, 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 && is_optimized_cbracket(common, offset >> 1))+ {+ SLJIT_ASSERT(private_data_ptr == OVECTOR(offset + 0));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);+ }+else switch (opcode)+ {+ case OP_ASSERT_NA:+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ break;+ case OP_ASSERT_SCS:+ OP1(SLJIT_MOV, TMP1, 0, STR_END, 0);+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);+ 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 + sizeof(sljit_sw), TMP1, 0);++ /* Nested scs blocks will not update this variable. */+ if (common->restore_end_ptr == private_data_ptr + SSIZE_OF(sw))+ common->restore_end_ptr = 0;+ break;+ }++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)+ {+ int framesize = BACKTRACK_AS(bracket_backtrack)->u.framesize;++ SLJIT_ASSERT(framesize != 0);+ 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));+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize - 1) * sizeof(sljit_sw));+ }+ }+ else if (ket == OP_KETRMIN)+ 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(!is_optimized_cbracket(common, offset));+ 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)+ 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 || *opcode == OP_ECLASS);+ *type = *opcode;+ class_len = (*type < OP_XCLASS) ? (int)(1 + (32 / sizeof(PCRE2_UCHAR))) : GET(cc, 1);+ *opcode = cc[class_len];+ cc++;++ 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;+ }+ return cc;+ }++ 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;+ }+ return cc;+ }++ SLJIT_ASSERT(*opcode == OP_CRRANGE || *opcode == OP_CRMINRANGE || *opcode == OP_CRPOSRANGE);+ *max = GET2(cc, (class_len + IMM2_SIZE));+ *exact = GET2(cc, class_len);+ *end = cc + class_len + 2 * IMM2_SIZE;++ if (*max == 0)+ {+ SLJIT_ASSERT(*exact > 1);+ if (*opcode == OP_CRRANGE)+ *opcode = OP_UPTO;+ else if (*opcode == OP_CRPOSRANGE)+ *opcode = OP_POSUPTO;+ else+ *opcode = OP_MINSTAR;+ return cc;+ }++ *max -= *exact;+ if (*max == 0)+ *opcode = OP_EXACT;+ else+ {+ SLJIT_ASSERT(*exact > 0 || *max > 1);+ if (*opcode == OP_CRRANGE)+ *opcode = OP_UPTO;+ else if (*opcode == OP_CRPOSRANGE)+ *opcode = OP_POSUPTO;+ else if (*max == 1)+ *opcode = OP_MINQUERY;+ else+ *opcode = OP_MINUPTO;+ }+ 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, jump_list **prev_backtracks)+{+DEFINE_COMPILER;+backtrack_common *backtrack = NULL;+PCRE2_SPTR begin = cc;+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, use_tmp;+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;++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, prev_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 = LOCAL2;+ }++if (opcode == OP_EXACT)+ {+ SLJIT_ASSERT(early_fail_ptr == 0 && exact >= 2);++ if (common->mode == PCRE2_JIT_COMPLETE+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ && !common->utf+#endif+ && type != OP_ANYNL && type != OP_EXTUNI)+ {+ OP2(SLJIT_SUB, TMP1, 0, STR_END, 0, STR_PTR, 0);+ add_jump(compiler, prev_backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, IN_UCHARS(exact)));++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 32+ if (type == OP_ALLANY && !common->invalid_utf)+#else+ if (type == OP_ALLANY)+#endif+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(exact));+ else+ {+ OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, exact);+ label = LABEL();+ compile_char1_matchingpath(common, type, cc, prev_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+ {+ SLJIT_ASSERT(tmp_base == TMP3 || common->locals_size >= 3 * SSIZE_OF(sw));+ OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, exact);+ label = LABEL();+ compile_char1_matchingpath(common, type, cc, prev_backtracks, TRUE);+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);+ JUMPTO(SLJIT_NOT_ZERO, label);+ }+ }++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, prev_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);+ }++if (opcode < OP_EXACT)+ PUSH_BACKTRACK(sizeof(char_iterator_backtrack), begin, NULL);++switch(opcode)+ {+ case OP_STAR:+ case OP_UPTO:+ SLJIT_ASSERT(backtrack != NULL && (early_fail_ptr == 0 || opcode == OP_STAR));+ max += exact;++ if (type == OP_EXTUNI)+ {+ SLJIT_ASSERT(private_data_ptr == 0);+ SLJIT_ASSERT(early_fail_ptr == 0);++ if (exact == 1)+ {+ SLJIT_ASSERT(opcode == OP_STAR);+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);+ }+ else+ {+ /* If OP_EXTUNI is present, it has a separate EXACT opcode. */+ SLJIT_ASSERT(exact == 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)+ {+ SLJIT_ASSERT(common->locals_size >= 3 * SSIZE_OF(sw));+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL2, SLJIT_IMM, max);+ }++ label = LABEL();+ compile_char1_matchingpath(common, type, cc, &backtrack->own_backtracks, TRUE);+ if (opcode == OP_UPTO)+ {+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCAL2);+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);+ jump = JUMP(SLJIT_ZERO);+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL2, 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 (exact == 1)+ detect_partial_match(common, prev_backtracks);++ 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 OP_ALLANY is present, it has a separate EXACT opcode. */+ SLJIT_ASSERT(exact == 0);++ 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;++ SLJIT_ASSERT(tmp_base == TMP3);+ 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)->charpos.charpos_enabled = TRUE;+ BACKTRACK_AS(char_iterator_backtrack)->charpos.chr = charpos_char;+ BACKTRACK_AS(char_iterator_backtrack)->charpos.othercasebit = charpos_othercasebit;++ if (private_data_ptr == 0)+ allocate_stack(common, 2);++ use_tmp = (opcode == OP_STAR);++ if (use_tmp)+ {+ OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0);+ OP1(SLJIT_MOV, base, offset0, TMP3, 0);+ }+ else+ {+ OP1(SLJIT_MOV, base, offset1, COUNT_MATCH, 0);+ OP1(SLJIT_MOV, COUNT_MATCH, 0, SLJIT_IMM, 0);+ OP1(SLJIT_MOV, base, offset0, COUNT_MATCH, 0);+ OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, exact == max ? 0 : (max + 1));+ }++ /* Search the first instance of charpos_char. */+ if (exact > 0)+ detect_partial_match(common, &no_match);+ else+ jump = JUMP(SLJIT_JUMP);++ label = LABEL();++ if (opcode == OP_UPTO)+ {+ if (exact == max)+ OP2(SLJIT_ADD, TMP3, 0, TMP3, 0, SLJIT_IMM, 1);+ else+ {+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP3, 0, TMP3, 0, SLJIT_IMM, 1);+ add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));+ }+ }++ 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);++ if (exact == 0)+ JUMPHERE(jump);++ detect_partial_match(common, &no_match);++ if (opcode == OP_UPTO && exact > 0)+ {+ if (exact == max)+ CMPTO(SLJIT_LESS, TMP3, 0, SLJIT_IMM, exact, label);+ else+ CMPTO(SLJIT_GREATER, TMP3, 0, SLJIT_IMM, (max + 1) - exact, label);+ }++ 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);++ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ if (use_tmp)+ {+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP3, 0, SLJIT_IMM, 0);+ SELECT(SLJIT_EQUAL, TMP3, STR_PTR, 0, TMP3);+ }+ else+ {+ OP2U(SLJIT_SUB | SLJIT_SET_Z, COUNT_MATCH, 0, SLJIT_IMM, 0);+ SELECT(SLJIT_EQUAL, COUNT_MATCH, STR_PTR, 0, COUNT_MATCH);+ }+ JUMPTO(SLJIT_JUMP, label);++ set_jumps(no_match, LABEL());+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);+ if (use_tmp)+ OP1(SLJIT_MOV, base, offset1, TMP3, 0);+ else+ {+ OP1(SLJIT_MOV, TMP1, 0, base, offset1);+ OP1(SLJIT_MOV, base, offset1, COUNT_MATCH, 0);+ OP1(SLJIT_MOV, COUNT_MATCH, 0, TMP1, 0);+ }++ add_jump(compiler, &backtrack->own_backtracks, CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0));++ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ break;+ }+ }++ if (private_data_ptr == 0)+ allocate_stack(common, 2);++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ use_tmp = (opcode == OP_STAR);++ if (common->utf)+ {+ if (!use_tmp)+ OP1(SLJIT_MOV, base, offset0, COUNT_MATCH, 0);++ OP1(SLJIT_MOV, use_tmp ? TMP3 : COUNT_MATCH, 0, STR_PTR, 0);+ }+#endif++ if (opcode == OP_UPTO)+ OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, exact == max ? -(sljit_sw)exact : (sljit_sw)max);++ if (opcode == OP_UPTO && exact > 0)+ {+ label = LABEL();+ detect_partial_match(common, &no_match);+ 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 : COUNT_MATCH, 0, STR_PTR, 0);+#endif++ if (exact == max)+ {+ OP2(SLJIT_ADD | SLJIT_SET_Z, TMP3, 0, TMP3, 0, SLJIT_IMM, 1);+ JUMPTO(SLJIT_NOT_ZERO, label);+ }+ else+ {+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP3, 0, TMP3, 0, SLJIT_IMM, 1);+ add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));+ CMPTO(SLJIT_NOT_EQUAL, TMP3, 0, SLJIT_IMM, max - exact, label);+ }++ OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);+ JUMPTO(SLJIT_JUMP, label);+ }+ else+ {+ OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);++ 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 : COUNT_MATCH, 0, STR_PTR, 0);+#endif++ if (opcode == OP_UPTO)+ {+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP3, 0, TMP3, 0, SLJIT_IMM, 1);+ add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));+ }++ detect_partial_match_to(common, label);+ }++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (common->utf)+ {+ set_jumps(no_char1_match, LABEL());+ 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, COUNT_MATCH, 0);+ OP1(SLJIT_MOV, COUNT_MATCH, 0, base, offset0);+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ }+ }+ else+#endif+ {+ if (opcode != OP_UPTO || exact == 0)+ 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());+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ }++ if (opcode == OP_UPTO)+ {+ if (exact > 0)+ {+ if (max == exact)+ jump = CMP(SLJIT_GREATER_EQUAL, TMP3, 0, SLJIT_IMM, -(sljit_sw)exact);+ else+ jump = CMP(SLJIT_GREATER, TMP3, 0, SLJIT_IMM, max - exact);++ add_jump(compiler, &backtrack->own_backtracks, jump);+ }+ }+ else if (exact == 1)+ add_jump(compiler, &backtrack->own_backtracks, CMP(SLJIT_EQUAL, base, offset1, 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_QUERY:+ SLJIT_ASSERT(backtrack != NULL && early_fail_ptr == 0);+ if (private_data_ptr == 0)+ allocate_stack(common, 1);+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ compile_char1_matchingpath(common, type, cc, &backtrack->own_backtracks, TRUE);+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();+ break;++ case OP_MINSTAR:+ case OP_MINQUERY:+ SLJIT_ASSERT(backtrack != NULL && (opcode == OP_MINSTAR || early_fail_ptr == 0));+ if (private_data_ptr == 0)+ allocate_stack(common, 1);++ if (exact >= 1)+ {+ if (exact >= 2)+ {+ /* Extuni has a separate exact opcode. */+ SLJIT_ASSERT(tmp_base == TMP3 && early_fail_ptr == 0);+ OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, exact);+ }++ if (opcode == OP_MINQUERY)+ OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, -1);++ label = LABEL();+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = label;++ compile_char1_matchingpath(common, type, cc, &backtrack->own_backtracks, TRUE);++ if (exact >= 2)+ {+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP3, 0, TMP3, 0, SLJIT_IMM, 1);+ JUMPTO(SLJIT_NOT_ZERO, label);+ }++ if (opcode == OP_MINQUERY)+ OP2(SLJIT_AND, base, offset0, base, offset0, STR_PTR, 0);+ else+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ }+ else+ {+ 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(backtrack != NULL && early_fail_ptr == 0);+ if (private_data_ptr == 0)+ allocate_stack(common, 2);++ OP1(SLJIT_MOV, base, offset1, SLJIT_IMM, max + 1);++ if (exact == 0)+ {+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();+ break;+ }++ if (exact >= 2)+ {+ /* Extuni has a separate exact opcode. */+ SLJIT_ASSERT(tmp_base == TMP3);+ OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, exact);+ }++ label = LABEL();+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = label;++ compile_char1_matchingpath(common, type, cc, &backtrack->own_backtracks, TRUE);++ if (exact >= 2)+ {+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP3, 0, TMP3, 0, SLJIT_IMM, 1);+ JUMPTO(SLJIT_NOT_ZERO, label);+ }++ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ break;++ case OP_EXACT:+ SLJIT_ASSERT(backtrack == NULL);+ break;++ case OP_POSSTAR:+ SLJIT_ASSERT(backtrack == NULL);+#if defined SUPPORT_UNICODE+ if (type == OP_ALLANY && !common->invalid_utf)+#else+ if (type == OP_ALLANY)+#endif+ {+ if (exact == 1)+ detect_partial_match(common, prev_backtracks);++ 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)+ {+ SLJIT_ASSERT(tmp_base == TMP3 || common->locals_size >= 3 * SSIZE_OF(sw));++ if (tmp_base != TMP3)+ {+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL2, COUNT_MATCH, 0);+ tmp_base = COUNT_MATCH;+ }++ OP1(SLJIT_MOV, tmp_base, 0, exact == 1 ? SLJIT_IMM : 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, 0, STR_PTR, 0);+ detect_partial_match_to(common, label);++ set_jumps(no_match, LABEL());+ OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, 0);++ if (tmp_base != TMP3)+ OP1(SLJIT_MOV, COUNT_MATCH, 0, SLJIT_MEM1(SLJIT_SP), LOCAL2);++ if (exact == 1)+ add_jump(compiler, prev_backtracks, CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0));++ if (early_fail_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0);+ break;+ }+#endif++ if (exact == 1)+ OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);++ detect_partial_match(common, &no_match);+ label = LABEL();+ /* Extuni never fails, so no_char1_match is not used in that case.+ Anynl optionally reads an extra character on success. */+ compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);+ detect_partial_match_to(common, label);+ if (type != OP_EXTUNI)+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++ set_jumps(no_char1_match, LABEL());+ if (type != OP_EXTUNI)+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));++ set_jumps(no_match, LABEL());++ if (exact == 1)+ add_jump(compiler, prev_backtracks, CMP(SLJIT_EQUAL, tmp_base, tmp_offset, STR_PTR, 0));++ if (early_fail_ptr != 0)+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0);+ break;++ case OP_POSUPTO:+ SLJIT_ASSERT(backtrack == NULL && early_fail_ptr == 0);+ max += exact;++#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+ if (type == OP_EXTUNI || common->utf)+#else+ if (type == OP_EXTUNI)+#endif+ {+ SLJIT_ASSERT(common->locals_size >= 3 * SSIZE_OF(sw));++ /* Count match is not modified by compile_char1_matchingpath. */+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL2, COUNT_MATCH, 0);+ OP1(SLJIT_MOV, COUNT_MATCH, 0, SLJIT_IMM, exact == max ? 0 : max);++ label = LABEL();+ /* Extuni only modifies TMP3 on successful match. */+ OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);+ compile_char1_matchingpath(common, type, cc, &no_match, TRUE);++ if (exact == max)+ {+ OP2(SLJIT_ADD, COUNT_MATCH, 0, COUNT_MATCH, 0, SLJIT_IMM, 1);+ JUMPTO(SLJIT_JUMP, label);+ }+ else+ {+ OP2(SLJIT_SUB | SLJIT_SET_Z, COUNT_MATCH, 0, COUNT_MATCH, 0, SLJIT_IMM, 1);+ JUMPTO(SLJIT_NOT_ZERO, label);+ OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);+ }++ set_jumps(no_match, LABEL());++ if (exact > 0)+ {+ if (exact == max)+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, COUNT_MATCH, 0, SLJIT_IMM, exact);+ else+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER, COUNT_MATCH, 0, SLJIT_IMM, max - exact);+ }++ OP1(SLJIT_MOV, COUNT_MATCH, 0, SLJIT_MEM1(SLJIT_SP), LOCAL2);++ if (exact > 0)+ add_jump(compiler, prev_backtracks, JUMP(exact == max ? SLJIT_LESS : SLJIT_GREATER));+ OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);+ break;+ }++ SLJIT_ASSERT(tmp_base == TMP3);++ OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, exact == max ? 0 : max);++ detect_partial_match(common, &no_match);+ label = LABEL();+ compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);++ if (exact == max)+ OP2(SLJIT_ADD, TMP3, 0, TMP3, 0, SLJIT_IMM, 1);+ else+ {+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP3, 0, TMP3, 0, 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());++ if (exact > 0)+ {+ if (exact == max)+ jump = CMP(SLJIT_LESS, TMP3, 0, SLJIT_IMM, exact);+ else+ jump = CMP(SLJIT_GREATER, TMP3, 0, SLJIT_IMM, max - exact);++ add_jump(compiler, prev_backtracks, jump);+ }+ break;++ case OP_POSQUERY:+ SLJIT_ASSERT(backtrack == NULL && early_fail_ptr == 0);+ SLJIT_ASSERT(tmp_base == TMP3 || common->locals_size >= 3 * SSIZE_OF(sw));+ 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 = is_optimized_cbracket(common, offset);++/* 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;+size_t op_len;++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, parent->top != NULL ? &parent->top->simple_backtracks : &parent->own_backtracks);+ 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, 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;++#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+ case OP_XCLASS:+ case OP_ECLASS:+ op_len = GET(cc, 1);+ if (cc[op_len] >= OP_CRSTAR && cc[op_len] <= OP_CRPOSRANGE)+ cc = compile_iterator_matchingpath(common, cc, parent, 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;+#endif++ case OP_REF:+ case OP_REFI:+ op_len = PRIV(OP_lengths)[*cc];+ if (cc[op_len] >= OP_CRSTAR && cc[op_len] <= 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 += op_len;+ }+ break;++ case OP_DNREF:+ case OP_DNREFI:+ op_len = PRIV(OP_lengths)[*cc];+ if (cc[op_len] >= OP_CRSTAR && cc[op_len] <= 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 += op_len;+ }+ 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_ASSERT_SCS:+ 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_newline_move_back(compiler_common *common)+{+DEFINE_COMPILER;+struct sljit_jump *jump;++OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+jump = CMP(SLJIT_LESS_EQUAL, TMP1, 0, TMP2, 0);+/* All newlines are single byte, or their last byte+is not equal to CHAR_NL/CHAR_CR even if UTF is enabled. */+OP1(MOV_UCHAR, SLJIT_TMP_DEST_REG, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));+OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));+OP2(SLJIT_SHL, SLJIT_TMP_DEST_REG, 0, SLJIT_TMP_DEST_REG, 0, SLJIT_IMM, 8);+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_TMP_DEST_REG, 0);+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_CR << 8 | 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_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);+JUMPHERE(jump);+}++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_EXTUNI)+ {+ SLJIT_ASSERT(private_data_ptr == 0);+ 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(char_iterator_backtrack)->matchingpath);+ }+ else+ {+ if (CURRENT_AS(char_iterator_backtrack)->charpos.charpos_enabled)+ {+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);+ OP1(SLJIT_MOV, TMP2, 0, base, offset1);++ jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);+ label = LABEL();+ if (type == OP_ANYNL)+ compile_newline_move_back(common);+ move_back(common, NULL, TRUE);++ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));+ if (CURRENT_AS(char_iterator_backtrack)->charpos.othercasebit != 0)+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, CURRENT_AS(char_iterator_backtrack)->charpos.othercasebit);+ CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CURRENT_AS(char_iterator_backtrack)->charpos.chr, CURRENT_AS(char_iterator_backtrack)->matchingpath);+ /* The range beginning must match, no need to compare. */+ JUMPTO(SLJIT_JUMP, label);++ set_jumps(current->own_backtracks, LABEL());+ current->own_backtracks = NULL;+ }+ else+ {+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);++ if (opcode == OP_STAR && exact == 1)+ {+ if (type == OP_ANYNL)+ {+ OP1(SLJIT_MOV, TMP2, 0, base, offset1);+ compile_newline_move_back(common);+ }++ move_back(common, NULL, TRUE);+ jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, base, offset1);+ }+ else+ {+ if (type == OP_ANYNL)+ {+ OP1(SLJIT_MOV, TMP2, 0, base, offset1);+ jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);+ compile_newline_move_back(common);+ }+ else+ 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);++ set_jumps(current->own_backtracks, LABEL());+ }++ JUMPHERE(jump);+ 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->own_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_MINSTAR:+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);+ if (exact == 0)+ {+ compile_char1_matchingpath(common, type, cc, &jumplist, TRUE);+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);+ }+ else if (exact > 1)+ OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1);++ JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);+ set_jumps(exact > 0 ? current->own_backtracks : 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);++ if (exact == 0)+ {+ 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());+ }+ else+ {+ if (exact > 1)+ OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1);+ OP1(SLJIT_MOV, base, offset1, TMP1, 0);+ JUMPTO(SLJIT_NOT_ZERO, CURRENT_AS(char_iterator_backtrack)->matchingpath);++ set_jumps(current->own_backtracks, LABEL());+ }++ if (private_data_ptr == 0)+ free_stack(common, 2);+ break;++ case OP_MINQUERY:+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);+ OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0);++ if (exact >= 1)+ {+ if (exact >= 2)+ OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1);+ CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(char_iterator_backtrack)->matchingpath);+ set_jumps(current->own_backtracks, LABEL());+ }+ else+ {+ 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;++ default:+ SLJIT_UNREACHABLE();+ break;+ }+}++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[PRIV(OP_lengths)[*cc]];++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;+const 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.no_capture != 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(!is_optimized_cbracket(common, offset >> 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), 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 (!is_optimized_cbracket(common, offset >> 1))+ {+ 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 if (SLJIT_UNLIKELY(opcode == OP_ASSERT_SCS))+ {+ OP1(SLJIT_MOV, TMP1, 0, STR_END, 0);+ 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 + sizeof(sljit_sw), TMP1, 0);++ /* Nested scs blocks will not update this variable. */+ if (common->restore_end_ptr == 0)+ common->restore_end_ptr = private_data_ptr + sizeof(sljit_sw);+ }++if (SLJIT_UNLIKELY(opcode == OP_ONCE))+ {+ int framesize = CURRENT_AS(bracket_backtrack)->u.framesize;++ SLJIT_ASSERT(framesize != 0);+ 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));+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (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)->matching_mov_addr != NULL);+ sljit_set_label(CURRENT_AS(bracket_backtrack)->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;+ SLJIT_ASSERT(assert->framesize != 0);+ 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.no_capture != NULL)+ {+ SLJIT_ASSERT(has_alternatives);+ cond = JUMP(SLJIT_JUMP);+ set_jumps(CURRENT_AS(bracket_backtrack)->u.no_capture, 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;++ switch (opcode)+ {+ case OP_ASSERTBACK:+ case 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);+ break;+ case OP_ASSERT_SCS:+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(2));+ break;+ case OP_ONCE:+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(needs_control_head ? 1 : 0));+ break;+ case OP_COND:+ case OP_SCOND:+ break;+ default:+ 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));+ break;+ }++ 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 (!is_optimized_cbracket(common, offset >> 1))+ 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_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_MEM1(STACK_TOP), STACK(stacksize));+ }++ if (offset != 0 && ket == OP_KETRMAX && is_optimized_cbracket(common, offset >> 1))+ {+ /* 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);+ if (ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT)+ {+ assert = CURRENT_AS(bracket_backtrack)->u.assert;+ SLJIT_ASSERT(assert->framesize != 0);+ if (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 (is_optimized_cbracket(common, offset >> 1))+ {+ 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_ASSERT_SCS)+ {+ 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, has_alternatives ? 3 : 2);++ set_jumps(CURRENT_AS(bracket_backtrack)->u.no_capture, LABEL());++ /* Nested scs blocks will not update this variable. */+ if (common->restore_end_ptr == private_data_ptr + SSIZE_OF(sw))+ common->restore_end_ptr = 0;+ }+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);+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(common->compiler)))+ return;+ 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);+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(common->compiler)))+ return;+ }+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->restore_end_ptr != 0 && opcode != OP_SKIP_ARG)+ OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->restore_end_ptr);++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));++ if (common->restore_end_ptr == 0)+ {+ 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;+ }++ jump = CMP(SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0);+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_R0, 0);+ OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->restore_end_ptr);+ add_jump(compiler, &common->reset_match, JUMP(SLJIT_JUMP));+ JUMPHERE(jump);+ 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 framesize;+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());++framesize = CURRENT_AS(then_trap_backtrack)->framesize;+SLJIT_ASSERT(framesize != 0);++/* STACK_TOP is set by THEN. */+if (framesize > 0)+ {+ 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));+ }+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:+ /* Since classes has no backtracking path, this+ backtrackingpath was pushed by an iterator. */+ case OP_CLASS:+ case OP_NCLASS:+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+ case OP_XCLASS:+ case OP_ECLASS:+#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_ASSERT_SCS:+ 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->restore_end_ptr != 0)+ OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->restore_end_ptr);++ 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_op_addr(compiler, SLJIT_MOV_ADDR, 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, private_data_length, 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 = (PCRE2_SPTR)((uint8_t *)re + re->code_start);++#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+/* PCRE2_UTF[16|32] have the same value as PCRE2_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 = LOCAL0;+/* Allocate space for temporary data structures. */+private_data_length = ccend - common->start;+/* The chance of overflow is very low, but might happen on 32 bit. */+if (private_data_length > ~(sljit_uw)0 / sizeof(sljit_s32))+ return PCRE2_ERROR_NOMEMORY;++private_data_length *= sizeof(sljit_s32);+/* Align to 32 bit. */+common->cbracket_bitset_length = ((re->top_bracket + 1) + (sljit_u32)7) & ~(sljit_u32)7;+total_length = common->cbracket_bitset_length << 1;+if (~(sljit_uw)0 - private_data_length < total_length)+ return PCRE2_ERROR_NOMEMORY;++total_length += private_data_length;+common->private_data_ptrs = (sljit_s32*)SLJIT_MALLOC(total_length, allocator_data);+if (!common->private_data_ptrs)+ return PCRE2_ERROR_NOMEMORY;++memset(common->private_data_ptrs, 0, private_data_length);+common->optimized_cbrackets = ((sljit_u8 *)common->private_data_ptrs) + private_data_length;+#if defined DEBUG_FORCE_UNOPTIMIZED_CBRAS && DEBUG_FORCE_UNOPTIMIZED_CBRAS == 1+memset(common->optimized_cbrackets, 0, common->cbracket_bitset_length);+#else+memset(common->optimized_cbrackets, 0xff, common->cbracket_bitset_length);+#endif+common->cbracket_bitset = common->optimized_cbrackets + common->cbracket_bitset_length;++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->private_data_ptrs, allocator_data);+ return PCRE2_ERROR_JIT_UNSUPPORTED;+ }++/* Checking flags and updating ovector_start. */+if (mode == PCRE2_JIT_COMPLETE &&+ (re->flags & PCRE2_LASTSET) != 0 &&+ (re->optimization_flags & PCRE2_OPTIM_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_cbrackets, 0, common->cbracket_bitset_length);++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);+private_data_size = common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw);++if ((re->overall_options & PCRE2_ANCHORED) == 0 &&+ (re->optimization_flags & PCRE2_OPTIM_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);+ return PCRE2_ERROR_JIT_UNSUPPORTED;+ }++if (common->has_then)+ {+ total_length = ccend - common->start;+ common->then_offsets = (sljit_u8 *)SLJIT_MALLOC(total_length, allocator_data);+ if (!common->then_offsets)+ {+ SLJIT_FREE(common->private_data_ptrs, allocator_data);+ return PCRE2_ERROR_NOMEMORY;+ }+ 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->private_data_ptrs, allocator_data);+ if (common->has_then)+ SLJIT_FREE(common->then_offsets, 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 | SLJIT_ENTER_VECTOR(SLJIT_NUMBER_OF_SCRATCH_VECTOR_REGISTERS), 5, 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->optimization_flags & PCRE2_OPTIM_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->optimization_flags & PCRE2_OPTIM_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->private_data_ptrs, allocator_data);+ if (common->has_then)+ SLJIT_FREE(common->then_offsets, 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);++/* Fail if we detect that the start position was moved to be either after+the end position (\K in lookahead) or before the start offset (\K in+lookbehind). */++if (common->has_set_som &&+ (common->re->extra_options & PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK) == 0)+ {+ 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));+ }+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));++ /* (ovector[0] < jit_arguments->str)? */+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, TMP1, 0);+ /* Unconditionally set R0 (aka TMP1), in between the comparison that needs to+ use TMP1, but before the jump. */+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_BAD_BACKSLASH_K);+ add_jump(compiler, &common->abort, JUMP(SLJIT_LESS));+ /* (ovector[0] > STR_PTR)? NB. ovector[1] hasn't yet been set to STR_PTR. */+ add_jump(compiler, &common->abort, CMP(SLJIT_GREATER, TMP2, 0, STR_PTR, 0));+ }++/* 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->private_data_ptrs, allocator_data);+ if (common->has_then)+ SLJIT_FREE(common->then_offsets, 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;+SLJIT_ASSERT(common->restore_end_ptr == 0);++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->private_data_ptrs, allocator_data);+ if (common->has_then)+ SLJIT_FREE(common->then_offsets, 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;+SLJIT_ASSERT(common->restore_end_ptr == 0);++/* Allocating stack, returns with PCRE2_ERROR_JIT_STACKLIMIT if fails. */+/* This is a (really) rare case. */+set_jumps(common->stackalloc, LABEL());+/* RETURN_ADDR is not a saved register. */+SLJIT_ASSERT(common->locals_size >= 2 * SSIZE_OF(sw));+sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), LOCAL0);++SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);++OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL1, 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), LOCAL0);+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCAL1);+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->private_data_ptrs, allocator_data);+if (common->has_then)+ SLJIT_FREE(common->then_offsets, 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+void *exec_memory;+executable_functions *functions;+static int executable_allocator_is_working = -1;++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. */+ exec_memory = SLJIT_MALLOC_EXEC(32, NULL);+ if (exec_memory != NULL)+ {+ SLJIT_FREE_EXEC(((sljit_u8*)(exec_memory)) + SLJIT_EXEC_OFFSET(exec_memory), NULL);+ executable_allocator_is_working = 1;+ }+ else executable_allocator_is_working = 0;+ }+#endif++if (options & PCRE2_JIT_TEST_ALLOC)+ {+ if (options != PCRE2_JIT_TEST_ALLOC)+ return PCRE2_ERROR_JIT_BADOPTION;++#ifdef SUPPORT_JIT+ return executable_allocator_is_working ? 0 : PCRE2_ERROR_NOMEMORY;+#else+ return PCRE2_ERROR_JIT_UNSUPPORTED;+#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)+ return PCRE2_ERROR_NOMEMORY;++if ((re->overall_options & PCRE2_MATCH_INVALID_UTF) != 0)+ options |= PCRE2_JIT_INVALID_UTF;++if ((options & PCRE2_JIT_COMPLETE) != 0 && (functions == NULL+ || functions->executable_funcs[0] == NULL)) {+ uint32_t excluded_options = (PCRE2_JIT_PARTIAL_SOFT | PCRE2_JIT_PARTIAL_HARD);+ int result = jit_compile(code, options & ~excluded_options);+ if (result != 0)+ return result;+ }++if ((options & PCRE2_JIT_PARTIAL_SOFT) != 0 && (functions == NULL+ || functions->executable_funcs[1] == NULL)) {+ uint32_t excluded_options = (PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_HARD);+ int result = jit_compile(code, options & ~excluded_options);+ if (result != 0)+ return result;+ }++if ((options & PCRE2_JIT_PARTIAL_HARD) != 0 && (functions == NULL+ || functions->executable_funcs[2] == NULL)) {+ uint32_t excluded_options = (PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_SOFT);+ int result = jit_compile(code, options & ~excluded_options);+ if (result != 0)+ return result;+ }++return 0;++#endif /* SUPPORT_JIT */+}++/* JIT compiler uses an all-in-one approach. This improves security,+ since the code generator functions are not exported. */++#define INCLUDED_FROM_PCRE2_JIT_COMPILE++#include "pcre2_jit_match_inc.h"+#include "pcre2_jit_misc_inc.h" /* End of pcre2_jit_compile.c */
− src/c/pcre2/src/pcre2_jit_match.c
@@ -1,200 +0,0 @@-/*************************************************-* 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- Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-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.-------------------------------------------------------------------------------*/--#ifndef INCLUDED_FROM_PCRE2_JIT_COMPILE-#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)-{-sljit_u8 local_space[MACHINE_STACK_SIZE];-struct sljit_stack local_stack;--local_stack.min_start = local_space;-local_stack.start = local_space;-local_stack.end = local_space + MACHINE_STACK_SIZE;-local_stack.top = local_space + MACHINE_STACK_SIZE;-arguments->stack = &local_stack;-return executable_func(arguments);-}--#endif---/*************************************************-* Do a JIT pattern match *-*************************************************/--/* This function runs a JIT pattern match.--Arguments:- code points to the compiled expression- subject points to the subject string- length length of subject string (may contain binary zeros)- start_offset where to start in the subject string- options option bits- match_data points to a match_data block- mcontext points to a match context--Returns: > 0 => success; value is the number of ovector pairs filled- = 0 => success, but ovector is not big enough- -1 => failed to match (PCRE_ERROR_NOMATCH)- < -1 => some kind of unexpected problem-*/--PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION-pcre2_jit_match(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length,- PCRE2_SIZE start_offset, uint32_t options, pcre2_match_data *match_data,- pcre2_match_context *mcontext)-{-#ifndef SUPPORT_JIT--(void)code;-(void)subject;-(void)length;-(void)start_offset;-(void)options;-(void)match_data;-(void)mcontext;-return PCRE2_ERROR_JIT_BADOPTION;--#else /* SUPPORT_JIT */--pcre2_real_code *re = (pcre2_real_code *)code;-executable_functions *functions = (executable_functions *)re->executable_jit;-pcre2_jit_stack *jit_stack;-uint32_t oveccount = match_data->oveccount;-uint32_t max_oveccount;-union {- void *executable_func;- jit_function call_executable_func;-} convert_executable_func;-jit_arguments arguments;-int rc;-int index = 0;--if ((options & PCRE2_PARTIAL_HARD) != 0)- index = 2;-else if ((options & PCRE2_PARTIAL_SOFT) != 0)- index = 1;--if (functions == NULL || functions->executable_funcs[index] == NULL)- return PCRE2_ERROR_JIT_BADOPTION;--/* Sanity checks should be handled by pcre2_match. */-arguments.str = subject + start_offset;-arguments.begin = subject;-arguments.end = subject + length;-arguments.match_data = match_data;-arguments.startchar_ptr = subject;-arguments.mark_ptr = NULL;-arguments.options = options;--if (mcontext != NULL)- {- arguments.callout = mcontext->callout;- arguments.callout_data = mcontext->callout_data;- arguments.offset_limit = mcontext->offset_limit;- arguments.limit_match = (mcontext->match_limit < re->limit_match)?- mcontext->match_limit : re->limit_match;- if (mcontext->jit_callback != NULL)- jit_stack = mcontext->jit_callback(mcontext->jit_callback_data);- else- jit_stack = (pcre2_jit_stack *)mcontext->jit_callback_data;- }-else- {- arguments.callout = NULL;- arguments.callout_data = NULL;- arguments.offset_limit = PCRE2_UNSET;- arguments.limit_match = (MATCH_LIMIT < re->limit_match)?- MATCH_LIMIT : re->limit_match;- jit_stack = NULL;- }---max_oveccount = functions->top_bracket;-if (oveccount > max_oveccount)- oveccount = max_oveccount;-arguments.oveccount = oveccount << 1;---convert_executable_func.executable_func = functions->executable_funcs[index];-if (jit_stack != NULL)- {- arguments.stack = (struct sljit_stack *)(jit_stack->stack);- rc = convert_executable_func.call_executable_func(&arguments);- }-else- rc = jit_machine_stack_exec(&arguments, convert_executable_func.call_executable_func);--if (rc > (int)oveccount)- 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;--#endif /* SUPPORT_JIT */-}--/* End of pcre2_jit_match.c */
+ src/c/pcre2/src/pcre2_jit_match_inc.h view
@@ -0,0 +1,202 @@+/*************************************************+* 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+ Original API code Copyright (c) 1997-2012 University of Cambridge+ New API code Copyright (c) 2016-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.+-----------------------------------------------------------------------------+*/++#ifndef INCLUDED_FROM_PCRE2_JIT_COMPILE+#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)+{+sljit_u8 local_space[MACHINE_STACK_SIZE];+struct sljit_stack local_stack;++local_stack.min_start = local_space;+local_stack.start = local_space;+local_stack.end = local_space + MACHINE_STACK_SIZE;+local_stack.top = local_space + MACHINE_STACK_SIZE;+arguments->stack = &local_stack;+return executable_func(arguments);+}++#endif+++/*************************************************+* Do a JIT pattern match *+*************************************************/++/* This function runs a JIT pattern match.++Arguments:+ code points to the compiled expression+ subject points to the subject string+ length length of subject string (may contain binary zeros)+ start_offset where to start in the subject string+ options option bits+ match_data points to a match_data block+ mcontext points to a match context++Returns: > 0 => success; value is the number of ovector pairs filled+ = 0 => success, but ovector is not big enough+ -1 => failed to match (PCRE2_ERROR_NOMATCH)+ < -1 => some kind of unexpected problem+*/++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_jit_match(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length,+ PCRE2_SIZE start_offset, uint32_t options, pcre2_match_data *match_data,+ pcre2_match_context *mcontext)+{+#ifndef SUPPORT_JIT++(void)code;+(void)subject;+(void)length;+(void)start_offset;+(void)options;+(void)mcontext;+return match_data->rc = PCRE2_ERROR_JIT_BADOPTION;++#else /* SUPPORT_JIT */++pcre2_real_code *re = (pcre2_real_code *)code;+executable_functions *functions = (executable_functions *)re->executable_jit;+pcre2_jit_stack *jit_stack;+uint32_t oveccount = match_data->oveccount;+uint32_t max_oveccount;+union {+ void *executable_func;+ jit_function call_executable_func;+} convert_executable_func;+jit_arguments arguments;+int rc;+int index = 0;++if ((options & PCRE2_PARTIAL_HARD) != 0)+ index = 2;+else if ((options & PCRE2_PARTIAL_SOFT) != 0)+ index = 1;++if (functions == NULL || functions->executable_funcs[index] == NULL)+ return match_data->rc = PCRE2_ERROR_JIT_BADOPTION;++/* Sanity checks should be handled by pcre2_match. */+arguments.str = subject + start_offset;+arguments.begin = subject;+arguments.end = subject + length;+arguments.match_data = match_data;+arguments.startchar_ptr = subject;+arguments.mark_ptr = NULL;+arguments.options = options;++if (mcontext != NULL)+ {+ arguments.callout = mcontext->callout;+ arguments.callout_data = mcontext->callout_data;+ arguments.offset_limit = mcontext->offset_limit;+ arguments.limit_match = (mcontext->match_limit < re->limit_match)?+ mcontext->match_limit : re->limit_match;+ if (mcontext->jit_callback != NULL)+ jit_stack = mcontext->jit_callback(mcontext->jit_callback_data);+ else+ jit_stack = (pcre2_jit_stack *)mcontext->jit_callback_data;+ }+else+ {+ arguments.callout = NULL;+ arguments.callout_data = NULL;+ arguments.offset_limit = PCRE2_UNSET;+ arguments.limit_match = (MATCH_LIMIT < re->limit_match)?+ MATCH_LIMIT : re->limit_match;+ jit_stack = NULL;+ }+++max_oveccount = functions->top_bracket;+if (oveccount > max_oveccount)+ oveccount = max_oveccount;+arguments.oveccount = oveccount << 1;+++convert_executable_func.executable_func = functions->executable_funcs[index];+if (jit_stack != NULL)+ {+ arguments.stack = (struct sljit_stack *)(jit_stack->stack);+ rc = convert_executable_func.call_executable_func(&arguments);+ }+else+ rc = jit_machine_stack_exec(&arguments, convert_executable_func.call_executable_func);++if (rc > (int)oveccount)+ rc = 0;+match_data->code = re;+match_data->subject =+ (rc >= 0 || rc == PCRE2_ERROR_NOMATCH || rc == PCRE2_ERROR_PARTIAL)? subject : NULL;+match_data->subject_length = length;+match_data->start_offset = start_offset;+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;+match_data->options = options;++#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;++#endif /* SUPPORT_JIT */+}++/* End of pcre2_jit_match_inc.h */
− src/c/pcre2/src/pcre2_jit_misc.c
@@ -1,234 +0,0 @@-/*************************************************-* 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- Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016 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.-------------------------------------------------------------------------------*/---#ifndef INCLUDED_FROM_PCRE2_JIT_COMPILE-#error This file must be included from pcre2_jit_compile.c.-#endif----/*************************************************-* Free JIT read-only data *-*************************************************/--void-PRIV(jit_free_rodata)(void *current, void *allocator_data)-{-#ifndef SUPPORT_JIT-(void)current;-(void)allocator_data;-#else /* SUPPORT_JIT */-void *next;--SLJIT_UNUSED_ARG(allocator_data);--while (current != NULL)- {- next = *(void**)current;- SLJIT_FREE(current, allocator_data);- current = next;- }--#endif /* SUPPORT_JIT */-}--/*************************************************-* Free JIT compiled code *-*************************************************/--void-PRIV(jit_free)(void *executable_jit, pcre2_memctl *memctl)-{-#ifndef SUPPORT_JIT-(void)executable_jit;-(void)memctl;-#else /* SUPPORT_JIT */--executable_functions *functions = (executable_functions *)executable_jit;-void *allocator_data = memctl;-int i;--for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++)- {- if (functions->executable_funcs[i] != NULL)- sljit_free_code(functions->executable_funcs[i], NULL);- PRIV(jit_free_rodata)(functions->read_only_data_heads[i], allocator_data);- }--SLJIT_FREE(functions, allocator_data);--#endif /* SUPPORT_JIT */-}---/*************************************************-* Free unused JIT memory *-*************************************************/--PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION-pcre2_jit_free_unused_memory(pcre2_general_context *gcontext)-{-#ifndef SUPPORT_JIT-(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 /* SLJIT_EXECUTABLE_ALLOCATOR */-#endif /* SUPPORT_JIT */-}----/*************************************************-* Allocate a JIT stack *-*************************************************/--PCRE2_EXP_DEFN pcre2_jit_stack * PCRE2_CALL_CONVENTION-pcre2_jit_stack_create(size_t startsize, size_t maxsize,- pcre2_general_context *gcontext)-{-#ifndef SUPPORT_JIT--(void)gcontext;-(void)startsize;-(void)maxsize;-return NULL;--#else /* SUPPORT_JIT */--pcre2_jit_stack *jit_stack;--if (startsize == 0 || maxsize == 0 || maxsize > SIZE_MAX - STACK_GROWTH_RATE)- return NULL;-if (startsize > maxsize)- startsize = maxsize;-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;-jit_stack->stack = sljit_allocate_stack(startsize, maxsize, &jit_stack->memctl);-if (jit_stack->stack == NULL)- {- jit_stack->memctl.free(jit_stack, jit_stack->memctl.memory_data);- return NULL;- }-return jit_stack;--#endif-}---/*************************************************-* Assign a JIT stack to a pattern *-*************************************************/--PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION-pcre2_jit_stack_assign(pcre2_match_context *mcontext, pcre2_jit_callback callback,- void *callback_data)-{-#ifndef SUPPORT_JIT-(void)mcontext;-(void)callback;-(void)callback_data;-#else /* SUPPORT_JIT */--if (mcontext == NULL) return;-mcontext->jit_callback = callback;-mcontext->jit_callback_data = callback_data;--#endif /* SUPPORT_JIT */-}---/*************************************************-* Free a JIT stack *-*************************************************/--PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION-pcre2_jit_stack_free(pcre2_jit_stack *jit_stack)-{-#ifndef SUPPORT_JIT-(void)jit_stack;-#else /* SUPPORT_JIT */-if (jit_stack != NULL)- {- sljit_free_stack((struct sljit_stack *)(jit_stack->stack), &jit_stack->memctl);- jit_stack->memctl.free(jit_stack, jit_stack->memctl.memory_data);- }-#endif /* SUPPORT_JIT */-}---/*************************************************-* Get target CPU type *-*************************************************/--const char*-PRIV(jit_get_target)(void)-{-#ifndef SUPPORT_JIT-return "JIT is not supported";-#else /* SUPPORT_JIT */-return sljit_get_platform_name();-#endif /* SUPPORT_JIT */-}---/*************************************************-* Get size of JIT code *-*************************************************/--size_t-PRIV(jit_get_size)(void *executable_jit)-{-#ifndef SUPPORT_JIT-(void)executable_jit;-return 0;-#else /* SUPPORT_JIT */-sljit_uw *executable_sizes = ((executable_functions *)executable_jit)->executable_sizes;-SLJIT_COMPILE_ASSERT(JIT_NUMBER_OF_COMPILE_MODES == 3, number_of_compile_modes_changed);-return executable_sizes[0] + executable_sizes[1] + executable_sizes[2];-#endif-}--/* End of pcre2_jit_misc.c */
+ src/c/pcre2/src/pcre2_jit_misc_inc.h view
@@ -0,0 +1,234 @@+/*************************************************+* 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+ Original API code Copyright (c) 1997-2012 University of Cambridge+ New API code Copyright (c) 2016 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.+-----------------------------------------------------------------------------+*/+++#ifndef INCLUDED_FROM_PCRE2_JIT_COMPILE+#error This file must be included from pcre2_jit_compile.c.+#endif++++/*************************************************+* Free JIT read-only data *+*************************************************/++void+PRIV(jit_free_rodata)(void *current, void *allocator_data)+{+#ifndef SUPPORT_JIT+(void)current;+(void)allocator_data;+#else /* SUPPORT_JIT */+void *next;++SLJIT_UNUSED_ARG(allocator_data);++while (current != NULL)+ {+ next = *(void**)current;+ SLJIT_FREE(current, allocator_data);+ current = next;+ }++#endif /* SUPPORT_JIT */+}++/*************************************************+* Free JIT compiled code *+*************************************************/++void+PRIV(jit_free)(void *executable_jit, pcre2_memctl *memctl)+{+#ifndef SUPPORT_JIT+(void)executable_jit;+(void)memctl;+#else /* SUPPORT_JIT */++executable_functions *functions = (executable_functions *)executable_jit;+void *allocator_data = memctl;+int i;++for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++)+ {+ if (functions->executable_funcs[i] != NULL)+ sljit_free_code(functions->executable_funcs[i], NULL);+ PRIV(jit_free_rodata)(functions->read_only_data_heads[i], allocator_data);+ }++SLJIT_FREE(functions, allocator_data);++#endif /* SUPPORT_JIT */+}+++/*************************************************+* Free unused JIT memory *+*************************************************/++PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION+pcre2_jit_free_unused_memory(pcre2_general_context *gcontext)+{+#ifndef SUPPORT_JIT+(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 /* SLJIT_EXECUTABLE_ALLOCATOR */+#endif /* SUPPORT_JIT */+}++++/*************************************************+* Allocate a JIT stack *+*************************************************/++PCRE2_EXP_DEFN pcre2_jit_stack * PCRE2_CALL_CONVENTION+pcre2_jit_stack_create(size_t startsize, size_t maxsize,+ pcre2_general_context *gcontext)+{+#ifndef SUPPORT_JIT++(void)gcontext;+(void)startsize;+(void)maxsize;+return NULL;++#else /* SUPPORT_JIT */++pcre2_jit_stack *jit_stack;++if (startsize == 0 || maxsize == 0 || maxsize > SIZE_MAX - STACK_GROWTH_RATE)+ return NULL;+if (startsize > maxsize)+ startsize = maxsize;+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;+jit_stack->stack = sljit_allocate_stack(startsize, maxsize, &jit_stack->memctl);+if (jit_stack->stack == NULL)+ {+ jit_stack->memctl.free(jit_stack, jit_stack->memctl.memory_data);+ return NULL;+ }+return jit_stack;++#endif+}+++/*************************************************+* Assign a JIT stack to a pattern *+*************************************************/++PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION+pcre2_jit_stack_assign(pcre2_match_context *mcontext, pcre2_jit_callback callback,+ void *callback_data)+{+#ifndef SUPPORT_JIT+(void)mcontext;+(void)callback;+(void)callback_data;+#else /* SUPPORT_JIT */++if (mcontext == NULL) return;+mcontext->jit_callback = callback;+mcontext->jit_callback_data = callback_data;++#endif /* SUPPORT_JIT */+}+++/*************************************************+* Free a JIT stack *+*************************************************/++PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION+pcre2_jit_stack_free(pcre2_jit_stack *jit_stack)+{+#ifndef SUPPORT_JIT+(void)jit_stack;+#else /* SUPPORT_JIT */+if (jit_stack != NULL)+ {+ sljit_free_stack((struct sljit_stack *)(jit_stack->stack), &jit_stack->memctl);+ jit_stack->memctl.free(jit_stack, jit_stack->memctl.memory_data);+ }+#endif /* SUPPORT_JIT */+}+++/*************************************************+* Get target CPU type *+*************************************************/++const char*+PRIV(jit_get_target)(void)+{+#ifndef SUPPORT_JIT+return "JIT is not supported";+#else /* SUPPORT_JIT */+return sljit_get_platform_name();+#endif /* SUPPORT_JIT */+}+++/*************************************************+* Get size of JIT code *+*************************************************/++size_t+PRIV(jit_get_size)(void *executable_jit)+{+#ifndef SUPPORT_JIT+(void)executable_jit;+return 0;+#else /* SUPPORT_JIT */+sljit_uw *executable_sizes = ((executable_functions *)executable_jit)->executable_sizes;+SLJIT_COMPILE_ASSERT(JIT_NUMBER_OF_COMPILE_MODES == 3, number_of_compile_modes_changed);+return executable_sizes[0] + executable_sizes[1] + executable_sizes[2];+#endif+}++/* End of pcre2_jit_misc_inc.h */
− src/c/pcre2/src/pcre2_jit_neon_inc.h
@@ -1,354 +0,0 @@-/*************************************************-* 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- This module by Zoltan Herczeg and Sebastian Pop- Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2019 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.-------------------------------------------------------------------------------*/--# if defined(FFCS)-# if defined(FF_UTF)-# define FF_FUN ffcs_utf-# else-# define FF_FUN ffcs-# endif--# elif defined(FFCS_2)-# if defined(FF_UTF)-# define FF_FUN ffcs_2_utf-# else-# define FF_FUN ffcs_2-# endif--# elif defined(FFCS_MASK)-# if defined(FF_UTF)-# define FF_FUN ffcs_mask_utf-# else-# define FF_FUN ffcs_mask-# endif--# elif defined(FFCPS_0)-# if defined (FF_UTF)-# define FF_FUN ffcps_0_utf-# else-# define FF_FUN ffcps_0-# endif--# elif defined (FFCPS_1)-# if defined (FF_UTF)-# define FF_FUN ffcps_1_utf-# else-# define FF_FUN ffcps_1-# endif--# elif defined (FFCPS_DEFAULT)-# if defined (FF_UTF)-# define FF_FUN ffcps_default_utf-# else-# define FF_FUN ffcps_default-# endif-# endif--#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;-int_char ic;--SLJIT_UNUSED_ARG(offs1);-SLJIT_UNUSED_ARG(offs2);--ic.x = chars;--#if defined(FFCS)-sljit_u8 c1 = ic.c.c1;-vect_t vc1 = VDUPQ(c1);--#elif defined(FFCS_2)-sljit_u8 c1 = ic.c.c1;-vect_t vc1 = VDUPQ(c1);-sljit_u8 c2 = ic.c.c2;-vect_t vc2 = VDUPQ(c2);--#elif defined(FFCS_MASK)-sljit_u8 c1 = ic.c.c1;-vect_t vc1 = VDUPQ(c1);-sljit_u8 mask = ic.c.c2;-vect_t vmask = VDUPQ(mask);-#endif--#if defined(FFCPS)-compare_type compare1_type = compare_match1;-compare_type compare2_type = compare_match1;-vect_t cmp1a, cmp1b, cmp2a, cmp2b;-const sljit_u32 diff = IN_UCHARS(offs1 - offs2);-PCRE2_UCHAR char1a = ic.c.c1;-PCRE2_UCHAR char2a = ic.c.c3;--# ifdef FFCPS_CHAR1A2A-cmp1a = VDUPQ(char1a);-cmp2a = VDUPQ(char2a);-cmp1b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */-cmp2b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */-# else-PCRE2_UCHAR char1b = ic.c.c2;-PCRE2_UCHAR char2b = ic.c.c4;-if (char1a == char1b)- {- cmp1a = VDUPQ(char1a);- cmp1b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */- }-else- {- sljit_u32 bit1 = char1a ^ char1b;- if (is_powerof2(bit1))- {- compare1_type = compare_match1i;- cmp1a = VDUPQ(char1a | bit1);- cmp1b = VDUPQ(bit1);- }- else- {- compare1_type = compare_match2;- cmp1a = VDUPQ(char1a);- cmp1b = VDUPQ(char1b);- }- }--if (char2a == char2b)- {- cmp2a = VDUPQ(char2a);- cmp2b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */- }-else- {- sljit_u32 bit2 = char2a ^ char2b;- if (is_powerof2(bit2))- {- compare2_type = compare_match1i;- cmp2a = VDUPQ(char2a | bit2);- cmp2b = VDUPQ(bit2);- }- else- {- compare2_type = compare_match2;- cmp2a = VDUPQ(char2a);- cmp2b = VDUPQ(char2b);- }- }-# endif--*str_ptr += IN_UCHARS(offs1);-#endif--#if PCRE2_CODE_UNIT_WIDTH != 8-vect_t char_mask = VDUPQ(0xff);-#endif--#if defined(FF_UTF)-restart:;-#endif--#if defined(FFCPS)-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);-#if PCRE2_CODE_UNIT_WIDTH != 8-data = VANDQ(data, char_mask);-#endif- -#if defined(FFCS)-vect_t eq = VCEQQ(data, vc1);--#elif defined(FFCS_2)-vect_t eq1 = VCEQQ(data, vc1);-vect_t eq2 = VCEQQ(data, vc2);-vect_t eq = VORRQ(eq1, eq2); --#elif defined(FFCS_MASK)-vect_t eq = VORRQ(data, vmask);-eq = VCEQQ(eq, vc1);--#elif defined(FFCPS)-# if defined(FFCPS_DIFF1)-vect_t prev_data = data;-# endif--vect_t data2;-if (p1 < *str_ptr)- {- data2 = VLD1Q(*str_ptr - diff);-#if PCRE2_CODE_UNIT_WIDTH != 8- data2 = VANDQ(data2, char_mask);-#endif- }-else- data2 = shift_left_n_lanes(data, offs1 - offs2);- -if (compare1_type == compare_match1)- data = VCEQQ(data, cmp1a);-else- data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);--if (compare2_type == compare_match1)- data2 = VCEQQ(data2, cmp2a);-else- data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);--vect_t eq = VANDQ(data, data2);-#endif--VST1Q(qw.mem, eq);-/* Ignore matches before the first STR_PTR. */-if (align_offset < 8)- {- qw.dw[0] >>= align_offset * 8;- if (qw.dw[0])- {- *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;- goto match;- }- }-else- {- qw.dw[1] >>= (align_offset - 8) * 8;- if (qw.dw[1])- {- *str_ptr += align_offset + __builtin_ctzll(qw.dw[1]) / 8;- goto match;- }- }-*str_ptr += 16;--while (*str_ptr < str_end)- {- vect_t orig_data = VLD1Q(*str_ptr);-#if PCRE2_CODE_UNIT_WIDTH != 8- orig_data = VANDQ(orig_data, char_mask);-#endif- data = orig_data;--#if defined(FFCS)- eq = VCEQQ(data, vc1);--#elif defined(FFCS_2)- eq1 = VCEQQ(data, vc1);- eq2 = VCEQQ(data, vc2);- eq = VORRQ(eq1, eq2); --#elif defined(FFCS_MASK)- eq = VORRQ(data, vmask);- eq = VCEQQ(eq, vc1);-#endif--#if defined(FFCPS)-# if defined (FFCPS_DIFF1)- data2 = VEXTQ(prev_data, data, VECTOR_FACTOR - 1);-# else- data2 = VLD1Q(*str_ptr - diff);-# if PCRE2_CODE_UNIT_WIDTH != 8- data2 = VANDQ(data2, char_mask);-# endif-# endif--# ifdef FFCPS_CHAR1A2A- data = VCEQQ(data, cmp1a);- data2 = VCEQQ(data2, cmp2a);-# else- if (compare1_type == compare_match1)- data = VCEQQ(data, cmp1a);- else- data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);- if (compare2_type == compare_match1)- data2 = VCEQQ(data2, cmp2a);- else- data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);-# endif-- eq = VANDQ(data, data2);-#endif-- VST1Q(qw.mem, eq);- if (qw.dw[0])- *str_ptr += __builtin_ctzll(qw.dw[0]) / 8;- else if (qw.dw[1])- *str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;- else {- *str_ptr += 16;-#if defined (FFCPS_DIFF1)- prev_data = orig_data;-#endif- continue;- }--match:;- if (*str_ptr >= str_end)- /* Failed match. */- return NULL;--#if defined(FF_UTF)- if (utf_continue((PCRE2_SPTR)*str_ptr - offs1))- {- /* Not a match. */- *str_ptr += IN_UCHARS(1);- goto restart;- }-#endif-- /* Match. */-#if defined (FFCPS)- *str_ptr -= IN_UCHARS(offs1);-#endif- return *str_ptr;- }--/* Failed match. */-return NULL;-}
src/c/pcre2/src/pcre2_jit_simd_inc.h view
@@ -42,6 +42,7 @@ #if !(defined SUPPORT_VALGRIND) #if ((defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \+ || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \ || (defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64)) @@ -100,7 +101,7 @@ } #endif -#endif /* SLJIT_CONFIG_X86 || SLJIT_CONFIG_S390X */+#endif /* SLJIT_CONFIG_X86 || SLJIT_CONFIG_ARM_64 || SLJIT_CONFIG_S390X || SLJIT_CONFIG_LOONGARCH_64 */ #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) @@ -228,7 +229,14 @@ } } +/* The AVX2 code path is currently disabled. #define JIT_HAS_FAST_FORWARD_CHAR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_SIMD))+*/+#if defined(SLJIT_CONFIG_X86_64) && SLJIT_CONFIG_X86_64+#define JIT_HAS_FAST_FORWARD_CHAR_SIMD 1+#else+#define JIT_HAS_FAST_FORWARD_CHAR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_FPU))+#endif static void fast_forward_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset) {@@ -246,10 +254,10 @@ 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_s32 data_ind = sljit_get_register_index(reg_type, SLJIT_VR0);+sljit_s32 cmp1_ind = sljit_get_register_index(reg_type, SLJIT_VR1);+sljit_s32 cmp2_ind = sljit_get_register_index(reg_type, SLJIT_VR2);+sljit_s32 tmp_ind = sljit_get_register_index(reg_type, SLJIT_VR3); sljit_u32 bit = 0; int i; @@ -273,17 +281,17 @@ /* 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));+sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR1, 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));+ sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR2, 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);+sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR1, SLJIT_VR1, 0); if (char1 != char2)- sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR2, SLJIT_FR2, 0);+ sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR2, SLJIT_VR2, 0); #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 restart = LABEL();@@ -294,12 +302,12 @@ 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);+sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_VR0, 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);+sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_VR0, TMP1, 0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0); @@ -318,11 +326,11 @@ 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);+sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_VR0, 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);+sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_VR0, TMP1, 0); CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start); JUMPHERE(quit);@@ -365,7 +373,14 @@ #endif } +/* The AVX2 code path is currently disabled. #define JIT_HAS_FAST_REQUESTED_CHAR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_SIMD))+*/+#if defined(SLJIT_CONFIG_X86_64) && SLJIT_CONFIG_X86_64+#define JIT_HAS_FAST_REQUESTED_CHAR_SIMD 1+#else+#define JIT_HAS_FAST_REQUESTED_CHAR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_FPU))+#endif static jump_list *fast_requested_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2) {@@ -380,10 +395,10 @@ 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_s32 data_ind = sljit_get_register_index(reg_type, SLJIT_VR0);+sljit_s32 cmp1_ind = sljit_get_register_index(reg_type, SLJIT_VR1);+sljit_s32 cmp2_ind = sljit_get_register_index(reg_type, SLJIT_VR2);+sljit_s32 tmp_ind = sljit_get_register_index(reg_type, SLJIT_VR3); sljit_u32 bit = 0; int i; @@ -406,29 +421,29 @@ /* 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));+sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR1, 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));+ sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR2, 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);+sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR1, SLJIT_VR1, 0); if (char1 != char2)- sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR2, SLJIT_FR2, 0);+ sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR2, SLJIT_VR2, 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);+sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_VR0, 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);+sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_VR0, TMP1, 0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0); @@ -445,12 +460,12 @@ 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);+sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_VR0, 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);+sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_VR0, TMP1, 0); CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start); JUMPHERE(quit);@@ -471,7 +486,14 @@ #ifndef _WIN64 +/* The AVX2 code path is currently disabled. #define JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_SIMD))+*/+#if defined(SLJIT_CONFIG_X86_64) && SLJIT_CONFIG_X86_64+#define JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD 1+#else+#define JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_FPU))+#endif 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)@@ -488,14 +510,14 @@ 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);+sljit_s32 data1_ind = sljit_get_register_index(reg_type, SLJIT_VR0);+sljit_s32 data2_ind = sljit_get_register_index(reg_type, SLJIT_VR1);+sljit_s32 cmp1a_ind = sljit_get_register_index(reg_type, SLJIT_VR2);+sljit_s32 cmp2a_ind = sljit_get_register_index(reg_type, SLJIT_VR3);+sljit_s32 cmp1b_ind = sljit_get_register_index(reg_type, SLJIT_VR4);+sljit_s32 cmp2b_ind = sljit_get_register_index(reg_type, SLJIT_VR5);+sljit_s32 tmp1_ind = sljit_get_register_index(reg_type, SLJIT_VR6);+sljit_s32 tmp2_ind = sljit_get_register_index(reg_type, SLJIT_TMP_DEST_VREG); struct sljit_label *start; #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 struct sljit_label *restart;@@ -541,10 +563,10 @@ } 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);+sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR2, 0, TMP1, 0); if (char1a != char1b)- sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR4, 0, TMP2, 0);+ sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR4, 0, TMP2, 0); if (char2a == char2b) OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a));@@ -566,18 +588,18 @@ } } -sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR3, 0, TMP1, 0);+sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR3, 0, TMP1, 0); if (char2a != char2b)- sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR5, 0, TMP2, 0);+ sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR5, 0, TMP2, 0); -sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR2, SLJIT_FR2, 0);+sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR2, SLJIT_VR2, 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_VR4, SLJIT_VR4, 0); -sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR3, SLJIT_FR3, 0);+sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR3, SLJIT_VR3, 0); if (char2a != char2b)- sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR5, SLJIT_FR5, 0);+ sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR5, SLJIT_VR5, 0); #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 restart = LABEL();@@ -589,11 +611,11 @@ 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);+sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_VR0, 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);+sljit_emit_simd_mov(compiler, reg_type, SLJIT_VR1, SLJIT_MEM1(STR_PTR), -(sljit_sw)diff); jump[1] = JUMP(SLJIT_JUMP); JUMPHERE(jump[0]);@@ -668,8 +690,8 @@ 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);+sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | reg_type, SLJIT_VR0, SLJIT_VR0, SLJIT_VR1, 0);+sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_VR0, TMP1, 0); /* Ignore matches before the first STR_PTR. */ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);@@ -687,17 +709,17 @@ 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);+sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_VR0, SLJIT_MEM1(STR_PTR), 0);+sljit_emit_simd_mov(compiler, reg_type, SLJIT_VR1, 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);+ fast_forward_char_pair_sse2_compare(compiler, compare1_type, reg_type, i, data1_ind, cmp1a_ind, cmp1b_ind, tmp1_ind);+ fast_forward_char_pair_sse2_compare(compiler, compare2_type, reg_type, i, data2_ind, cmp2a_ind, cmp2b_ind, tmp2_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);+sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | reg_type, SLJIT_VR0, SLJIT_VR0, SLJIT_VR1, 0);+sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_VR0, TMP1, 0); CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start); @@ -744,367 +766,499 @@ #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;+#define PCRE2_REPLICATE_TYPE (SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_8) #elif PCRE2_CODE_UNIT_WIDTH == 16-return (*s & 0xfc00) == 0xdc00;+#define PCRE2_REPLICATE_TYPE (SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_16)+#elif PCRE2_CODE_UNIT_WIDTH == 32+#define PCRE2_REPLICATE_TYPE (SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32) #else-#error "Unknown code width"+#error "Unsupported unit width" #endif-}-#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */ +#define JIT_HAS_FAST_FORWARD_CHAR_SIMD 1++static void fast_forward_char_pair_sse2_compare(struct sljit_compiler *compiler, vector_compare_type compare_type,+ int step, sljit_u32 dst_ind, sljit_u32 cmp1_ind, sljit_u32 cmp2_ind, sljit_u32 tmp_ind)+{+sljit_u32 instruction; #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;+sljit_u32 size = 0 << 22; #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;+sljit_u32 size = 1 << 22;+#elif PCRE2_CODE_UNIT_WIDTH == 32+sljit_u32 size = 2 << 22; #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;+#error "Unsupported unit width" #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+SLJIT_ASSERT(step >= 0 && step <= 2); -#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+if (step == 1)+ {+ /* CMEQ */+ instruction = 0x6e208c00 | size | (cmp1_ind << 16) | (dst_ind << 5) | dst_ind;+ sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));+ return;+ } -#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+if (compare_type != vector_compare_match2)+ {+ if (step == 0 && compare_type == vector_compare_match1i)+ {+ /* ORR */+ instruction = 0x4ea01c00 | (cmp2_ind << 16) | (dst_ind << 5) | dst_ind;+ sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));+ }+ return;+ } -#define JIT_HAS_FAST_FORWARD_CHAR_SIMD 1+switch (step)+ {+ case 0:+ /* CMEQ */+ instruction = 0x6e208c00 | size | (cmp2_ind << 16) | (dst_ind << 5) | tmp_ind;+ sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));+ return; + case 2:+ /* ORR */+ instruction = 0x4ea01c00 | (tmp_ind << 16) | (dst_ind << 5) | dst_ind;+ sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));+ return;+ }+}+ 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);+sljit_u32 instruction;+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_u32 data_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR0);+sljit_u32 cmp1_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR1);+sljit_u32 cmp2_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR2);+sljit_u32 tmp_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR3);+sljit_u32 bit = 0;+int i; -/* 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);+SLJIT_UNUSED_ARG(offset); -if (char1 == char2)+if (char1 != char2) {- ic.c.c1 = char1;- ic.c.c2 = char2;- OP1(SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, ic.x);+ bit = char1 ^ char2;+ compare_type = vector_compare_match1i; -#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))+ if (!is_powerof2(bit)) {- 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+ bit = 0;+ compare_type = vector_compare_match2; }- else- {- ic.c.c1 = char1;- ic.c.c2 = char2;- OP1(SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, ic.x);+ } +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) */+if (char1 != char2)+ sljit_emit_op1(compiler, SLJIT_MOV, TMP2, 0, SLJIT_IMM, bit != 0 ? bit : char2);+sljit_emit_op1(compiler, SLJIT_MOV, TMP1, 0, SLJIT_IMM, char1 | bit);++if (char1 != char2)+ sljit_emit_simd_replicate(compiler, PCRE2_REPLICATE_TYPE, SLJIT_VR2, TMP2, 0);+sljit_emit_simd_replicate(compiler, PCRE2_REPLICATE_TYPE, SLJIT_VR1, TMP1, 0);++OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);+ #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));+restart = LABEL(); #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);+OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~(sljit_sw)0xf);+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);++sljit_emit_simd_mov(compiler, SLJIT_SIMD_REG_128 | SLJIT_SIMD_MEM_ALIGNED_128, SLJIT_VR0, SLJIT_MEM1(STR_PTR), 0);++for (i = 0; i < 3; i++)+ fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++/* SHRN */+instruction = 0x0f0c8400 | (data_ind << 5) | data_ind;+sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));++sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_64, SLJIT_VR0, 0, TMP1, 0);++OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, TMP2, 0);++quit = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 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);+ add_jump(compiler, &common->failed_match, partial_quit[1]); -/* Fast forward STR_PTR to the result of memchr. */-OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);+sljit_emit_simd_mov(compiler, SLJIT_SIMD_REG_128 | SLJIT_SIMD_MEM_ALIGNED_128, SLJIT_VR0, SLJIT_MEM1(STR_PTR), 0);+for (i = 0; i < 3; i++)+ fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++/* SHRN */+instruction = 0x0f0c8400 | (data_ind << 5) | data_ind;+sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));++sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_64, SLJIT_VR0, 0, TMP1, 0);+CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);++JUMPHERE(quit);++sljit_emit_op1(compiler, SLJIT_CTZ, TMP1, 0, TMP1, 0);+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 2);+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);+ if (common->mode != PCRE2_JIT_COMPLETE) {- quit = CMP(SLJIT_NOT_ZERO, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);- JUMPHERE(partial_quit);+ 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);- JUMPHERE(quit); }-}--typedef enum {- compare_match1,- compare_match1i,- compare_match2,-} compare_type;+else+ add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); -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)+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32+if (common->utf && offset > 0) {- vect_t tmp = dst;- dst = VCEQQ(dst, cmp1);- tmp = VCEQQ(tmp, cmp2);- dst = VORRQ(dst, tmp);- return dst;- }+ SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE); -if (ctype == compare_match1i)- dst = VORRQ(dst, cmp2);-dst = VCEQQ(dst, cmp1);-return dst;-}+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset)); -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"+ 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 } -/* ARM doesn't have a shift left across lanes. */-static SLJIT_INLINE vect_t shift_left_n_lanes(vect_t a, sljit_u8 n)+#define JIT_HAS_FAST_REQUESTED_CHAR_SIMD 1++static jump_list *fast_requested_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2) {-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)+DEFINE_COMPILER;+sljit_u32 instruction;+struct sljit_label *start;+struct sljit_jump *quit;+jump_list *not_found = NULL;+vector_compare_type compare_type = vector_compare_match1;+sljit_u32 data_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR0);+sljit_u32 cmp1_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR1);+sljit_u32 cmp2_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR2);+sljit_u32 tmp_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR3);+sljit_u32 bit = 0;+int i;++if (char1 != char2) {- 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;+ bit = char1 ^ char2;+ compare_type = vector_compare_match1i;++ if (!is_powerof2(bit))+ {+ bit = 0;+ compare_type = vector_compare_match2;+ } }-} -#define FFCPS-#define FFCPS_DIFF1-#define FFCPS_CHAR1A2A+add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0)); -#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+/* First part (unaligned start) */ -#undef FFCPS_CHAR1A2A+if (char1 != char2)+ sljit_emit_op1(compiler, SLJIT_MOV, TMP3, 0, SLJIT_IMM, bit != 0 ? bit : char2);+sljit_emit_op1(compiler, SLJIT_MOV, TMP2, 0, SLJIT_IMM, char1 | bit); -#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+if (char1 != char2)+ sljit_emit_simd_replicate(compiler, PCRE2_REPLICATE_TYPE, SLJIT_VR2, TMP3, 0);+sljit_emit_simd_replicate(compiler, PCRE2_REPLICATE_TYPE, SLJIT_VR1, TMP2, 0); -#undef FFCPS_DIFF1+OP2(SLJIT_AND, TMP3, 0, TMP1, 0, SLJIT_IMM, ~(sljit_sw)0xf);+OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xf); -#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+sljit_emit_simd_mov(compiler, SLJIT_SIMD_REG_128 | SLJIT_SIMD_MEM_ALIGNED_128, SLJIT_VR0, SLJIT_MEM1(TMP3), 0); +for (i = 0; i < 3; i++)+ fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++/* SHRN */+instruction = 0x0f0c8400 | (data_ind << 5) | data_ind;+sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));++sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_64, SLJIT_VR0, 0, TMP1, 0);++OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, TMP2, 0);++quit = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0);++/* Second part (aligned) */+start = LABEL();++OP2(SLJIT_ADD, TMP3, 0, TMP3, 0, SLJIT_IMM, 16);++add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP3, 0, STR_END, 0));++sljit_emit_simd_mov(compiler, SLJIT_SIMD_REG_128 | SLJIT_SIMD_MEM_ALIGNED_128, SLJIT_VR0, SLJIT_MEM1(TMP3), 0);++for (i = 0; i < 3; i++)+ fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);++/* SHRN */+instruction = 0x0f0c8400 | (data_ind << 5) | data_ind;+sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));++sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_64, SLJIT_VR0, 0, TMP1, 0);+CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);++JUMPHERE(quit);++sljit_emit_op1(compiler, SLJIT_CTZ, TMP1, 0, TMP1, 0);+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 2);+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP3, 0);+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_u32 instruction;+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);-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);+sljit_u32 data1_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR0);+sljit_u32 data2_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR1);+sljit_u32 cmp1a_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR2);+sljit_u32 cmp2a_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR3);+sljit_u32 cmp1b_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR4);+sljit_u32 cmp2b_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR5);+sljit_u32 tmp1_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR6);+sljit_u32 tmp2_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR7);+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; -/* Save temporary register STR_PTR. */-OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0);+SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE && offs1 > offs2 && offs2 >= 0);+SLJIT_ASSERT(diff <= (unsigned)IN_UCHARS(max_fast_forward_char_pair_offset())); -/* Prepare arguments for the function call. */-if (common->match_end_ptr == 0)- OP1(SLJIT_MOV, SLJIT_R0, 0, STR_END, 0);-else+if (char1a != char1b) {- 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));+ bit1 = char1a ^ char1b;+ compare1_type = vector_compare_match1i; - OP2U(SLJIT_SUB | SLJIT_SET_LESS, STR_END, 0, SLJIT_R0, 0);- SELECT(SLJIT_LESS, SLJIT_R0, STR_END, 0, SLJIT_R0);+ if (!is_powerof2(bit1))+ {+ bit1 = 0;+ compare1_type = vector_compare_match2;+ } } -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 (char2a != char2b)+ {+ bit2 = char2a ^ char2b;+ compare2_type = vector_compare_match1i; -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 (!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));++sljit_emit_op1(compiler, SLJIT_MOV, TMP1, 0, SLJIT_IMM, char1a | bit1);+sljit_emit_op1(compiler, SLJIT_MOV, TMP2, 0, SLJIT_IMM, char2a | bit2);+sljit_emit_simd_replicate(compiler, PCRE2_REPLICATE_TYPE, SLJIT_VR2, TMP1, 0);+sljit_emit_simd_replicate(compiler, PCRE2_REPLICATE_TYPE, SLJIT_VR3, TMP2, 0);++if (char1a != char1b)+ sljit_emit_op1(compiler, SLJIT_MOV, TMP1, 0, SLJIT_IMM, bit1 != 0 ? bit1 : char1b);++if (char2a != char2b)+ sljit_emit_op1(compiler, SLJIT_MOV, TMP2, 0, SLJIT_IMM, bit2 != 0 ? bit2 : char2b);++if (char1a != char1b)+ sljit_emit_simd_replicate(compiler, PCRE2_REPLICATE_TYPE, SLJIT_VR4, TMP1, 0);++if (char2a != char2b)+ sljit_emit_simd_replicate(compiler, PCRE2_REPLICATE_TYPE, SLJIT_VR5, TMP2, 0);+ #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+restart = LABEL(); #endif- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_1));++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, ~(sljit_sw)0xf);++sljit_emit_simd_mov(compiler, SLJIT_SIMD_REG_128 | SLJIT_SIMD_MEM_ALIGNED_128, SLJIT_VR0, SLJIT_MEM1(STR_PTR), 0);++jump[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_PTR, 0);++sljit_emit_simd_mov(compiler, SLJIT_SIMD_REG_128, SLJIT_VR1, SLJIT_MEM1(STR_PTR), -(sljit_sw)diff);+jump[1] = JUMP(SLJIT_JUMP);++JUMPHERE(jump[0]);++if (diff >= 8)+ {+ /* MOV (element) */+ instruction = 0x6e180400 | (data1_ind << 5) | data2_ind;+ sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));++ if (diff > 8)+ {+ /* SHL */+ instruction = 0x4f405400 | ((diff - 8) << 19) | (data2_ind << 5) | data2_ind;+ sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));+ } }-} else {+else+ {+ /* MOV (element) */+ instruction = 0x6e180400 | (data1_ind << 5) | tmp1_ind;+ sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));++ /* SHL */+ instruction = 0x4f405400 | (diff << 19) | (data1_ind << 5) | data2_ind;+ sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));++ /* USHR */+ instruction = 0x6f400400 | (diff << 19) | (tmp1_ind << 5) | tmp1_ind;+ sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));++ sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_OR | SLJIT_SIMD_REG_128, SLJIT_VR1, SLJIT_VR1, SLJIT_VR6, 0);+ }++JUMPHERE(jump[1]);++OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);++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);+ }++sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | SLJIT_SIMD_REG_128, SLJIT_VR0, SLJIT_VR0, SLJIT_VR1, 0);++/* SHRN */+instruction = 0x0f0c8400 | (data1_ind << 5) | data1_ind;+sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));++sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_64, SLJIT_VR0, 0, TMP1, 0);++/* Ignore matches before the first STR_PTR. */+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, TMP2, 0);++jump[0] = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 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));++sljit_emit_simd_mov(compiler, SLJIT_SIMD_REG_128 | SLJIT_SIMD_MEM_ALIGNED_128, SLJIT_VR0, SLJIT_MEM1(STR_PTR), 0);+sljit_emit_simd_mov(compiler, SLJIT_SIMD_REG_128, SLJIT_VR1, SLJIT_MEM1(STR_PTR), -(sljit_sw)diff);++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);+ }++sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | SLJIT_SIMD_REG_128, SLJIT_VR0, SLJIT_VR0, SLJIT_VR1, 0);++/* SHRN */+instruction = 0x0f0c8400 | (data1_ind << 5) | data1_ind;+sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));++sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_64, SLJIT_VR0, 0, TMP1, 0);++CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);++JUMPHERE(jump[0]);++sljit_emit_op1(compiler, SLJIT_CTZ, TMP1, 0, TMP1, 0);+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 2);+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)- 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));-}+if (common->utf)+ {+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offs1)); -/* Restore STR_PTR register. */-OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);+ jump[0] = jump_if_utf_char_start(compiler, TMP1); -/* Check return value. */-partial_quit = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);-add_jump(compiler, &common->failed_match, partial_quit);+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));+ CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, restart); -/* Fast forward STR_PTR to the result of memchr. */-OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);+ add_jump(compiler, &common->failed_match, JUMP(SLJIT_JUMP)); -JUMPHERE(partial_quit);+ 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); } +#undef PCRE2_REPLICATE_TYPE+ #endif /* SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64 */ #if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)@@ -1288,7 +1442,7 @@ #else /* PCRE2_CODE_UNIT_WIDTH == 32 */ -for (int i = 0; i < 2; i++)+for (i = 0; i < 2; i++) { replicate_imm_vector(compiler, i, cmp1_ind, char1 | bit, TMP1); @@ -1482,7 +1636,7 @@ #else /* PCRE2_CODE_UNIT_WIDTH == 32 */ -for (int i = 0; i < 2; i++)+for (i = 0; i < 2; i++) { replicate_imm_vector(compiler, i, cmp1_ind, char1 | bit, TMP3); @@ -1698,7 +1852,7 @@ #else /* PCRE2_CODE_UNIT_WIDTH == 32 */ -for (int i = 0; i < 2; i++)+for (i = 0; i < 2; i++) { replicate_imm_vector(compiler, i, cmp1a_ind, char1a | bit1, TMP1); @@ -1864,21 +2018,18 @@ #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 VREPLGR2VR_X 0x729f0000 #define VSEQ 0x70000000 #elif PCRE2_CODE_UNIT_WIDTH == 16-#define VREPLGR2VR 0x729f0400+#define VREPLGR2VR_X 0x729f0400 #define VSEQ 0x70008000 #else-#define VREPLGR2VR 0x729f0800+#define VREPLGR2VR_X 0x729f0800 #define VSEQ 0x70010000 #endif @@ -1955,14 +2106,14 @@ 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));+push_inst(compiler, VREPLGR2VR_X | 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));+ push_inst(compiler, VREPLGR2VR_X | VD(cmp2_ind) | RJ_V(tmp1_reg_ind)); } OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);@@ -2085,14 +2236,14 @@ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, char1 | bit); -/* VREPLGR2VR vd, rj */-push_inst(compiler, VREPLGR2VR | VD(cmp1_ind) | RJ_V(tmp1_reg_ind));+/* VREPLGR2VR.B/H/W vd, rj */+push_inst(compiler, VREPLGR2VR_X | 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));+ /* VREPLGR2VR.B/H/W vd, rj */+ push_inst(compiler, VREPLGR2VR_X | VD(cmp2_ind) | RJ_V(tmp1_reg_ind)); } OP1(SLJIT_MOV, STR_PTR, 0, TMP2, 0);@@ -2212,13 +2363,13 @@ } } -/* VREPLGR2VR vd, rj */-push_inst(compiler, VREPLGR2VR | VD(cmp1a_ind) | RJ_V(tmp1_reg_ind));+/* VREPLGR2VR.B/H/W vd, rj */+push_inst(compiler, VREPLGR2VR_X | 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));+ /* VREPLGR2VR.B/H/W vd, rj */+ push_inst(compiler, VREPLGR2VR_X | VD(cmp1b_ind) | RJ_V(tmp2_reg_ind)); } if (char2a == char2b)@@ -2241,13 +2392,13 @@ } } -/* VREPLGR2VR vd, rj */-push_inst(compiler, VREPLGR2VR | VD(cmp2a_ind) | RJ_V(tmp1_reg_ind));+/* VREPLGR2VR.B/H/W vd, rj */+push_inst(compiler, VREPLGR2VR_X | 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));+ /* VREPLGR2VR.B/H/W vd, rj */+ push_inst(compiler, VREPLGR2VR_X | VD(cmp2b_ind) | RJ_V(tmp2_reg_ind)); } #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
src/c/pcre2/src/pcre2_jit_test.c view
@@ -38,10 +38,14 @@ ----------------------------------------------------------------------------- */ -#ifdef HAVE_CONFIG_H++#if defined HAVE_CONFIG_H && !defined PCRE2_CONFIG_H_IDEMPOTENT_GUARD+#define PCRE2_CONFIG_H_IDEMPOTENT_GUARD #include "config.h" #endif ++ #include <stdio.h> #include <string.h> @@ -286,6 +290,7 @@ { CMU, A, 0, 0, "(a|b)?\?d((?:e)?)", "ABABdx" }, { MU, A, 0, 0, "(a|b)?\?d((?:e)?)", "abcde" }, { MU, A, 0, 0, "((?:ab)?\?g|b(?:g(nn|d)?\?)?)?\?(?:n)?m", "abgnbgnnbgdnmm" },+ { M, A, 0, 0, "(?:a?|a)b", "ba" }, /* Greedy and non-greedy + operators */ { MU, A, 0, 0, "(aa)+aa", "aaaaaaa" },@@ -360,6 +365,7 @@ { 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>" },+ { MU, A, 0, 0, "([a-z]{0,3}c;)+", "ccccc;c;cc;ccc;cccccccccccccccc;" }, /* Bracket repeats with limit. */ { MU, A, 0, 0, "(?:(ab){2}){5}M", "abababababababababababM" },@@ -426,6 +432,7 @@ { 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#" },+ { MUP, 0, 0, 0 | F_PROPERTY, "[\\x80-\\xff\\x{800}\\x{802}\\x{804}\\p{Cc}]", "\xdf\xbf\xe0\xa0\x80" }, /* Possible empty brackets. */ { MU, A, 0, 0, "(?:|ab||bc|a)+d", "abcxabcabd" },@@ -472,10 +479,17 @@ { MU, A, 0, 0, "\\R+", "ab\r\n\r" }, { MU, A, 0, 0, "\\R*", "ab\r\n\r" }, { MU, A, 0, 0, "\\R*", "\r\n\r" },+ { M, A, 0, 0, "\\R+\x85", "\r\n\n\r#\r\x85\n" }, { MU, A, 0, 0, "\\R{2,4}", "\r\nab\r\r" }, { MU, A, 0, 0, "\\R{2,4}", "\r\nab\n\n\n\r\r\r" }, { MU, A, 0, 0, "\\R{2,}", "\r\nab\n\n\n\r\r\r" }, { MU, A, 0, 0, "\\R{0,3}", "\r\n\r\n\r\n\r\n\r\n" },+ { MU, A, 0, 0, "\\R{2,4}\n", "\r\n\nab\r\r\nab\r\r\n\n" },+ { MU, A, 0, 0, "\\R{2,4}\n", "\r\n\nab\n\n\n\r\r\n" },+ { MU, A, 0, 0, "\\R{3,}\n", "\r\n\r\n\nab\n\n\n\r\r\n\n" },+ { MU, A, 0, 0, "\\R{0,3}\n", "\r\n\r\n\r\n\n" },+ { MU, A, 0, 0, "\\R{0,3}\n", "\r\n\r\n\r\n\r" },+ { MU, A, 0, 0, "(\\R{0,3}\n;)+", "\r\n\r\n\r\n\r\n\n;\n;\n\n;\n\n\n;\n\n\n\n\n;" }, { MU, A, 0, 0 | F_NOMATCH, "\\R+\\R\\R", "\r\n\r\n" }, { MU, A, 0, 0, "\\R+\\R\\R", "\r\r\r" }, { MU, A, 0, 0, "\\R*\\R\\R", "\n\r" },@@ -601,6 +615,7 @@ { 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_DUPNAMES, A, 0, 0, "^(?P<NAME>..)(?P<NAME>..)\\k<NAME>{2,4}", "AaAAAaAaAaaA" }, { MU | PCRE2_MATCH_UNSET_BACKREF, A, 0, 0, "(a)|\\1+c", "xxc" }, { MU | PCRE2_MATCH_UNSET_BACKREF, A, 0, 0, "\\1+?()", "" }, @@ -640,6 +655,7 @@ { MU, A, 0, 0, "a(?=)b", "ab" }, { MU, A, 0, 0 | F_NOMATCH, "a(?!)b", "ab" }, { MU, A, 0, 0, "(?(?<!|(|a)))", "a" },+ { MU, A, 0, 0, "(?=((?|(a)(.)|(b)(..)|(c)(...)))(?1(2,3))).x", "b12c123bx2c123" }, /* Not empty, ACCEPT, FAIL */ { MU, A, PCRE2_NOTEMPTY, 0 | F_NOMATCH, "a*", "bcx" },@@ -811,6 +827,8 @@ { MU, A, PCRE2_PARTIAL_SOFT, 0, "abc|(?<=xxa)bc", "xxab" }, { MU, A, PCRE2_PARTIAL_SOFT, 0, "a\\B", "a" }, { MU, A, PCRE2_PARTIAL_HARD, 0, "a\\b", "a" },+ { M | PCRE2_DUPNAMES, A, PCRE2_PARTIAL_HARD, 0, "^(?P<NAME>..)(?P<NAME>..)\\k<NAME>{2,4}", "AaAAAaAaAaA" },+ { M | PCRE2_DUPNAMES, A, PCRE2_PARTIAL_HARD, 0, "^(?P<NAME>..)(?P<NAME>..)\\k<NAME>{2,4}", "AaAAAaAaAaa" }, /* (*MARK) verb. */ { MU, A, 0, 0, "a(*MARK:aa)a", "ababaa" },
src/c/pcre2/src/pcre2_maketables.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-2020 University of Cambridge+ New API code Copyright (c) 2016-2024 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -45,13 +45,13 @@ pcre2_dftables.c as a freestanding program, in which case the macro PCRE2_DFTABLES is defined. */ + #ifndef PCRE2_DFTABLES /* Compiling the library */-# ifdef HAVE_CONFIG_H-# include "config.h"-# endif-# include "pcre2_internal.h"+#include "pcre2_internal.h" #endif ++ /************************************************* * Create PCRE2 character tables * *************************************************/@@ -64,14 +64,15 @@ freestanding auxiliary program) malloc() is used, and the function has a different name so as not to clash with the prototype in pcre2.h. -Arguments: none when PCRE2_DFTABLES is defined+Arguments: pointers to character-transforming functions when PCRE2_DFTABLES is+ defined; else a PCRE2 general context or NULL-Returns: pointer to the contiguous block of data+Returns: pointer to the contiguous block of data; else NULL if memory allocation failed */ #ifdef PCRE2_DFTABLES /* Included in freestanding pcre2_dftables program */-static const uint8_t *maketables(void)+static const uint8_t *maketables(int (*charfn_to)(int), int (*charfn_from)(int)) { uint8_t *yield = (uint8_t *)malloc(TABLES_LENGTH); @@ -82,6 +83,9 @@ uint8_t *yield = (uint8_t *)((gcontext != NULL)? gcontext->memctl.malloc(TABLES_LENGTH, gcontext->memctl.memory_data) : malloc(TABLES_LENGTH));++#define charfn_to(c) (c)+#define charfn_from(c) (c) #endif /* PCRE2_DFTABLES */ int i;@@ -92,13 +96,18 @@ /* First comes the lower casing table */ -for (i = 0; i < 256; i++) *p++ = tolower(i);+for (i = 0; i < 256; i++)+ {+ int c = charfn_from(tolower(charfn_to(i)));+ *p++ = (c < 256)? c : i;+ } /* Next the case-flipping table */ for (i = 0; i < 256; i++) {- int c = islower(i)? toupper(i) : tolower(i);+ int c = charfn_from(islower(charfn_to(i))? toupper(charfn_to(i))+ : tolower(charfn_to(i))); *p++ = (c < 256)? c : i; } @@ -118,17 +127,17 @@ memset(p, 0, cbit_length); for (i = 0; i < 256; i++) {- if (isdigit(i)) p[cbit_digit + i/8] |= 1u << (i&7);- if (isupper(i)) p[cbit_upper + i/8] |= 1u << (i&7);- if (islower(i)) p[cbit_lower + i/8] |= 1u << (i&7);- if (isalnum(i)) p[cbit_word + i/8] |= 1u << (i&7);- if (i == '_') p[cbit_word + i/8] |= 1u << (i&7);- if (isspace(i)) p[cbit_space + i/8] |= 1u << (i&7);- if (isxdigit(i)) p[cbit_xdigit + i/8] |= 1u << (i&7);- if (isgraph(i)) p[cbit_graph + i/8] |= 1u << (i&7);- if (isprint(i)) p[cbit_print + i/8] |= 1u << (i&7);- if (ispunct(i)) p[cbit_punct + i/8] |= 1u << (i&7);- if (iscntrl(i)) p[cbit_cntrl + i/8] |= 1u << (i&7);+ if (isdigit(charfn_to(i))) p[cbit_digit + i/8] |= 1u << (i&7);+ if (isupper(charfn_to(i))) p[cbit_upper + i/8] |= 1u << (i&7);+ if (islower(charfn_to(i))) p[cbit_lower + i/8] |= 1u << (i&7);+ if (isalnum(charfn_to(i))) p[cbit_word + i/8] |= 1u << (i&7);+ if (i == CHAR_UNDERSCORE) p[cbit_word + i/8] |= 1u << (i&7);+ if (isspace(charfn_to(i))) p[cbit_space + i/8] |= 1u << (i&7);+ if (isxdigit(charfn_to(i))) p[cbit_xdigit + i/8] |= 1u << (i&7);+ if (isgraph(charfn_to(i))) p[cbit_graph + i/8] |= 1u << (i&7);+ if (isprint(charfn_to(i))) p[cbit_print + i/8] |= 1u << (i&7);+ if (ispunct(charfn_to(i))) p[cbit_punct + i/8] |= 1u << (i&7);+ if (iscntrl(charfn_to(i))) p[cbit_cntrl + i/8] |= 1u << (i&7); } p += cbit_length; @@ -140,11 +149,11 @@ for (i = 0; i < 256; i++) { int x = 0;- if (isspace(i)) x += ctype_space;- if (isalpha(i)) x += ctype_letter;- if (islower(i)) x += ctype_lcletter;- if (isdigit(i)) x += ctype_digit;- if (isalnum(i) || i == '_') x += ctype_word;+ if (isspace(charfn_to(i))) x += ctype_space;+ if (isalpha(charfn_to(i))) x += ctype_letter;+ if (islower(charfn_to(i))) x += ctype_lcletter;+ if (isdigit(charfn_to(i))) x += ctype_digit;+ if (isalnum(charfn_to(i)) || i == CHAR_UNDERSCORE) x += ctype_word; *p++ = x; } @@ -152,13 +161,16 @@ } #ifndef PCRE2_DFTABLES /* Compiling the library */+#undef charfn_to+#undef charfn_from+ PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION pcre2_maketables_free(pcre2_general_context *gcontext, const uint8_t *tables) {- if (gcontext)- gcontext->memctl.free((void *)tables, gcontext->memctl.memory_data);- else- free((void *)tables);+if (gcontext != NULL)+ gcontext->memctl.free((void *)tables, gcontext->memctl.memory_data);+else+ free((void *)tables); } #endif
src/c/pcre2/src/pcre2_match.c view
@@ -39,12 +39,10 @@ */ -#ifdef HAVE_CONFIG_H-#include "config.h"-#endif- #include "pcre2_internal.h" ++ /* These defines enable debugging code */ /* #define DEBUG_FRAMES_DISPLAY */@@ -155,17 +153,17 @@ 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, RM37 };+ RM31, RM32, RM33, RM34, RM35, RM36, RM37, RM38, RM39 }; #ifdef SUPPORT_WIDE_CHARS-enum { RM100=100, RM101 };+enum { RM100=100, RM101, RM102, RM103 }; #endif #ifdef SUPPORT_UNICODE enum { RM200=200, RM201, RM202, RM203, RM204, RM205, RM206, RM207, RM208, RM209, RM210, RM211, RM212, RM213, RM214, RM215, RM216, RM217, RM218, RM219, RM220, RM221, RM222, RM223,- RM224, RM225 };+ RM224 }; #endif /* Define short names for general fields in the current backtrack frame, which@@ -348,6 +346,7 @@ Arguments: offset index into the offset vector caseless TRUE if caseless+ caseopts bitmask of REFI_FLAG_XYZ values F the current backtracking frame pointer mb points to match block lengthptr pointer for returning the length matched@@ -358,14 +357,18 @@ */ static int-match_ref(PCRE2_SIZE offset, BOOL caseless, heapframe *F, match_block *mb,- PCRE2_SIZE *lengthptr)+match_ref(PCRE2_SIZE offset, BOOL caseless, int caseopts, heapframe *F,+ match_block *mb, PCRE2_SIZE *lengthptr) { PCRE2_SPTR p; PCRE2_SIZE length; PCRE2_SPTR eptr; PCRE2_SPTR eptr_start; +#ifndef SUPPORT_UNICODE+(void)caseopts; /* Avoid compiler warning. */+#endif+ /* Deal with an unset group. The default is no match, but there is an option to match an empty string. */ @@ -384,11 +387,14 @@ eptr = eptr_start = Feptr; p = mb->start_subject + Fovector[offset]; length = Fovector[offset+1] - Fovector[offset];+PCRE2_ASSERT(eptr <= mb->end_subject); if (caseless) { #if defined SUPPORT_UNICODE BOOL utf = (mb->poptions & PCRE2_UTF) != 0;+ BOOL caseless_restrict = (caseopts & REFI_FLAG_CASELESS_RESTRICT) != 0;+ BOOL turkish_casing = !caseless_restrict && (caseopts & REFI_FLAG_TURKISH_CASING) != 0; if (utf || (mb->poptions & PCRE2_UCP) != 0) {@@ -401,7 +407,7 @@ bytes in UTF-8); a sequence of 3 of the former uses 6 bytes, as does a sequence of two of the latter. It is important, therefore, to check the length along the reference, not along the subject (earlier code did this- wrong). UCP without uses Unicode properties but without UTF encoding. */+ wrong). UCP uses Unicode properties but without UTF encoding. */ while (p < endptr) {@@ -420,10 +426,20 @@ d = *p++; } - ur = GET_UCD(d);- if (c != d && c != (uint32_t)((int)d + ur->other_case))+ if (turkish_casing && UCD_ANY_I(d)) {+ c = UCD_FOLD_I_TURKISH(c);+ d = UCD_FOLD_I_TURKISH(d);+ if (c != d) return -1; /* No match */+ }+ else if (c != d && c != (uint32_t)((int)d + (ur = GET_UCD(d))->other_case))+ { const uint32_t *pp = PRIV(ucd_caseless_sets) + ur->caseset;++ /* When PCRE2_EXTRA_CASELESS_RESTRICT is set, ignore any caseless sets+ that start with an ASCII character. */+ if (caseless_restrict && *pp < 128) return -1; /* No match */+ for (;;) { if (c < *pp) return -1; /* No match */@@ -470,8 +486,8 @@ else {- if ((PCRE2_SIZE)(mb->end_subject - eptr) < length) return 1; /* Partial */- if (memcmp(p, eptr, CU2BYTES(length)) != 0) return -1; /* No match */+ if ((PCRE2_SIZE)(mb->end_subject - eptr) < length ||+ memcmp(p, eptr, CU2BYTES(length)) != 0) return -1; /* No match */ eptr += length; } }@@ -482,6 +498,75 @@ +/*************************************************+* Restore offsets after a recurse *+*************************************************/++/* This function restores the ovector values when+a recursive block reaches its end, and the triggering+recurse has and argument list.++Arguments:+ F the current backtracking frame pointer+ P the previous backtracking frame pointer+*/++static void+recurse_update_offsets(heapframe *F, heapframe *P)+{+PCRE2_SIZE *dst = F->ovector;+PCRE2_SIZE *src = P->ovector;+/* The first bracket has offset 2, because+offset 0 is reserved for the full match. */+PCRE2_SIZE offset = 2;+PCRE2_SIZE offset_top = Foffset_top + 2;+PCRE2_SIZE diff;+PCRE2_SPTR ecode = Fecode;++do+ {+ diff = (GET2(ecode, 1) << 1) - offset;+ ecode += 1 + IMM2_SIZE;++ if (offset + diff >= offset_top)+ {+ /* Some OP_CREF opcodes are not+ processed, they must be skipped. */+ while (*ecode == OP_CREF) ecode += 1 + IMM2_SIZE;+ break;+ }++ if (diff == 2)+ {+ dst[0] = src[0];+ dst[1] = src[1];+ }+ else if (diff >= 4)+ memcpy(dst, src, diff * sizeof(PCRE2_SIZE));++ /* Skip the unmodified entry. */+ diff += 2;+ offset += diff;+ dst += diff;+ src += diff;+ }+while (*ecode == OP_CREF);++diff = offset_top - offset;+if (diff == 2)+ {+ dst[0] = src[0];+ dst[1] = src[1];+ }+else if (diff >= 4)+ memcpy(dst, src, diff * sizeof(PCRE2_SIZE));++Fecode = ecode;+Foffset_top = (offset <= P->offset_top) ? P->offset_top : (offset - 2);+}+++ /****************************************************************************** ******************************************************************************* "Recursion" in the match() function@@ -528,38 +613,46 @@ carrying on means that a complete match on the current subject will be sought. A partial match is returned only if no complete match can be found. */ -#define CHECK_PARTIAL()\- if (Feptr >= mb->end_subject) \- { \- SCHECK_PARTIAL(); \- }+#define CHECK_PARTIAL() \+ do { \+ if (Feptr >= mb->end_subject) \+ { \+ SCHECK_PARTIAL(); \+ } \+ } \+ while (0) -#define SCHECK_PARTIAL()\- if (mb->partial != 0 && \- (Feptr > mb->start_used_ptr || mb->allowemptypartial)) \- { \- mb->hitend = TRUE; \- if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; \- }+#define SCHECK_PARTIAL() \+ do { \+ if (mb->partial != 0 && \+ (Feptr > mb->start_used_ptr || mb->allowemptypartial)) \+ { \+ mb->hitend = TRUE; \+ if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; \+ } \+ } \+ while (0) /* These macros are used to implement backtracking. They simulate a recursive call to the match() function by means of a local vector of frames which remember the backtracking points. */ -#define RMATCH(ra,rb)\- {\- start_ecode = ra;\- Freturn_id = rb;\- goto MATCH_RECURSE;\- L_##rb:;\- }+#define RMATCH(ra,rb) \+ do { \+ start_ecode = ra; \+ Freturn_id = rb; \+ goto MATCH_RECURSE; \+ L_##rb:; \+ } \+ while (0) -#define RRETURN(ra)\- {\- rrc = ra;\- goto RETURN_SWITCH;\- }+#define RRETURN(ra) \+ do { \+ rrc = ra; \+ goto RETURN_SWITCH; \+ } \+ while (0) @@ -813,7 +906,10 @@ offset = Flast_group_offset; for(;;) {+ /* Corrupted heapframes?. Trigger an assert and return an error */+ PCRE2_ASSERT(offset != PCRE2_UNSET); if (offset == PCRE2_UNSET) return PCRE2_ERROR_INTERNAL;+ N = (heapframe *)((char *)match_data->heapframes + offset); P = (heapframe *)((char *)N - frame_size); if (N->group_frame_type == (GF_CAPTURE | number)) break;@@ -852,7 +948,10 @@ offset = Flast_group_offset; for(;;) {+ /* Corrupted heapframes?. Trigger an assert and return an error */+ PCRE2_ASSERT(offset != PCRE2_UNSET); if (offset == PCRE2_UNSET) return PCRE2_ERROR_INTERNAL;+ N = (heapframe *)((char *)match_data->heapframes + offset); P = (heapframe *)((char *)N - frame_size); if (GF_IDMASK(N->group_frame_type) == GF_RECURSE) break;@@ -871,7 +970,7 @@ Fecode += 1 + LINK_SIZE; continue; }- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ /* 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. */@@ -911,11 +1010,28 @@ } #ifdef DEBUG_SHOW_OPS- fprintf(stderr, "++ Failed ACCEPT not at end (endanchnored set)\n");+ fprintf(stderr, "++ Failed ACCEPT not at end (endanchored set)\n"); #endif return MATCH_NOMATCH; /* (*ACCEPT) */ } + /* Fail if we detect that the start position was moved to be either after+ the end position (\K in lookahead) or before the start offset (\K in+ lookbehind). If this occurs, the pattern must have used \K in a somewhat+ sneaky way (e.g. by pattern recursion), because if the \K is actually+ syntactically inside the lookaround, it's blocked at compile-time. */++ if (Fstart_match < mb->start_subject + mb->start_offset ||+ Fstart_match > Feptr)+ {+ /* The \K expression is fairly rare. We assert it was used so that we+ catch any unexpected invalid data in start_match. */+ PCRE2_ASSERT(mb->hasbsk);++ if (!mb->allowlookaroundbsk)+ return PCRE2_ERROR_BAD_BACKSLASH_K;+ }+ /* We have a successful match of the whole pattern. Record the result and then do a direct return from the function. If there is space in the offset vector, set any pairs that follow the highest-numbered captured string but@@ -955,7 +1071,7 @@ mb->hitend = TRUE; if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; }- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ /* Match any single character whatsoever. */ @@ -1329,7 +1445,7 @@ RRETURN(MATCH_NOMATCH); } }- /* Control never gets here */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ } else /* Maximize */@@ -1430,7 +1546,7 @@ if (Lc != cc && Loc != cc) RRETURN(MATCH_NOMATCH); Feptr++; }- /* Control never gets here */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ } else /* Maximize */@@ -1488,7 +1604,7 @@ } if (Lc != UCHAR21INCTEST(Feptr)) RRETURN(MATCH_NOMATCH); }- /* Control never gets here */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ } else /* Maximize */ {@@ -1706,7 +1822,7 @@ Feptr++; } }- /* Control never gets here */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ } /* Maximize case */@@ -1844,7 +1960,7 @@ if (Lc == *Feptr++) RRETURN(MATCH_NOMATCH); } }- /* Control never gets here */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ } /* Maximize case */@@ -1928,7 +2044,7 @@ #define Lmax F->temp_32[1] #define Lstart_eptr F->temp_sptr[0] #define Lbyte_map_address F->temp_sptr[1]-#define Lbyte_map ((unsigned char *)Lbyte_map_address)+#define Lbyte_map ((const unsigned char *)Lbyte_map_address) case OP_NCLASS: case OP_CLASS:@@ -2071,7 +2187,7 @@ if ((Lbyte_map[fc/8] & (1u << (fc&7))) == 0) RRETURN(MATCH_NOMATCH); } }- /* Control never gets here */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ } /* If maximizing, find the longest possible run, then work backwards. */@@ -2151,8 +2267,9 @@ RRETURN(MATCH_NOMATCH); } }- /* Control never gets here */ + PCRE2_UNREACHABLE(); /* Control never reaches here */+ #undef Lbyte_map_address #undef Lbyte_map #undef Lstart_eptr@@ -2219,7 +2336,9 @@ RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(fc, Feptr);- if (!PRIV(xclass)(fc, Lxclass_data, utf)) RRETURN(MATCH_NOMATCH);+ if (!PRIV(xclass)(fc, Lxclass_data,+ (const uint8_t*)mb->start_code, utf))+ RRETURN(MATCH_NOMATCH); } /* If Lmax == Lmin we can just continue with the main loop. */@@ -2242,9 +2361,11 @@ RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(fc, Feptr);- if (!PRIV(xclass)(fc, Lxclass_data, utf)) RRETURN(MATCH_NOMATCH);+ if (!PRIV(xclass)(fc, Lxclass_data,+ (const uint8_t*)mb->start_code, utf))+ RRETURN(MATCH_NOMATCH); }- /* Control never gets here */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ } /* If maximizing, find the longest possible run, then work backwards. */@@ -2265,7 +2386,8 @@ #else fc = *Feptr; #endif- if (!PRIV(xclass)(fc, Lxclass_data, utf)) break;+ if (!PRIV(xclass)(fc, Lxclass_data,+ (const uint8_t*)mb->start_code, utf)) break; Feptr += len; } @@ -2287,7 +2409,7 @@ RRETURN(MATCH_NOMATCH); } - /* Control never gets here */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ } #endif /* SUPPORT_WIDE_CHARS: end of XCLASS */ @@ -2298,6 +2420,151 @@ /* ===================================================================== */+ /* Match a complex, set-based character class. This opcodes are used when+ there is complex nesting or logical operations within the character+ class. */++#define Lstart_eptr F->temp_sptr[0]+#define Leclass_data F->temp_sptr[1]+#define Leclass_len F->temp_size+#define Lmin F->temp_32[0]+#define Lmax F->temp_32[1]++#ifdef SUPPORT_WIDE_CHARS+ case OP_ECLASS:+ {+ Leclass_data = Fecode + 1 + LINK_SIZE; /* Save for matching */+ Fecode += GET(Fecode, 1); /* Advance past the item */+ Leclass_len = (PCRE2_SIZE)(Fecode - Leclass_data);++ switch (*Fecode)+ {+ 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:+ fc = *Fecode++ - OP_CRSTAR;+ Lmin = rep_min[fc];+ Lmax = rep_max[fc];+ reptype = rep_typ[fc];+ break;++ case OP_CRRANGE:+ case OP_CRMINRANGE:+ case OP_CRPOSRANGE:+ Lmin = GET2(Fecode, 1);+ Lmax = GET2(Fecode, 1 + IMM2_SIZE);+ if (Lmax == 0) Lmax = UINT32_MAX; /* Max 0 => infinity */+ reptype = rep_typ[*Fecode - OP_CRSTAR];+ Fecode += 1 + 2 * IMM2_SIZE;+ break;++ default: /* No repeat follows */+ Lmin = Lmax = 1;+ break;+ }++ /* First, ensure the minimum number of matches are present. */++ for (i = 1; i <= Lmin; i++)+ {+ if (Feptr >= mb->end_subject)+ {+ SCHECK_PARTIAL();+ RRETURN(MATCH_NOMATCH);+ }+ GETCHARINCTEST(fc, Feptr);+ if (!PRIV(eclass)(fc, Leclass_data, Leclass_data + Leclass_len,+ (const uint8_t*)mb->start_code, utf))+ RRETURN(MATCH_NOMATCH);+ }++ /* If Lmax == Lmin we can just continue with the main loop. */++ if (Lmin == Lmax) continue;++ /* If minimizing, keep testing the rest of the expression and advancing+ the pointer while it matches the class. */++ if (reptype == REPTYPE_MIN)+ {+ for (;;)+ {+ RMATCH(Fecode, RM102);+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);+ if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);+ if (Feptr >= mb->end_subject)+ {+ SCHECK_PARTIAL();+ RRETURN(MATCH_NOMATCH);+ }+ GETCHARINCTEST(fc, Feptr);+ if (!PRIV(eclass)(fc, Leclass_data, Leclass_data + Leclass_len,+ (const uint8_t*)mb->start_code, utf))+ RRETURN(MATCH_NOMATCH);+ }+ PCRE2_UNREACHABLE(); /* Control never reaches here */+ }++ /* If maximizing, find the longest possible run, then work backwards. */++ else+ {+ Lstart_eptr = Feptr;+ for (i = Lmin; i < Lmax; i++)+ {+ int len = 1;+ if (Feptr >= mb->end_subject)+ {+ SCHECK_PARTIAL();+ break;+ }+#ifdef SUPPORT_UNICODE+ GETCHARLENTEST(fc, Feptr, len);+#else+ fc = *Feptr;+#endif+ if (!PRIV(eclass)(fc, Leclass_data, Leclass_data + Leclass_len,+ (const uint8_t*)mb->start_code, utf))+ break;+ Feptr += len;+ }++ if (reptype == REPTYPE_POS) continue; /* No backtracking */++ /* After \C in UTF mode, Lstart_eptr might be in the middle of a+ Unicode character. Use <= Lstart_eptr to ensure backtracking doesn't+ go too far. */++ for(;;)+ {+ RMATCH(Fecode, RM103);+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);+ if (Feptr-- <= Lstart_eptr) break; /* Tried at original position */+#ifdef SUPPORT_UNICODE+ if (utf) BACKCHAR(Feptr);+#endif+ }+ RRETURN(MATCH_NOMATCH);+ }++ PCRE2_UNREACHABLE(); /* Control never reaches here */+ }+#endif /* SUPPORT_WIDE_CHARS: end of ECLASS */++#undef Lstart_eptr+#undef Leclass_data+#undef Leclass_len+#undef Lmin+#undef Lmax+++ /* ===================================================================== */ /* Match various character types when PCRE2_UCP is not set. These opcodes are not generated when PCRE2_UCP is set - instead appropriate property tests are compiled. */@@ -2492,10 +2759,6 @@ switch(Fecode[1]) {- case PT_ANY:- if (notmatch) RRETURN(MATCH_NOMATCH);- break;- case PT_LAMP: chartype = prop->chartype; if ((chartype == ucp_Lu ||@@ -2605,8 +2868,11 @@ /* This should never occur */ + /* LCOV_EXCL_START */ default:+ PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL;+ /* LCOV_EXCL_STOP */ } Fecode += 3;@@ -2728,19 +2994,6 @@ BOOL notmatch = Lctype == OP_NOTPROP; switch(proptype) {- case PT_ANY:- if (notmatch) RRETURN(MATCH_NOMATCH);- for (i = 1; i <= Lmin; i++)- {- if (Feptr >= mb->end_subject)- {- SCHECK_PARTIAL();- RRETURN(MATCH_NOMATCH);- }- GETCHARINCTEST(fc, Feptr);- }- break;- case PT_LAMP: for (i = 1; i <= Lmin; i++) {@@ -2968,8 +3221,11 @@ /* This should not occur */ + /* LCOV_EXCL_START */ default:+ PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL;+ /* LCOV_EXCL_STOP */ } } @@ -3243,8 +3499,11 @@ } break; + /* LCOV_EXCL_START */ default:+ PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL;+ /* LCOV_EXCL_STOP */ } /* End switch(Lctype) */ else@@ -3495,8 +3754,11 @@ } break; + /* LCOV_EXCL_START */ default:+ PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL;+ /* LCOV_EXCL_STOP */ } } @@ -3516,27 +3778,11 @@ { switch(proptype) {- case PT_ANY:- for (;;)- {- RMATCH(Fecode, RM208);- if (rrc != MATCH_NOMATCH) RRETURN(rrc);- if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);- if (Feptr >= mb->end_subject)- {- SCHECK_PARTIAL();- RRETURN(MATCH_NOMATCH);- }- GETCHARINCTEST(fc, Feptr);- if (Lctype == OP_NOTPROP) RRETURN(MATCH_NOMATCH);- }- /* Control never gets here */- case PT_LAMP: for (;;) { int chartype;- RMATCH(Fecode, RM209);+ RMATCH(Fecode, RM208); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject)@@ -3551,12 +3797,12 @@ chartype == ucp_Lt) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); }- /* Control never gets here */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ case PT_GC: for (;;) {- RMATCH(Fecode, RM210);+ RMATCH(Fecode, RM209); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject)@@ -3568,12 +3814,12 @@ if ((UCD_CATEGORY(fc) == Lpropvalue) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); }- /* Control never gets here */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ case PT_PC: for (;;) {- RMATCH(Fecode, RM211);+ RMATCH(Fecode, RM210); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject)@@ -3585,12 +3831,12 @@ if ((UCD_CHARTYPE(fc) == Lpropvalue) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); }- /* Control never gets here */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ case PT_SC: for (;;) {- RMATCH(Fecode, RM212);+ RMATCH(Fecode, RM211); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject)@@ -3602,14 +3848,14 @@ if ((UCD_SCRIPT(fc) == Lpropvalue) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); }- /* Control never gets here */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ case PT_SCX: for (;;) { BOOL ok; const ucd_record *prop;- RMATCH(Fecode, RM225);+ RMATCH(Fecode, RM224); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject)@@ -3624,13 +3870,13 @@ if (ok == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); }- /* Control never gets here */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ case PT_ALNUM: for (;;) { int category;- RMATCH(Fecode, RM213);+ RMATCH(Fecode, RM212); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject)@@ -3643,7 +3889,7 @@ if ((category == ucp_L || category == ucp_N) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); }- /* Control never gets here */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ /* Perl space used to exclude VT, but from Perl 5.18 it is included, which means that Perl space and POSIX space are now identical. PCRE@@ -3653,7 +3899,7 @@ case PT_PXSPACE: /* POSIX space */ for (;;) {- RMATCH(Fecode, RM214);+ RMATCH(Fecode, RM213); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject)@@ -3675,13 +3921,13 @@ break; } }- /* Control never gets here */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ case PT_WORD: for (;;) { int chartype, category;- RMATCH(Fecode, RM215);+ RMATCH(Fecode, RM214); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject)@@ -3698,13 +3944,13 @@ chartype == ucp_Pc) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); }- /* Control never gets here */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ case PT_CLIST: for (;;) { const uint32_t *cp;- RMATCH(Fecode, RM216);+ RMATCH(Fecode, RM215); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject)@@ -3735,12 +3981,12 @@ } } }- /* Control never gets here */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ case PT_UCNC: for (;;) {- RMATCH(Fecode, RM217);+ RMATCH(Fecode, RM216); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject)@@ -3754,12 +4000,12 @@ fc >= 0xe000) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); }- /* Control never gets here */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ case PT_BIDICL: for (;;) {- RMATCH(Fecode, RM224);+ RMATCH(Fecode, RM223); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject)@@ -3771,14 +4017,14 @@ if ((UCD_BIDICLASS(fc) == Lpropvalue) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); }- /* Control never gets here */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ case PT_BOOL: for (;;) { BOOL ok; const ucd_record *prop;- RMATCH(Fecode, RM223);+ RMATCH(Fecode, RM222); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject)@@ -3793,11 +4039,15 @@ if (ok == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); }- /* Control never gets here */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ /* This should never occur */++ /* LCOV_EXCL_START */ default:+ PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL;+ /* LCOV_EXCL_STOP */ } } @@ -3808,7 +4058,7 @@ { for (;;) {- RMATCH(Fecode, RM218);+ RMATCH(Fecode, RM217); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject)@@ -3835,7 +4085,7 @@ { for (;;) {- RMATCH(Fecode, RM219);+ RMATCH(Fecode, RM218); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); if (Feptr >= mb->end_subject)@@ -3950,8 +4200,11 @@ RRETURN(MATCH_NOMATCH); break; + /* LCOV_EXCL_START */ default:+ PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL;+ /* LCOV_EXCL_STOP */ } } }@@ -4094,12 +4347,16 @@ RRETURN(MATCH_NOMATCH); break; + /* LCOV_EXCL_START */ default:+ PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL;+ /* LCOV_EXCL_STOP */ } } }- /* Control never gets here */++ PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */ } /* If maximizing, it is worth using inline code for speed, doing the type@@ -4117,21 +4374,6 @@ BOOL notmatch = Lctype == OP_NOTPROP; switch(proptype) {- case PT_ANY:- for (i = Lmin; i < Lmax; i++)- {- int len = 1;- if (Feptr >= mb->end_subject)- {- SCHECK_PARTIAL();- break;- }- GETCHARLENTEST(fc, Feptr, len);- if (notmatch) break;- Feptr+= len;- }- break;- case PT_LAMP: for (i = Lmin; i < Lmax; i++) {@@ -4376,8 +4618,11 @@ } break; + /* LCOV_EXCL_START */ default:+ PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL;+ /* LCOV_EXCL_STOP */ } /* Feptr is now past the end of the maximum run */@@ -4391,7 +4636,7 @@ for(;;) { if (Feptr <= Lstart_eptr) break;- RMATCH(Fecode, RM222);+ RMATCH(Fecode, RM221); if (rrc != MATCH_NOMATCH) RRETURN(rrc); Feptr--; if (utf) BACKCHAR(Feptr);@@ -4434,7 +4679,7 @@ PCRE2_SPTR fptr; if (Feptr <= Lstart_eptr) break; /* At start of char run */- RMATCH(Fecode, RM220);+ RMATCH(Fecode, RM219); if (rrc != MATCH_NOMATCH) RRETURN(rrc); /* Backtracking over an extended grapheme cluster involves inspecting@@ -4694,8 +4939,11 @@ } break; + /* LCOV_EXCL_START */ default:+ PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL;+ /* LCOV_EXCL_STOP */ } if (reptype == REPTYPE_POS) continue; /* No backtracking */@@ -4707,7 +4955,7 @@ for(;;) { if (Feptr <= Lstart_eptr) break;- RMATCH(Fecode, RM221);+ RMATCH(Fecode, RM220); if (rrc != MATCH_NOMATCH) RRETURN(rrc); Feptr--; BACKCHAR(Feptr);@@ -4951,8 +5199,11 @@ } break; + /* LCOV_EXCL_START */ default:+ PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL;+ /* LCOV_EXCL_STOP */ } if (reptype == REPTYPE_POS) continue; /* No backtracking */@@ -4988,16 +5239,18 @@ #define Lmin F->temp_32[0] #define Lmax F->temp_32[1] #define Lcaseless F->temp_32[2]+#define Lcaseopts F->temp_32[3] #define Lstart F->temp_sptr[0] #define Loffset F->temp_size case OP_DNREF: case OP_DNREFI: Lcaseless = (Fop == OP_DNREFI);+ Lcaseopts = (Fop == OP_DNREFI)? Fecode[1 + 2*IMM2_SIZE] : 0; { int count = GET2(Fecode, 1+IMM2_SIZE); PCRE2_SPTR slot = mb->name_table + GET2(Fecode, 1) * mb->name_entry_size;- Fecode += 1 + 2*IMM2_SIZE;+ Fecode += 1 + 2*IMM2_SIZE + (Fop == OP_DNREFI? 1 : 0); while (count-- > 0) {@@ -5011,8 +5264,9 @@ case OP_REF: case OP_REFI: Lcaseless = (Fop == OP_REFI);+ Lcaseopts = (Fop == OP_REFI)? Fecode[1 + IMM2_SIZE] : 0; Loffset = (GET2(Fecode, 1) << 1) - 2;- Fecode += 1 + IMM2_SIZE;+ Fecode += 1 + IMM2_SIZE + (Fop == OP_REFI? 1 : 0); /* Set up for repetition, or handle the non-repeated case. The maximum and minimum must be in the heap frame, but as they are short-term values, we@@ -5044,7 +5298,7 @@ default: /* No repeat follows */ {- rrc = match_ref(Loffset, Lcaseless, F, mb, &length);+ rrc = match_ref(Loffset, Lcaseless, Lcaseopts, F, mb, &length); if (rrc != 0) { if (rrc > 0) Feptr = mb->end_subject; /* Partial match */@@ -5078,7 +5332,7 @@ for (i = 1; i <= Lmin; i++) { PCRE2_SIZE slength;- rrc = match_ref(Loffset, Lcaseless, F, mb, &slength);+ rrc = match_ref(Loffset, Lcaseless, Lcaseopts, F, mb, &slength); if (rrc != 0) { if (rrc > 0) Feptr = mb->end_subject; /* Partial match */@@ -5102,7 +5356,7 @@ RMATCH(Fecode, RM20); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);- rrc = match_ref(Loffset, Lcaseless, F, mb, &slength);+ rrc = match_ref(Loffset, Lcaseless, Lcaseopts, F, mb, &slength); if (rrc != 0) { if (rrc > 0) Feptr = mb->end_subject; /* Partial match */@@ -5111,7 +5365,8 @@ } Feptr += slength; }- /* Control never gets here */++ PCRE2_UNREACHABLE(); /* Control never reaches here */ } /* If maximizing, find the longest string and work backwards, as long as@@ -5126,7 +5381,7 @@ for (i = Lmin; i < Lmax; i++) { PCRE2_SIZE slength;- rrc = match_ref(Loffset, Lcaseless, F, mb, &slength);+ rrc = match_ref(Loffset, Lcaseless, Lcaseopts, F, mb, &slength); if (rrc != 0) { /* Can't use CHECK_PARTIAL because we don't want to update Feptr in@@ -5177,7 +5432,7 @@ for (i = Lmin; i < Lmax; i++) { PCRE2_SIZE slength;- (void)match_ref(Loffset, Lcaseless, F, mb, &slength);+ (void)match_ref(Loffset, Lcaseless, Lcaseopts, F, mb, &slength); Feptr += slength; } }@@ -5185,8 +5440,9 @@ RRETURN(MATCH_NOMATCH); }- /* Control never gets here */ + PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */+ #undef Lcaseless #undef Lmin #undef Lmax@@ -5409,7 +5665,7 @@ Fecode += GET(Fecode, 1); if (*Fecode != OP_ALT) RRETURN(MATCH_NOMATCH); }- /* Control never reaches here. */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ #undef Lframe_type @@ -5494,7 +5750,7 @@ Lstart_branch = next_ecode; if (*Lstart_branch != OP_ALT) RRETURN(MATCH_NOMATCH); }- /* Control never reaches here. */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ #undef Lframe_type #undef Lstart_branch@@ -5585,7 +5841,136 @@ #undef Lframe_type + /* ===================================================================== */+ /* Handle scan substring operation. */ +#define Lframe_type F->temp_32[0]+#define Lextra_size F->temp_32[1]+#define Lsaved_moptions F->temp_32[2]+#define Lsaved_end_subject F->temp_sptr[0]+#define Lsaved_eptr F->temp_sptr[1]+#define Ltrue_end_extra F->temp_size++ case OP_ASSERT_SCS:+ {+ PCRE2_SPTR ecode = Fecode + 1 + LINK_SIZE;+ uint32_t extra_size = 0;+ int count;+ PCRE2_SPTR slot;++ /* Disable compiler warning. */+ offset = 0;+ (void)offset;++ for (;;)+ {+ if (*ecode == OP_CREF)+ {+ extra_size += 1+IMM2_SIZE;+ offset = (GET2(ecode, 1) << 1) - 2;+ ecode += 1+IMM2_SIZE;+ if (offset < Foffset_top && Fovector[offset] != PCRE2_UNSET)+ goto SCS_OFFSET_FOUND;+ continue;+ }++ if (*ecode != OP_DNCREF) RRETURN(MATCH_NOMATCH);++ count = GET2(ecode, 1 + IMM2_SIZE);+ slot = mb->name_table + GET2(ecode, 1) * mb->name_entry_size;+ extra_size += 1+2*IMM2_SIZE;+ ecode += 1+2*IMM2_SIZE;++ while (count > 0)+ {+ offset = (GET2(slot, 0) << 1) - 2;+ if (offset < Foffset_top && Fovector[offset] != PCRE2_UNSET)+ goto SCS_OFFSET_FOUND;+ slot += mb->name_entry_size;+ count--;+ }+ }++ SCS_OFFSET_FOUND:++ /* Skip remaining options. */+ for (;;)+ {+ if (*ecode == OP_CREF)+ {+ extra_size += 1+IMM2_SIZE;+ ecode += 1+IMM2_SIZE;+ }+ else if (*ecode == OP_DNCREF)+ {+ extra_size += 1+2*IMM2_SIZE;+ ecode += 1+2*IMM2_SIZE;+ }+ else break;+ }++ Lextra_size = extra_size;+ }++ Lsaved_end_subject = mb->end_subject;+ Ltrue_end_extra = mb->true_end_subject - mb->end_subject;+ Lsaved_eptr = Feptr;+ Lsaved_moptions = mb->moptions;++ Feptr = mb->start_subject + Fovector[offset];+ mb->true_end_subject = mb->end_subject =+ mb->start_subject + Fovector[offset + 1];+ mb->moptions &= ~PCRE2_NOTEOL;++ Lframe_type = GF_NOCAPTURE | Fop;+ for (;;)+ {+ group_frame_type = Lframe_type;+ RMATCH(Fecode + 1 + LINK_SIZE + Lextra_size, RM38);+ if (rrc == MATCH_ACCEPT)+ {+ memcpy(Fovector,+ (char *)assert_accept_frame + offsetof(heapframe, ovector),+ assert_accept_frame->offset_top * sizeof(PCRE2_SIZE));+ Foffset_top = assert_accept_frame->offset_top;+ Fmark = assert_accept_frame->mark;+ mb->end_subject = Lsaved_end_subject;+ mb->true_end_subject = mb->end_subject + Ltrue_end_extra;+ mb->moptions = Lsaved_moptions;+ break;+ }++ if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN)+ {+ mb->end_subject = Lsaved_end_subject;+ mb->true_end_subject = mb->end_subject + Ltrue_end_extra;+ mb->moptions = Lsaved_moptions;+ RRETURN(rrc);+ }++ Fecode += GET(Fecode, 1);+ if (*Fecode != OP_ALT)+ {+ mb->end_subject = Lsaved_end_subject;+ mb->true_end_subject = mb->end_subject + Ltrue_end_extra;+ mb->moptions = Lsaved_moptions;+ RRETURN(MATCH_NOMATCH);+ }+ Lextra_size = 0;+ }++ do Fecode += GET(Fecode, 1); while (*Fecode == OP_ALT);+ Fecode += 1 + LINK_SIZE;+ Feptr = Lsaved_eptr;+ break;++#undef Lframe_type+#undef Lextra_size+#undef Lsaved_end_subject+#undef Lsaved_eptr+#undef Ltrue_end_extra+#undef Lsave_moptions+ /* ===================================================================== */ /* The callout item calls an external function, if one is provided, passing details of the match so far. This is mainly for debugging, though the@@ -5715,7 +6100,7 @@ assert_accept_frame->offset_top * sizeof(PCRE2_SIZE)); Foffset_top = assert_accept_frame->offset_top; - /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ /* In the case of a match, the captures have already been put into the current frame. */ @@ -5795,8 +6180,11 @@ #ifdef SUPPORT_UNICODE if (utf) {- while (number-- > 0)+ /* We used to do a simpler `while (number-- > 0)` but that triggers+ clang's unsigned integer overflow sanitizer. */+ while (number > 0) {+ --number; if (Feptr <= mb->check_subject) RRETURN(MATCH_NOMATCH); Feptr--; BACKCHAR(Feptr);@@ -5869,7 +6257,7 @@ } /* Now try matching, moving forward one character on failure, until we- reach the mimimum back length. */+ reach the minimum back length. */ for (;;) {@@ -5881,7 +6269,7 @@ if (utf) { FORWARDCHARTEST(Feptr, mb->end_subject); } #endif }- /* Control never reaches here */+ PCRE2_UNREACHABLE(); /* Control never reaches here */ #undef Lmin #undef Lmax@@ -5931,14 +6319,20 @@ (char *)P->eptr - (char *)mb->start_subject); #endif - /* If we are at the end of an assertion that is a condition, return a- match, discarding any intermediate backtracking points. Copy back the- mark setting and the captures into the frame before N so that they are- set on return. Doing this for all assertions, both positive and negative,- seems to match what Perl does. */+ /* If we are at the end of an assertion that is a condition, first check+ to see if we are at the end of a variable-length branch in a lookbehind.+ If this is the case and we have not landed on the current character,+ return no match. Compare code below for non-condition lookbehinds. In+ other cases, return a match, discarding any intermediate backtracking+ points. Copy back the mark setting and the captures into the frame before+ N so that they are set on return. Doing this for all assertions, both+ positive and negative, seems to match what Perl does. */ if (GF_IDMASK(N->group_frame_type) == GF_CONDASSERT) {+ if ((*bracode == OP_ASSERTBACK || *bracode == OP_ASSERTBACK_NOT) &&+ branch_start[1 + LINK_SIZE] == OP_VREVERSE && Feptr != P->eptr)+ RRETURN(MATCH_NOMATCH); memcpy((char *)P + offsetof(heapframe, ovector), Fovector, Foffset_top * sizeof(PCRE2_SIZE)); P->offset_top = Foffset_top;@@ -5967,7 +6361,11 @@ /* It is the end of whole-pattern recursion. */ offset = Flast_group_offset;++ /* Corrupted heapframes?. Trigger an assert and return an error */+ PCRE2_ASSERT(offset != PCRE2_UNSET); 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;@@ -5975,12 +6373,18 @@ /* 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;+ Fecode = P->ecode + 1 + LINK_SIZE;++ if (*Fecode != OP_CREF)+ {+ memcpy(F->ovector, P->ovector, Foffset_top * sizeof(PCRE2_SIZE));+ Foffset_top = P->offset_top;+ }+ else+ recurse_update_offsets(F, P);+ 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 */@@ -5994,7 +6398,7 @@ case OP_ASSERTBACK_NA: if (branch_start[1 + LINK_SIZE] == OP_VREVERSE && Feptr != P->eptr) RRETURN(MATCH_NOMATCH);- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case OP_ASSERT_NA: if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr;@@ -6008,12 +6412,12 @@ case OP_ASSERTBACK: if (branch_start[1 + LINK_SIZE] == OP_VREVERSE && Feptr != P->eptr) RRETURN(MATCH_NOMATCH);- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case OP_ASSERT: if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr; Feptr = P->eptr;- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ /* For an atomic group, discard internal backtracking points. We must also ensure that any remaining branches within the top-level of the group@@ -6037,11 +6441,28 @@ case OP_ASSERTBACK_NOT: if (branch_start[1 + LINK_SIZE] == OP_VREVERSE && Feptr != P->eptr) RRETURN(MATCH_NOMATCH);- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case OP_ASSERT_NOT: RRETURN(MATCH_MATCH); + /* A scan substring group must preserve the current end_subject,+ and restore it before the backtracking is performed into its sub+ pattern. */++ case OP_ASSERT_SCS:+ F->temp_sptr[0] = mb->end_subject;+ mb->end_subject = P->temp_sptr[0];+ mb->true_end_subject = mb->end_subject + P->temp_size;+ Feptr = P->temp_sptr[1];++ RMATCH(Fecode + 1 + LINK_SIZE, RM39);++ mb->end_subject = F->temp_sptr[0];+ mb->true_end_subject = mb->end_subject;+ RRETURN(rrc);+ break;+ /* At the end of a script run, apply the script-checking rules. This code will never by exercised if Unicode support it not compiled, because in that environment script runs cause an error at compile time. */@@ -6065,12 +6486,18 @@ if (Fcurrent_recurse == number) { P = (heapframe *)((char *)N - frame_size);- memcpy((char *)F + offsetof(heapframe, ovector), P->ovector,- Foffset_top * sizeof(PCRE2_SIZE));- Foffset_top = P->offset_top;+ Fecode = P->ecode + 1 + LINK_SIZE;++ if (*Fecode != OP_CREF)+ {+ memcpy(F->ovector, P->ovector, Foffset_top * sizeof(PCRE2_SIZE));+ Foffset_top = P->offset_top;+ }+ else+ recurse_update_offsets(F, P);+ Fcapture_last = P->capture_last; Fcurrent_recurse = P->current_recurse;- Fecode = P->ecode + 1 + LINK_SIZE; continue; /* With next opcode */ } @@ -6148,7 +6575,7 @@ if ((mb->moptions & PCRE2_NOTEOL) != 0) RRETURN(MATCH_NOMATCH); if ((mb->poptions & PCRE2_DOLLAR_ENDONLY) == 0) goto ASSERT_NL_OR_EOS; - /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ /* Unconditional end of subject assertion (\z). */ case OP_EOD:@@ -6165,8 +6592,8 @@ case OP_EODN: ASSERT_NL_OR_EOS:- if (Feptr < mb->end_subject &&- (!IS_NEWLINE(Feptr) || Feptr != mb->end_subject - mb->nllen))+ if (Feptr < mb->true_end_subject &&+ (!IS_NEWLINE(Feptr) || Feptr != mb->true_end_subject - mb->nllen)) { if (mb->partial != 0 && Feptr + 1 >= mb->end_subject &&@@ -6446,8 +6873,11 @@ /* There's been some horrible disaster. Arrival here can only mean there is something seriously wrong in the code above or the OP_xxx definitions. */ + /* LCOV_EXCL_START */ default:+ PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL;+ /* LCOV_EXCL_STOP */ } /* Do not insert any code in here without much thought; it is assumed@@ -6455,8 +6885,8 @@ loop. */ } /* End of main loop */-/* Control never reaches here */ +PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */ /* ========================================================================= */ /* The RRETURN() macro jumps here. The number that is saved in Freturn_id@@ -6482,21 +6912,24 @@ 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(37)+ LBL(33) LBL(34) LBL(35) LBL(36) LBL(37) LBL(38) LBL(39) #ifdef SUPPORT_WIDE_CHARS- LBL(100) LBL(101)+ LBL(100) LBL(101) LBL(102) LBL(103) #endif #ifdef SUPPORT_UNICODE LBL(200) LBL(201) LBL(202) LBL(203) LBL(204) LBL(205) LBL(206) LBL(207) LBL(208) LBL(209) LBL(210) LBL(211) LBL(212) LBL(213) LBL(214) LBL(215) LBL(216) LBL(217) LBL(218) LBL(219) LBL(220)- LBL(221) LBL(222) LBL(223) LBL(224) LBL(225)+ LBL(221) LBL(222) LBL(223) LBL(224) #endif + /* LCOV_EXCL_START */ default:+ PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL;+ /* LCOV_EXCL_STOP */ } #undef LBL }@@ -6532,9 +6965,9 @@ pcre2_match_context *mcontext) { int rc;-int was_zero_terminated = 0; const uint8_t *start_bits = NULL; const pcre2_real_code *re = (const pcre2_real_code *)code;+uint32_t original_options = options; BOOL anchored; BOOL firstline;@@ -6552,6 +6985,8 @@ PCRE2_UCHAR req_cu = 0; PCRE2_UCHAR req_cu2 = 0; +PCRE2_UCHAR null_str[1] = { 0xcd };+PCRE2_SPTR original_subject = subject; PCRE2_SPTR bumpalong_limit; PCRE2_SPTR end_subject; PCRE2_SPTR true_end_subject;@@ -6590,38 +7025,40 @@ /* Recognize NULL, length 0 as an empty string. */ -if (subject == NULL && length == 0) subject = (PCRE2_SPTR)"";+if (subject == NULL && length == 0) subject = null_str; /* Plausibility checks */ -if ((options & ~PUBLIC_MATCH_OPTIONS) != 0) return PCRE2_ERROR_BADOPTION;-if (code == NULL || subject == NULL || match_data == NULL)- return PCRE2_ERROR_NULL;+if (match_data == NULL) return PCRE2_ERROR_NULL;+if (code == NULL || subject == NULL)+ return match_data->rc = PCRE2_ERROR_NULL;+if ((options & ~PUBLIC_MATCH_OPTIONS) != 0)+ return match_data->rc = PCRE2_ERROR_BADOPTION; start_match = subject + start_offset; req_cu_ptr = start_match - 1; if (length == PCRE2_ZERO_TERMINATED) { length = PRIV(strlen)(subject);- was_zero_terminated = 1; } true_end_subject = end_subject = subject + length; -if (start_offset > length) return PCRE2_ERROR_BADOFFSET;+if (start_offset > length) return match_data->rc = PCRE2_ERROR_BADOFFSET; /* Check that the first field in the block is the magic number. */ -if (re->magic_number != MAGIC_NUMBER) return PCRE2_ERROR_BADMAGIC;+if (re->magic_number != MAGIC_NUMBER)+ return match_data->rc = PCRE2_ERROR_BADMAGIC; /* Check the code unit width. */ if ((re->flags & PCRE2_MODE_MASK) != PCRE2_CODE_UNIT_WIDTH/8)- return PCRE2_ERROR_BADMODE;+ return match_data->rc = PCRE2_ERROR_BADMODE; /* PCRE2_NOTEMPTY and PCRE2_NOTEMPTY_ATSTART are match-time flags in the options variable for this function. Users of PCRE2 who are not calling the function directly would like to have a way of setting these flags, in the same-way that they can set pcre2_compile() flags like PCRE2_NO_AUTOPOSSESS with+way that they can set pcre2_compile() flags like PCRE2_NO_AUTO_POSSESS with constructions like (*NO_AUTOPOSSESS). To enable this, (*NOTEMPTY) and (*NOTEMPTY_ATSTART) set bits in the pattern's "flag" function which we now transfer to the options for this function. The bits are guaranteed to be@@ -6663,17 +7100,18 @@ if (mb->partial != 0 && ((re->overall_options | options) & PCRE2_ENDANCHORED) != 0)- return PCRE2_ERROR_BADOPTION;+ return match_data->rc = PCRE2_ERROR_BADOPTION; /* It is an error to set an offset limit without setting the flag at compile time. */ if (mcontext != NULL && mcontext->offset_limit != PCRE2_UNSET && (re->overall_options & PCRE2_USE_OFFSET_LIMIT) == 0)- return PCRE2_ERROR_BADOFFSETLIMIT;+ return match_data->rc = PCRE2_ERROR_BADOFFSETLIMIT; /* If the match data block was previously used with PCRE2_COPY_MATCHED_SUBJECT,-free the memory that was obtained. Set the field to NULL for no match cases. */+free the memory that was obtained. Set the field to NULL for match error+cases. */ if ((match_data->flags & PCRE2_MD_COPIED_SUBJECT) != 0) {@@ -6703,9 +7141,6 @@ #ifdef SUPPORT_UNICODE if (utf && (options & PCRE2_NO_UTF_CHECK) == 0 && !allow_invalid) {-#if PCRE2_CODE_UNIT_WIDTH != 32- unsigned int i;-#endif /* For 8-bit and 16-bit UTF, check that the first code unit is a valid character start. */@@ -6713,11 +7148,11 @@ #if PCRE2_CODE_UNIT_WIDTH != 32 if (start_match < end_subject && NOT_FIRSTCU(*start_match)) {- if (start_offset > 0) return PCRE2_ERROR_BADUTFOFFSET;+ if (start_offset > 0) return match_data->rc = PCRE2_ERROR_BADUTFOFFSET; #if PCRE2_CODE_UNIT_WIDTH == 8- return PCRE2_ERROR_UTF8_ERR20; /* Isolated 0x80 byte */+ return match_data->rc = PCRE2_ERROR_UTF8_ERR20; /* Isolated 0x80 byte */ #else- return PCRE2_ERROR_UTF16_ERR3; /* Isolated low surrogate */+ return match_data->rc = PCRE2_ERROR_UTF16_ERR3; /* Isolated low surrogate */ #endif } #endif /* WIDTH != 32 */@@ -6726,7 +7161,7 @@ start of matching. */ #if PCRE2_CODE_UNIT_WIDTH != 32- for (i = re->max_lookbehind; i > 0 && start_match > subject; i--)+ for (unsigned int i = re->max_lookbehind; i > 0 && start_match > subject; i--) { start_match--; while (start_match > subject &&@@ -6752,12 +7187,12 @@ /* Validate the relevant portion of the subject. Adjust the offset of an invalid code point to be an absolute offset in the whole string. */ - match_data->rc = PRIV(valid_utf)(start_match,+ rc = PRIV(valid_utf)(start_match, length - (start_match - subject), &(match_data->startchar));- if (match_data->rc != 0)+ if (rc != 0) { match_data->startchar += start_match - subject;- return match_data->rc;+ return match_data->rc = rc; } jit_checked_utf = TRUE; }@@ -6770,16 +7205,27 @@ match_data, mcontext); if (rc != PCRE2_ERROR_JIT_BADOPTION) {- match_data->subject_length = length;+ match_data->options = original_options; if (rc >= 0 && (options & PCRE2_COPY_MATCHED_SUBJECT) != 0) {- length = CU2BYTES(length + was_zero_terminated);- match_data->subject = match_data->memctl.malloc(length,- match_data->memctl.memory_data);- if (match_data->subject == NULL) return PCRE2_ERROR_NOMEMORY;- memcpy((void *)match_data->subject, subject, length);+ if (length != 0)+ {+ match_data->subject = match_data->memctl.malloc(CU2BYTES(length),+ match_data->memctl.memory_data);+ if (match_data->subject == NULL)+ return match_data->rc = PCRE2_ERROR_NOMEMORY;+ memcpy((void *)match_data->subject, subject, CU2BYTES(length));+ }+ else+ match_data->subject = NULL; match_data->flags |= PCRE2_MD_COPIED_SUBJECT; }+ else+ {+ /* When pcre2_jit_match sets the subject, it doesn't know what the+ original passed-in pointer was. */+ if (match_data->subject != NULL) match_data->subject = original_subject;+ } return rc; } }@@ -6836,11 +7282,11 @@ } else if (start_match < end_subject && NOT_FIRSTCU(*start_match)) {- if (start_offset > 0) return PCRE2_ERROR_BADUTFOFFSET;+ if (start_offset > 0) return match_data->rc = PCRE2_ERROR_BADUTFOFFSET; #if PCRE2_CODE_UNIT_WIDTH == 8- return PCRE2_ERROR_UTF8_ERR20; /* Isolated 0x80 byte */+ return match_data->rc = PCRE2_ERROR_UTF8_ERR20; /* Isolated 0x80 byte */ #else- return PCRE2_ERROR_UTF16_ERR3; /* Isolated low surrogate */+ return match_data->rc = PCRE2_ERROR_UTF16_ERR3; /* Isolated low surrogate */ #endif } #endif /* WIDTH != 32 */@@ -6888,10 +7334,10 @@ for (;;) {- match_data->rc = PRIV(valid_utf)(mb->check_subject,+ rc = PRIV(valid_utf)(mb->check_subject, length - (mb->check_subject - subject), &(match_data->startchar)); - if (match_data->rc == 0) break; /* Valid UTF string */+ if (rc == 0) break; /* Valid UTF string */ /* Invalid UTF string. Adjust the offset to be an absolute offset in the whole string. If we are handling invalid UTF strings, set end_subject to@@ -6899,7 +7345,7 @@ Otherwise return the error. */ match_data->startchar += mb->check_subject - subject;- if (!allow_invalid || match_data->rc > 0) return match_data->rc;+ if (!allow_invalid || rc > 0) return match_data->rc = rc; end_subject = subject + match_data->startchar; /* If the end precedes start_match, it means there is invalid UTF in the@@ -6964,8 +7410,11 @@ mb->end_subject = end_subject; mb->true_end_subject = true_end_subject; mb->hasthen = (re->flags & PCRE2_HASTHEN) != 0;+mb->hasbsk = (re->flags & PCRE2_HASBSK) != 0; mb->allowemptypartial = (re->max_lookbehind > 0) || (re->flags & PCRE2_MATCH_EMPTY) != 0;+mb->allowlookaroundbsk =+ (re->extra_options & PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK) != 0; mb->poptions = re->overall_options; /* Pattern options */ mb->ignore_skip_arg = 0; mb->mark = mb->nomatch_mark = NULL; /* In case never set */@@ -6973,10 +7422,10 @@ /* The name table is needed for finding all the numbers associated with a given name, for condition testing. The code follows the name table. */ -mb->name_table = (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code));+mb->name_table = (PCRE2_SPTR)((const uint8_t *)re + sizeof(pcre2_real_code)); mb->name_count = re->name_count; mb->name_entry_size = re->name_entry_size;-mb->start_code = mb->name_table + re->name_count * re->name_entry_size;+mb->start_code = (PCRE2_SPTR)((const uint8_t *)re + re->code_start); /* Process the \R and newline settings. */ @@ -7013,7 +7462,11 @@ mb->nltype = NLTYPE_ANYCRLF; break; - default: return PCRE2_ERROR_INTERNAL;+ /* LCOV_EXCL_START */+ default:+ PCRE2_DEBUG_UNREACHABLE();+ return match_data->rc = PCRE2_ERROR_INTERNAL;+ /* LCOV_EXCL_STOP */ } /* The backtracking frames have fixed data at the front, and a PCRE2_SIZE@@ -7055,7 +7508,7 @@ if (heapframes_size / 1024 > mb->heap_limit) { PCRE2_SIZE max_size = 1024 * mb->heap_limit;- if (max_size < frame_size) return PCRE2_ERROR_HEAPLIMIT;+ if (max_size < frame_size) return match_data->rc = PCRE2_ERROR_HEAPLIMIT; heapframes_size = max_size; } @@ -7071,7 +7524,7 @@ if (match_data->heapframes == NULL) { match_data->heapframes_size = 0;- return PCRE2_ERROR_NOMEMORY;+ return match_data->rc = PCRE2_ERROR_NOMEMORY; } match_data->heapframes_size = heapframes_size; }@@ -7159,7 +7612,7 @@ However, there is an option (settable at compile time) that disables these, for testing and for ensuring that all callouts do actually occur. */ - if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)+ if ((re->optimization_flags & PCRE2_OPTIM_START_OPTIMIZE) != 0) { /* If firstline is TRUE, the start of the match is constrained to the first line of a multiline string. That is, the match must be before or at the@@ -7547,7 +8000,7 @@ new_start_match = mb->verb_skip_ptr; break; }- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ /* NOMATCH and PRUNE advance by one character. THEN at this level acts exactly like PRUNE. Unset ignore SKIP-with-argument. */@@ -7705,6 +8158,7 @@ match_data->code = re; match_data->mark = mb->mark; match_data->matchedby = PCRE2_MATCHEDBY_INTERPRETER;+match_data->options = original_options; /* Handle a fully successful match. Set the return code to the number of captured strings, or 0 if there were too many to fit into the ovector, and then@@ -7716,20 +8170,26 @@ 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->start_offset = start_offset; 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)? mb->last_used_ptr : mb->end_match_ptr) - subject; if ((options & PCRE2_COPY_MATCHED_SUBJECT) != 0) {- length = CU2BYTES(length + was_zero_terminated);- match_data->subject = match_data->memctl.malloc(length,- match_data->memctl.memory_data);- if (match_data->subject == NULL) return PCRE2_ERROR_NOMEMORY;- memcpy((void *)match_data->subject, subject, length);+ if (length != 0)+ {+ match_data->subject = match_data->memctl.malloc(CU2BYTES(length),+ match_data->memctl.memory_data);+ if (match_data->subject == NULL)+ return match_data->rc = PCRE2_ERROR_NOMEMORY;+ memcpy((void *)match_data->subject, subject, CU2BYTES(length));+ }+ else+ match_data->subject = NULL; match_data->flags |= PCRE2_MD_COPIED_SUBJECT; }- else match_data->subject = subject;+ else match_data->subject = original_subject; return match_data->rc; }@@ -7751,8 +8211,9 @@ else if (match_partial != NULL) {- match_data->subject = subject;+ match_data->subject = original_subject; match_data->subject_length = length;+ match_data->start_offset = start_offset; match_data->ovector[0] = match_partial - subject; match_data->ovector[1] = end_subject - subject; match_data->startchar = match_partial - subject;@@ -7763,7 +8224,13 @@ /* Else this is the classic nomatch case. */ -else match_data->rc = PCRE2_ERROR_NOMATCH;+else+ {+ match_data->subject = original_subject;+ match_data->subject_length = length;+ match_data->start_offset = start_offset;+ match_data->rc = PCRE2_ERROR_NOMATCH;+ } return match_data->rc; }
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-2022 University of Cambridge+ New API code Copyright (c) 2016-2024 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -39,10 +39,6 @@ */ -#ifdef HAVE_CONFIG_H-#include "config.h"-#endif- #include "pcre2_internal.h" @@ -77,14 +73,17 @@ * Create a match data block using pattern data * *************************************************/ -/* If no context is supplied, use the memory allocator from the code. */+/* If no context is supplied, use the memory allocator from the code. This code+assumes that a general context contains nothing other than a memory allocator.+If that ever changes, this code will need fixing. */ PCRE2_EXP_DEFN pcre2_match_data * PCRE2_CALL_CONVENTION pcre2_match_data_create_from_pattern(const pcre2_code *code, pcre2_general_context *gcontext) {+if (code == NULL) return NULL; if (gcontext == NULL) gcontext = (pcre2_general_context *)code;-return pcre2_match_data_create(((pcre2_real_code *)code)->top_bracket + 1,+return pcre2_match_data_create(((const pcre2_real_code *)code)->top_bracket + 1, gcontext); }
+ src/c/pcre2/src/pcre2_match_next.c view
@@ -0,0 +1,171 @@+/*************************************************+* 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+ Original API code Copyright (c) 1997-2012 University of Cambridge+ 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.+-----------------------------------------------------------------------------+*/+++#include "pcre2_internal.h"++++/* Advance the offset by one code unit, and return the new value.+It is only called when the offset is not at the end of the subject. */++static PCRE2_SIZE do_bumpalong(pcre2_match_data *match_data,+ PCRE2_SIZE offset)+{+PCRE2_SPTR subject = match_data->subject;+PCRE2_SIZE subject_length = match_data->subject_length;+#ifdef SUPPORT_UNICODE+BOOL utf = (match_data->code->overall_options & PCRE2_UTF) != 0;+#endif++/* Skip over CRLF as an atomic sequence, if CRLF is configured as a newline+sequence. */++if (subject[offset] == CHAR_CR && offset + 1 < subject_length &&+ subject[offset + 1] == CHAR_LF)+ {+ switch(match_data->code->newline_convention)+ {+ case PCRE2_NEWLINE_CRLF:+ case PCRE2_NEWLINE_ANY:+ case PCRE2_NEWLINE_ANYCRLF:+ return offset + 2;+ }+ }++/* Advance by one full character if in UTF mode. */++#ifdef SUPPORT_UNICODE+if (utf)+ {+ PCRE2_SPTR next = subject + offset + 1;+ PCRE2_SPTR subject_end = subject + subject_length;++ (void)subject_end; /* Suppress warning; 32-bit FORWARDCHARTEST ignores this */+ FORWARDCHARTEST(next, subject_end);+ return next - subject;+ }+#endif++return offset + 1;+}++++/*************************************************+* Advance the match *+*************************************************/++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_next_match(pcre2_match_data *match_data, PCRE2_SIZE *pstart_offset,+ uint32_t *poptions)+{+int rc = match_data->rc;+PCRE2_SIZE start_offset = match_data->start_offset;+PCRE2_SIZE *ovector = match_data->ovector;++/* Match error, or no match: no further iteration possible. In previous versions+of PCRE2, we recommended that clients use a strategy which involved retrying in+certain cases after PCRE2_ERROR_NOMATCH, but this is no longer required. */++if (rc < 0)+ return FALSE;++/* Match succeeded: get the start offset for the next match */++/* Although \K can affect the position of ovector[0], there are no ways to do+anything surprising with ovector[1], which must always be >= start_offset. */++PCRE2_ASSERT(ovector[1] >= start_offset);++/* Special handling for patterns which contain \K in a lookaround, which enables+the match start to be pushed back to before the starting search offset+(ovector[0] < start_offset) or after the match ends (ovector[0] > ovector[1]).+This is not a problem if ovector[1] > start_offset, because in this case, we can+just attempt the next match at ovector[1]: we are making progress, which is all+that we require.++However, if we have ovector[1] == start_offset, then we have a very rare case+which must be handled specially, because it's a non-empty match which+nonetheless fails to make progress through the subject. */++if (ovector[0] != start_offset && ovector[1] == start_offset)+ {+ /* If the match end is at the end of the subject, we are done. */++ if (start_offset >= match_data->subject_length)+ return FALSE;++ /* Otherwise, bump along by one code unit, and do a normal search. */++ *pstart_offset = do_bumpalong(match_data, ovector[1]);+ *poptions = 0;+ return TRUE;+ }++/* If the previous match was for an empty string, we are finished if we are at+the end of the subject. Otherwise, arrange to run another match at the same+point to see if a non-empty match can be found. */++if (ovector[0] == ovector[1])+ {+ /* If the match is at the end of the subject, we are done. */++ if (ovector[0] >= match_data->subject_length)+ return FALSE;++ /* Otherwise, continue at this exact same point, but we must set the flag+ which ensures that we don't return the exact same empty match again. */++ *pstart_offset = ovector[1];+ *poptions = PCRE2_NOTEMPTY_ATSTART;+ return TRUE;+ }++/* Finally, we must be in the happy state of a non-empty match, where the end of+the match is further on in the subject than start_offset, so we are easily able+to continue and make progress. */++*pstart_offset = ovector[1];+*poptions = 0;+return TRUE;+}++/* End of pcre2_match_next.c */
src/c/pcre2/src/pcre2_newline.c view
@@ -48,10 +48,6 @@ http://unicode.org/unicode/reports/tr18/. */ -#ifdef HAVE_CONFIG_H-#include "config.h"-#endif- #include "pcre2_internal.h"
src/c/pcre2/src/pcre2_ord2utf.c view
@@ -43,13 +43,10 @@ into a UTF string. The behaviour is different for each code unit width. */ -#ifdef HAVE_CONFIG_H-#include "config.h"-#endif- #include "pcre2_internal.h" + /* If SUPPORT_UNICODE is not defined, this function will never be called. Supply a dummy function because some compilers do not like empty source modules. */@@ -83,16 +80,17 @@ /* Convert to UTF-8 */ #if PCRE2_CODE_UNIT_WIDTH == 8-int i, j;+unsigned int i;+ for (i = 0; i < PRIV(utf8_table1_size); i++) if ((int)cvalue <= PRIV(utf8_table1)[i]) break; buffer += i;-for (j = i; j > 0; j--)+for (unsigned int j = i; j != 0; j--) { *buffer-- = 0x80 | (cvalue & 0x3f); cvalue >>= 6; }-*buffer = PRIV(utf8_table2)[i] | cvalue;+*buffer = (PCRE2_UCHAR)(PRIV(utf8_table2)[i] | (int)cvalue); return i + 1; /* Convert to UTF-16 */@@ -117,4 +115,4 @@ } #endif /* SUPPORT_UNICODE */ -/* End of pcre_ord2utf.c */+/* End of pcre2_ord2utf.c */
src/c/pcre2/src/pcre2_pattern_info.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@@ -39,13 +39,10 @@ */ -#ifdef HAVE_CONFIG_H-#include "config.h"-#endif- #include "pcre2_internal.h" + /************************************************* * Return info about compiled pattern * *************************************************/@@ -64,7 +61,7 @@ PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION pcre2_pattern_info(const pcre2_code *code, uint32_t what, void *where) {-const pcre2_real_code *re = (pcre2_real_code *)code;+const pcre2_real_code *re = (const pcre2_real_code *)code; if (where == NULL) /* Requests field length */ {@@ -230,7 +227,8 @@ break; case PCRE2_INFO_NAMETABLE:- *((PCRE2_SPTR *)where) = (PCRE2_SPTR)((char *)re + sizeof(pcre2_real_code));+ *((PCRE2_SPTR *)where) = (PCRE2_SPTR)((const char *)re ++ sizeof(pcre2_real_code)); break; case PCRE2_INFO_NEWLINE:@@ -268,7 +266,7 @@ pcre2_callout_enumerate(const pcre2_code *code, int (*callback)(pcre2_callout_enumerate_block *, void *), void *callout_data) {-pcre2_real_code *re = (pcre2_real_code *)code;+const pcre2_real_code *re = (const pcre2_real_code *)code; pcre2_callout_enumerate_block cb; PCRE2_SPTR cc; #ifdef SUPPORT_UNICODE@@ -291,8 +289,7 @@ if ((re->flags & (PCRE2_CODE_UNIT_WIDTH/8)) == 0) return PCRE2_ERROR_BADMODE; cb.version = 0;-cc = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code))- + re->name_count * re->name_entry_size;+cc = (PCRE2_SPTR)((uint8_t *)re + re->code_start); while (TRUE) {@@ -383,8 +380,9 @@ #endif break; -#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8+#ifdef SUPPORT_WIDE_CHARS case OP_XCLASS:+ case OP_ECLASS: cc += GET(cc, 1); break; #endif
− src/c/pcre2/src/pcre2_printint.c
@@ -1,886 +0,0 @@-/*************************************************-* 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- Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-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 module contains a PCRE private debugging function for printing out the-internal form of a compiled regular expression, along with some supporting-local functions. This source file is #included in pcre2test.c at each supported-code unit width, with PCRE2_SUFFIX set appropriately, just like the functions-that comprise the library. It can also optionally be included in-pcre2_compile.c for detailed debugging in error situations. */---/* Tables of operator names. The same 8-bit table is used for all code unit-widths, so it must be defined only once. The list itself is defined in-pcre2_internal.h, which is #included by pcre2test before this file. */--#ifndef OP_LISTS_DEFINED-static const char *OP_names[] = { OP_NAME_LIST };-#define OP_LISTS_DEFINED-#endif--/* The functions and tables herein must all have mode-dependent names. */--#define OP_lengths PCRE2_SUFFIX(OP_lengths_)-#define get_ucpname PCRE2_SUFFIX(get_ucpname_)-#define pcre2_printint PCRE2_SUFFIX(pcre2_printint_)-#define print_char PCRE2_SUFFIX(print_char_)-#define print_custring PCRE2_SUFFIX(print_custring_)-#define print_custring_bylen PCRE2_SUFFIX(print_custring_bylen_)-#define print_prop PCRE2_SUFFIX(print_prop_)--/* Table of sizes for the fixed-length opcodes. It's defined in a macro so that-the definition is next to the definition of the opcodes in pcre2_internal.h.-The contents of the table are, however, mode-dependent. */--static const uint8_t OP_lengths[] = { OP_LENGTHS };----/*************************************************-* Print one character from a string *-*************************************************/--/* In UTF mode the character may occupy more than one code unit.--Arguments:- f file to write to- ptr pointer to first code unit of the character- utf TRUE if string is UTF (will be FALSE if UTF is not supported)--Returns: number of additional code units used-*/--static unsigned int-print_char(FILE *f, PCRE2_SPTR ptr, BOOL utf)-{-uint32_t c = *ptr;-BOOL one_code_unit = !utf;--/* If UTF is supported and requested, check for a valid single code unit. */--#ifdef SUPPORT_UNICODE-if (utf)- {-#if PCRE2_CODE_UNIT_WIDTH == 8- one_code_unit = c < 0x80;-#elif PCRE2_CODE_UNIT_WIDTH == 16- one_code_unit = (c & 0xfc00) != 0xd800;-#else- one_code_unit = (c & 0xfffff800u) != 0xd800u;-#endif /* CODE_UNIT_WIDTH */- }-#endif /* SUPPORT_UNICODE */--/* Handle a valid one-code-unit character at any width. */--if (one_code_unit)- {- if (PRINTABLE(c)) fprintf(f, "%c", (char)c);- else if (c < 0x80) fprintf(f, "\\x%02x", c);- else fprintf(f, "\\x{%02x}", c);- return 0;- }--/* Code for invalid UTF code units and multi-unit UTF characters is different-for each width. If UTF is not supported, control should never get here, but we-need a return statement to keep the compiler happy. */--#ifndef SUPPORT_UNICODE-return 0;-#else--/* Malformed UTF-8 should occur only if the sanity check has been turned off.-Rather than swallow random bytes, just stop if we hit a bad one. Print it with-\X instead of \x as an indication. */--#if PCRE2_CODE_UNIT_WIDTH == 8-if ((c & 0xc0) != 0xc0)- {- fprintf(f, "\\X{%x}", c); /* Invalid starting byte */- return 0;- }-else- {- int i;- int a = PRIV(utf8_table4)[c & 0x3f]; /* Number of additional bytes */- int s = 6*a;- c = (c & PRIV(utf8_table3)[a]) << s;- for (i = 1; i <= a; i++)- {- if ((ptr[i] & 0xc0) != 0x80)- {- fprintf(f, "\\X{%x}", c); /* Invalid secondary byte */- return i - 1;- }- s -= 6;- c |= (ptr[i] & 0x3f) << s;- }- fprintf(f, "\\x{%x}", c);- return a;-}-#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */--/* UTF-16: rather than swallow a low surrogate, just stop if we hit a bad one.-Print it with \X instead of \x as an indication. */--#if PCRE2_CODE_UNIT_WIDTH == 16-if ((ptr[1] & 0xfc00) != 0xdc00)- {- fprintf(f, "\\X{%x}", c);- return 0;- }-c = (((c & 0x3ff) << 10) | (ptr[1] & 0x3ff)) + 0x10000;-fprintf(f, "\\x{%x}", c);-return 1;-#endif /* PCRE2_CODE_UNIT_WIDTH == 16 */--/* For UTF-32 we get here only for a malformed code unit, which should only-occur if the sanity check has been turned off. Print it with \X instead of \x-as an indication. */--#if PCRE2_CODE_UNIT_WIDTH == 32-fprintf(f, "\\X{%x}", c);-return 0;-#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */-#endif /* SUPPORT_UNICODE */-}----/*************************************************-* Print string as a list of code units *-*************************************************/--/* These take no account of UTF as they always print each individual code unit.-The string is zero-terminated for print_custring(); the length is given for-print_custring_bylen().--Arguments:- f file to write to- ptr point to the string- len length for print_custring_bylen()--Returns: nothing-*/--static void-print_custring(FILE *f, PCRE2_SPTR ptr)-{-while (*ptr != '\0')- {- uint32_t c = *ptr++;- if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x{%x}", c);- }-}--static void-print_custring_bylen(FILE *f, PCRE2_SPTR ptr, PCRE2_UCHAR len)-{-for (; len > 0; len--)- {- uint32_t c = *ptr++;- if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x{%x}", c);- }-}----/*************************************************-* Find Unicode property name *-*************************************************/--/* When there is no UTF/UCP support, the table of names does not exist. This-function should not be called in such configurations, because a pattern that-tries to use Unicode properties won't compile. Rather than put lots of #ifdefs-into the main code, however, we just put one into this function.--Now that the table contains both full names and their abbreviations, we do some-fiddling to try to get the full name, which is either the longer of two found-names, or a 3-character script name. */--static const char *-get_ucpname(unsigned int ptype, unsigned int pvalue)-{-#ifdef SUPPORT_UNICODE-int count = 0;-const char *yield = "??";-size_t len = 0;-unsigned int ptypex = (ptype == PT_SC)? PT_SCX : ptype;--for (int i = PRIV(utt_size) - 1; i >= 0; i--)- {- const ucp_type_table *u = PRIV(utt) + i;-- if ((ptype == u->type || ptypex == u->type) && pvalue == u->value)- {- const char *s = PRIV(utt_names) + u->name_offset;- size_t sl = strlen(s);-- if (sl == 3 && (u->type == PT_SC || u->type == PT_SCX))- {- yield = s;- break;- }-- if (sl > len)- {- yield = s;- len = sl;- }-- if (++count >= 2) break;- }- }--return yield;--#else /* No UTF support */-(void)ptype;-(void)pvalue;-return "??";-#endif /* SUPPORT_UNICODE */-}----/*************************************************-* Print Unicode property value *-*************************************************/--/* "Normal" properties can be printed from tables. The PT_CLIST property is a-pseudo-property that contains a pointer to a list of case-equivalent-characters.--Arguments:- f file to write to- code pointer in the compiled code- before text to print before- after text to print after--Returns: nothing-*/--static void-print_prop(FILE *f, PCRE2_SPTR code, const char *before, const char *after)-{-if (code[1] != PT_CLIST)- {- const char *sc = (code[1] == PT_SC)? "script:" : "";- const char *s = get_ucpname(code[1], code[2]);- fprintf(f, "%s%s %s%c%s%s", before, OP_names[*code], sc, toupper(s[0]), s+1, after);- }-else- {- const uint32_t *p = PRIV(ucd_caseless_sets) + code[2];- fprintf (f, "%s%sclist", before, (*code == OP_PROP)? "" : "not ");- while (*p < NOTACHAR) fprintf(f, " %04x", *p++);- fprintf(f, "%s", after);- }-}----/*************************************************-* Print compiled pattern *-*************************************************/--/* The print_lengths flag controls whether offsets and lengths of items are-printed. Lenths can be turned off from pcre2test so that automatic tests on-bytecode can be written that do not depend on the value of LINK_SIZE.--Arguments:- re a compiled pattern- f the file to write to- print_lengths show various lengths--Returns: nothing-*/--static void-pcre2_printint(pcre2_code *re, FILE *f, BOOL print_lengths)-{-PCRE2_SPTR codestart, nametable, code;-uint32_t nesize = re->name_entry_size;-BOOL utf = (re->overall_options & PCRE2_UTF) != 0;--nametable = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code));-code = codestart = nametable + re->name_count * re->name_entry_size;--for(;;)- {- PCRE2_SPTR ccode;- uint32_t c;- int i;- const char *flag = " ";- unsigned int extra = 0;-- if (print_lengths)- fprintf(f, "%3d ", (int)(code - codestart));- else- fprintf(f, " ");-- switch(*code)- {-/* ========================================================================== */- /* These cases are never obeyed. This is a fudge that causes a compile-- time error if the vectors OP_names or OP_lengths, which are indexed- by opcode, are not the correct length. It seems to be the only way to do- such a check at compile time, as the sizeof() operator does not work in- the C preprocessor. */-- case OP_TABLE_LENGTH:- case OP_TABLE_LENGTH +- ((sizeof(OP_names)/sizeof(const char *) == OP_TABLE_LENGTH) &&- (sizeof(OP_lengths) == OP_TABLE_LENGTH)):- return;-/* ========================================================================== */-- case OP_END:- fprintf(f, " %s\n", OP_names[*code]);- fprintf(f, "------------------------------------------------------------------\n");- return;-- case OP_CHAR:- fprintf(f, " ");- do- {- code++;- code += 1 + print_char(f, code, utf);- }- while (*code == OP_CHAR);- fprintf(f, "\n");- continue;-- case OP_CHARI:- fprintf(f, " /i ");- do- {- code++;- code += 1 + print_char(f, code, utf);- }- while (*code == OP_CHARI);- fprintf(f, "\n");- continue;-- case OP_CBRA:- case OP_CBRAPOS:- case OP_SCBRA:- case OP_SCBRAPOS:- if (print_lengths) fprintf(f, "%3d ", GET(code, 1));- else fprintf(f, " ");- fprintf(f, "%s %d", OP_names[*code], GET2(code, 1+LINK_SIZE));- break;-- case OP_BRA:- case OP_BRAPOS:- case OP_SBRA:- case OP_SBRAPOS:- case OP_KETRMAX:- case OP_KETRMIN:- case OP_KETRPOS:- case OP_ALT:- case OP_KET:- 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_COND:- case OP_SCOND:- 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;-- case OP_CREF:- fprintf(f, "%3d %s", GET2(code,1), OP_names[*code]);- break;-- case OP_DNCREF:- {- PCRE2_SPTR entry = nametable + (GET2(code, 1) * nesize) + IMM2_SIZE;- fprintf(f, " %s Cond ref <", flag);- print_custring(f, entry);- fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));- }- break;-- case OP_RREF:- c = GET2(code, 1);- if (c == RREF_ANY)- fprintf(f, " Cond recurse any");- else- fprintf(f, " Cond recurse %d", c);- break;-- case OP_DNRREF:- {- PCRE2_SPTR entry = nametable + (GET2(code, 1) * nesize) + IMM2_SIZE;- fprintf(f, " %s Cond recurse <", flag);- print_custring(f, entry);- fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));- }- break;-- case OP_FALSE:- fprintf(f, " Cond false");- break;-- case OP_TRUE:- fprintf(f, " Cond true");- break;-- case OP_STARI:- case OP_MINSTARI:- case OP_POSSTARI:- case OP_PLUSI:- case OP_MINPLUSI:- case OP_POSPLUSI:- case OP_QUERYI:- case OP_MINQUERYI:- case OP_POSQUERYI:- flag = "/i";- /* Fall through */- case OP_STAR:- case OP_MINSTAR:- case OP_POSSTAR:- case OP_PLUS:- case OP_MINPLUS:- case OP_POSPLUS:- case OP_QUERY:- case OP_MINQUERY:- case OP_POSQUERY:- case OP_TYPESTAR:- case OP_TYPEMINSTAR:- case OP_TYPEPOSSTAR:- case OP_TYPEPLUS:- case OP_TYPEMINPLUS:- case OP_TYPEPOSPLUS:- case OP_TYPEQUERY:- case OP_TYPEMINQUERY:- case OP_TYPEPOSQUERY:- fprintf(f, " %s ", flag);-- if (*code >= OP_TYPESTAR)- {- if (code[1] == OP_PROP || code[1] == OP_NOTPROP)- {- print_prop(f, code + 1, "", " ");- extra = 2;- }- else fprintf(f, "%s", OP_names[code[1]]);- }- else extra = print_char(f, code+1, utf);- fprintf(f, "%s", OP_names[*code]);- break;-- case OP_EXACTI:- case OP_UPTOI:- case OP_MINUPTOI:- case OP_POSUPTOI:- flag = "/i";- /* Fall through */- case OP_EXACT:- case OP_UPTO:- case OP_MINUPTO:- case OP_POSUPTO:- fprintf(f, " %s ", flag);- extra = print_char(f, code + 1 + IMM2_SIZE, utf);- fprintf(f, "{");- if (*code != OP_EXACT && *code != OP_EXACTI) fprintf(f, "0,");- fprintf(f, "%d}", GET2(code,1));- if (*code == OP_MINUPTO || *code == OP_MINUPTOI) fprintf(f, "?");- else if (*code == OP_POSUPTO || *code == OP_POSUPTOI) fprintf(f, "+");- break;-- case OP_TYPEEXACT:- case OP_TYPEUPTO:- case OP_TYPEMINUPTO:- case OP_TYPEPOSUPTO:- if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)- {- print_prop(f, code + IMM2_SIZE + 1, " ", " ");- extra = 2;- }- else fprintf(f, " %s", OP_names[code[1 + IMM2_SIZE]]);- fprintf(f, "{");- if (*code != OP_TYPEEXACT) fprintf(f, "0,");- fprintf(f, "%d}", GET2(code,1));- if (*code == OP_TYPEMINUPTO) fprintf(f, "?");- else if (*code == OP_TYPEPOSUPTO) fprintf(f, "+");- break;-- case OP_NOTI:- flag = "/i";- /* Fall through */- case OP_NOT:- fprintf(f, " %s [^", flag);- extra = print_char(f, code + 1, utf);- fprintf(f, "]");- break;-- case OP_NOTSTARI:- case OP_NOTMINSTARI:- case OP_NOTPOSSTARI:- case OP_NOTPLUSI:- case OP_NOTMINPLUSI:- case OP_NOTPOSPLUSI:- case OP_NOTQUERYI:- case OP_NOTMINQUERYI:- case OP_NOTPOSQUERYI:- flag = "/i";- /* Fall through */-- case OP_NOTSTAR:- case OP_NOTMINSTAR:- case OP_NOTPOSSTAR:- case OP_NOTPLUS:- case OP_NOTMINPLUS:- case OP_NOTPOSPLUS:- case OP_NOTQUERY:- case OP_NOTMINQUERY:- case OP_NOTPOSQUERY:- fprintf(f, " %s [^", flag);- extra = print_char(f, code + 1, utf);- fprintf(f, "]%s", OP_names[*code]);- break;-- case OP_NOTEXACTI:- case OP_NOTUPTOI:- case OP_NOTMINUPTOI:- case OP_NOTPOSUPTOI:- flag = "/i";- /* Fall through */-- case OP_NOTEXACT:- case OP_NOTUPTO:- case OP_NOTMINUPTO:- case OP_NOTPOSUPTO:- fprintf(f, " %s [^", flag);- extra = print_char(f, code + 1 + IMM2_SIZE, utf);- fprintf(f, "]{");- if (*code != OP_NOTEXACT && *code != OP_NOTEXACTI) fprintf(f, "0,");- fprintf(f, "%d}", GET2(code,1));- if (*code == OP_NOTMINUPTO || *code == OP_NOTMINUPTOI) fprintf(f, "?");- else- if (*code == OP_NOTPOSUPTO || *code == OP_NOTPOSUPTOI) fprintf(f, "+");- break;-- case OP_RECURSE:- if (print_lengths) fprintf(f, "%3d ", GET(code, 1));- else fprintf(f, " ");- fprintf(f, "%s", OP_names[*code]);- break;-- case OP_REFI:- flag = "/i";- /* Fall through */- case OP_REF:- fprintf(f, " %s \\%d", flag, GET2(code,1));- ccode = code + OP_lengths[*code];- goto CLASS_REF_REPEAT;-- case OP_DNREFI:- flag = "/i";- /* Fall through */- case OP_DNREF:- {- PCRE2_SPTR entry = nametable + (GET2(code, 1) * nesize) + IMM2_SIZE;- fprintf(f, " %s \\k<", flag);- print_custring(f, entry);- fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));- }- ccode = code + OP_lengths[*code];- goto CLASS_REF_REPEAT;-- case OP_CALLOUT:- fprintf(f, " %s %d %d %d", OP_names[*code], code[1 + 2*LINK_SIZE],- GET(code, 1), GET(code, 1 + LINK_SIZE));- break;-- case OP_CALLOUT_STR:- c = code[1 + 4*LINK_SIZE];- fprintf(f, " %s %c", OP_names[*code], c);- extra = GET(code, 1 + 2*LINK_SIZE);- print_custring_bylen(f, code + 2 + 4*LINK_SIZE, extra - 3 - 4*LINK_SIZE);- for (i = 0; PRIV(callout_start_delims)[i] != 0; i++)- if (c == PRIV(callout_start_delims)[i])- {- c = PRIV(callout_end_delims)[i];- break;- }- fprintf(f, "%c %d %d %d", c, GET(code, 1 + 3*LINK_SIZE), GET(code, 1),- GET(code, 1 + LINK_SIZE));- break;-- case OP_PROP:- case OP_NOTPROP:- print_prop(f, code, " ", "");- break;-- /* OP_XCLASS cannot occur in 8-bit, non-UTF mode. However, there's no harm- in having this code always here, and it makes it less messy without all- those #ifdefs. */-- case OP_CLASS:- case OP_NCLASS:- case OP_XCLASS:- {- 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);- ccode = code + LINK_SIZE + 1;- printmap = (*ccode & XCL_MAP) != 0;- if ((*ccode & XCL_NOT) != 0)- {- invertmap = (*ccode & XCL_HASPROP) == 0;- fprintf(f, "^");- }- ccode++;- }- else /* CLASS or NCLASS */- {- printmap = TRUE;- ccode = code + 1;- }-- /* Print a bit map */-- if (printmap)- {- uint8_t inverted_map[32];- uint8_t *map = (uint8_t *)ccode;-- if (invertmap)- {- /* Using 255 ^ instead of ~ avoids clang sanitize warning. */- for (i = 0; i < 32; i++) inverted_map[i] = 255 ^ map[i];- map = inverted_map;- }-- for (i = 0; i < 256; i++)- {- if ((map[i/8] & (1u << (i&7))) != 0)- {- int j;- for (j = i+1; j < 256; j++)- if ((map[j/8] & (1u << (j&7))) == 0) break;- if (i == '-' || i == ']') fprintf(f, "\\");- if (PRINTABLE(i)) fprintf(f, "%c", i);- else fprintf(f, "\\x%02x", i);- if (--j > i)- {- if (j != i + 1) fprintf(f, "-");- if (j == '-' || j == ']') fprintf(f, "\\");- if (PRINTABLE(j)) fprintf(f, "%c", j);- else fprintf(f, "\\x%02x", j);- }- i = j;- }- }- ccode += 32 / sizeof(PCRE2_UCHAR);- }- }-- /* For an XCLASS there is always some additional data */-- if (*code == OP_XCLASS)- {- PCRE2_UCHAR ch;- while ((ch = *ccode++) != XCL_END)- {- const char *notch = "";-- switch(ch)- {- case XCL_NOTPROP:- notch = "^";- /* Fall through */-- case XCL_PROP:- {- unsigned int ptype = *ccode++;- unsigned int pvalue = *ccode++;- const char *s;-- switch(ptype)- {- case PT_PXGRAPH:- fprintf(f, "[:%sgraph:]", notch);- break;-- case PT_PXPRINT:- fprintf(f, "[:%sprint:]", 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}", ((notch[0] == '^')? 'P':'p'),- toupper(s[0]), s+1);- break;- }- }- break;-- default:- ccode += 1 + print_char(f, ccode, utf);- if (ch == XCL_RANGE)- {- fprintf(f, "-");- ccode += 1 + print_char(f, ccode, utf);- }- break;- }- }- }-- /* Indicate a non-UTF class which was created by negation */-- fprintf(f, "]%s", (*code == OP_NCLASS)? " (neg)" : "");-- /* Handle repeats after a class or a back reference */-- CLASS_REF_REPEAT:- switch(*ccode)- {- unsigned int min, max;-- 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;-- 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;-- /* 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;-- case OP_MARK:- case OP_COMMIT_ARG:- case OP_PRUNE_ARG:- case OP_SKIP_ARG:- case OP_THEN_ARG:- fprintf(f, " %s ", OP_names[*code]);- print_custring_bylen(f, code + 2, code[1]);- extra += code[1];- break;-- case OP_THEN:- fprintf(f, " %s", OP_names[*code]);- break;-- case OP_CIRCM:- case OP_DOLLM:- flag = "/m";- /* Fall through */-- /* Anything else is just an item with no data, but possibly a flag. */-- default:- fprintf(f, " %s %s", flag, OP_names[*code]);- break;- }-- code += OP_lengths[*code] + extra;- fprintf(f, "\n");- }-}--/* End of pcre2_printint.c */
+ src/c/pcre2/src/pcre2_printint_inc.h view
@@ -0,0 +1,1098 @@+/*************************************************+* 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+ Original API code Copyright (c) 1997-2012 University of Cambridge+ 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.+-----------------------------------------------------------------------------+*/+++/* This module contains a PCRE private debugging function for printing out the+internal form of a compiled regular expression, along with some supporting+local functions. This source file is #included in pcre2test.c at each supported+code unit width, with PCRE2_SUFFIX set appropriately, just like the functions+that comprise the library. It can also optionally be included in+pcre2_compile.c for detailed debugging in error situations. */++++/* Tables of operator names. The same 8-bit table is used for all code unit+widths, so it must be defined only once. The list itself is defined in+pcre2_internal.h, which is #included by pcre2test before this file. */++#ifndef OP_LISTS_DEFINED+static const char *OP_names[] = { OP_NAME_LIST };+STATIC_ASSERT(sizeof(OP_names)/sizeof(*OP_names) == OP_TABLE_LENGTH, OP_names);+#define OP_LISTS_DEFINED+#endif++/* The functions and tables herein must all have mode-dependent names. */++#define OP_lengths PCRE2_SUFFIX(OP_lengths_)+#define get_ucpname PCRE2_SUFFIX(get_ucpname_)+#define pcre2_printint PCRE2_SUFFIX(pcre2_printint_)+#define print_char PCRE2_SUFFIX(print_char_)+#define print_custring PCRE2_SUFFIX(print_custring_)+#define print_custring_bylen PCRE2_SUFFIX(print_custring_bylen_)+#define print_prop PCRE2_SUFFIX(print_prop_)+#define print_char_list PCRE2_SUFFIX(print_char_list_)+#define print_map PCRE2_SUFFIX(print_map_)+#define print_class PCRE2_SUFFIX(print_class_)++/* Table of sizes for the fixed-length opcodes. It's defined in a macro so that+the definition is next to the definition of the opcodes in pcre2_internal.h.+The contents of the table are, however, mode-dependent. */++static const uint8_t OP_lengths[] = { OP_LENGTHS };+STATIC_ASSERT(sizeof(OP_lengths)/sizeof(*OP_lengths) == OP_TABLE_LENGTH,+ PCRE2_SUFFIX(OP_lengths_));+++/*************************************************+* Print one character from a string *+*************************************************/++/* In UTF mode the character may occupy more than one code unit.++Arguments:+ f file to write to+ ptr pointer to first code unit of the character+ utf TRUE if string is UTF (will be FALSE if UTF is not supported)++Returns: number of additional code units used+*/++static unsigned int+print_char(FILE *f, PCRE2_SPTR ptr, BOOL utf)+{+uint32_t c = *ptr;+BOOL one_code_unit = !utf;++/* If UTF is supported and requested, check for a valid single code unit. */++#ifdef SUPPORT_UNICODE+if (utf)+ {+#if PCRE2_CODE_UNIT_WIDTH == 8+ one_code_unit = c < 0x80;+#elif PCRE2_CODE_UNIT_WIDTH == 16+ one_code_unit = (c & 0xfc00) != 0xd800;+#else+ one_code_unit = (c & 0xfffff800u) != 0xd800u;+#endif /* CODE_UNIT_WIDTH */+ }+#endif /* SUPPORT_UNICODE */++/* Handle a valid one-code-unit character at any width. */++if (one_code_unit)+ {+ if (PRINTABLE(c))+ fprintf(f, "%c", CHAR_OUTPUT(c));+ else+ {+ c = CHAR_OUTPUT_HEX(c);+ if (c < 0x80) fprintf(f, "\\x%02x", c);+ else fprintf(f, "\\x{%02x}", c);+ }+ return 0;+ }++/* Code for invalid UTF code units and multi-unit UTF characters is different+for each width. If UTF is not supported, control should never get here, but we+need a return statement to keep the compiler happy. */++#ifndef SUPPORT_UNICODE+return 0;+#else++/* Malformed UTF-8 should occur only if the sanity check has been turned off.+Rather than swallow random bytes, just stop if we hit a bad one. Print it with+\X instead of \x as an indication. */++#if PCRE2_CODE_UNIT_WIDTH == 8+if ((c & 0xc0) != 0xc0)+ {+ fprintf(f, "\\X{%x}", c); /* Invalid starting byte */+ return 0;+ }+else+ {+ int i;+ int a = PRIV(utf8_table4)[c & 0x3f]; /* Number of additional bytes */+ int s = 6*a;+ c = (c & PRIV(utf8_table3)[a]) << s;+ for (i = 1; i <= a; i++)+ {+ if ((ptr[i] & 0xc0) != 0x80)+ {+ fprintf(f, "\\X{%x}", c); /* Invalid secondary byte */+ return i - 1;+ }+ s -= 6;+ c |= (ptr[i] & 0x3f) << s;+ }+ fprintf(f, "\\x{%x}", c);+ return a;+}+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */++/* UTF-16: rather than swallow a low surrogate, just stop if we hit a bad one.+Print it with \X instead of \x as an indication. */++#if PCRE2_CODE_UNIT_WIDTH == 16+if ((ptr[1] & 0xfc00) != 0xdc00)+ {+ fprintf(f, "\\X{%x}", c);+ return 0;+ }+c = (((c & 0x3ff) << 10) | (ptr[1] & 0x3ff)) + 0x10000;+fprintf(f, "\\x{%x}", c);+return 1;+#endif /* PCRE2_CODE_UNIT_WIDTH == 16 */++/* For UTF-32 we get here only for a malformed code unit, which should only+occur if the sanity check has been turned off. Print it with \X instead of \x+as an indication. */++#if PCRE2_CODE_UNIT_WIDTH == 32+fprintf(f, "\\X{%x}", c);+return 0;+#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */+#endif /* SUPPORT_UNICODE */+}++++/*************************************************+* Print string as a list of code units *+*************************************************/++/* These take no account of UTF as they always print each individual code unit.+The string is zero-terminated for print_custring(); the length is given for+print_custring_bylen().++Arguments:+ f file to write to+ ptr point to the string+ len length for print_custring_bylen()++Returns: nothing+*/++static void+print_custring(FILE *f, PCRE2_SPTR ptr)+{+while (*ptr != '\0')+ {+ uint32_t c = *ptr++;+ if (PRINTABLE(c)) fprintf(f, "%c", CHAR_OUTPUT(c));+ else fprintf(f, "\\x{%x}", CHAR_OUTPUT_HEX(c));+ }+}++static void+print_custring_bylen(FILE *f, PCRE2_SPTR ptr, PCRE2_UCHAR len)+{+for (; len > 0; len--)+ {+ uint32_t c = *ptr++;+ if (PRINTABLE(c)) fprintf(f, "%c", CHAR_OUTPUT(c));+ else fprintf(f, "\\x{%x}", CHAR_OUTPUT_HEX(c));+ }+}++++/*************************************************+* Find Unicode property name *+*************************************************/++/* When there is no UTF/UCP support, the table of names does not exist. This+function should not be called in such configurations, because a pattern that+tries to use Unicode properties won't compile. Rather than put lots of #ifdefs+into the main code, however, we just put one into this function.++Now that the table contains both full names and their abbreviations, we do some+fiddling to try to get the full name, which is either the longer of two found+names, or a 3-character script name. */++static const char *+get_ucpname(unsigned int ptype, unsigned int pvalue)+{+#ifdef SUPPORT_UNICODE+int count = 0;+const char *yield = "??";+size_t len = 0;+unsigned int ptypex = (ptype == PT_SC)? PT_SCX : ptype;++for (ptrdiff_t i = PRIV(utt_size) - 1; i >= 0; i--)+ {+ const ucp_type_table *u = PRIV(utt) + i;++ if ((ptype == u->type || ptypex == u->type) && pvalue == u->value)+ {+ const char *s = PRIV(utt_names) + u->name_offset;+ size_t sl = strlen(s);++ if (sl == 3 && (u->type == PT_SC || u->type == PT_SCX))+ {+ yield = s;+ break;+ }++ if (sl > len)+ {+ yield = s;+ len = sl;+ }++ if (++count >= 2) break;+ }+ }++return yield;++#else /* No UTF support */+(void)ptype;+(void)pvalue;+return "??";+#endif /* SUPPORT_UNICODE */+}++++/*************************************************+* Print Unicode property value *+*************************************************/++/* "Normal" properties can be printed from tables. The PT_CLIST property is a+pseudo-property that contains a pointer to a list of case-equivalent+characters.++Arguments:+ f file to write to+ code pointer in the compiled code+ before text to print before+ after text to print after++Returns: nothing+*/++static void+print_prop(FILE *f, PCRE2_SPTR code, const char *before, const char *after)+{+if (code[1] != PT_CLIST)+ {+ const char *sc = (code[1] == PT_SC)? "script:" : "";+ const char *s = get_ucpname(code[1], code[2]);+ fprintf(f, "%s%s %s%c%s%s", before, OP_names[*code], sc, toupper(s[0]), s+1, after);+ }+else+ {+ const uint32_t *p = PRIV(ucd_caseless_sets) + code[2];+ fprintf (f, "%s%sclist", before, (*code == OP_PROP)? "" : "not ");+ while (*p < NOTACHAR) fprintf(f, " %04x", *p++);+ fprintf(f, "%s", after);+ }+}++++/*************************************************+* Print character list *+*************************************************/++/* Prints the characters and character ranges in a character list.++Arguments:+ f file to write to+ code pointer in the compiled code+*/++static PCRE2_SPTR+print_char_list(FILE *f, PCRE2_SPTR code, const uint8_t *char_lists_end)+{+uint32_t type, list_ind;+uint32_t char_list_add = XCL_CHAR_LIST_LOW_16_ADD;+uint32_t range_start = ~(uint32_t)0, range_end = 0;+const uint8_t *next_char;++#if PCRE2_CODE_UNIT_WIDTH == 8+type = (uint32_t)(code[0] << 8) | code[1];+code += 2;+#else+type = code[0];+code++;+#endif /* CODE_UNIT_WIDTH */++/* Align characters. */+next_char = char_lists_end - (GET(code, 0) << 1);+type &= XCL_TYPE_MASK;+list_ind = 0;++if ((type & XCL_BEGIN_WITH_RANGE) != 0)+ range_start = XCL_CHAR_LIST_LOW_16_START;++while (type > 0)+ {+ uint32_t item_count = type & XCL_ITEM_COUNT_MASK;++ if (item_count == XCL_ITEM_COUNT_MASK)+ {+ if (list_ind <= 1)+ {+ item_count = *(const uint16_t*)next_char;+ next_char += 2;+ }+ else+ {+ item_count = *(const uint32_t*)next_char;+ next_char += 4;+ }+ }++ while (item_count > 0)+ {+ if (list_ind <= 1)+ {+ range_end = *(const uint16_t*)next_char;+ next_char += 2;+ }+ else+ {+ range_end = *(const uint32_t*)next_char;+ next_char += 4;+ }++ if ((range_end & XCL_CHAR_END) != 0)+ {+ range_end = char_list_add + (range_end >> XCL_CHAR_SHIFT);++ if (range_start < range_end)+ fprintf(f, "\\x{%x}-", range_start);++ fprintf(f, "\\x{%x}", range_end);+ range_start = ~(uint32_t)0;+ }+ else+ range_start = char_list_add + (range_end >> XCL_CHAR_SHIFT);++ item_count--;+ }++ list_ind++;+ type >>= XCL_TYPE_BIT_LEN;++ /* The following code could be optimized to 8/16/32 bit,+ but it is not worth it for a debugging function. */++ if (range_start == ~(uint32_t)0)+ {+ if ((type & XCL_BEGIN_WITH_RANGE) != 0)+ {+ if (list_ind == 1) range_start = XCL_CHAR_LIST_HIGH_16_START;+ else if (list_ind == 2) range_start = XCL_CHAR_LIST_LOW_32_START;+ else range_start = XCL_CHAR_LIST_HIGH_32_START;+ }+ }+ else if ((type & XCL_BEGIN_WITH_RANGE) == 0)+ {+ fprintf(f, "\\x{%x}-", range_start);++ if (list_ind == 1) range_end = XCL_CHAR_LIST_LOW_16_END;+ else if (list_ind == 2) range_end = XCL_CHAR_LIST_HIGH_16_END;+ else if (list_ind == 3) range_end = XCL_CHAR_LIST_LOW_32_END;+ else range_end = XCL_CHAR_LIST_HIGH_32_END;++ fprintf(f, "\\x{%x}", range_end);+ range_start = ~(uint32_t)0;+ }++ if (list_ind == 1) char_list_add = XCL_CHAR_LIST_HIGH_16_ADD;+ else if (list_ind == 2) char_list_add = XCL_CHAR_LIST_LOW_32_ADD;+ else char_list_add = XCL_CHAR_LIST_HIGH_32_ADD;+ }++return code + LINK_SIZE;+}++++/*************************************************+* Print a character bitmap *+*************************************************/++/* Prints a 32-byte bitmap, which occurs within a character class opcode.++Arguments:+ f file to write to+ map pointer to the bitmap+ negated TRUE if the bitmap will be printed as negated++Returns: nothing+*/++static void+print_map(FILE *f, const uint8_t *map, BOOL negated)+{+BOOL first = TRUE;+uint8_t inverted_map[32];+int i, input;++if (negated)+ {+ /* Using 255 ^ instead of ~ avoids clang sanitize warning. */+ for (i = 0; i < 32; i++) inverted_map[i] = 255 ^ map[i];+ map = inverted_map;+ }++for (input = 0; input < 256; input++)+ {+ i = CHAR_INPUT_HEX(input);+ if ((map[i/8] & (1u << (i&7))) != 0)+ {+ int j, jinput;+ for (jinput = input; jinput+1 < 256; jinput++)+ {+ j = CHAR_INPUT_HEX(jinput+1);+ if ((map[j/8] & (1u << (j&7))) == 0) break;+ }+ j = CHAR_INPUT_HEX(jinput);+ if (i == CHAR_MINUS || i == CHAR_BACKSLASH ||+ i == CHAR_RIGHT_SQUARE_BRACKET ||+ (first && i == CHAR_CIRCUMFLEX_ACCENT))+ fprintf(f, "\\");+ if (PRINTABLE(i)) fprintf(f, "%c", CHAR_OUTPUT(i));+ else fprintf(f, "\\x%02x", CHAR_OUTPUT_HEX(i));+ first = FALSE;+ if (jinput > input)+ {+ if (jinput != input + 1) fprintf(f, "-");+ if (j == CHAR_MINUS || j == CHAR_BACKSLASH ||+ j == CHAR_RIGHT_SQUARE_BRACKET)+ fprintf(f, "\\");+ if (PRINTABLE(j)) fprintf(f, "%c", CHAR_OUTPUT(j));+ else fprintf(f, "\\x%02x", CHAR_OUTPUT_HEX(j));+ }+ input = jinput;+ }+ }+}++++/*************************************************+* Print character class *+*************************************************/++/* Prints a character class, which must be either an OP_CLASS, OP_NCLASS, or+OP_XCLASS.++Arguments:+ f file to write to+ type OP_CLASS, OP_NCLASS, or OP_XCLASS+ code pointer in the compiled code (after the OP tag)+ utf TRUE if re is UTF (will be FALSE if UTF is not supported)+ before text to print before+ after text to print after++Returns: nothing+*/++static void+print_class(FILE *f, int type, PCRE2_SPTR code, const uint8_t *char_lists_end,+ BOOL utf, const char *before, const char *after)+{+BOOL printmap, negated;+PCRE2_SPTR ccode;++/* Negative XCLASS and NCLASS both have a bitmap indicating which characters+are accepted. For clarity we print this inverted and prefixed by "^". */+if (type == OP_XCLASS)+ {+ ccode = code + LINK_SIZE;+ printmap = (*ccode & XCL_MAP) != 0;+ negated = (*ccode & XCL_NOT) != 0;+ ccode++;+ }+else /* CLASS or NCLASS */+ {+ printmap = TRUE;+ negated = type == OP_NCLASS;+ ccode = code;+ }++fprintf(f, "%s[%s", before, negated? "^" : "");++/* Print a bit map */+if (printmap)+ {+ print_map(f, (const uint8_t *)ccode, negated);+ ccode += 32 / sizeof(PCRE2_UCHAR);+ }++/* For an XCLASS there is always some additional data */+if (type == OP_XCLASS)+ {+ PCRE2_UCHAR ch;++ while ((ch = *ccode++) != XCL_END)+ {+ const char *notch = "";++ if (ch >= XCL_LIST)+ {+ ccode = print_char_list(f, ccode - 1, char_lists_end);+ break;+ }++ switch(ch)+ {+ case XCL_NOTPROP:+ notch = "^";+ PCRE2_FALLTHROUGH /* Fall through */+ case XCL_PROP:+ {+ unsigned int ptype = *ccode++;+ unsigned int pvalue = *ccode++;+ const char *s;+ switch(ptype)+ {+ case PT_PXGRAPH:+ fprintf(f, "[:%sgraph:]", notch);+ break;+ case PT_PXPRINT:+ fprintf(f, "[:%sprint:]", 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}", ((notch[0] == '^')? 'P':'p'),+ toupper(s[0]), s+1);+ break;+ }+ }+ break;++ default:+ ccode += 1 + print_char(f, ccode, utf);+ if (ch == XCL_RANGE)+ {+ fprintf(f, "-");+ ccode += 1 + print_char(f, ccode, utf);+ }+ break;+ }+ }++ PCRE2_ASSERT(ccode == code + (GET(code, 0) - 1));+ }++/* Indicate a non-UTF class which was created by negation */+fprintf(f, "]%s", after);+}++++/*************************************************+* Print compiled pattern *+*************************************************/++/* The print_lengths flag controls whether offsets and lengths of items are+printed. Lenths can be turned off from pcre2test so that automatic tests on+bytecode can be written that do not depend on the value of LINK_SIZE.++Arguments:+ re a compiled pattern+ f the file to write to+ print_lengths show various lengths++Returns: nothing+*/++static void+pcre2_printint(pcre2_code *re, FILE *f, BOOL print_lengths)+{+PCRE2_SPTR codestart, nametable, code;+uint32_t nesize = re->name_entry_size;+BOOL utf = (re->overall_options & PCRE2_UTF) != 0;++nametable = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code));+code = codestart = (PCRE2_SPTR)((uint8_t *)re + re->code_start);++for(;;)+ {+ PCRE2_SPTR ccode;+ uint32_t c;+ int i;+ const char *flag = " ";+ unsigned int extra = 0;++ if (print_lengths)+ fprintf(f, "%3d ", (int)(code - codestart));+ else+ fprintf(f, " ");++ switch(*code)+ {+ case OP_END:+ fprintf(f, " %s\n", OP_names[*code]);+ fprintf(f, "------------------------------------------------------------------\n");+ return;++ case OP_CHAR:+ fprintf(f, " ");+ do+ {+ code++;+ code += 1 + print_char(f, code, utf);+ }+ while (*code == OP_CHAR);+ fprintf(f, "\n");+ continue;++ case OP_CHARI:+ fprintf(f, " /i ");+ do+ {+ code++;+ code += 1 + print_char(f, code, utf);+ }+ while (*code == OP_CHARI);+ fprintf(f, "\n");+ continue;++ case OP_CBRA:+ case OP_CBRAPOS:+ case OP_SCBRA:+ case OP_SCBRAPOS:+ if (print_lengths) fprintf(f, "%3d ", GET(code, 1));+ else fprintf(f, " ");+ fprintf(f, "%s %d", OP_names[*code], GET2(code, 1+LINK_SIZE));+ break;++ case OP_BRA:+ case OP_BRAPOS:+ case OP_SBRA:+ case OP_SBRAPOS:+ case OP_KETRMAX:+ case OP_KETRMIN:+ case OP_KETRPOS:+ case OP_ALT:+ case OP_KET:+ case OP_ASSERT:+ case OP_ASSERT_NOT:+ case OP_ASSERTBACK:+ case OP_ASSERTBACK_NOT:+ case OP_ASSERT_NA:+ case OP_ASSERTBACK_NA:+ case OP_ASSERT_SCS:+ case OP_ONCE:+ case OP_SCRIPT_RUN:+ case OP_COND:+ case OP_SCOND:+ if (print_lengths) fprintf(f, "%3d ", GET(code, 1));+ else fprintf(f, " ");+ fprintf(f, "%s", OP_names[*code]);+ break;++ case OP_CLOSE:+ fprintf(f, " %s %d", OP_names[*code], GET2(code, 1));+ break;++ case OP_CREF:+ case OP_REVERSE:+ case OP_VREVERSE:+ fprintf(f, "%3d %s", GET2(code, 1), OP_names[*code]);+ if (*code == OP_VREVERSE) fprintf(f, " %d", GET2(code, 1 + IMM2_SIZE));+ break;++ case OP_DNCREF:+ case OP_DNRREF:+ {+ PCRE2_SPTR entry = nametable + (GET2(code, 1) * nesize) + IMM2_SIZE;+ fprintf(f, " %s %s<", flag, OP_names[*code]);+ print_custring(f, entry);+ fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));+ }+ break;++ case OP_RREF:+ c = GET2(code, 1);+ if (c == RREF_ANY)+ fprintf(f, " %s any", OP_names[*code]);+ else+ fprintf(f, " %s %d", OP_names[*code], c);+ break;++ case OP_STARI:+ case OP_MINSTARI:+ case OP_POSSTARI:+ case OP_PLUSI:+ case OP_MINPLUSI:+ case OP_POSPLUSI:+ case OP_QUERYI:+ case OP_MINQUERYI:+ case OP_POSQUERYI:+ flag = "/i";+ PCRE2_FALLTHROUGH /* Fall through */+ case OP_STAR:+ case OP_MINSTAR:+ case OP_POSSTAR:+ case OP_PLUS:+ case OP_MINPLUS:+ case OP_POSPLUS:+ case OP_QUERY:+ case OP_MINQUERY:+ case OP_POSQUERY:+ case OP_TYPESTAR:+ case OP_TYPEMINSTAR:+ case OP_TYPEPOSSTAR:+ case OP_TYPEPLUS:+ case OP_TYPEMINPLUS:+ case OP_TYPEPOSPLUS:+ case OP_TYPEQUERY:+ case OP_TYPEMINQUERY:+ case OP_TYPEPOSQUERY:+ fprintf(f, " %s ", flag);++ if (*code >= OP_TYPESTAR)+ {+ if (code[1] == OP_PROP || code[1] == OP_NOTPROP)+ {+ print_prop(f, code + 1, "", " ");+ extra = 2;+ }+ else fprintf(f, "%s", OP_names[code[1]]);+ }+ else extra = print_char(f, code+1, utf);+ fprintf(f, "%s", OP_names[*code]);+ break;++ case OP_EXACTI:+ case OP_UPTOI:+ case OP_MINUPTOI:+ case OP_POSUPTOI:+ flag = "/i";+ PCRE2_FALLTHROUGH /* Fall through */+ case OP_EXACT:+ case OP_UPTO:+ case OP_MINUPTO:+ case OP_POSUPTO:+ fprintf(f, " %s ", flag);+ extra = print_char(f, code + 1 + IMM2_SIZE, utf);+ fprintf(f, "{");+ if (*code != OP_EXACT && *code != OP_EXACTI) fprintf(f, "0,");+ fprintf(f, "%d}", GET2(code,1));+ if (*code == OP_MINUPTO || *code == OP_MINUPTOI) fprintf(f, "?");+ else if (*code == OP_POSUPTO || *code == OP_POSUPTOI) fprintf(f, "+");+ break;++ case OP_TYPEEXACT:+ case OP_TYPEUPTO:+ case OP_TYPEMINUPTO:+ case OP_TYPEPOSUPTO:+ if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)+ {+ print_prop(f, code + IMM2_SIZE + 1, " ", " ");+ extra = 2;+ }+ else fprintf(f, " %s", OP_names[code[1 + IMM2_SIZE]]);+ fprintf(f, "{");+ if (*code != OP_TYPEEXACT) fprintf(f, "0,");+ fprintf(f, "%d}", GET2(code,1));+ if (*code == OP_TYPEMINUPTO) fprintf(f, "?");+ else if (*code == OP_TYPEPOSUPTO) fprintf(f, "+");+ break;++ case OP_NOTI:+ flag = "/i";+ PCRE2_FALLTHROUGH /* Fall through */+ case OP_NOT:+ fprintf(f, " %s [^", flag);+ extra = print_char(f, code + 1, utf);+ fprintf(f, "] (not)");+ break;++ case OP_NOTSTARI:+ case OP_NOTMINSTARI:+ case OP_NOTPOSSTARI:+ case OP_NOTPLUSI:+ case OP_NOTMINPLUSI:+ case OP_NOTPOSPLUSI:+ case OP_NOTQUERYI:+ case OP_NOTMINQUERYI:+ case OP_NOTPOSQUERYI:+ flag = "/i";+ PCRE2_FALLTHROUGH /* Fall through */++ case OP_NOTSTAR:+ case OP_NOTMINSTAR:+ case OP_NOTPOSSTAR:+ case OP_NOTPLUS:+ case OP_NOTMINPLUS:+ case OP_NOTPOSPLUS:+ case OP_NOTQUERY:+ case OP_NOTMINQUERY:+ case OP_NOTPOSQUERY:+ fprintf(f, " %s [^", flag);+ extra = print_char(f, code + 1, utf);+ fprintf(f, "]%s (not)", OP_names[*code]);+ break;++ case OP_NOTEXACTI:+ case OP_NOTUPTOI:+ case OP_NOTMINUPTOI:+ case OP_NOTPOSUPTOI:+ flag = "/i";+ PCRE2_FALLTHROUGH /* Fall through */++ case OP_NOTEXACT:+ case OP_NOTUPTO:+ case OP_NOTMINUPTO:+ case OP_NOTPOSUPTO:+ fprintf(f, " %s [^", flag);+ extra = print_char(f, code + 1 + IMM2_SIZE, utf);+ fprintf(f, "]{");+ if (*code != OP_NOTEXACT && *code != OP_NOTEXACTI) fprintf(f, "0,");+ fprintf(f, "%d}", GET2(code,1));+ if (*code == OP_NOTMINUPTO || *code == OP_NOTMINUPTOI) fprintf(f, "?");+ else+ if (*code == OP_NOTPOSUPTO || *code == OP_NOTPOSUPTOI) fprintf(f, "+");+ fprintf(f, " (not)");+ break;++ case OP_RECURSE:+ if (print_lengths) fprintf(f, "%3d ", GET(code, 1));+ else fprintf(f, " ");+ fprintf(f, "%s", OP_names[*code]);+ break;++ case OP_REFI:+ flag = "/i";+ PCRE2_FALLTHROUGH /* Fall through */+ case OP_REF:+ fprintf(f, " %s \\g{%d}", flag, GET2(code, 1));+ i = (*code == OP_REFI)? code[1 + IMM2_SIZE] : 0;+ if (i != 0) fprintf(f, " 0x%02x", i);+ ccode = code + OP_lengths[*code];+ goto CLASS_REF_REPEAT;++ case OP_DNREFI:+ flag = "/i";+ PCRE2_FALLTHROUGH /* Fall through */+ case OP_DNREF:+ {+ PCRE2_SPTR entry = nametable + (GET2(code, 1) * nesize) + IMM2_SIZE;+ fprintf(f, " %s \\k<", flag);+ print_custring(f, entry);+ fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));+ i = (*code == OP_DNREFI)? code[1 + 2*IMM2_SIZE] : 0;+ if (i != 0) fprintf(f, " 0x%02x", i);+ }+ ccode = code + OP_lengths[*code];+ goto CLASS_REF_REPEAT;++ case OP_CALLOUT:+ fprintf(f, " %s %d %d %d", OP_names[*code], code[1 + 2*LINK_SIZE],+ GET(code, 1), GET(code, 1 + LINK_SIZE));+ break;++ case OP_CALLOUT_STR:+ c = code[1 + 4*LINK_SIZE];+ fprintf(f, " %s %c", OP_names[*code], CHAR_OUTPUT(c));+ extra = GET(code, 1 + 2*LINK_SIZE);+ print_custring_bylen(f, code + 2 + 4*LINK_SIZE, extra - 3 - 4*LINK_SIZE);+ for (i = 0; PRIV(callout_start_delims)[i] != 0; i++)+ if (c == PRIV(callout_start_delims)[i])+ {+ c = PRIV(callout_end_delims)[i];+ break;+ }+ fprintf(f, "%c %d %d %d", CHAR_OUTPUT(c), GET(code, 1 + 3*LINK_SIZE),+ GET(code, 1), GET(code, 1 + LINK_SIZE));+ break;++ case OP_PROP:+ case OP_NOTPROP:+ print_prop(f, code, " ", "");+ break;++#ifdef SUPPORT_WIDE_CHARS+ case OP_ECLASS:+ extra = GET(code, 1);+ fprintf(f, " eclass[\n");+ /* We print the opcodes contained inside as well. */+ ccode = code + 1 + LINK_SIZE + 1;+ if ((ccode[-1] & ECL_MAP) != 0)+ {+ const uint8_t *map = (const uint8_t *)ccode;+ /* The first 6 ASCII characters (SOH...ACK) are totally, utterly useless.+ If they're set in the bitmap, then it's clearly been formed by negation.*/+ BOOL print_negated = (map[0] & 0x7e) == 0x7e;++ fprintf(f, " bitmap: [%s", print_negated? "^" : "");+ print_map(f, map, print_negated);+ fprintf(f, "]\n");+ ccode += 32 / sizeof(PCRE2_UCHAR);+ }+ else+ fprintf(f, " no bitmap\n");+ while (ccode < code + extra)+ {+ if (print_lengths)+ fprintf(f, "%3d ", (int)(ccode - codestart));+ else+ fprintf(f, " ");++ switch (*ccode)+ {+ case ECL_AND:+ fprintf(f, " AND\n");+ ccode += 1;+ break;+ case ECL_OR:+ fprintf(f, " OR\n");+ ccode += 1;+ break;+ case ECL_XOR:+ fprintf(f, " XOR\n");+ ccode += 1;+ break;+ case ECL_NOT:+ fprintf(f, " NOT\n");+ ccode += 1;+ break;++ case ECL_XCLASS:+ print_class(f, OP_XCLASS, ccode+1, (uint8_t*)codestart, utf,+ " xclass: ", "\n");+ ccode += GET(ccode, 1);+ break;++ default:+ fprintf(f, " UNEXPECTED\n");+ ccode += 1;+ break;+ }+ }+ fprintf(f, " ]");+ goto CLASS_REF_REPEAT;+#endif /* SUPPORT_WIDE_CHARS */++ case OP_CLASS:+ case OP_NCLASS:+#ifdef SUPPORT_WIDE_CHARS+ case OP_XCLASS:+ if (*code == OP_XCLASS)+ extra = GET(code, 1);+#endif+ print_class(f, *code, code+1, (uint8_t*)codestart, utf, " ", "");+ ccode = code + OP_lengths[*code] + extra;++ /* Handle repeats after a class or a back reference */++ CLASS_REF_REPEAT:+ switch(*ccode)+ {+ unsigned int min, max;++ 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;++ 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;++ /* 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;++ case OP_MARK:+ case OP_COMMIT_ARG:+ case OP_PRUNE_ARG:+ case OP_SKIP_ARG:+ case OP_THEN_ARG:+ fprintf(f, " %s ", OP_names[*code]);+ print_custring_bylen(f, code + 2, code[1]);+ extra += code[1];+ break;++ case OP_CIRCM:+ case OP_DOLLM:+ flag = "/m";+ PCRE2_FALLTHROUGH /* Fall through */++ /* Anything else is just an item with no data, but possibly a flag. */++ default:+ fprintf(f, " %s %s", flag, OP_names[*code]);+ break;+ }++ code += OP_lengths[*code] + extra;+ putc('\n', f);+ }+}++/* End of pcre2_printint_inc.h */
src/c/pcre2/src/pcre2_script_run.c view
@@ -38,13 +38,12 @@ ----------------------------------------------------------------------------- */ + /* This module contains the function for checking a script run. */ -#ifdef HAVE_CONFIG_H-#include "config.h"-#endif #include "pcre2_internal.h"+ /*************************************************
src/c/pcre2/src/pcre2_serialize.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-2020 University of Cambridge+ New API code Copyright (c) 2016-2024 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -38,16 +38,14 @@ ----------------------------------------------------------------------------- */ + /* This module contains functions for serializing and deserializing a sequence of compiled codes. */ -#ifdef HAVE_CONFIG_H-#include "config.h"-#endif+#include "pcre2_internal.h" -#include "pcre2_internal.h" /* Magic number to provide a small check against being handed junk. */ @@ -127,25 +125,25 @@ for (i = 0; i < number_of_codes; i++) { re = (const pcre2_real_code *)(codes[i]);- (void)memcpy(dst_bytes, (char *)re, re->blocksize);- - /* Certain fields in the compiled code block are re-set during - deserialization. In order to ensure that the serialized data stream is always - the same for the same pattern, set them to zero here. We can't assume the - copy of the pattern is correctly aligned for accessing the fields as part of + (void)memcpy(dst_bytes, (const char *)re, re->blocksize);++ /* Certain fields in the compiled code block are re-set during+ deserialization. In order to ensure that the serialized data stream is always+ the same for the same pattern, set them to zero here. We can't assume the+ copy of the pattern is correctly aligned for accessing the fields as part of a structure. Note the use of sizeof(void *) in the second of these, to- specify the size of a pointer. If sizeof(uint8_t *) is used (tables is a - pointer to uint8_t), gcc gives a warning because the first argument is also a - pointer to uint8_t. Casting the first argument to (void *) can stop this, but + specify the size of a pointer. If sizeof(uint8_t *) is used (tables is a+ pointer to uint8_t), gcc gives a warning because the first argument is also a+ pointer to uint8_t. Casting the first argument to (void *) can stop this, but it didn't stop Coverity giving the same complaint. */- - (void)memset(dst_bytes + offsetof(pcre2_real_code, memctl), 0, ++ (void)memset(dst_bytes + offsetof(pcre2_real_code, memctl), 0, sizeof(pcre2_memctl));- (void)memset(dst_bytes + offsetof(pcre2_real_code, tables), 0, + (void)memset(dst_bytes + offsetof(pcre2_real_code, tables), 0, sizeof(void *)); (void)memset(dst_bytes + offsetof(pcre2_real_code, executable_jit), 0,- sizeof(void *)); - + sizeof(void *));+ dst_bytes += re->blocksize; } @@ -232,10 +230,10 @@ if (dst_re->magic_number != MAGIC_NUMBER || dst_re->name_entry_size > MAX_NAME_SIZE + IMM2_SIZE + 1 || dst_re->name_count > MAX_NAME_COUNT)- { - memctl->free(dst_re, memctl->memory_data); + {+ memctl->free(dst_re, memctl->memory_data); return PCRE2_ERROR_BADSERIALIZEDDATA;- } + } /* At the moment only one table is supported. */
src/c/pcre2/src/pcre2_string_utils.c view
@@ -38,52 +38,14 @@ ----------------------------------------------------------------------------- */ + /* This module contains internal functions for comparing and finding the length of strings. These are used instead of strcmp() etc because the standard functions work only on 8-bit data. */ -#ifdef HAVE_CONFIG_H-#include "config.h"-#endif- #include "pcre2_internal.h" --/*************************************************-* Emulated memmove() for systems without it *-*************************************************/--/* This function can make use of bcopy() if it is available. Otherwise do it by-steam, as there some non-Unix environments that lack both memmove() and-bcopy(). */--#if !defined(VPCOMPAT) && !defined(HAVE_MEMMOVE)-void *-PRIV(memmove)(void *d, const void *s, size_t n)-{-#ifdef HAVE_BCOPY-bcopy(s, d, n);-return d;-#else-size_t i;-unsigned char *dest = (unsigned char *)d;-const unsigned char *src = (const unsigned char *)s;-if (dest > src)- {- dest += n;- src += n;- for (i = 0; i < n; ++i) *(--dest) = *(--src);- return (void *)dest;- }-else- {- for (i = 0; i < n; ++i) *dest++ = *src++;- return (void *)(dest - n);- }-#endif /* not HAVE_BCOPY */-}-#endif /* not VPCOMPAT && not HAVE_MEMMOVE */ /*************************************************
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-2023 University of Cambridge+ New API code Copyright (c) 2016-2024 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -38,16 +38,15 @@ ----------------------------------------------------------------------------- */ + /* This module contains functions for scanning a compiled pattern and collecting data (e.g. minimum matching length). */ -#ifdef HAVE_CONFIG_H-#include "config.h"-#endif- #include "pcre2_internal.h" ++ /* The maximum remembered capturing brackets minimum. */ #define MAX_CACHE_BACKREF 128@@ -114,7 +113,7 @@ BOOL had_recurse = FALSE; BOOL dupcapused = (re->flags & PCRE2_DUPCAPUSED) != 0; PCRE2_SPTR nextbranch = code + GET(code, 1);-PCRE2_UCHAR *cc = (PCRE2_UCHAR *)code + 1 + LINK_SIZE;+PCRE2_SPTR cc = code + 1 + LINK_SIZE; recurse_check this_recurse; /* If this is a "could be empty" group, its minimum length is 0. */@@ -136,12 +135,13 @@ for (;;) { int d, min, recno;- PCRE2_UCHAR op, *cs, *ce;+ PCRE2_UCHAR op;+ PCRE2_SPTR cs, ce; - if (branchlength >= UINT16_MAX)+ if (branchlength >= (int)UINT16_MAX) { branchlength = UINT16_MAX;- cc = (PCRE2_UCHAR *)nextbranch;+ cc = nextbranch; } op = *cc;@@ -175,7 +175,7 @@ cc += 1 + LINK_SIZE; break; }- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case OP_ONCE: case OP_SCRIPT_RUN:@@ -249,9 +249,10 @@ case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: case OP_ASSERT_NA:+ case OP_ASSERT_SCS: case OP_ASSERTBACK_NA: do cc += GET(cc, 1); while (*cc == OP_ALT);- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ /* Skip over things that don't match chars */ @@ -351,7 +352,7 @@ case OP_PROP: case OP_NOTPROP: cc += 2;- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case OP_NOT_DIGIT: case OP_DIGIT:@@ -417,15 +418,14 @@ case OP_NCLASS: #ifdef SUPPORT_WIDE_CHARS case OP_XCLASS:+ case OP_ECLASS: /* The original code caused an unsigned overflow in 64 bit systems, so now we use a conditional statement. */- if (op == OP_XCLASS)+ if (op == OP_XCLASS || op == OP_ECLASS) cc += GET(cc, 1); else- cc += PRIV(OP_lengths)[OP_CLASS];-#else- cc += PRIV(OP_lengths)[OP_CLASS]; #endif+ cc += PRIV(OP_lengths)[OP_CLASS]; switch (*cc) {@@ -433,7 +433,7 @@ case OP_CRMINPLUS: case OP_CRPOSPLUS: branchlength++;- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case OP_CRSTAR: case OP_CRMINSTAR:@@ -479,8 +479,8 @@ if (!dupcapused && (re->overall_options & PCRE2_MATCH_UNSET_BACKREF) == 0) { int count = GET2(cc, 1+IMM2_SIZE);- PCRE2_UCHAR *slot =- (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code)) ++ PCRE2_SPTR slot =+ (PCRE2_SPTR)((const uint8_t *)re + sizeof(pcre2_real_code)) + GET2(cc, 1) * re->name_entry_size; d = INT_MAX;@@ -496,13 +496,12 @@ dd = backref_cache[recno]; else {- ce = cs = (PCRE2_UCHAR *)PRIV(find_bracket)(startcode, utf, recno);+ ce = cs = PRIV(find_bracket)(startcode, utf, recno); if (cs == NULL) return -2; do ce += GET(ce, 1); while (*ce == OP_ALT); dd = 0;- if (!dupcapused ||- (PCRE2_UCHAR *)PRIV(find_bracket)(ce, utf, recno) == NULL)+ if (!dupcapused || PRIV(find_bracket)(ce, utf, recno) == NULL) { if (cc > cs && cc < ce) /* Simple recursion */ {@@ -539,7 +538,7 @@ } } else d = 0;- cc += 1 + 2*IMM2_SIZE;+ cc += PRIV(OP_lengths)[*cc]; goto REPEAT_BACK_REFERENCE; /* Single back reference by number. References by name are converted to by@@ -557,12 +556,11 @@ if ((re->overall_options & PCRE2_MATCH_UNSET_BACKREF) == 0) {- ce = cs = (PCRE2_UCHAR *)PRIV(find_bracket)(startcode, utf, recno);+ ce = cs = PRIV(find_bracket)(startcode, utf, recno); if (cs == NULL) return -2; do ce += GET(ce, 1); while (*ce == OP_ALT); - if (!dupcapused ||- (PCRE2_UCHAR *)PRIV(find_bracket)(ce, utf, recno) == NULL)+ if (!dupcapused || PRIV(find_bracket)(ce, utf, recno) == NULL) { if (cc > cs && cc < ce) /* Simple recursion */ {@@ -593,7 +591,7 @@ backref_cache[0] = recno; } - cc += 1 + IMM2_SIZE;+ cc += PRIV(OP_lengths)[*cc]; /* Handle repeated back references */ @@ -629,11 +627,11 @@ break; } - /* Take care not to overflow: (1) min and d are ints, so check that their- product is not greater than INT_MAX. (2) branchlength is limited to- UINT16_MAX (checked at the top of the loop). */+ /* Take care not to overflow: (1) min and d are ints, so check that their+ product is not greater than INT_MAX. (2) branchlength is limited to+ UINT16_MAX (checked at the top of the loop). */ - if ((d > 0 && (INT_MAX/d) < min) || UINT16_MAX - branchlength < min*d)+ if ((d > 0 && (INT_MAX/d) < min) || (int)UINT16_MAX - branchlength < min*d) branchlength = UINT16_MAX; else branchlength += min * d; break;@@ -643,7 +641,7 @@ pattern contains multiple subpatterns with the same number. */ case OP_RECURSE:- cs = ce = (PCRE2_UCHAR *)startcode + GET(cc, 1);+ cs = ce = startcode + GET(cc, 1); recno = GET2(cs, 1+LINK_SIZE); if (recno == prev_recurse_recno) {@@ -754,11 +752,18 @@ /* This should not occur: we list all opcodes explicitly so that when new ones get added they are properly considered. */ + /* LCOV_EXCL_START */ default:+ PCRE2_DEBUG_UNREACHABLE(); return -3;+ /* LCOV_EXCL_STOP */ } }-/* Control never gets here */++/* LCOV_EXCL_START */+PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */+return -3; /* Avoid compiler warnings */+/* LCOV_EXCL_STOP */ } @@ -919,7 +924,139 @@ +#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 /*************************************************+* Set starting bits for a character list. *+*************************************************/++/* This function sets starting bits for a character list. It enumerates+all characters and character ranges in the character list, and sets+the starting bits accordingly.++Arguments:+ code pointer to the code+ start_bitmap pointer to the starting bitmap++Returns: nothing+*/+static void+study_char_list(PCRE2_SPTR code, uint8_t *start_bitmap,+ const uint8_t *char_lists_end)+{+uint32_t type, list_ind;+uint32_t char_list_add = XCL_CHAR_LIST_LOW_16_ADD;+uint32_t range_start = ~(uint32_t)0, range_end = 0;+const uint8_t *next_char;+PCRE2_UCHAR start_buffer[6], end_buffer[6];+PCRE2_UCHAR start, end;++/* Only needed in 8-bit mode at the moment. */+type = (uint32_t)(code[0] << 8) | code[1];+code += 2;++/* Align characters. */+next_char = char_lists_end - (GET(code, 0) << 1);+type &= XCL_TYPE_MASK;+list_ind = 0;++if ((type & XCL_BEGIN_WITH_RANGE) != 0)+ range_start = XCL_CHAR_LIST_LOW_16_START;++while (type > 0)+ {+ uint32_t item_count = type & XCL_ITEM_COUNT_MASK;++ if (item_count == XCL_ITEM_COUNT_MASK)+ {+ if (list_ind <= 1)+ {+ item_count = *(const uint16_t*)next_char;+ next_char += 2;+ }+ else+ {+ item_count = *(const uint32_t*)next_char;+ next_char += 4;+ }+ }++ while (item_count > 0)+ {+ if (list_ind <= 1)+ {+ range_end = *(const uint16_t*)next_char;+ next_char += 2;+ }+ else+ {+ range_end = *(const uint32_t*)next_char;+ next_char += 4;+ }++ if ((range_end & XCL_CHAR_END) != 0)+ {+ range_end = char_list_add + (range_end >> XCL_CHAR_SHIFT);++ PRIV(ord2utf)(range_end, end_buffer);+ end = end_buffer[0];++ if (range_start < range_end)+ {+ PRIV(ord2utf)(range_start, start_buffer);+ for (start = start_buffer[0]; start <= end; start++)+ start_bitmap[start / 8] |= (1u << (start & 7));+ }+ else+ start_bitmap[end / 8] |= (1u << (end & 7));++ range_start = ~(uint32_t)0;+ }+ else+ range_start = char_list_add + (range_end >> XCL_CHAR_SHIFT);++ item_count--;+ }++ list_ind++;+ type >>= XCL_TYPE_BIT_LEN;++ if (range_start == ~(uint32_t)0)+ {+ if ((type & XCL_BEGIN_WITH_RANGE) != 0)+ {+ /* In 8 bit mode XCL_CHAR_LIST_HIGH_32_START is not possible. */+ if (list_ind == 1) range_start = XCL_CHAR_LIST_HIGH_16_START;+ else range_start = XCL_CHAR_LIST_LOW_32_START;+ }+ }+ else if ((type & XCL_BEGIN_WITH_RANGE) == 0)+ {+ PRIV(ord2utf)(range_start, start_buffer);++ /* In 8 bit mode XCL_CHAR_LIST_LOW_32_END and+ XCL_CHAR_LIST_HIGH_32_END are not possible. */+ if (list_ind == 1) range_end = XCL_CHAR_LIST_LOW_16_END;+ else range_end = XCL_CHAR_LIST_HIGH_16_END;++ PRIV(ord2utf)(range_end, end_buffer);+ end = end_buffer[0];++ for (start = start_buffer[0]; start <= end; start++)+ start_bitmap[start / 8] |= (1u << (start & 7));++ range_start = ~(uint32_t)0;+ }++ /* In 8 bit mode XCL_CHAR_LIST_HIGH_32_ADD is not possible. */+ if (list_ind == 1) char_list_add = XCL_CHAR_LIST_HIGH_16_ADD;+ else char_list_add = XCL_CHAR_LIST_LOW_32_ADD;+ }+}+#endif++++/************************************************* * Create bitmap of starting code units * *************************************************/ @@ -980,7 +1117,7 @@ { int rc; PCRE2_SPTR ncode;- uint8_t *classmap = NULL;+ const uint8_t *classmap = NULL; #ifdef SUPPORT_WIDE_CHARS PCRE2_UCHAR xclassflags; #endif@@ -1134,6 +1271,7 @@ case OP_ASSERTBACK_NOT: case OP_ASSERT_NA: case OP_ASSERTBACK_NA:+ case OP_ASSERT_SCS: ncode += GET(ncode, 1); while (*ncode == OP_ALT) ncode += GET(ncode, 1); ncode += 1 + LINK_SIZE;@@ -1169,7 +1307,7 @@ case OP_PROP: if (ncode[1] != PT_CLIST) break;- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case OP_ANYNL: case OP_CHAR: case OP_CHARI:@@ -1193,7 +1331,7 @@ tcode = ncode; continue; /* With the following significant opcode */ }- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ /* For a group bracket or a positive assertion without an immediately following mandatory setting, recurse to set bits from within the@@ -1252,12 +1390,14 @@ tcode += GET(tcode, 1 + 2*LINK_SIZE); break; - /* Skip over lookbehind and negative lookahead assertions */+ /* Skip over lookbehind, negative lookahead, and scan substring+ assertions */ case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: case OP_ASSERTBACK_NA:+ case OP_ASSERT_SCS: do tcode += GET(tcode, 1); while (*tcode == OP_ALT); tcode += 1 + LINK_SIZE; break;@@ -1319,7 +1459,7 @@ case OP_EXACT: tcode += IMM2_SIZE;- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case OP_CHAR: case OP_PLUS: case OP_MINPLUS:@@ -1330,7 +1470,7 @@ case OP_EXACTI: tcode += IMM2_SIZE;- /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ case OP_CHARI: case OP_PLUSI: case OP_MINPLUSI:@@ -1350,10 +1490,10 @@ SET_BIT(CHAR_SPACE); /* For the 16-bit and 32-bit libraries (which can never be EBCDIC), set- the bits for 0xA0 and for code units >= 255, independently of UTF. */+ the bits for NBSP and for code units >= 255, independently of UTF. */ #if PCRE2_CODE_UNIT_WIDTH != 8- SET_BIT(0xA0);+ SET_BIT(CHAR_NBSP); SET_BIT(0xFF); #else /* For the 8-bit library in UTF-8 mode, set the bits for the first code@@ -1369,12 +1509,9 @@ } else #endif- /* For the 8-bit library not in UTF-8 mode, set the bit for 0xA0, unless- the code is EBCDIC. */+ /* For the 8-bit library not in UTF-8 mode, set the bit for NBSP. */ {-#ifndef EBCDIC- SET_BIT(0xA0);-#endif /* Not EBCDIC */+ SET_BIT(CHAR_NBSP); } #endif /* 8-bit support */ @@ -1469,7 +1606,8 @@ case OP_TYPEUPTO: case OP_TYPEMINUPTO: case OP_TYPEPOSUPTO:- tcode += IMM2_SIZE; /* Fall through */+ tcode += IMM2_SIZE;+ PCRE2_FALLTHROUGH /* Fall through */ case OP_TYPESTAR: case OP_TYPEMINSTAR:@@ -1489,10 +1627,10 @@ SET_BIT(CHAR_SPACE); /* For the 16-bit and 32-bit libraries (which can never be EBCDIC), set- the bits for 0xA0 and for code units >= 255, independently of UTF. */+ the bits for NBSP and for code units >= 255, independently of UTF. */ #if PCRE2_CODE_UNIT_WIDTH != 8- SET_BIT(0xA0);+ SET_BIT(CHAR_NBSP); SET_BIT(0xFF); #else /* For the 8-bit library in UTF-8 mode, set the bits for the first code@@ -1508,12 +1646,9 @@ } else #endif- /* For the 8-bit library not in UTF-8 mode, set the bit for 0xA0, unless- the code is EBCDIC. */+ /* For the 8-bit library not in UTF-8 mode, set the bit for NBSP. */ {-#ifndef EBCDIC- SET_BIT(0xA0);-#endif /* Not EBCDIC */+ SET_BIT(CHAR_NBSP); } #endif /* 8-bit support */ break;@@ -1578,6 +1713,13 @@ tcode += 2; break; + /* Set-based ECLASS: treat it the same as a "complex" XCLASS; give up. */++#ifdef SUPPORT_WIDE_CHARS+ case OP_ECLASS:+ return SSB_FAIL;+#endif+ /* Extended class: if there are any property checks, or if this is a negative XCLASS without a map, give up. If there are no property checks, there must be wide characters on the XCLASS list, because otherwise an@@ -1596,7 +1738,7 @@ map pointer if there is one, and fall through. */ classmap = ((xclassflags & XCL_MAP) == 0)? NULL :- (uint8_t *)(tcode + 1 + LINK_SIZE + 1);+ (const uint8_t *)(tcode + 1 + LINK_SIZE + 1); /* In UTF-8 mode, scan the character list and set bits for leading bytes, then jump to handle the map. */@@ -1608,6 +1750,13 @@ PCRE2_SPTR p = tcode + 1 + LINK_SIZE + 1 + ((classmap == NULL)? 0:32); tcode += GET(tcode, 1); + if (*p >= XCL_LIST)+ {+ study_char_list(p, re->start_bitmap,+ ((const uint8_t *)re + re->code_start));+ goto HANDLE_CLASSMAP;+ }+ for (;;) switch (*p++) { case XCL_SINGLE:@@ -1628,8 +1777,11 @@ case XCL_END: goto HANDLE_CLASSMAP; + /* LCOV_EXCL_START */ default:+ PCRE2_DEBUG_UNREACHABLE(); return SSB_UNKNOWN; /* Internal error, should not occur */+ /* LCOV_EXCL_STOP */ } } #endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */@@ -1638,7 +1790,7 @@ /* It seems that the fall through comment must be outside the #ifdef if it is to avoid the gcc compiler warning. */ - /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ /* Enter here for a negative non-XCLASS. In the 8-bit library, if we are in UTF mode, any byte with a value >= 0xc4 is a potentially valid starter@@ -1653,19 +1805,20 @@ re->start_bitmap[24] |= 0xf0; /* Bits for 0xc4 - 0xc8 */ memset(re->start_bitmap+25, 0xff, 7); /* Bits for 0xc9 - 0xff */ }+ PCRE2_FALLTHROUGH /* Fall through */ #elif PCRE2_CODE_UNIT_WIDTH != 8 SET_BIT(0xFF); /* For characters >= 255 */+ PCRE2_FALLTHROUGH /* Fall through */ #endif- /* Fall through */ /* Enter here for a positive non-XCLASS. If we have fallen through from an XCLASS, classmap will already be set; just advance the code pointer.- Otherwise, set up classmap for a a non-XCLASS and advance past it. */+ Otherwise, set up classmap for a non-XCLASS and advance past it. */ case OP_CLASS: if (*tcode == OP_XCLASS) tcode += GET(tcode, 1); else {- classmap = (uint8_t *)(++tcode);+ classmap = (const uint8_t *)(++tcode); tcode += 32 / sizeof(PCRE2_UCHAR); } @@ -1768,8 +1921,7 @@ /* Find start of compiled code */ -code = (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code)) +- re->name_entry_size * re->name_count;+code = (PCRE2_UCHAR *)((uint8_t *)re + re->code_start); /* For a pattern that has a first code unit, or a multiline pattern that matches only at "line start", there is no point in seeking a list of starting@@ -1779,7 +1931,13 @@ { int depth = 0; int rc = set_start_bits(re, code, utf, ucp, &depth);- if (rc == SSB_UNKNOWN) return 1;+ /* LCOV_EXCL_START */+ if (rc == SSB_UNKNOWN)+ {+ PCRE2_DEBUG_UNREACHABLE();+ return 1;+ }+ /* LCOV_EXCL_STOP */ /* If a list of starting code units was set up, scan the list to see if only one or two were listed. Having only one listed is rare because usually a@@ -1847,30 +2005,37 @@ if (d != a) goto DONE; /* Not the other case of a */ b = c; /* Save second in b */++#ifdef EBCDIC+ /* To match ASCII (which puts the uppercase one in a), swap a & b+ if needed. This doesn't really matter, but neatens the tests. */+ if (TABLE_GET((unsigned int)a, re->tables + lcc_offset, a) == a)+ {+ b = a;+ a = c;+ }+#endif } else goto DONE; /* More than two characters found */ } } - /* Replace the start code unit bits with a first code unit, but only if it- is not the same as a required later code unit. This is because a search for- a required code unit starts after an explicit first code unit, but at a- code unit found from the bitmap. Patterns such as /a*a/ don't work- if both the start unit and required unit are the same. */+ /* Replace the start code unit bits with a first code unit. If it is the+ same as a required later code unit, then clear the required later code+ unit. This is because a search for a required code unit starts after an+ explicit first code unit, but at a code unit found from the bitmap.+ Patterns such as /a*a/ don't work if both the start unit and required+ unit are the same. */ - if (a >= 0 &&- (- (re->flags & PCRE2_LASTSET) == 0 ||- (- re->last_codeunit != (uint32_t)a &&- (b < 0 || re->last_codeunit != (uint32_t)b)- )- ))- {+ if (a >= 0) {+ if ((re->flags & PCRE2_LASTSET) && (re->last_codeunit == (uint32_t)a || (b >= 0 && re->last_codeunit == (uint32_t)b))) {+ re->flags &= ~(PCRE2_LASTSET | PCRE2_LASTCASELESS);+ re->last_codeunit = 0;+ } re->first_codeunit = a; flags = PCRE2_FIRSTSET; if (b >= 0) flags |= PCRE2_FIRSTCASELESS;- }+ } DONE: re->flags |= flags;@@ -1897,14 +2062,20 @@ case -1: /* \C in UTF mode or over-complex regex */ break; /* Leave minlength unchanged (will be zero) */ + /* LCOV_EXCL_START */ case -2:+ PCRE2_DEBUG_UNREACHABLE(); return 2; /* missing capturing bracket */+ /* LCOV_EXCL_STOP */ + /* LCOV_EXCL_START */ case -3:+ PCRE2_DEBUG_UNREACHABLE(); return 3; /* unrecognized opcode */+ /* LCOV_EXCL_STOP */ default:- re->minlength = (min > UINT16_MAX)? UINT16_MAX : min;+ re->minlength = (min > (int)UINT16_MAX)? (int)UINT16_MAX : min; break; } }
src/c/pcre2/src/pcre2_substitute.c view
@@ -7,991 +7,1743 @@ 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--#include "pcre2_internal.h"--#define PTR_STACK_SIZE 20--#define SUBSTITUTE_OPTIONS \- (PCRE2_SUBSTITUTE_EXTENDED|PCRE2_SUBSTITUTE_GLOBAL| \- PCRE2_SUBSTITUTE_LITERAL|PCRE2_SUBSTITUTE_MATCHED| \- PCRE2_SUBSTITUTE_OVERFLOW_LENGTH|PCRE2_SUBSTITUTE_REPLACEMENT_ONLY| \- PCRE2_SUBSTITUTE_UNKNOWN_UNSET|PCRE2_SUBSTITUTE_UNSET_EMPTY)----/*************************************************-* Find end of substitute text *-*************************************************/--/* In extended mode, we recognize ${name:+set text:unset text} and similar-constructions. This requires the identification of unescaped : and }-characters. This function scans for such. It must deal with nested ${-constructions. The pointer to the text is updated, either to the required end-character, or to where an error was detected.--Arguments:- code points to the compiled expression (for options)- ptrptr points to the pointer to the start of the text (updated)- ptrend end of the whole string- last TRUE if the last expected string (only } recognized)--Returns: 0 on success- negative error code on failure-*/--static int-find_text_end(const pcre2_code *code, PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend,- BOOL last)-{-int rc = 0;-uint32_t nestlevel = 0;-BOOL literal = FALSE;-PCRE2_SPTR ptr = *ptrptr;--for (; ptr < ptrend; ptr++)- {- if (literal)- {- if (ptr[0] == CHAR_BACKSLASH && ptr < ptrend - 1 && ptr[1] == CHAR_E)- {- literal = FALSE;- ptr += 1;- }- }-- else if (*ptr == CHAR_RIGHT_CURLY_BRACKET)- {- if (nestlevel == 0) goto EXIT;- nestlevel--;- }-- else if (*ptr == CHAR_COLON && !last && nestlevel == 0) goto EXIT;-- else if (*ptr == CHAR_DOLLAR_SIGN)- {- if (ptr < ptrend - 1 && ptr[1] == CHAR_LEFT_CURLY_BRACKET)- {- nestlevel++;- ptr += 1;- }- }-- else if (*ptr == CHAR_BACKSLASH)- {- int erc;- int errorcode;- uint32_t ch;-- if (ptr < ptrend - 1) switch (ptr[1])- {- case CHAR_L:- case CHAR_l:- case CHAR_U:- case CHAR_u:- ptr += 1;- continue;- }-- ptr += 1; /* Must point after \ */- erc = PRIV(check_escape)(&ptr, ptrend, &ch, &errorcode,- code->overall_options, code->extra_options, FALSE, NULL);- ptr -= 1; /* Back to last code unit of escape */- if (errorcode != 0)- {- rc = errorcode;- goto EXIT;- }-- switch(erc)- {- case 0: /* Data character */- case ESC_E: /* Isolated \E is ignored */- break;-- case ESC_Q:- literal = TRUE;- break;-- default:- rc = PCRE2_ERROR_BADREPESCAPE;- goto EXIT;- }- }- }--rc = PCRE2_ERROR_REPMISSINGBRACE; /* Terminator not found */--EXIT:-*ptrptr = ptr;-return rc;-}----/*************************************************-* Match and substitute *-*************************************************/--/* This function applies a compiled re to a subject string and creates a new-string with substitutions. The first 7 arguments are the same as for-pcre2_match(). Either string length may be PCRE2_ZERO_TERMINATED.--Arguments:- code points to the compiled expression- subject points to the subject string- length length of subject string (may contain binary zeros)- start_offset where to start in the subject string- options option bits- match_data points to a match_data block, or is NULL- context points a PCRE2 context- replacement points to the replacement string- rlength length of replacement string- buffer where to put the substituted string- blength points to length of buffer; updated to length of string--Returns: >= 0 number of substitutions made- < 0 an error code- PCRE2_ERROR_BADREPLACEMENT means invalid use of $-*/--/* This macro checks for space in the buffer before copying into it. On-overflow, either give an error immediately, or keep on, accumulating the-length. */--#define CHECKMEMCPY(from,length) \- { \- if (!overflowed && lengthleft < length) \- { \- if ((suboptions & PCRE2_SUBSTITUTE_OVERFLOW_LENGTH) == 0) goto NOROOM; \- overflowed = TRUE; \- extra_needed = length - lengthleft; \- } \- else if (overflowed) \- { \- extra_needed += length; \- } \- else \- { \- memcpy(buffer + buff_offset, from, CU2BYTES(length)); \- buff_offset += length; \- lengthleft -= length; \- } \- }--/* Here's the function */--PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION-pcre2_substitute(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length,- PCRE2_SIZE start_offset, uint32_t options, pcre2_match_data *match_data,- pcre2_match_context *mcontext, PCRE2_SPTR replacement, PCRE2_SIZE rlength,- PCRE2_UCHAR *buffer, PCRE2_SIZE *blength)-{-int rc;-int subs;-int forcecase = 0;-int forcecasereset = 0;-uint32_t ovector_count;-uint32_t goptions = 0;-uint32_t suboptions;-pcre2_match_data *internal_match_data = NULL;-BOOL escaped_literal = FALSE;-BOOL overflowed = FALSE;-BOOL use_existing_match;-BOOL replacement_only;-#ifdef SUPPORT_UNICODE-BOOL utf = (code->overall_options & PCRE2_UTF) != 0;-BOOL ucp = (code->overall_options & PCRE2_UCP) != 0;-#endif-PCRE2_UCHAR temp[6];-PCRE2_SPTR ptr;-PCRE2_SPTR repend;-PCRE2_SIZE extra_needed = 0;-PCRE2_SIZE buff_offset, buff_length, lengthleft, fraglength;-PCRE2_SIZE *ovector;-PCRE2_SIZE ovecsave[3];-pcre2_substitute_callout_block scb;--/* General initialization */--buff_offset = 0;-lengthleft = buff_length = *blength;-*blength = PCRE2_UNSET;-ovecsave[0] = ovecsave[1] = ovecsave[2] = PCRE2_UNSET;--/* Partial matching is not valid. This must come after setting *blength to-PCRE2_UNSET, so as not to imply an offset in the replacement. */--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-zero length is interpreted as an empty string. */--if (replacement == NULL)- {- if (rlength != 0) return PCRE2_ERROR_NULL;- replacement = (PCRE2_SPTR)"";- }--if (rlength == PCRE2_ZERO_TERMINATED) rlength = PRIV(strlen)(replacement);-repend = replacement + rlength;--/* Check for using a match that has already happened. Note that the subject-pointer in the match data may be NULL after a no-match. */--use_existing_match = ((options & PCRE2_SUBSTITUTE_MATCHED) != 0);-replacement_only = ((options & PCRE2_SUBSTITUTE_REPLACEMENT_ONLY) != 0);--/* If starting from an existing match, there must be an externally provided-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, 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)- {- pcre2_general_context *gcontext;- if (use_existing_match) return PCRE2_ERROR_NULL;- gcontext = (mcontext == NULL)?- (pcre2_general_context *)code :- (pcre2_general_context *)mcontext;- match_data = internal_match_data =- pcre2_match_data_create_from_pattern(code, gcontext);- if (internal_match_data == NULL) return PCRE2_ERROR_NOMEMORY;- }--else if (use_existing_match)- {- pcre2_general_context *gcontext = (mcontext == NULL)?- (pcre2_general_context *)code :- (pcre2_general_context *)mcontext;- int pairs = (code->top_bracket + 1 < match_data->oveccount)?- code->top_bracket + 1 : match_data->oveccount;- internal_match_data = pcre2_match_data_create(match_data->oveccount,- gcontext);- 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;- }--/* Remember ovector details */--ovector = pcre2_get_ovector_pointer(match_data);-ovector_count = pcre2_get_ovector_count(match_data);--/* Fixed things in the callout block */--scb.version = 0;-scb.input = subject;-scb.output = (PCRE2_SPTR)buffer;-scb.ovector = ovector;--/* A NULL subject of zero length is treated as an empty string. */--if (subject == NULL)- {- if (length != 0) return PCRE2_ERROR_NULL;- subject = (PCRE2_SPTR)"";- }--/* Find length of zero-terminated subject */--if (length == PCRE2_ZERO_TERMINATED)- length = subject? PRIV(strlen)(subject) : 0;--/* Check UTF replacement string if necessary. */--#ifdef SUPPORT_UNICODE-if (utf && (options & PCRE2_NO_UTF_CHECK) == 0)- {- rc = PRIV(valid_utf)(replacement, rlength, &(match_data->startchar));- if (rc != 0)- {- match_data->leftchar = 0;- goto EXIT;- }- }-#endif /* SUPPORT_UNICODE */--/* Save the substitute options and remove them from the match options. */--suboptions = options & SUBSTITUTE_OPTIONS;-options &= ~SUBSTITUTE_OPTIONS;--/* Error if the start match offset is greater than the length of the subject. */--if (start_offset > length)- {- match_data->leftchar = 0;- rc = PCRE2_ERROR_BADOFFSET;- goto EXIT;- }--/* Copy up to the start offset, unless only the replacement is required. */--if (!replacement_only) CHECKMEMCPY(subject, start_offset);--/* Loop for global substituting. If PCRE2_SUBSTITUTE_MATCHED is set, the first-match is taken from the match_data that was passed in. */--subs = 0;-do- {- PCRE2_SPTR ptrstack[PTR_STACK_SIZE];- uint32_t ptrstackptr = 0;-- if (use_existing_match)- {- rc = match_data->rc;- use_existing_match = FALSE;- }- else rc = pcre2_match(code, subject, length, start_offset, options|goptions,- match_data, mcontext);--#ifdef SUPPORT_UNICODE- if (utf) options |= PCRE2_NO_UTF_CHECK; /* Only need to check once */-#endif-- /* Any error other than no match returns the error code. No match when not- doing the special after-empty-match global rematch, or when at the end of the- subject, breaks the global loop. Otherwise, advance the starting point by one- character, copying it to the output, and try again. */-- if (rc < 0)- {- PCRE2_SIZE save_start;-- if (rc != PCRE2_ERROR_NOMATCH) goto EXIT;- if (goptions == 0 || start_offset >= length) break;-- /* Advance by one code point. Then, if CRLF is a valid newline sequence and- we have advanced into the middle of it, advance one more code point. In- other words, do not start in the middle of CRLF, even if CR and LF on their- own are valid newlines. */-- save_start = start_offset++;- if (subject[start_offset-1] == CHAR_CR &&- code->newline_convention != PCRE2_NEWLINE_CR &&- code->newline_convention != PCRE2_NEWLINE_LF &&- start_offset < length &&- subject[start_offset] == CHAR_LF)- start_offset++;-- /* Otherwise, in UTF mode, advance past any secondary code points. */-- else if ((code->overall_options & PCRE2_UTF) != 0)- {-#if PCRE2_CODE_UNIT_WIDTH == 8- while (start_offset < length && (subject[start_offset] & 0xc0) == 0x80)- start_offset++;-#elif PCRE2_CODE_UNIT_WIDTH == 16- while (start_offset < length &&- (subject[start_offset] & 0xfc00) == 0xdc00)- start_offset++;-#endif- }-- /* Copy what we have advanced past (unless not required), reset the special- global options, and continue to the next match. */-- fraglength = start_offset - save_start;- if (!replacement_only) CHECKMEMCPY(subject + save_start, fraglength);- goptions = 0;- continue;- }-- /* Handle a successful match. Matches that use \K to end before they start- or start before the current point in the subject are not supported. */-- if (ovector[1] < ovector[0] || ovector[0] < start_offset)- {- rc = PCRE2_ERROR_BADSUBSPATTERN;- goto EXIT;- }-- /* Check for the same match as previous. This is legitimate after matching an- empty string that starts after the initial match offset. We have tried again- at the match point in case the pattern is one like /(?<=\G.)/ which can never- match at its starting point, so running the match achieves the bumpalong. If- we do get the same (null) match at the original match point, it isn't such a- pattern, so we now do the empty string magic. In all other cases, a repeat- match should never occur. */-- if (ovecsave[0] == ovector[0] && ovecsave[1] == ovector[1])- {- if (ovector[0] == ovector[1] && ovecsave[2] != start_offset)- {- goptions = PCRE2_NOTEMPTY_ATSTART | PCRE2_ANCHORED;- ovecsave[2] = start_offset;- continue; /* Back to the top of the loop */- }- rc = PCRE2_ERROR_INTERNAL_DUPMATCH;- goto EXIT;- }-- /* Count substitutions with a paranoid check for integer overflow; surely no- real call to this function would ever hit this! */-- if (subs == INT_MAX)- {- rc = PCRE2_ERROR_TOOMANYREPLACE;- goto EXIT;- }- subs++;-- /* Copy the text leading up to the match (unless not required), and remember- where the insert begins and how many ovector pairs are set. */-- if (rc == 0) rc = ovector_count;- fraglength = ovector[0] - start_offset;- if (!replacement_only) CHECKMEMCPY(subject + start_offset, fraglength);- scb.output_offsets[0] = buff_offset;- scb.oveccount = rc;-- /* Process the replacement string. If the entire replacement is literal, just- copy it with length check. */-- ptr = replacement;- if ((suboptions & PCRE2_SUBSTITUTE_LITERAL) != 0)- {- CHECKMEMCPY(ptr, rlength);- }-- /* Within a non-literal replacement, which must be scanned character by- character, local literal mode can be set by \Q, but only in extended mode- when backslashes are being interpreted. In extended mode we must handle- nested substrings that are to be reprocessed. */-- else for (;;)- {- uint32_t ch;- unsigned int chlen;-- /* If at the end of a nested substring, pop the stack. */-- if (ptr >= repend)- {- if (ptrstackptr == 0) break; /* End of replacement string */- repend = ptrstack[--ptrstackptr];- ptr = ptrstack[--ptrstackptr];- continue;- }-- /* Handle the next character */-- if (escaped_literal)- {- if (ptr[0] == CHAR_BACKSLASH && ptr < repend - 1 && ptr[1] == CHAR_E)- {- escaped_literal = FALSE;- ptr += 2;- continue;- }- goto LOADLITERAL;- }-- /* Not in literal mode. */-- if (*ptr == CHAR_DOLLAR_SIGN)- {- int group, n;- uint32_t special = 0;- BOOL inparens;- BOOL star;- PCRE2_SIZE sublength;- PCRE2_SPTR text1_start = NULL;- PCRE2_SPTR text1_end = NULL;- PCRE2_SPTR text2_start = NULL;- PCRE2_SPTR text2_end = NULL;- PCRE2_UCHAR next;- PCRE2_UCHAR name[33];-- if (++ptr >= repend) goto BAD;- if ((next = *ptr) == CHAR_DOLLAR_SIGN) goto LOADLITERAL;-- group = -1;- n = 0;- inparens = FALSE;- star = FALSE;-- if (next == CHAR_LEFT_CURLY_BRACKET)- {- if (++ptr >= repend) goto BAD;- next = *ptr;- inparens = TRUE;- }-- if (next == CHAR_ASTERISK)- {- if (++ptr >= repend) goto BAD;- next = *ptr;- star = TRUE;- }-- if (!star && next >= CHAR_0 && next <= CHAR_9)- {- group = next - CHAR_0;- while (++ptr < repend)- {- next = *ptr;- if (next < CHAR_0 || next > CHAR_9) break;- group = group * 10 + next - CHAR_0;-- /* A check for a number greater than the hightest captured group- is sufficient here; no need for a separate overflow check. If unknown- groups are to be treated as unset, just skip over any remaining- digits and carry on. */-- if (group > code->top_bracket)- {- if ((suboptions & PCRE2_SUBSTITUTE_UNKNOWN_UNSET) != 0)- {- while (++ptr < repend && *ptr >= CHAR_0 && *ptr <= CHAR_9);- break;- }- else- {- rc = PCRE2_ERROR_NOSUBSTRING;- goto PTREXIT;- }- }- }- }- else- {- const uint8_t *ctypes = code->tables + ctypes_offset;- while (MAX_255(next) && (ctypes[next] & ctype_word) != 0)- {- name[n++] = next;- if (n > 32) goto BAD;- if (++ptr >= repend) break;- next = *ptr;- }- if (n == 0) goto BAD;- name[n] = 0;- }-- /* In extended mode we recognize ${name:+set text:unset text} and- ${name:-default text}. */-- if (inparens)- {- if ((suboptions & PCRE2_SUBSTITUTE_EXTENDED) != 0 &&- !star && ptr < repend - 2 && next == CHAR_COLON)- {- special = *(++ptr);- if (special != CHAR_PLUS && special != CHAR_MINUS)- {- rc = PCRE2_ERROR_BADSUBSTITUTION;- goto PTREXIT;- }-- text1_start = ++ptr;- rc = find_text_end(code, &ptr, repend, special == CHAR_MINUS);- if (rc != 0) goto PTREXIT;- text1_end = ptr;-- if (special == CHAR_PLUS && *ptr == CHAR_COLON)- {- text2_start = ++ptr;- rc = find_text_end(code, &ptr, repend, TRUE);- if (rc != 0) goto PTREXIT;- text2_end = ptr;- }- }-- else- {- if (ptr >= repend || *ptr != CHAR_RIGHT_CURLY_BRACKET)- {- rc = PCRE2_ERROR_REPMISSINGBRACE;- goto PTREXIT;- }- }-- ptr++;- }-- /* Have found a syntactically correct group number or name, or *name.- Only *MARK is currently recognized. */-- if (star)- {- if (PRIV(strcmp_c8)(name, STRING_MARK) == 0)- {- PCRE2_SPTR mark = pcre2_get_mark(match_data);- if (mark != NULL)- {- PCRE2_SPTR mark_start = mark;- while (*mark != 0) mark++;- fraglength = mark - mark_start;- CHECKMEMCPY(mark_start, fraglength);- }- }- else goto BAD;- }-- /* Substitute the contents of a group. We don't use substring_copy- functions any more, in order to support case forcing. */-- else- {- PCRE2_SPTR subptr, subptrend;-- /* Find a number for a named group. In case there are duplicate names,- search for the first one that is set. If the name is not found when- PCRE2_SUBSTITUTE_UNKNOWN_EMPTY is set, set the group number to a- non-existent group. */-- if (group < 0)- {- PCRE2_SPTR first, last, entry;- rc = pcre2_substring_nametable_scan(code, name, &first, &last);- if (rc == PCRE2_ERROR_NOSUBSTRING &&- (suboptions & PCRE2_SUBSTITUTE_UNKNOWN_UNSET) != 0)- {- group = code->top_bracket + 1;- }- else- {- if (rc < 0) goto PTREXIT;- for (entry = first; entry <= last; entry += rc)- {- uint32_t ng = GET2(entry, 0);- if (ng < ovector_count)- {- if (group < 0) group = ng; /* First in ovector */- if (ovector[ng*2] != PCRE2_UNSET)- {- group = ng; /* First that is set */- break;- }- }- }-- /* If group is still negative, it means we did not find a group- that is in the ovector. Just set the first group. */-- if (group < 0) group = GET2(first, 0);- }- }-- /* We now have a group that is identified by number. Find the length of- the captured string. If a group in a non-special substitution is unset- when PCRE2_SUBSTITUTE_UNSET_EMPTY is set, substitute nothing. */-- rc = pcre2_substring_length_bynumber(match_data, group, &sublength);- if (rc < 0)- {- if (rc == PCRE2_ERROR_NOSUBSTRING &&- (suboptions & PCRE2_SUBSTITUTE_UNKNOWN_UNSET) != 0)- {- rc = PCRE2_ERROR_UNSET;- }- if (rc != PCRE2_ERROR_UNSET) goto PTREXIT; /* Non-unset errors */- if (special == 0) /* Plain substitution */- {- if ((suboptions & PCRE2_SUBSTITUTE_UNSET_EMPTY) != 0) continue;- goto PTREXIT; /* Else error */- }- }-- /* If special is '+' we have a 'set' and possibly an 'unset' text,- both of which are reprocessed when used. If special is '-' we have a- default text for when the group is unset; it must be reprocessed. */-- if (special != 0)- {- if (special == CHAR_MINUS)- {- if (rc == 0) goto LITERAL_SUBSTITUTE;- text2_start = text1_start;- text2_end = text1_end;- }-- if (ptrstackptr >= PTR_STACK_SIZE) goto BAD;- ptrstack[ptrstackptr++] = ptr;- ptrstack[ptrstackptr++] = repend;-- if (rc == 0)- {- ptr = text1_start;- repend = text1_end;- }- else- {- ptr = text2_start;- repend = text2_end;- }- continue;- }-- /* Otherwise we have a literal substitution of a group's contents. */-- LITERAL_SUBSTITUTE:- subptr = subject + ovector[group*2];- subptrend = subject + ovector[group*2 + 1];-- /* Substitute a literal string, possibly forcing alphabetic case. */-- while (subptr < subptrend)- {- GETCHARINCTEST(ch, subptr);- if (forcecase != 0)- {-#ifdef SUPPORT_UNICODE- if (utf || ucp)- {- uint32_t type = UCD_CHARTYPE(ch);- if (PRIV(ucp_gentype)[type] == ucp_L &&- type != ((forcecase > 0)? ucp_Lu : ucp_Ll))- ch = UCD_OTHERCASE(ch);- }- else-#endif- {- if (((code->tables + cbits_offset +- ((forcecase > 0)? cbit_upper:cbit_lower)- )[ch/8] & (1u << (ch%8))) == 0)- ch = (code->tables + fcc_offset)[ch];- }- forcecase = forcecasereset;- }--#ifdef SUPPORT_UNICODE- if (utf) chlen = PRIV(ord2utf)(ch, temp); else-#endif- {- temp[0] = ch;- chlen = 1;- }- CHECKMEMCPY(temp, chlen);- }- }- }-- /* Handle an escape sequence in extended mode. We can use check_escape()- to process \Q, \E, \c, \o, \x and \ followed by non-alphanumerics, but- the case-forcing escapes are not supported in pcre2_compile() so must be- recognized here. */-- else if ((suboptions & PCRE2_SUBSTITUTE_EXTENDED) != 0 &&- *ptr == CHAR_BACKSLASH)- {- int errorcode;-- if (ptr < repend - 1) switch (ptr[1])- {- case CHAR_L:- forcecase = forcecasereset = -1;- ptr += 2;- continue;-- case CHAR_l:- forcecase = -1;- forcecasereset = 0;- ptr += 2;- continue;-- case CHAR_U:- forcecase = forcecasereset = 1;- ptr += 2;- continue;-- case CHAR_u:- forcecase = 1;- forcecasereset = 0;- ptr += 2;- continue;-- default:- break;- }-- ptr++; /* Point after \ */- rc = PRIV(check_escape)(&ptr, repend, &ch, &errorcode,- code->overall_options, code->extra_options, FALSE, NULL);- if (errorcode != 0) goto BADESCAPE;-- switch(rc)- {- case ESC_E:- forcecase = forcecasereset = 0;- continue;-- case ESC_Q:- escaped_literal = TRUE;- continue;-- case 0: /* Data character */- goto LITERAL;-- default:- goto BADESCAPE;- }- }-- /* Handle a literal code unit */-- else- {- LOADLITERAL:- GETCHARINCTEST(ch, ptr); /* Get character value, increment pointer */-- LITERAL:- if (forcecase != 0)- {-#ifdef SUPPORT_UNICODE- if (utf || ucp)- {- uint32_t type = UCD_CHARTYPE(ch);- if (PRIV(ucp_gentype)[type] == ucp_L &&- type != ((forcecase > 0)? ucp_Lu : ucp_Ll))- ch = UCD_OTHERCASE(ch);- }- else-#endif- {- if (((code->tables + cbits_offset +- ((forcecase > 0)? cbit_upper:cbit_lower)- )[ch/8] & (1u << (ch%8))) == 0)- ch = (code->tables + fcc_offset)[ch];- }- forcecase = forcecasereset;- }--#ifdef SUPPORT_UNICODE- if (utf) chlen = PRIV(ord2utf)(ch, temp); else-#endif- {- temp[0] = ch;- chlen = 1;- }- CHECKMEMCPY(temp, chlen);- } /* End handling a literal code unit */- } /* End of loop for scanning the replacement. */-- /* The replacement has been copied to the output, or its size has been- remembered. Do the callout if there is one and we have done an actual- replacement. */-- if (!overflowed && mcontext != NULL && mcontext->substitute_callout != NULL)- {- scb.subscount = subs;- scb.output_offsets[1] = buff_offset;- rc = mcontext->substitute_callout(&scb, mcontext->substitute_callout_data);-- /* A non-zero return means cancel this substitution. Instead, copy the- matched string fragment. */-- if (rc != 0)- {- PCRE2_SIZE newlength = scb.output_offsets[1] - scb.output_offsets[0];- PCRE2_SIZE oldlength = ovector[1] - ovector[0];-- buff_offset -= newlength;- lengthleft += newlength;- if (!replacement_only) CHECKMEMCPY(subject + ovector[0], oldlength);-- /* A negative return means do not do any more. */-- if (rc < 0) suboptions &= (~PCRE2_SUBSTITUTE_GLOBAL);- }- }-- /* Save the details of this match. See above for how this data is used. If we- matched an empty string, do the magic for global matches. Update the start- offset to point to the rest of the subject string. If we re-used an existing- match for the first match, switch to the internal match data block. */-- ovecsave[0] = ovector[0];- ovecsave[1] = ovector[1];- ovecsave[2] = start_offset;-- goptions = (ovector[0] != ovector[1] || ovector[0] > start_offset)? 0 :- PCRE2_ANCHORED|PCRE2_NOTEMPTY_ATSTART;- start_offset = ovector[1];- } while ((suboptions & PCRE2_SUBSTITUTE_GLOBAL) != 0); /* Repeat "do" loop */--/* Copy the rest of the subject unless not required, and terminate the output-with a binary zero. */--if (!replacement_only)- {- fraglength = length - start_offset;- CHECKMEMCPY(subject + start_offset, fraglength);- }--temp[0] = 0;-CHECKMEMCPY(temp, 1);--/* If overflowed is set it means the PCRE2_SUBSTITUTE_OVERFLOW_LENGTH is set,-and matching has carried on after a full buffer, in order to compute the length-needed. Otherwise, an overflow generates an immediate error return. */--if (overflowed)- {- rc = PCRE2_ERROR_NOMEMORY;- *blength = buff_length + extra_needed;- }--/* After a successful execution, return the number of substitutions and set the-length of buffer used, excluding the trailing zero. */--else- {- rc = subs;- *blength = buff_offset - 1;- }--EXIT:-if (internal_match_data != NULL) pcre2_match_data_free(internal_match_data);- else match_data->rc = rc;-return rc;--NOROOM:-rc = PCRE2_ERROR_NOMEMORY;+ 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.+-----------------------------------------------------------------------------+*/+++#include "pcre2_internal.h"++++#define PTR_STACK_SIZE 20++#define SUBSTITUTE_OPTIONS \+ (PCRE2_SUBSTITUTE_EXTENDED|PCRE2_SUBSTITUTE_GLOBAL| \+ PCRE2_SUBSTITUTE_LITERAL|PCRE2_SUBSTITUTE_MATCHED| \+ PCRE2_SUBSTITUTE_OVERFLOW_LENGTH|PCRE2_SUBSTITUTE_REPLACEMENT_ONLY| \+ PCRE2_SUBSTITUTE_UNKNOWN_UNSET|PCRE2_SUBSTITUTE_UNSET_EMPTY)++++/*************************************************+* Find end of substitute text *+*************************************************/++/* In extended mode, we recognize ${name:+set text:unset text} and similar+constructions. This requires the identification of unescaped : and }+characters. This function scans for such. It must deal with nested ${+constructions. The pointer to the text is updated, either to the required end+character, or to where an error was detected.++Arguments:+ code points to the compiled expression (for options)+ ptrptr points to the pointer to the start of the text (updated)+ ptrend end of the whole string+ last TRUE if the last expected string (only } recognized)++Returns: 0 on success+ negative error code on failure+*/++static int+find_text_end(const pcre2_code *code, PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend,+ BOOL last)+{+int rc = 0;+uint32_t nestlevel = 0;+BOOL literal = FALSE;+PCRE2_SPTR ptr = *ptrptr;++for (; ptr < ptrend; ptr++)+ {+ if (literal)+ {+ if (ptr[0] == CHAR_BACKSLASH && ptr < ptrend - 1 && ptr[1] == CHAR_E)+ {+ literal = FALSE;+ ptr += 1;+ }+ }++ else if (*ptr == CHAR_RIGHT_CURLY_BRACKET)+ {+ if (nestlevel == 0) goto EXIT;+ nestlevel--;+ }++ else if (*ptr == CHAR_COLON && !last && nestlevel == 0) goto EXIT;++ else if (*ptr == CHAR_DOLLAR_SIGN)+ {+ if (ptr < ptrend - 1 && ptr[1] == CHAR_LEFT_CURLY_BRACKET)+ {+ nestlevel++;+ ptr += 1;+ }+ }++ else if (*ptr == CHAR_BACKSLASH)+ {+ int erc;+ int errorcode;+ uint32_t ch;++ if (ptr < ptrend - 1) switch (ptr[1])+ {+ case CHAR_L:+ case CHAR_l:+ case CHAR_U:+ case CHAR_u:+ ptr += 1;+ continue;+ }++ ptr += 1; /* Must point after \ */+ erc = PRIV(check_escape)(&ptr, ptrend, &ch, &errorcode,+ code->overall_options, code->extra_options, code->top_bracket, FALSE, NULL);+ if (errorcode != 0)+ {+ /* errorcode from check_escape is positive, so must not be returned by+ pcre2_substitute(). */+ rc = PCRE2_ERROR_BADREPESCAPE;+ goto EXIT;+ }++ switch(erc)+ {+ case 0: /* Data character */+ case ESC_b: /* Data character */+ case ESC_v: /* Data character */+ case ESC_E: /* Isolated \E is ignored */+ break;++ case ESC_Q:+ literal = TRUE;+ break;++ case ESC_g:+ /* The \g<name> form (\g<number> already handled by check_escape)++ Don't worry about finding the matching ">". We are super, super lenient+ about validating ${} replacements inside find_text_end(), so we certainly+ don't need to worry about other syntax. Importantly, a \g<..> or $<...>+ sequence can't contain a '}' character. */+ break;++ default:+ if (erc < 0)+ break; /* capture group reference */+ rc = PCRE2_ERROR_BADREPESCAPE;+ goto EXIT;+ }+ }+ }++rc = PCRE2_ERROR_REPMISSINGBRACE; /* Terminator not found */++EXIT:+*ptrptr = ptr;+return rc;+}+++/*************************************************+* Validate group name *+*************************************************/++/* This function scans for a capture group name, validating it+consists of legal characters, is not empty, and does not exceed+MAX_NAME_SIZE.++Arguments:+ ptrptr points to the pointer to the start of the text (updated)+ ptrend end of the whole string+ utf true if the input is UTF-encoded+ ctypes pointer to the character types table++Returns: TRUE if a name was read+ FALSE otherwise+*/++static BOOL+read_name_subst(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, BOOL utf,+ const uint8_t* ctypes)+{+PCRE2_SPTR ptr = *ptrptr;+PCRE2_SPTR nameptr = ptr;++if (ptr >= ptrend) /* No characters in name */+ goto FAILED;++/* We do not need to check whether the name starts with a non-digit.+We are simply referencing names here, not defining them. */++/* See read_name in the pcre2_compile.c for the corresponding logic+restricting group names inside the pattern itself. */++#ifdef SUPPORT_UNICODE+if (utf)+ {+ uint32_t c, type;++ while (ptr < ptrend)+ {+ GETCHAR(c, ptr);+ type = UCD_CHARTYPE(c);+ if (type != ucp_Nd && PRIV(ucp_gentype)[type] != ucp_L &&+ c != CHAR_UNDERSCORE) break;+ ptr++;+ FORWARDCHARTEST(ptr, ptrend);+ }+ }+else+#else+(void)utf; /* Avoid compiler warning */+#endif /* SUPPORT_UNICODE */++/* Handle group names in non-UTF modes. */++ {+ while (ptr < ptrend && MAX_255(*ptr) && (ctypes[*ptr] & ctype_word) != 0)+ {+ ptr++;+ }+ }++/* Check name length */++if (ptr - nameptr > MAX_NAME_SIZE)+ goto FAILED;++/* Subpattern names must not be empty */+if (ptr == nameptr)+ goto FAILED;++*ptrptr = ptr;+return TRUE;++FAILED:+*ptrptr = ptr;+return FALSE;+}+++/*************************************************+* Case transformations *+*************************************************/++#define PCRE2_SUBSTITUTE_CASE_NONE 0+// 1, 2, 3 are PCRE2_SUBSTITUTE_CASE_LOWER, UPPER, TITLE_FIRST.+#define PCRE2_SUBSTITUTE_CASE_REVERSE_TITLE_FIRST 4++typedef struct {+ int to_case; /* One of PCRE2_SUBSTITUTE_CASE_xyz */+ BOOL single_char;+} case_state;++/* Helper to guess how much a string is likely to increase in size when+case-transformed. Usually, strings don't change size at all, but some rare+characters do grow. Estimate +10%, plus another few characters.++Performing this estimation is unfortunate, but inevitable, since we can't call+the callout if we ran out of buffer space to prepare its input.++Because this estimate is inexact (and in pathological cases, underestimates the+required buffer size) we must document that when you have a+substitute_case_callout, and you are using PCRE2_SUBSTITUTE_OVERFLOW_LENGTH, you+may need more than two calls to determine the final buffer size. */++static PCRE2_SIZE+pessimistic_case_inflation(PCRE2_SIZE len)+{+return (len >> 3u) + 10;+}++/* Case transformation behaviour if no callout is passed. */++static PCRE2_SIZE+default_substitute_case_callout(+ PCRE2_SPTR input, PCRE2_SIZE input_len,+ PCRE2_UCHAR *output, PCRE2_SIZE output_cap,+ case_state *state, const pcre2_code *code)+{+PCRE2_SPTR input_end = input + input_len;+#ifdef SUPPORT_UNICODE+BOOL utf;+BOOL ucp;+#endif+PCRE2_UCHAR temp[6];+BOOL next_to_upper;+BOOL rest_to_upper;+BOOL single_char;+BOOL overflow = FALSE;+PCRE2_SIZE written = 0;++/* Helpful simplifying invariant: input and output are disjoint buffers.+I believe that this code is technically undefined behaviour, because the two+pointers input/output are "unrelated" pointers and hence not comparable. Casting+via char* bypasses some but not all of those technical rules. It is not included+in release builds, in any case. */+PCRE2_ASSERT((char *)(input + input_len) <= (char *)output ||+ (char *)(output + output_cap) <= (char *)input);++#ifdef SUPPORT_UNICODE+utf = (code->overall_options & PCRE2_UTF) != 0;+ucp = (code->overall_options & PCRE2_UCP) != 0;+#endif++if (input_len == 0) return 0;++switch (state->to_case)+ {+ /* LCOV_EXCL_START */+ default:+ PCRE2_DEBUG_UNREACHABLE();+ return 0;+ /* LCOV_EXCL_STOP */++ case PCRE2_SUBSTITUTE_CASE_LOWER: // Can be single_char TRUE or FALSE+ case PCRE2_SUBSTITUTE_CASE_UPPER: // Can only be single_char FALSE+ next_to_upper = rest_to_upper = (state->to_case == PCRE2_SUBSTITUTE_CASE_UPPER);+ break;++ case PCRE2_SUBSTITUTE_CASE_TITLE_FIRST: // Can be single_char TRUE or FALSE+ next_to_upper = TRUE;+ rest_to_upper = FALSE;+ state->to_case = PCRE2_SUBSTITUTE_CASE_LOWER;+ break;++ case PCRE2_SUBSTITUTE_CASE_REVERSE_TITLE_FIRST: // Can only be single_char FALSE+ next_to_upper = FALSE;+ rest_to_upper = TRUE;+ state->to_case = PCRE2_SUBSTITUTE_CASE_UPPER;+ break;+ }++single_char = state->single_char;+if (single_char)+ state->to_case = PCRE2_SUBSTITUTE_CASE_NONE;++while (input < input_end)+ {+ uint32_t ch;+ unsigned int chlen;++ GETCHARINCTEST(ch, input);++#ifdef SUPPORT_UNICODE+ if ((utf || ucp) && ch >= 128)+ {+ uint32_t type = UCD_CHARTYPE(ch);+ if (PRIV(ucp_gentype)[type] == ucp_L &&+ type != (next_to_upper? ucp_Lu : ucp_Ll))+ ch = UCD_OTHERCASE(ch);++ /* TODO This is far from correct... it doesn't support the SpecialCasing.txt+ mappings, but worse, it's not even correct for all the ordinary case+ mappings. We should add support for those (at least), and then add the+ SpecialCasing.txt mappings for Esszet and ligatures, and finally use the+ Turkish casing flag on the match context. */+ }+ else+#endif+ if (MAX_255(ch))+ {+ if (((code->tables + cbits_offset ++ (next_to_upper? cbit_upper:cbit_lower)+ )[ch/8] & (1u << (ch%8))) == 0)+ ch = (code->tables + fcc_offset)[ch];+ }++#ifdef SUPPORT_UNICODE+ if (utf) chlen = PRIV(ord2utf)(ch, temp); else+#endif+ {+ temp[0] = ch;+ chlen = 1;+ }++ if (!overflow && chlen <= output_cap)+ {+ memcpy(output, temp, CU2BYTES(chlen));+ output += chlen;+ output_cap -= chlen;+ }+ else+ {+ overflow = TRUE;+ }++ if (chlen > ~(PCRE2_SIZE)0 - written) /* Integer overflow */+ return ~(PCRE2_SIZE)0;+ written += chlen;++ next_to_upper = rest_to_upper;++ /* memcpy the remainder, if only transforming a single character. */++ if (single_char)+ {+ PCRE2_SIZE rest_len = input_end - input;++ if (!overflow && rest_len <= output_cap)+ memcpy(output, input, CU2BYTES(rest_len));++ if (rest_len > ~(PCRE2_SIZE)0 - written) /* Integer overflow */+ return ~(PCRE2_SIZE)0;+ written += rest_len;++ return written;+ }+ }++return written;+}++/* Helper to perform the call to the substitute_case_callout. We wrap the+user-provided callout because our internal arguments are slightly extended. We+don't want the user callout to handle the case of "\l" (first character only to+lowercase) or "\l\U" (first character to lowercase, rest to uppercase) because+those are not operations defined by Unicode. Instead the user callout simply+needs to provide the three Unicode primitives: lower, upper, titlecase. */++static PCRE2_SIZE+do_case_copy(+ PCRE2_UCHAR *input_output, PCRE2_SIZE input_len, PCRE2_SIZE output_cap,+ case_state *state, BOOL utf,+ PCRE2_SIZE (*substitute_case_callout)(PCRE2_SPTR, PCRE2_SIZE, PCRE2_UCHAR *,+ PCRE2_SIZE, int, void *),+ void *substitute_case_callout_data)+{+PCRE2_SPTR input = input_output;+PCRE2_UCHAR *output = input_output;+PCRE2_SIZE rc;+PCRE2_SIZE rc2;+int ch1_to_case;+int rest_to_case;+PCRE2_UCHAR ch1[6];+PCRE2_SIZE ch1_len;+PCRE2_SPTR rest;+PCRE2_SIZE rest_len;+BOOL ch1_overflow = FALSE;+BOOL rest_overflow = FALSE;++#if PCRE2_CODE_UNIT_WIDTH == 32 || !defined(SUPPORT_UNICODE)+(void)utf; /* Avoid compiler warning. */+#endif++PCRE2_ASSERT(input_len != 0);++switch (state->to_case)+ {+ /* LCOV_EXCL_START */+ default:+ PCRE2_DEBUG_UNREACHABLE();+ return 0;+ /* LCOV_EXCL_STOP */++ case PCRE2_SUBSTITUTE_CASE_LOWER: // Can be single_char TRUE or FALSE+ case PCRE2_SUBSTITUTE_CASE_UPPER: // Can only be single_char FALSE+ case PCRE2_SUBSTITUTE_CASE_TITLE_FIRST: // Can be single_char TRUE or FALSE++ /* The easy case, where our internal casing operations align with those of+ the callout. */++ if (state->single_char == FALSE)+ {+ rc = substitute_case_callout(input, input_len, output, output_cap,+ state->to_case, substitute_case_callout_data);++ if (state->to_case == PCRE2_SUBSTITUTE_CASE_TITLE_FIRST)+ state->to_case = PCRE2_SUBSTITUTE_CASE_LOWER;++ return rc;+ }++ ch1_to_case = state->to_case;+ rest_to_case = PCRE2_SUBSTITUTE_CASE_NONE;+ break;++ case PCRE2_SUBSTITUTE_CASE_REVERSE_TITLE_FIRST: // Can only be single_char FALSE+ ch1_to_case = PCRE2_SUBSTITUTE_CASE_LOWER;+ rest_to_case = PCRE2_SUBSTITUTE_CASE_UPPER;+ break;+ }++/* Identify the leading character. Take copy, because its storage overlaps with+`output`, and hence may be scrambled by the callout. */++ {+ PCRE2_SPTR ch_end = input;+ uint32_t ch;++ GETCHARINCTEST(ch, ch_end);+ (void) ch;+ PCRE2_ASSERT(ch_end <= input + input_len && ch_end - input <= 6);+ ch1_len = ch_end - input;+ memcpy(ch1, input, CU2BYTES(ch1_len));+ }++rest = input + ch1_len;+rest_len = input_len - ch1_len;++/* Transform just ch1. The buffers are always in-place (input == output). With a+custom callout, we need a loop to discover its required buffer size. The loop+wouldn't be required if the callout were well-behaved, but it might be naughty+and return "5" the first time, then "10" the next time we call it using the+exact same input! */++ {+ PCRE2_SIZE ch1_cap;+ PCRE2_SIZE max_ch1_cap;++ ch1_cap = ch1_len; /* First attempt uses the space vacated by ch1. */+ PCRE2_ASSERT(output_cap >= input_len && input_len >= rest_len);+ max_ch1_cap = output_cap - rest_len;++ while (TRUE)+ {+ rc = substitute_case_callout(ch1, ch1_len, output, ch1_cap, ch1_to_case,+ substitute_case_callout_data);+ if (rc == ~(PCRE2_SIZE)0) return rc;++ if (rc <= ch1_cap) break;++ if (rc > max_ch1_cap)+ {+ ch1_overflow = TRUE;+ break;+ }++ /* Move the rest to the right, to make room for expanding ch1. */++ memmove(input_output + rc, rest, CU2BYTES(rest_len));+ rest = input + rc;++ ch1_cap = rc;++ /* Proof of loop termination: `ch1_cap` is growing on each iteration, but+ the loop ends if `rc` reaches the (unchanging) upper bound of output_cap. */+ }+ }++if (rest_to_case == PCRE2_SUBSTITUTE_CASE_NONE)+ {+ if (!ch1_overflow)+ {+ PCRE2_ASSERT(rest_len <= output_cap - rc);+ memmove(output + rc, rest, CU2BYTES(rest_len));+ }+ rc2 = rest_len;++ state->to_case = PCRE2_SUBSTITUTE_CASE_NONE;+ }+else+ {+ PCRE2_UCHAR dummy[1];++ rc2 = substitute_case_callout(rest, rest_len,+ ch1_overflow? dummy : output + rc,+ ch1_overflow? 0u : output_cap - rc,+ rest_to_case, substitute_case_callout_data);+ if (rc2 == ~(PCRE2_SIZE)0) return rc2;++ if (!ch1_overflow && rc2 > output_cap - rc) rest_overflow = TRUE;++ /* If ch1 grows so that `xform(ch1)+rest` can't fit in the buffer, but then+ `rest` shrinks, it's actually possible for the total calculated length of+ `xform(ch1)+xform(rest)` to come out at less than output_cap. But we can't+ report that, because it would make it seem that the operation succeeded.+ If either of xform(ch1) or xform(rest) won't fit in the buffer, our final+ result must be > output_cap. */+ if (ch1_overflow && rc2 < rest_len)+ rc2 = rest_len;++ state->to_case = PCRE2_SUBSTITUTE_CASE_UPPER;+ }++if (rc2 > ~(PCRE2_SIZE)0 - rc) /* Integer overflow */+ return ~(PCRE2_SIZE)0;++PCRE2_ASSERT(!(ch1_overflow || rest_overflow) || rc + rc2 > output_cap);+(void)rest_overflow;++return rc + rc2;+}+++/*************************************************+* Match and substitute *+*************************************************/++/* This function applies a compiled re to a subject string and creates a new+string with substitutions. The first 7 arguments are the same as for+pcre2_match(). Either string length may be PCRE2_ZERO_TERMINATED.++Arguments:+ code points to the compiled expression+ subject points to the subject string+ length length of subject string (may contain binary zeros)+ start_offset where to start in the subject string+ options option bits+ match_data points to a match_data block, or is NULL+ context points a PCRE2 context+ replacement points to the replacement string+ rlength length of replacement string+ buffer where to put the substituted string+ blength points to length of buffer; updated to length of string++Returns: >= 0 number of substitutions made+ < 0 an error code+ PCRE2_ERROR_BADREPLACEMENT means invalid use of $+*/++/* This macro checks for space in the buffer before copying into it. On+overflow, either give an error immediately, or keep on, accumulating the+length. */++#define CHECKMEMCPY(from, length_) \+ do { \+ PCRE2_SIZE chkmc_length = length_; \+ if (overflowed) \+ { \+ if (chkmc_length > ~(PCRE2_SIZE)0 - extra_needed) /* Integer overflow */ \+ goto TOOLARGEREPLACE; \+ extra_needed += chkmc_length; \+ } \+ else if (lengthleft < chkmc_length) \+ { \+ if ((suboptions & PCRE2_SUBSTITUTE_OVERFLOW_LENGTH) == 0) goto NOROOM; \+ overflowed = TRUE; \+ extra_needed = chkmc_length - lengthleft; \+ } \+ else \+ { \+ memcpy(buffer + buff_offset, from, CU2BYTES(chkmc_length)); \+ buff_offset += chkmc_length; \+ lengthleft -= chkmc_length; \+ } \+ } \+ while (0)++/* This macro checks for space and copies characters with casing modifications.+On overflow, it behaves as for CHECKMEMCPY().++When substitute_case_callout is NULL, the source and destination buffers must+not overlap, because our default handler does not support this. */++#define CHECKCASECPY_BASE(length_, do_call) \+ do { \+ PCRE2_SIZE chkcc_length = (PCRE2_SIZE)(length_); \+ PCRE2_SIZE chkcc_rc; \+ do_call \+ if (lengthleft < chkcc_rc) \+ { \+ if ((suboptions & PCRE2_SUBSTITUTE_OVERFLOW_LENGTH) == 0) goto NOROOM; \+ overflowed = TRUE; \+ extra_needed = chkcc_rc - lengthleft; \+ } \+ else \+ { \+ buff_offset += chkcc_rc; \+ lengthleft -= chkcc_rc; \+ } \+ } \+ while (0)++#define CHECKCASECPY_DEFAULT(from, length_) \+ CHECKCASECPY_BASE(length_, { \+ chkcc_rc = default_substitute_case_callout(from, chkcc_length, \+ buffer + buff_offset, \+ overflowed? 0 : lengthleft, \+ &forcecase, code); \+ if (overflowed) \+ { \+ if (chkcc_rc > ~(PCRE2_SIZE)0 - extra_needed) /* Integer overflow */ \+ goto TOOLARGEREPLACE; \+ extra_needed += chkcc_rc; \+ break; \+ } \+ })++#define CHECKCASECPY_CALLOUT(length_) \+ CHECKCASECPY_BASE(length_, { \+ chkcc_rc = do_case_copy(buffer + buff_offset, chkcc_length, \+ lengthleft, &forcecase, utf, \+ substitute_case_callout, \+ substitute_case_callout_data); \+ if (chkcc_rc == ~(PCRE2_SIZE)0) goto CASEERROR; \+ })++/* This macro does a delayed case transformation, for the situation when we have+a case-forcing callout. */++#define DELAYEDFORCECASE() \+ do { \+ PCRE2_SIZE chars_outstanding = (buff_offset - casestart_offset) + \+ (extra_needed - casestart_extra_needed); \+ if (chars_outstanding > 0) \+ { \+ if (overflowed) \+ { \+ PCRE2_SIZE guess = pessimistic_case_inflation(chars_outstanding); \+ if (guess > ~(PCRE2_SIZE)0 - extra_needed) /* Integer overflow */ \+ goto TOOLARGEREPLACE; \+ extra_needed += guess; \+ } \+ else \+ { \+ /* Rewind the buffer */ \+ lengthleft += (buff_offset - casestart_offset); \+ buff_offset = casestart_offset; \+ /* Care! In-place case transformation */ \+ CHECKCASECPY_CALLOUT(chars_outstanding); \+ } \+ } \+ } \+ while (0)+++/* Here's the function */++PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION+pcre2_substitute(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length,+ PCRE2_SIZE start_offset, uint32_t options, pcre2_match_data *match_data,+ pcre2_match_context *mcontext, PCRE2_SPTR replacement, PCRE2_SIZE rlength,+ PCRE2_UCHAR *buffer, PCRE2_SIZE *blength)+{+int rc;+int subs;+uint32_t ovector_count;+uint32_t goptions = 0;+uint32_t suboptions;+pcre2_match_data *internal_match_data = NULL;+BOOL escaped_literal = FALSE;+BOOL overflowed = FALSE;+BOOL use_existing_match;+BOOL replacement_only;+BOOL utf = (code->overall_options & PCRE2_UTF) != 0;+PCRE2_UCHAR temp[6];+PCRE2_UCHAR null_str[1] = { 0xcd };+PCRE2_SPTR original_subject = subject;+PCRE2_SPTR ptr;+PCRE2_SPTR repend = NULL;+PCRE2_SIZE extra_needed = 0;+PCRE2_SIZE buff_offset, buff_length, lengthleft, fraglength;+PCRE2_SIZE *ovector;+PCRE2_SIZE ovecsave[2] = { 0, 0 };+pcre2_substitute_callout_block scb;+PCRE2_SIZE sub_start_extra_needed;+PCRE2_SIZE (*substitute_case_callout)(PCRE2_SPTR, PCRE2_SIZE, PCRE2_UCHAR *,+ PCRE2_SIZE, int, void *) = NULL;+void *substitute_case_callout_data = NULL;++/* General initialization */++buff_offset = 0;+lengthleft = buff_length = *blength;+*blength = PCRE2_UNSET;++if (mcontext != NULL)+ {+ substitute_case_callout = mcontext->substitute_case_callout;+ substitute_case_callout_data = mcontext->substitute_case_callout_data;+ }++/* Partial matching is not valid. This must come after setting *blength to+PCRE2_UNSET, so as not to imply an offset in the replacement. */++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+zero length is interpreted as an empty string. */++if (replacement == NULL)+ {+ if (rlength != 0) return PCRE2_ERROR_NULL;+ replacement = null_str;+ }++if (rlength == PCRE2_ZERO_TERMINATED) rlength = PRIV(strlen)(replacement);+repend = replacement + rlength;++/* A NULL subject of zero length is treated as an empty string. */++if (subject == NULL)+ {+ if (length != 0) return PCRE2_ERROR_NULL;+ subject = null_str;+ }++if (length == PCRE2_ZERO_TERMINATED) length = PRIV(strlen)(subject);++/* Check for using a match that has already happened. Note that the subject+pointer in the match data may be NULL after a no-match. */++use_existing_match = ((options & PCRE2_SUBSTITUTE_MATCHED) != 0);+replacement_only = ((options & PCRE2_SUBSTITUTE_REPLACEMENT_ONLY) != 0);++if (use_existing_match && match_data == NULL) return PCRE2_ERROR_NULL;++/* If an existing match is being passed in, we should check that it matches+the passed-in subject pointer, length, and match options. We don't currently+have a use-case for someone to match on one subject, then try and use that+match data on a different subject. In a UTF-encoded string, a simple change+like replacing one character for another won't preserve the code unit offsets,+so it's hard to see, in the general case, how it would be safe or useful to+support swapping or mutating the subject string.++Similarly, using different match options between the first (external) and+subsequent (internal, global) matches is hard to justify. */++if (use_existing_match)+ {+ /* Return early, as the rest of the match_data may not have been+ initialised. This duplicates and must be in sync with the check below that+ aborts substitution on any result other than success or no-match. */+ if (match_data->rc < 0 && match_data->rc != PCRE2_ERROR_NOMATCH)+ return match_data->rc;++ /* Not supported if the passed-in match was from the DFA interpreter. */+ if (match_data->matchedby == PCRE2_MATCHEDBY_DFA_INTERPRETER)+ return PCRE2_ERROR_DFA_UFUNC;++ if (code != match_data->code)+ return PCRE2_ERROR_DIFFSUBSPATTERN;++ /* We want the passed-in subject strings to match. This implies the effective+ length must match, and either: the pointers are equal (with strict matching+ of NULL against NULL); or, the special case of PCRE2_COPY_MATCHED_SUBJECT+ where we cannot compare pointers but we can verify the contents. */+ if (length != match_data->subject_length ||+ !(original_subject == match_data->subject ||+ ((match_data->flags & PCRE2_MD_COPIED_SUBJECT) != 0 &&+ (length == 0 ||+ memcmp(subject, match_data->subject, CU2BYTES(length)) == 0))))+ return PCRE2_ERROR_DIFFSUBSSUBJECT;++ if (start_offset != match_data->start_offset)+ return PCRE2_ERROR_DIFFSUBSOFFSET;++ if ((options & ~SUBSTITUTE_OPTIONS) != match_data->options)+ return PCRE2_ERROR_DIFFSUBSOPTIONS;+ }++/* If starting from an existing match, there must be an externally provided+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, except for any cached+heap frame size and pointer. This ensures that no changes are made to the+external match data block. */++/* WARNING: In both cases below a general context is constructed "by hand"+because calling pcre2_general_context_create() involves a memory allocation. If+the contents of a general context control block are ever changed there will+have to be changes below. */++if (match_data == NULL)+ {+ pcre2_general_context gcontext;+ gcontext.memctl = (mcontext == NULL)?+ ((pcre2_real_code *)code)->memctl :+ ((pcre2_real_match_context *)mcontext)->memctl;+ match_data = internal_match_data =+ pcre2_match_data_create_from_pattern(code, &gcontext);+ if (internal_match_data == NULL) return PCRE2_ERROR_NOMEMORY;+ }++else if (use_existing_match)+ {+ int pairs;+ pcre2_general_context gcontext;+ gcontext.memctl = (mcontext == NULL)?+ ((pcre2_real_code *)code)->memctl :+ ((pcre2_real_match_context *)mcontext)->memctl;+ pairs = (code->top_bracket + 1 < match_data->oveccount)?+ code->top_bracket + 1 : match_data->oveccount;+ internal_match_data = pcre2_match_data_create(match_data->oveccount,+ &gcontext);+ 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;+ /* Ensure that the subject is not freed when internal_match_data is */+ internal_match_data->flags &= ~PCRE2_MD_COPIED_SUBJECT;+ match_data = internal_match_data;+ }++/* If using an internal match data, there's no need to copy the subject. */++if (internal_match_data != NULL) options &= ~PCRE2_COPY_MATCHED_SUBJECT;++/* Remember ovector details */++ovector = pcre2_get_ovector_pointer(match_data);+ovector_count = pcre2_get_ovector_count(match_data);++/* Fixed things in the callout block */++scb.version = 0;+scb.input = subject;+scb.output = (PCRE2_SPTR)buffer;+scb.ovector = ovector;++/* Check UTF replacement string if necessary. */++#ifdef SUPPORT_UNICODE+if (utf && (options & PCRE2_NO_UTF_CHECK) == 0)+ {+ rc = PRIV(valid_utf)(replacement, rlength, &(match_data->startchar));+ if (rc != 0)+ {+ match_data->leftchar = 0;+ goto EXIT;+ }+ }+#endif /* SUPPORT_UNICODE */++/* Save the substitute options and remove them from the match options. */++suboptions = options & SUBSTITUTE_OPTIONS;+options &= ~SUBSTITUTE_OPTIONS;++/* Error if the start match offset is greater than the length of the subject. */++if (start_offset > length)+ {+ match_data->leftchar = 0;+ rc = PCRE2_ERROR_BADOFFSET;+ goto EXIT;+ }++/* Copy up to the start offset, unless only the replacement is required. */++if (!replacement_only) CHECKMEMCPY(subject, start_offset);++/* Loop for global substituting. If PCRE2_SUBSTITUTE_MATCHED is set, the first+match is taken from the match_data that was passed in. */++subs = 0;+for (;;)+ {+ PCRE2_SPTR ptrstack[PTR_STACK_SIZE];+ uint32_t ptrstackptr = 0;+ case_state forcecase = { PCRE2_SUBSTITUTE_CASE_NONE, FALSE };+ PCRE2_SIZE casestart_offset = 0;+ PCRE2_SIZE casestart_extra_needed = 0;++ if (use_existing_match)+ {+ rc = match_data->rc;+ use_existing_match = FALSE;+ }+ else rc = pcre2_match(code, subject, length, start_offset, options|goptions,+ match_data, mcontext);++#ifdef SUPPORT_UNICODE+ if (utf) options |= PCRE2_NO_UTF_CHECK; /* Only need to check once */+#endif++ /* Any error other than no match returns the error code. No match breaks the+ global loop. */++ if (rc == PCRE2_ERROR_NOMATCH) break;++ if (rc < 0) goto EXIT;++ /* Handle a successful match. Matches that use \K to end before they start+ or start before the current point in the subject are not supported. */++ if (ovector[1] < ovector[0] || ovector[0] < start_offset)+ {+ rc = PCRE2_ERROR_BADSUBSPATTERN;+ goto EXIT;+ }++ /* Assert that our replacement loop is making progress, checked even in+ release builds. This should be impossible to hit, however, an infinite loop+ would be fairly catastrophic.++ "Progress" is measured as ovector[1] strictly advancing, or, an empty match+ after a non-empty match. */++ /* LCOV_EXCL_START */+ if (subs > 0 &&+ !(ovector[1] > ovecsave[1] ||+ (ovector[1] == ovector[0] && ovecsave[1] > ovecsave[0] &&+ ovector[1] == ovecsave[1])))+ {+ PCRE2_DEBUG_UNREACHABLE();+ rc = PCRE2_ERROR_INTERNAL_DUPMATCH;+ goto EXIT;+ }+ /* LCOV_EXCL_STOP */++ ovecsave[0] = ovector[0];+ ovecsave[1] = ovector[1];++ /* Count substitutions with a paranoid check for integer overflow; surely no+ real call to this function would ever hit this! */++ if (subs == INT_MAX)+ {+ rc = PCRE2_ERROR_TOOMANYREPLACE;+ goto EXIT;+ }+ subs++;++ /* Copy the text leading up to the match (unless not required); remember+ where the insert begins and how many ovector pairs are set; and remember how+ much space we have requested in extra_needed. */++ if (rc == 0) rc = ovector_count;+ fraglength = ovector[0] - start_offset;+ if (!replacement_only) CHECKMEMCPY(subject + start_offset, fraglength);+ scb.output_offsets[0] = buff_offset;+ scb.oveccount = rc;+ sub_start_extra_needed = extra_needed;++ /* Process the replacement string. If the entire replacement is literal, just+ copy it with length check. */++ ptr = replacement;+ if ((suboptions & PCRE2_SUBSTITUTE_LITERAL) != 0)+ {+ CHECKMEMCPY(ptr, rlength);+ }++ /* Within a non-literal replacement, which must be scanned character by+ character, local literal mode can be set by \Q, but only in extended mode+ when backslashes are being interpreted. In extended mode we must handle+ nested substrings that are to be reprocessed. */++ else for (;;)+ {+ uint32_t ch;+ unsigned int chlen;+ int group;+ uint32_t special;+ PCRE2_SPTR text1_start = NULL;+ PCRE2_SPTR text1_end = NULL;+ PCRE2_SPTR text2_start = NULL;+ PCRE2_SPTR text2_end = NULL;+ PCRE2_UCHAR name[MAX_NAME_SIZE + 1];++ /* If at the end of a nested substring, pop the stack. */++ if (ptr >= repend)+ {+ if (ptrstackptr == 0) break; /* End of replacement string */+ repend = ptrstack[--ptrstackptr];+ ptr = ptrstack[--ptrstackptr];+ continue;+ }++ /* Handle the next character */++ if (escaped_literal)+ {+ if (ptr[0] == CHAR_BACKSLASH && ptr < repend - 1 && ptr[1] == CHAR_E)+ {+ escaped_literal = FALSE;+ ptr += 2;+ continue;+ }+ goto LOADLITERAL;+ }++ /* Not in literal mode. */++ if (*ptr == CHAR_DOLLAR_SIGN)+ {+ BOOL inparens;+ BOOL inangle;+ BOOL star;+ PCRE2_SIZE sublength;+ PCRE2_UCHAR next;+ PCRE2_SPTR subptr, subptrend;++ if (++ptr >= repend) goto BAD;+ if ((next = *ptr) == CHAR_DOLLAR_SIGN) goto LOADLITERAL;++ special = 0;+ text1_start = NULL;+ text1_end = NULL;+ text2_start = NULL;+ text2_end = NULL;+ group = -1;+ inparens = FALSE;+ inangle = FALSE;+ star = FALSE;+ subptr = NULL;+ subptrend = NULL;++ /* Special $ sequences, as supported by Perl, JavaScript, .NET and others. */+ if (next == CHAR_AMPERSAND)+ {+ ++ptr;+ group = 0;+ goto GROUP_SUBSTITUTE;+ }+ if (next == CHAR_GRAVE_ACCENT || next == CHAR_APOSTROPHE)+ {+ ++ptr;+ rc = pcre2_substring_length_bynumber(match_data, 0, &sublength);+ if (rc < 0) goto PTREXIT; /* (Sanity-check ovector before reading from it.) */++ if (next == CHAR_GRAVE_ACCENT)+ {+ subptr = subject;+ subptrend = subject + ovector[0];+ }+ else+ {+ subptr = subject + ovector[1];+ subptrend = subject + length;+ }++ goto SUBPTR_SUBSTITUTE;+ }+ if (next == CHAR_UNDERSCORE)+ {+ /* Java, .NET support $_ for "entire input string". */+ ++ptr;+ subptr = subject;+ subptrend = subject + length;+ goto SUBPTR_SUBSTITUTE;+ }+ else if (next == CHAR_PLUS &&+ !(ptr+1 < repend && ptr[1] == CHAR_LEFT_CURLY_BRACKET))+ {+ /* Perl supports $+ for "highest captured group" (not the same as $^N+ which is mainly only useful inside Perl's match callbacks). We also+ don't accept "$+{..." since that's Perl syntax for our ${name}. */+ ++ptr;+ if (code->top_bracket == 0)+ {+ /* Treat either as "no such group" or "all groups unset" based on the+ PCRE2_SUBSTITUTE_UNKNOWN_UNSET option. */+ if ((suboptions & PCRE2_SUBSTITUTE_UNKNOWN_UNSET) == 0)+ {+ rc = PCRE2_ERROR_NOSUBSTRING;+ goto PTREXIT;+ }+ group = 0;+ }+ else+ {+ /* If we have any capture groups, then the ovector needs to be large+ enough for all of them, or the result won't be accurate. */+ if (match_data->oveccount < code->top_bracket + 1)+ {+ rc = PCRE2_ERROR_UNAVAILABLE;+ goto PTREXIT;+ }+ for (group = code->top_bracket; group > 0; group--)+ if (ovector[2*group] != PCRE2_UNSET) break;+ }+ if (group == 0)+ {+ if ((suboptions & PCRE2_SUBSTITUTE_UNSET_EMPTY) != 0) continue;+ rc = PCRE2_ERROR_UNSET;+ goto PTREXIT;+ }+ goto GROUP_SUBSTITUTE;+ }++ if (next == CHAR_LEFT_CURLY_BRACKET)+ {+ if (++ptr >= repend) goto BAD;+ next = *ptr;+ inparens = TRUE;+ }+ else if (next == CHAR_LESS_THAN_SIGN)+ {+ /* JavaScript compatibility syntax, $<name>. Processes only named+ groups (not numbered) and does not support extensions such as star+ (you can do ${name} and ${*name}, but not $<*name>). */+ if (++ptr >= repend) goto BAD;+ next = *ptr;+ inangle = TRUE;+ }++ if (!inangle && next == CHAR_ASTERISK)+ {+ if (++ptr >= repend) goto BAD;+ next = *ptr;+ star = TRUE;+ }++ if (!star && !inangle && next >= CHAR_0 && next <= CHAR_9)+ {+ group = next - CHAR_0;+ while (++ptr < repend)+ {+ next = *ptr;+ if (next < CHAR_0 || next > CHAR_9) break;+ group = group * 10 + (next - CHAR_0);++ /* A check for a number greater than the hightest captured group+ is sufficient here; no need for a separate overflow check. If unknown+ groups are to be treated as unset, just skip over any remaining+ digits and carry on. */++ if (group > code->top_bracket)+ {+ if ((suboptions & PCRE2_SUBSTITUTE_UNKNOWN_UNSET) != 0)+ {+ while (++ptr < repend && *ptr >= CHAR_0 && *ptr <= CHAR_9);+ break;+ }+ else+ {+ rc = PCRE2_ERROR_NOSUBSTRING;+ goto PTREXIT;+ }+ }+ }+ }+ else+ {+ PCRE2_SIZE name_len;+ PCRE2_SPTR name_start = ptr;+ if (!read_name_subst(&ptr, repend, utf, code->tables + ctypes_offset))+ goto BAD;+ name_len = ptr - name_start;+ memcpy(name, name_start, CU2BYTES(name_len));+ name[name_len] = 0;+ }++ next = 0; /* not used or updated after this point */+ (void)next;++ /* In extended mode we recognize ${name:+set text:unset text} and+ ${name:-default text}. */++ if (inparens)+ {+ if ((suboptions & PCRE2_SUBSTITUTE_EXTENDED) != 0 &&+ !star && ptr < repend - 2 && *ptr == CHAR_COLON)+ {+ special = *(++ptr);+ if (special != CHAR_PLUS && special != CHAR_MINUS)+ {+ rc = PCRE2_ERROR_BADSUBSTITUTION;+ goto PTREXIT;+ }++ text1_start = ++ptr;+ rc = find_text_end(code, &ptr, repend, special == CHAR_MINUS);+ if (rc != 0) goto PTREXIT;+ text1_end = ptr;++ if (special == CHAR_PLUS && *ptr == CHAR_COLON)+ {+ text2_start = ++ptr;+ rc = find_text_end(code, &ptr, repend, TRUE);+ if (rc != 0) goto PTREXIT;+ text2_end = ptr;+ }+ }++ else+ {+ if (ptr >= repend || *ptr != CHAR_RIGHT_CURLY_BRACKET)+ {+ rc = PCRE2_ERROR_REPMISSINGBRACE;+ goto PTREXIT;+ }+ }++ ptr++;+ }++ if (inangle)+ {+ if (ptr >= repend || *ptr != CHAR_GREATER_THAN_SIGN)+ goto BAD;+ ptr++;+ }++ /* Have found a syntactically correct group number or name, or *name.+ Only *MARK is currently recognized. */++ if (star)+ {+ if (PRIV(strcmp_c8)(name, STRING_MARK) == 0)+ {+ PCRE2_SPTR mark = pcre2_get_mark(match_data);+ if (mark != NULL)+ {+ /* Peek backwards one code unit to obtain the length of the mark.+ It can (theoretically) contain an embedded NUL. */+ fraglength = mark[-1];+ if (forcecase.to_case != PCRE2_SUBSTITUTE_CASE_NONE &&+ substitute_case_callout == NULL)+ CHECKCASECPY_DEFAULT(mark, fraglength);+ else+ CHECKMEMCPY(mark, fraglength);+ }+ }+ else goto BAD;+ }++ /* Substitute the contents of a group. We don't use substring_copy+ functions any more, in order to support case forcing. */++ else+ {+ GROUP_SUBSTITUTE:+ /* Find a number for a named group. In case there are duplicate names,+ search for the first one that is set. If the name is not found when+ PCRE2_SUBSTITUTE_UNKNOWN_EMPTY is set, set the group number to a+ non-existent group. */++ if (group < 0)+ {+ PCRE2_SPTR first, last, entry;+ rc = pcre2_substring_nametable_scan(code, name, &first, &last);+ if (rc == PCRE2_ERROR_NOSUBSTRING &&+ (suboptions & PCRE2_SUBSTITUTE_UNKNOWN_UNSET) != 0)+ {+ group = code->top_bracket + 1;+ }+ else+ {+ if (rc < 0) goto PTREXIT;+ for (entry = first; entry <= last; entry += rc)+ {+ uint32_t ng = GET2(entry, 0);+ if (ng < ovector_count)+ {+ if (group < 0) group = ng; /* First in ovector */+ if (ovector[ng*2] != PCRE2_UNSET)+ {+ group = ng; /* First that is set */+ break;+ }+ }+ }++ /* If group is still negative, it means we did not find a group+ that is in the ovector. Just set the first group. */++ if (group < 0) group = GET2(first, 0);+ }+ }++ /* We now have a group that is identified by number. Find the length of+ the captured string. If a group in a non-special substitution is unset+ when PCRE2_SUBSTITUTE_UNSET_EMPTY is set, substitute nothing. */++ rc = pcre2_substring_length_bynumber(match_data, group, &sublength);+ if (rc < 0)+ {+ if (rc == PCRE2_ERROR_NOSUBSTRING &&+ (suboptions & PCRE2_SUBSTITUTE_UNKNOWN_UNSET) != 0)+ {+ rc = PCRE2_ERROR_UNSET;+ }+ if (rc != PCRE2_ERROR_UNSET) goto PTREXIT; /* Non-unset errors */+ if (special == 0) /* Plain substitution */+ {+ if ((suboptions & PCRE2_SUBSTITUTE_UNSET_EMPTY) != 0) continue;+ goto PTREXIT; /* Else error */+ }+ }++ /* If special is '+' we have a 'set' and possibly an 'unset' text,+ both of which are reprocessed when used. If special is '-' we have a+ default text for when the group is unset; it must be reprocessed. */++ if (special != 0)+ {+ if (special == CHAR_MINUS)+ {+ if (rc == 0) goto LITERAL_SUBSTITUTE;+ text2_start = text1_start;+ text2_end = text1_end;+ }++ if (ptrstackptr >= PTR_STACK_SIZE) goto BAD;+ ptrstack[ptrstackptr++] = ptr;+ ptrstack[ptrstackptr++] = repend;++ if (rc == 0)+ {+ ptr = text1_start;+ repend = text1_end;+ }+ else+ {+ ptr = text2_start;+ repend = text2_end;+ }+ continue;+ }++ /* Otherwise we have a literal substitution of a group's contents. */++ LITERAL_SUBSTITUTE:+ subptr = subject + ovector[group*2];+ subptrend = subject + ovector[group*2 + 1];++ /* Substitute a literal string, possibly forcing alphabetic case. */++ SUBPTR_SUBSTITUTE:+ if (forcecase.to_case != PCRE2_SUBSTITUTE_CASE_NONE &&+ substitute_case_callout == NULL)+ CHECKCASECPY_DEFAULT(subptr, subptrend - subptr);+ else+ CHECKMEMCPY(subptr, subptrend - subptr);+ }+ } /* End of $ processing */++ /* Handle an escape sequence in extended mode. We can use check_escape()+ to process \Q, \E, \c, \o, \x and \ followed by non-alphanumerics, but+ the case-forcing escapes are not supported in pcre2_compile() so must be+ recognized here. */++ else if ((suboptions & PCRE2_SUBSTITUTE_EXTENDED) != 0 &&+ *ptr == CHAR_BACKSLASH)+ {+ int errorcode;+ case_state new_forcecase = { PCRE2_SUBSTITUTE_CASE_NONE, FALSE };++ if (ptr < repend - 1) switch (ptr[1])+ {+ case CHAR_L:+ new_forcecase.to_case = PCRE2_SUBSTITUTE_CASE_LOWER;+ new_forcecase.single_char = FALSE;+ ptr += 2;+ break;++ case CHAR_l:+ new_forcecase.to_case = PCRE2_SUBSTITUTE_CASE_LOWER;+ new_forcecase.single_char = TRUE;+ ptr += 2;+ if (ptr + 2 < repend && ptr[0] == CHAR_BACKSLASH && ptr[1] == CHAR_U)+ {+ /* Perl reverse-title-casing feature for \l\U */+ new_forcecase.to_case = PCRE2_SUBSTITUTE_CASE_REVERSE_TITLE_FIRST;+ new_forcecase.single_char = FALSE;+ ptr += 2;+ }+ break;++ case CHAR_U:+ new_forcecase.to_case = PCRE2_SUBSTITUTE_CASE_UPPER;+ new_forcecase.single_char = FALSE;+ ptr += 2;+ break;++ case CHAR_u:+ new_forcecase.to_case = PCRE2_SUBSTITUTE_CASE_TITLE_FIRST;+ new_forcecase.single_char = TRUE;+ ptr += 2;+ if (ptr + 2 < repend && ptr[0] == CHAR_BACKSLASH && ptr[1] == CHAR_L)+ {+ /* Perl title-casing feature for \u\L */+ new_forcecase.to_case = PCRE2_SUBSTITUTE_CASE_TITLE_FIRST;+ new_forcecase.single_char = FALSE;+ ptr += 2;+ }+ break;++ default:+ break;+ }++ if (new_forcecase.to_case != PCRE2_SUBSTITUTE_CASE_NONE)+ {+ SETFORCECASE:++ /* If the substitute_case_callout is unset, our case-forcing is done+ immediately. If there is a callout however, then its action is delayed+ until all the characters have been collected.++ Apply the callout now, before we set the new casing mode. */++ if (substitute_case_callout != NULL &&+ forcecase.to_case != PCRE2_SUBSTITUTE_CASE_NONE)+ DELAYEDFORCECASE();++ forcecase = new_forcecase;+ casestart_offset = buff_offset;+ casestart_extra_needed = extra_needed;+ continue;+ }++ ptr++; /* Point after \ */+ rc = PRIV(check_escape)(&ptr, repend, &ch, &errorcode,+ code->overall_options, code->extra_options, code->top_bracket, FALSE, NULL);+ if (errorcode != 0) goto BADESCAPE;++ switch(rc)+ {+ case ESC_E:+ goto SETFORCECASE;++ case ESC_Q:+ escaped_literal = TRUE;+ continue;++ case 0: /* Data character */+ case ESC_b: /* \b is backspace in a substitution */+ case ESC_v: /* \v is vertical tab in a substitution */++ if (rc == ESC_b) ch = CHAR_BS;+ if (rc == ESC_v) ch = CHAR_VT;++#ifdef SUPPORT_UNICODE+ if (utf) chlen = PRIV(ord2utf)(ch, temp); else+#endif+ {+ temp[0] = ch;+ chlen = 1;+ }++ if (forcecase.to_case != PCRE2_SUBSTITUTE_CASE_NONE &&+ substitute_case_callout == NULL)+ CHECKCASECPY_DEFAULT(temp, chlen);+ else+ CHECKMEMCPY(temp, chlen);+ continue;++ case ESC_g:+ {+ PCRE2_SIZE name_len;+ PCRE2_SPTR name_start;++ /* Parse the \g<name> form (\g<number> already handled by check_escape) */+ if (ptr >= repend || *ptr != CHAR_LESS_THAN_SIGN)+ goto BADESCAPE;+ ++ptr;++ name_start = ptr;+ if (!read_name_subst(&ptr, repend, utf, code->tables + ctypes_offset))+ goto BADESCAPE;+ name_len = ptr - name_start;++ if (ptr >= repend || *ptr != CHAR_GREATER_THAN_SIGN)+ goto BADESCAPE;+ ++ptr;++ special = 0;+ group = -1;+ memcpy(name, name_start, CU2BYTES(name_len));+ name[name_len] = 0;+ goto GROUP_SUBSTITUTE;+ }++ default:+ if (rc < 0)+ {+ special = 0;+ group = -rc - 1;+ goto GROUP_SUBSTITUTE;+ }+ goto BADESCAPE;+ }+ } /* End of backslash processing */++ /* Handle a literal code unit */++ else+ {+ PCRE2_SPTR ch_start;++ LOADLITERAL:+ ch_start = ptr;+ GETCHARINCTEST(ch, ptr); /* Get character value, increment pointer */+ (void) ch;++ if (forcecase.to_case != PCRE2_SUBSTITUTE_CASE_NONE &&+ substitute_case_callout == NULL)+ CHECKCASECPY_DEFAULT(ch_start, ptr - ch_start);+ else+ CHECKMEMCPY(ch_start, ptr - ch_start);+ } /* End handling a literal code unit */+ } /* End of loop for scanning the replacement. */++ /* If the substitute_case_callout is unset, our case-forcing is done+ immediately. If there is a callout however, then its action is delayed+ until all the characters have been collected.++ We now clean up any trailing section of the replacement for which we deferred+ the case-forcing. */++ if (substitute_case_callout != NULL &&+ forcecase.to_case != PCRE2_SUBSTITUTE_CASE_NONE)+ DELAYEDFORCECASE();++ /* The replacement has been copied to the output, or its size has been+ remembered. Handle the callout if there is one. */++ if (mcontext != NULL && mcontext->substitute_callout != NULL)+ {+ /* If we an actual (non-simulated) replacement, do the callout. */++ if (!overflowed)+ {+ scb.subscount = subs;+ scb.output_offsets[1] = buff_offset;+ rc = mcontext->substitute_callout(&scb,+ mcontext->substitute_callout_data);++ /* A non-zero return means cancel this substitution. Instead, copy the+ matched string fragment. */++ if (rc != 0)+ {+ PCRE2_SIZE newlength = scb.output_offsets[1] - scb.output_offsets[0];+ PCRE2_SIZE oldlength = ovector[1] - ovector[0];++ buff_offset -= newlength;+ lengthleft += newlength;+ if (!replacement_only) CHECKMEMCPY(subject + ovector[0], oldlength);++ /* A negative return means do not do any more. */++ if (rc < 0) suboptions &= (~PCRE2_SUBSTITUTE_GLOBAL);+ }+ }++ /* In this interesting case, we cannot do the callout, so it's hard to+ estimate the required buffer size. What callers want is to be able to make+ two calls to pcre2_substitute(), once with PCRE2_SUBSTITUTE_OVERFLOW_LENGTH+ to discover the buffer size, and then a second and final call. Older+ versions of PCRE2 violated this assumption, by proceding as if the callout+ had returned zero - but on the second call to pcre2_substitute() it could+ return non-zero and then overflow the buffer again. Callers probably don't+ want to keep on looping to incrementally discover the buffer size. */++ else+ {+ PCRE2_SIZE newlength_buf = buff_offset - scb.output_offsets[0];+ PCRE2_SIZE newlength_extra = extra_needed - sub_start_extra_needed;+ PCRE2_SIZE newlength =+ (newlength_extra > ~(PCRE2_SIZE)0 - newlength_buf)? /* Integer overflow */+ ~(PCRE2_SIZE)0 : newlength_buf + newlength_extra; /* Cap the addition */+ PCRE2_SIZE oldlength = ovector[1] - ovector[0];++ /* Be pessimistic: request whichever buffer size is larger out of+ accepting or rejecting the substitution. */++ if (oldlength > newlength)+ {+ PCRE2_SIZE additional = oldlength - newlength;+ if (additional > ~(PCRE2_SIZE)0 - extra_needed) /* Integer overflow */+ goto TOOLARGEREPLACE;+ extra_needed += additional;+ }++ /* Proceed as if the callout did not return a negative. A negative+ effectively rejects all future substitutions, but we want to examine them+ pessimistically. */+ }+ }++ /* Exit the global loop if we are not in global mode, or if pcre2_next_match()+ indicates we have reached the end of the subject. */++ if ((suboptions & PCRE2_SUBSTITUTE_GLOBAL) == 0 ||+ !pcre2_next_match(match_data, &start_offset, &goptions))+ {+ start_offset = ovector[1];+ break;+ }++ /* Verify that pcre2_next_match() has not done a bumpalong (because we have+ already returned PCRE2_ERROR_BADSUBSPATTERN for \K in lookarounds).++ We would otherwise have to memcpy the fragment spanning from ovector[1] to the+ new start_offset.*/++ PCRE2_ASSERT(start_offset == ovector[1]);++ } /* End of global loop */++/* Copy the rest of the subject unless not required, and terminate the output+with a binary zero. */++if (!replacement_only)+ {+ fraglength = length - start_offset;+ CHECKMEMCPY(subject + start_offset, fraglength);+ }++temp[0] = 0;+CHECKMEMCPY(temp, 1);++/* If overflowed is set it means the PCRE2_SUBSTITUTE_OVERFLOW_LENGTH is set,+and matching has carried on after a full buffer, in order to compute the length+needed. Otherwise, an overflow generates an immediate error return. */++if (overflowed)+ {+ rc = PCRE2_ERROR_NOMEMORY;++ if (extra_needed > ~(PCRE2_SIZE)0 - buff_length) /* Integer overflow */+ goto TOOLARGEREPLACE;+ *blength = buff_length + extra_needed;+ }++/* After a successful execution, return the number of substitutions and set the+length of buffer used, excluding the trailing zero. */++else+ {+ rc = subs;+ *blength = buff_offset - 1;+ }++EXIT:+if (internal_match_data != NULL) pcre2_match_data_free(internal_match_data);+ else match_data->rc = rc;+return rc;++NOROOM:+rc = PCRE2_ERROR_NOMEMORY;+goto EXIT;++CASEERROR:+rc = PCRE2_ERROR_REPLACECASE;+goto EXIT;++TOOLARGEREPLACE:+rc = PCRE2_ERROR_TOOLARGEREPLACE; goto EXIT; BAD:
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-2023 University of Cambridge+ New API code Copyright (c) 2016-2024 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -39,10 +39,6 @@ */ -#ifdef HAVE_CONFIG_H-#include "config.h"-#endif- #include "pcre2_internal.h" @@ -126,7 +122,7 @@ rc = pcre2_substring_length_bynumber(match_data, stringnumber, &size); if (rc < 0) return rc; if (size + 1 > *sizeptr) return PCRE2_ERROR_NOMEMORY;-memcpy(buffer, match_data->subject + match_data->ovector[stringnumber*2],+if (size != 0) memcpy(buffer, match_data->subject + match_data->ovector[stringnumber*2], CU2BYTES(size)); buffer[size] = 0; *sizeptr = size;@@ -218,7 +214,7 @@ (size + 1)*PCRE2_CODE_UNIT_WIDTH, (pcre2_memctl *)match_data); if (yield == NULL) return PCRE2_ERROR_NOMEMORY; yield = (PCRE2_UCHAR *)(((char *)yield) + sizeof(pcre2_memctl));-memcpy(yield, match_data->subject + match_data->ovector[stringnumber*2],+if (size != 0) memcpy(yield, match_data->subject + match_data->ovector[stringnumber*2], CU2BYTES(size)); yield[size] = 0; *stringptr = yield;@@ -259,7 +255,7 @@ Arguments: match_data pointer to match data stringname the name of the required substring- sizeptr where to put the length+ sizeptr where to put the length, if not NULL Returns: 0 if successful, else a negative error number */@@ -342,8 +338,15 @@ left = match_data->ovector[stringnumber*2]; right = match_data->ovector[stringnumber*2+1];+/* LCOV_EXCL_START - this appears to be unreachable, as the ovector and+subject_length should always be set consistently, no matter what misbehaviour+the caller has committed. */ if (left > match_data->subject_length || right > match_data->subject_length)+ {+ PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INVALIDOFFSET;+ }+/* LCOV_EXCL_STOP */ if (sizeptr != NULL) *sizeptr = (left > right)? 0 : right - left; return 0; }@@ -486,7 +489,7 @@ uint16_t bot = 0; uint16_t top = code->name_count; uint16_t entrysize = code->name_entry_size;-PCRE2_SPTR nametable = (PCRE2_SPTR)((char *)code + sizeof(pcre2_real_code));+PCRE2_SPTR nametable = (PCRE2_SPTR)((const char *)code + sizeof(pcre2_real_code)); while (top > bot) {
src/c/pcre2/src/pcre2_tables.c view
@@ -38,27 +38,33 @@ ----------------------------------------------------------------------------- */ + /* This module contains some fixed tables that are used by more than one of the PCRE2 code modules. The tables are also #included by the pcre2test program, which uses macros to change their names from _pcre2_xxx to xxxx, thereby avoiding name clashes with the library. In this case, PCRE2_PCRE2TEST is defined. */ -#ifndef PCRE2_PCRE2TEST /* We're compiling the library */-#ifdef HAVE_CONFIG_H-#include "config.h"-#endif++#if !defined(PCRE2_PCRE2TEST) && !defined(PCRE2_DFTABLES) && \+ !defined(PCRE2_PCRE2POSIX) /* We're compiling the library */ #include "pcre2_internal.h"-#endif /* PCRE2_PCRE2TEST */+#endif ++/* Utility macros */+#define ARR_SIZE(x) sizeof(x)/sizeof(x[0])+++#if !defined(PCRE2_PCRE2TEST) && !defined(PCRE2_DFTABLES) && \+ !defined(PCRE2_PCRE2POSIX)+ /* Table of sizes for the fixed-length opcodes. It's defined in a macro so that the definition is next to the definition of the opcodes in pcre2_internal.h. This is mode-dependent, so it is skipped when this file is included by pcre2test. */ -#ifndef PCRE2_PCRE2TEST const uint8_t PRIV(OP_lengths)[] = { OP_LENGTHS };-#endif /* Tables of horizontal and vertical whitespace characters, suitable for adding to classes. */@@ -66,6 +72,11 @@ const uint32_t PRIV(hspace_list)[] = { HSPACE_LIST }; const uint32_t PRIV(vspace_list)[] = { VSPACE_LIST }; +#endif /* !PCRE2_PCRE2TEST && !PCRE2_DFTABLES && !PCRE2_PCRE2POSIX */+++#if !defined(PCRE2_DFTABLES) && !defined(PCRE2_PCRE2POSIX)+ /* These tables are the pairs of delimiters that are valid for callout string arguments. For each starting delimiter there must be a matching ending delimiter, which in fact is different only for bracket-like delimiters. */@@ -80,7 +91,9 @@ CHAR_CIRCUMFLEX_ACCENT, CHAR_PERCENT_SIGN, CHAR_NUMBER_SIGN, CHAR_DOLLAR_SIGN, CHAR_RIGHT_CURLY_BRACKET, 0 }; +#endif /* !PCRE2_DFTABLES && !PCRE2_PCRE2POSIX */ + /************************************************* * Tables for UTF-8 support * *************************************************/@@ -90,23 +103,24 @@ handling wide characters. */ #if defined PCRE2_PCRE2TEST || \- (defined SUPPORT_UNICODE && \- defined PCRE2_CODE_UNIT_WIDTH && \- PCRE2_CODE_UNIT_WIDTH == 8)+ (!defined(PCRE2_DFTABLES) && !defined(PCRE2_PCRE2POSIX) && \+ defined SUPPORT_UNICODE && \+ defined PCRE2_CODE_UNIT_WIDTH && \+ PCRE2_CODE_UNIT_WIDTH == 8) /* These are the breakpoints for different numbers of bytes in a UTF-8 character. */ const int PRIV(utf8_table1)[] =- { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff};+ { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff }; -const int PRIV(utf8_table1_size) = sizeof(PRIV(utf8_table1)) / sizeof(int);+const unsigned PRIV(utf8_table1_size) = ARR_SIZE(PRIV(utf8_table1)); /* These are the indicator bits and the mask for the data bits to set in the first byte of a character, indexed by the number of additional bytes. */ -const int PRIV(utf8_table2)[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc};-const int PRIV(utf8_table3)[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};+const int PRIV(utf8_table2)[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc };+const int PRIV(utf8_table3)[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; /* Table of the number of extra bytes, indexed by the first byte masked with 0x3f. The highest number for a valid UTF-8 first byte is in fact 0x3d. */@@ -120,10 +134,11 @@ #endif /* UTF-8 support needed */ /* Tables concerned with Unicode properties are relevant only when Unicode-support is enabled. See also the pcre2_ucptables.c file, which is generated by+support is enabled. See also the pcre2_ucptables_inc.h file, which is generated by a Python script from Unicode data files. */ -#ifdef SUPPORT_UNICODE+#if !defined(PCRE2_DFTABLES) && !defined(PCRE2_PCRE2POSIX) && \+ defined(SUPPORT_UNICODE) /* Table to translate from particular type value to the general value. */ @@ -227,8 +242,69 @@ /* Finally, include the tables that are auto-generated from the Unicode data files. */ -#include "pcre2_ucptables.c"+#include "pcre2_ucptables_inc.h" -#endif /* SUPPORT_UNICODE */+#endif /* Unicode support needed */+++/*************************************************+* Tables for EBCDIC support *+*************************************************/++#if defined(EBCDIC) && \+ (defined(PCRE2_PCRE2TEST) || defined(PCRE2_DFTABLES) || 'a' != 0x81)++const uint8_t PRIV(ebcdic_1047_to_ascii)[256] = {+ 0x00,0x01,0x02,0x03,0x9c,0x09,0x86,0x7f,0x97,0x8d,0x8e,0x0b,0x0c,0x0d,0x0e,0x0f,+#ifdef EBCDIC_NL25+ 0x10,0x11,0x12,0x13,0x9d,0x85,0x08,0x87,0x18,0x19,0x92,0x8f,0x1c,0x1d,0x1e,0x1f,+ 0x80,0x81,0x82,0x83,0x84,0x0a,0x17,0x1b,0x88,0x89,0x8a,0x8b,0x8c,0x05,0x06,0x07,+#else+ 0x10,0x11,0x12,0x13,0x9d,0x0a,0x08,0x87,0x18,0x19,0x92,0x8f,0x1c,0x1d,0x1e,0x1f,+ 0x80,0x81,0x82,0x83,0x84,0x85,0x17,0x1b,0x88,0x89,0x8a,0x8b,0x8c,0x05,0x06,0x07,+#endif+ 0x90,0x91,0x16,0x93,0x94,0x95,0x96,0x04,0x98,0x99,0x9a,0x9b,0x14,0x15,0x9e,0x1a,+ 0x20,0xa0,0xe2,0xe4,0xe0,0xe1,0xe3,0xe5,0xe7,0xf1,0xa2,0x2e,0x3c,0x28,0x2b,0x7c,+ 0x26,0xe9,0xea,0xeb,0xe8,0xed,0xee,0xef,0xec,0xdf,0x21,0x24,0x2a,0x29,0x3b,0x5e,+ 0x2d,0x2f,0xc2,0xc4,0xc0,0xc1,0xc3,0xc5,0xc7,0xd1,0xa6,0x2c,0x25,0x5f,0x3e,0x3f,+ 0xf8,0xc9,0xca,0xcb,0xc8,0xcd,0xce,0xcf,0xcc,0x60,0x3a,0x23,0x40,0x27,0x3d,0x22,+ 0xd8,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0xab,0xbb,0xf0,0xfd,0xfe,0xb1,+ 0xb0,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0xaa,0xba,0xe6,0xb8,0xc6,0xa4,+ 0xb5,0x7e,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0xa1,0xbf,0xd0,0x5b,0xde,0xae,+ 0xac,0xa3,0xa5,0xb7,0xa9,0xa7,0xb6,0xbc,0xbd,0xbe,0xdd,0xa8,0xaf,0x5d,0xb4,0xd7,+ 0x7b,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0xad,0xf4,0xf6,0xf2,0xf3,0xf5,+ 0x7d,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0xb9,0xfb,0xfc,0xf9,0xfa,0xff,+ 0x5c,0xf7,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0xb2,0xd4,0xd6,0xd2,0xd3,0xd5,+ 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0xb3,0xdb,0xdc,0xd9,0xda,0x9f,+};++const uint8_t PRIV(ascii_to_ebcdic_1047)[256] = {+#ifdef EBCDIC_NL25+ 0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f,0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f,+#else+ 0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f,0x16,0x05,0x15,0x0b,0x0c,0x0d,0x0e,0x0f,+#endif+ 0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26,0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f,+ 0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d,0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61,+ 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f,+ 0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,+ 0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xad,0xe0,0xbd,0x5f,0x6d,+ 0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96,+ 0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07,+#ifdef EBCDIC_NL25+ 0x20,0x21,0x22,0x23,0x24,0x15,0x06,0x17,0x28,0x29,0x2a,0x2b,0x2c,0x09,0x0a,0x1b,+#else+ 0x20,0x21,0x22,0x23,0x24,0x25,0x06,0x17,0x28,0x29,0x2a,0x2b,0x2c,0x09,0x0a,0x1b,+#endif+ 0x30,0x31,0x1a,0x33,0x34,0x35,0x36,0x08,0x38,0x39,0x3a,0x3b,0x04,0x14,0x3e,0xff,+ 0x41,0xaa,0x4a,0xb1,0x9f,0xb2,0x6a,0xb5,0xbb,0xb4,0x9a,0x8a,0xb0,0xca,0xaf,0xbc,+ 0x90,0x8f,0xea,0xfa,0xbe,0xa0,0xb6,0xb3,0x9d,0xda,0x9b,0x8b,0xb7,0xb8,0xb9,0xab,+ 0x64,0x65,0x62,0x66,0x63,0x67,0x9e,0x68,0x74,0x71,0x72,0x73,0x78,0x75,0x76,0x77,+ 0xac,0x69,0xed,0xee,0xeb,0xef,0xec,0xbf,0x80,0xfd,0xfe,0xfb,0xfc,0xba,0xae,0x59,+ 0x44,0x45,0x42,0x46,0x43,0x47,0x9c,0x48,0x54,0x51,0x52,0x53,0x58,0x55,0x56,0x57,+ 0x8c,0x49,0xcd,0xce,0xcb,0xcf,0xcc,0xe1,0x70,0xdd,0xde,0xdb,0xdc,0x8d,0x8e,0xdf,+};++#endif /* EBCDIC support needed */ /* End of pcre2_tables.c */
src/c/pcre2/src/pcre2_ucd.c view
@@ -42,5412 +42,5757 @@ ----------------------------------------------------------------------------- */ -/* This file contains tables of Unicode properties that are extracted from-Unicode data files. See the comments at the start of maint/GenerateUcd.py for-details.--As well as being part of the PCRE2 library, this file is #included by the-pcre2test program, which redefines the PRIV macro to change table names from-_pcre2_xxx to xxxx, thereby avoiding name clashes with the library. At present,-just one of these tables is actually needed. When compiling the library, some-headers are needed. */--#ifndef PCRE2_PCRE2TEST-#ifdef HAVE_CONFIG_H-#include "config.h"-#endif-#include "pcre2_internal.h"-#endif /* PCRE2_PCRE2TEST */--/* The tables herein are needed only when UCP support is built, and in PCRE2-that happens automatically with UTF support. This module should not be-referenced otherwise, so it should not matter whether it is compiled or not.-However a comment was received about space saving - maybe the guy linked all-the modules rather than using a library - so we include a condition to cut out-the tables when not needed. But don't leave a totally empty module because some-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: 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,++/* This file contains tables of Unicode properties that are extracted from+Unicode data files. See the comments at the start of maint/GenerateUcd.py for+details.++As well as being part of the PCRE2 library, this file is #included by the+pcre2test program, which redefines the PRIV macro to change table names from+_pcre2_xxx to xxxx, thereby avoiding name clashes with the library. At present,+just one of these tables is actually needed. When compiling the library, some+headers are needed. */+++#ifndef PCRE2_PCRE2TEST+#include "pcre2_internal.h"+#endif /* PCRE2_PCRE2TEST */++++/* The tables herein are needed only when UCP support is built, and in PCRE2+that happens automatically with UTF support. This module should not be+referenced otherwise, so it should not matter whether it is compiled or not.+However a comment was received about space saving - maybe the guy linked all+the modules rather than using a library - so we include a condition to cut out+the tables when not needed. But don't leave a totally empty module because some+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};+const uint32_t PRIV(ucd_nocase_ranges)[] = {0};+const uint32_t PRIV(ucd_nocase_ranges_size) = 0;+#else++/* Total size: 116564 bytes, block size: 128. */++const char *PRIV(unicode_version) = "16.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,+ 0x0069, 0x0130, NOTACHAR,+ 0x0049, 0x0131, NOTACHAR,+};++/* This is the index, within ucd_caseless_sets, of the additional+Turkish case-equivalences. The dotted I ones are this offset; the+dotless I are +3 from here. */++const uint32_t PRIV(ucd_turkish_dotted_i_caseset) = 112;++/* 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 contains character ranges, where the characters in the range have+no other case. Both start and end values are excluded from the range. */++const uint32_t PRIV(ucd_nocase_ranges)[] = {+ 0x0000, 0x0041, /* 64 */+ 0x007a, 0x00b5, /* 58 */+ 0x00b5, 0x00c0, /* 10 */+ 0x0292, 0x029d, /* 10 */+ 0x029e, 0x0345, /* 166 */+ 0x0345, 0x0370, /* 42 */+ 0x0481, 0x048a, /* 8 */+ 0x0556, 0x0561, /* 10 */+ 0x0586, 0x10a0, /* 2841 */+ 0x10ff, 0x13a0, /* 672 */+ 0x13fd, 0x1c80, /* 2178 */+ 0x1cbf, 0x1d79, /* 185 */+ 0x1d7d, 0x1d8e, /* 16 */+ 0x1d8e, 0x1e00, /* 113 */+ 0x1ffc, 0x2126, /* 297 */+ 0x2132, 0x214e, /* 27 */+ 0x214e, 0x2160, /* 17 */+ 0x2184, 0x24b6, /* 817 */+ 0x24e9, 0x2c00, /* 1814 */+ 0x2cf3, 0x2d00, /* 12 */+ 0x2d2d, 0xa640, /* 30994 */+ 0xa66d, 0xa680, /* 18 */+ 0xa69b, 0xa722, /* 134 */+ 0xa76f, 0xa779, /* 9 */+ 0xa7dc, 0xa7f5, /* 24 */+ 0xa7f6, 0xab53, /* 860 */+ 0xab53, 0xab70, /* 28 */+ 0xabbf, 0xfb05, /* 20293 */+ 0xfb06, 0xff21, /* 1050 */+ 0xff5a, 0x10400, /* 1189 */+ 0x1044f, 0x104b0, /* 96 */+ 0x104fb, 0x10570, /* 116 */+ 0x105bc, 0x10c80, /* 1731 */+ 0x10cb2, 0x10cc0, /* 13 */+ 0x10cf2, 0x10d50, /* 93 */+ 0x10d65, 0x10d70, /* 10 */+ 0x10d85, 0x118a0, /* 2842 */+ 0x118df, 0x16e40, /* 21856 */+ 0x16e7f, 0x1e900, /* 31360 */+ 0x1e943, 0x110000, /* 988860 */+ 0xffffffff, 0xffffffff /* terminator */+};++/* Total: 1110933 characters. */+const uint32_t PRIV(ucd_nocase_ranges_size) = 80;++/* 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)[] = {+ 76, /* 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, 0x10d49,+ 0x1106f, 0x110f9, 0x1113f, 0x111d9, 0x112f9, 0x11459, 0x114d9, 0x11659,+ 0x116c9, 0x116d9, 0x116e3, 0x11739, 0x118e9, 0x11959, 0x11bf9, 0x11c59,+ 0x11d59, 0x11da9, 0x11f59, 0x16139, 0x16a69, 0x16ac9, 0x16b59, 0x16d79,+ 0x1ccf9, 0x1d7d7, 0x1d7e1, 0x1d7eb, 0x1d7f5, 0x1d7ff, 0x1e149, 0x1e2f9,+ 0x1e4f9, 0x1e5fa, 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, 0x00000000u,+ 0x40200003u, 0x00381901u, 0x00100246u, 0x00000000u,+ 0x00040305u, 0x00800000u, 0x08000000u, 0x00000000u,+ 0x20000001u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x00000001u, 0x00800000u, 0x00000000u, 0x00000000u,+ 0x00040001u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x01000007u, 0x00000840u, 0x80000200u, 0x00000000u,+ 0x01000007u, 0x00000040u, 0x80010000u, 0x00000001u,+ 0x01000005u, 0x00002000u, 0x00000000u, 0x00000000u,+ 0x00040041u, 0x00001000u, 0x80000000u, 0x00000000u,+ 0x01000047u, 0x00002801u, 0x00010001u, 0x00000001u,+ 0x10000001u, 0x00001801u, 0x00000004u, 0x00000000u,+ 0x00000007u, 0x00000000u, 0x00000200u, 0x00000000u,+ 0x00000051u, 0x00002840u, 0x00000202u, 0x00000001u,+ 0x0000005fu, 0x00000041u, 0x00000202u, 0x00000000u,+ 0x00000001u, 0x00002000u, 0x00000000u, 0x00000000u,+ 0x00000041u, 0x00000000u, 0x00000002u, 0x00000000u,+ 0x01000005u, 0x00000000u, 0x00010000u, 0x00000000u,+ 0x01000001u, 0x00000040u, 0x00000000u, 0x00000000u,+ 0x00000001u, 0x00000000u, 0x80000000u, 0x00000000u,+ 0x00800001u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x00000005u, 0x00000000u, 0x00000000u, 0x00000001u,+ 0x00000003u, 0x00000000u, 0x00000200u, 0x00000001u,+ 0x00000041u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x11000041u, 0x00000000u, 0x00000002u, 0x00000000u,+ 0x01000041u, 0x00000000u, 0x00000002u, 0x00000000u,+ 0x00000041u, 0x00000000u, 0x80000000u, 0x00000000u,+ 0x01000041u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x01040001u, 0x00000001u, 0x80000001u, 0x00000000u,+ 0x00000002u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x00000001u, 0x00000000u, 0x00010000u, 0x00000000u,+ 0x00000001u, 0x00000000u, 0x00000001u, 0x00000001u,+ 0x00000001u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x00000002u, 0x00000800u, 0x00000000u, 0x00000000u,+ 0x00000004u, 0x00000000u, 0x00000200u, 0x00000000u,+ 0x00000004u, 0x00001000u, 0x00000000u, 0x00000000u,+ 0x00000005u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x00200008u, 0x00001000u, 0x00000000u, 0x00000000u,+ 0x000000e0u, 0x00010000u, 0x11200000u, 0x00000000u,+ 0x000000e0u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x000000e0u, 0x00010000u, 0x11208000u, 0x00000000u,+ 0x00000060u, 0x08000000u, 0x04608480u, 0x00000000u,+ 0x00000060u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x000000a0u, 0x00000000u, 0x01000000u, 0x00000000u,+ 0x00000020u, 0x00000000u, 0x00200000u, 0x00000000u,+ 0x0001ff01u, 0x40000000u, 0x00001008u, 0x00000000u,+ 0x0001ff01u, 0x00000000u, 0x00001008u, 0x00000000u,+ 0x0003ff00u, 0x80004000u, 0x409c1848u, 0x00000000u,+ 0x0003ff00u, 0x80004020u, 0x609c1848u, 0x00000000u,+ 0x00000100u, 0x04000000u, 0x00080040u, 0x00000000u,+ 0x00000200u, 0x10004000u, 0x00000000u, 0x00000000u,+ 0x00000400u, 0x00000000u, 0x00002000u, 0x00000000u,+ 0x00000800u, 0x00000000u, 0x00000010u, 0x00000000u,+ 0x00002000u, 0x00000000u, 0x00000008u, 0x00000000u,+ 0x00008000u, 0x00000000u, 0x00800000u, 0x00000002u,+ 0x00100000u, 0x10000040u, 0x00000000u, 0x00000000u,+ 0x00200001u, 0x00001000u, 0x00000000u, 0x00000000u,+ 0x02000000u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x00000000u, 0x0000001eu, 0x00000000u, 0x00000000u,+ 0x04000000u, 0x00008000u, 0x00000000u, 0x00000000u,+ 0x00008300u, 0x00000000u, 0x00000008u, 0x00000000u,+ 0x00000100u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x00008100u, 0x00000000u, 0x00000008u, 0x00000000u,+ 0x00000300u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x00000100u, 0x40000000u, 0x00000000u, 0x00000000u,+ 0x0001f100u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x00000100u, 0x00000000u, 0x00800000u, 0x00000000u,+ 0x0003d300u, 0x00000000u, 0x00801008u, 0x00000002u,+ 0x00000100u, 0x00000000u, 0x00000008u, 0x00000000u,+ 0x00008100u, 0x00000000u, 0x00000008u, 0x00000002u,+ 0x00000200u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x00000000u, 0x00000000u, 0x00800000u, 0x00000000u,+ 0x00000045u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x00000040u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x04000001u, 0x00008000u, 0x00000000u, 0x00000000u,+ 0x00000020u, 0x00000000u, 0x00008000u, 0x00000000u,+ 0x00200000u, 0x020c1000u, 0x00004000u, 0x00000000u,+ 0x00000002u, 0x20080000u, 0x00004000u, 0x00000000u,+ 0x00000101u, 0x00000000u, 0x00000008u, 0x00000000u,+ 0x00000001u, 0x00000800u, 0x00000000u, 0x00000000u,+ 0x00000000u, 0x02200000u, 0x00000000u, 0x00000000u,+ 0x00200000u, 0x04780000u, 0x00004000u, 0x00000000u,+ 0x00000000u, 0x00000000u, 0x00000002u, 0x00000000u,+ 0x00000020u, 0x00000000u, 0x0000c000u, 0x00000000u,+ 0x40000000u, 0x00000000u, 0x00020000u, 0x00000000u,+ 0xfc400000u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0xfc400000u, 0x00008000u, 0x00000000u, 0x00000000u,+ 0x78400000u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x40000000u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0xfc480000u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0xfc480000u, 0x00800000u, 0x00000000u, 0x00000000u,+ 0xf8400000u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x60000000u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x18000000u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x58000000u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x40000001u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x00018d00u, 0xc4000000u, 0x00881950u, 0x00000002u,+ 0x00008d00u, 0xc4000000u, 0x00881950u, 0x00000002u,+ 0x00000d00u, 0x84000000u, 0x00081950u, 0x00000000u,+ 0x00000d00u, 0xc4000000u, 0x00081950u, 0x00000000u,+ 0x00000300u, 0x00000000u, 0x00000000u, 0x00000002u,+ 0x00002100u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x00100001u, 0x00020000u, 0x00000000u, 0x00000000u,+ 0x00000000u, 0x01000400u, 0x00000000u, 0x00000000u,+ 0x00000020u, 0x00010000u, 0x00000000u, 0x00000000u,+ 0x000000a0u, 0x00000000u, 0x00000000u, 0x00000000u,+ 0x00000000u, 0x00000280u, 0x02000000u, 0x00000000u,+ 0x00000000u, 0x00000280u, 0x00000000u, 0x00000000u,+ 0x00000000u, 0x00000280u, 0x00000020u, 0x00000000u,+ 0x00000020u, 0x00000800u, 0x00000000u, 0x00000000u,+ 0x00000000u, 0x00000000u, 0x04000080u, 0x00000000u,+};++/* 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, 0x00400800u,+ 0x00800001u, 0x00400800u,+ 0x00800001u, 0x00050400u,+ 0x00800001u, 0x00002400u,+ 0x00830001u, 0x00000400u,+ 0x00800001u, 0x00000400u,+ 0x00800021u, 0x00002400u,+ 0x00800011u, 0x00000400u,+ 0x00800001u, 0x00000480u,+ 0x00800001u, 0x00040400u,+ 0x00801001u, 0x00000400u,+ 0x00800021u, 0x00050400u,+ 0x04830003u, 0x00800001u,+ 0x00800021u, 0x00040400u,+ 0x00800011u, 0x00000480u,+ 0x048003c7u, 0x01900003u,+ 0x008003c5u, 0x01900003u,+ 0x00808021u, 0x00000480u,+ 0x00800001u, 0x00800001u,+ 0x00808021u, 0x00000400u,+ 0x04800d47u, 0x01800043u,+ 0x00800d45u, 0x01800043u,+ 0x00800d45u, 0x01820043u,+ 0x00000000u, 0x00400800u,+ 0x00800000u, 0x00400000u,+ 0x00800000u, 0x00000400u,+ 0x00808020u, 0x00000000u,+ 0x00a10000u, 0x00000400u,+ 0x00800044u, 0x01800043u,+ 0x00800010u, 0x00002400u,+ 0x00800000u, 0x00000480u,+ 0x00002020u, 0x00000000u,+ 0x40800000u, 0x00000000u,+ 0x00800dc4u, 0x01800043u,+ 0x00c08020u, 0x00800001u,+ 0x00800000u, 0x00000000u,+ 0x008003c4u, 0x01900003u,+ 0x00800d44u, 0x01800043u,+ 0x00800d44u, 0x01820043u,+ 0x00804dc4u, 0x01800043u,+ 0x00800004u, 0x01800003u,+ 0x008007c4u, 0x01900003u,+ 0x00800bc4u, 0x01800003u,+ 0x00808064u, 0x01800043u,+ 0x00808064u, 0x01820043u,+ 0x00808024u, 0x01800003u,+ 0x00c08024u, 0x01800003u,+ 0x01008020u, 0x00800009u,+ 0x01008de4u, 0x00800049u,+ 0x01002020u, 0x00800009u,+ 0x01000020u, 0x00800009u,+ 0x01000024u, 0x00800009u,+ 0x00808064u, 0x00000043u,+ 0x00800000u, 0x00040000u,+ 0x00800020u, 0x00840001u,+ 0x00800dc4u, 0x018000c3u,+ 0x00800044u, 0x01900083u,+ 0x00800044u, 0x01900003u,+ 0x008003c4u, 0x01900083u,+ 0x00800000u, 0x00000080u,+ 0x01000020u, 0x00000008u,+ 0x00800020u, 0x00000000u,+ 0x00800000u, 0x00050000u,+ 0x00801000u, 0x00000000u,+ 0x01008024u, 0x00800009u,+ 0x00000020u, 0x00001000u,+ 0x00002028u, 0x00000000u,+ 0x00c00024u, 0x01800003u,+ 0x01000024u, 0x00800109u,+ 0x01008020u, 0x00800109u,+ 0x00800000u, 0x00800001u,+ 0x00804004u, 0x01800003u,+ 0x00800024u, 0x01800003u,+ 0x01000020u, 0x00800109u,+ 0x01008024u, 0x00800109u,+ 0x00800004u, 0x00800001u,+ 0x00800004u, 0x0180000bu,+ 0x03008020u, 0x00800009u,+ 0x01000004u, 0x00800009u,+ 0x01400024u, 0x00800009u,+ 0x01408020u, 0x00800009u,+ 0x00800004u, 0x00800003u,+ 0x03008024u, 0x00800009u,+ 0x00800004u, 0x01800023u,+ 0x00800010u, 0x00000000u,+ 0x00808000u, 0x00800001u,+ 0x01004024u, 0x00800009u,+ 0x00808004u, 0x00800001u,+ 0x00800944u, 0x01800043u,+ 0x00800064u, 0x01800043u,+ 0x00802004u, 0x01800003u,+ 0x00800344u, 0x01900003u,+ 0x03008000u, 0x00800009u,+ 0x00c00000u, 0x00000000u,+ 0x01002020u, 0x00a00009u,+ 0x01000024u, 0x0180000bu,+ 0x01008020u, 0x00000008u,+ 0x01408024u, 0x00800009u,+ 0x00808000u, 0x00000000u,+ 0x00800044u, 0x01820043u,+ 0x00800064u, 0x01820043u,+ 0x01002020u, 0x00800011u,+ 0x00022020u, 0x00800019u,+ 0x00002028u, 0x00000800u,+ 0x00801000u, 0x00000400u,+ 0x00800020u, 0x00002400u,+ 0x00800000u, 0x00002400u,+ 0x00800020u, 0x00050400u,+ 0x00800020u, 0x00000400u,+ 0x00a10000u, 0x00050400u,+ 0x00800000u, 0x00050400u,+ 0x00800000u, 0x00800081u,+ 0x00800010u, 0x00000400u,+ 0x00002020u, 0x00000080u,+ 0x00002000u, 0x00000000u,+ 0x00006020u, 0x00000000u,+ 0x40800000u, 0x00000080u,+ 0x40801000u, 0x00000080u,+ 0x40800010u, 0x00000080u,+ 0x01000020u, 0x00800089u,+ 0x01020020u, 0x00000008u,+ 0x00800044u, 0x018000c3u,+ 0x00800000u, 0x01800083u,+ 0x00a10000u, 0x00000000u,+ 0x00800000u, 0x01800003u,+ 0x00800004u, 0x01800083u,+ 0x00a10044u, 0x01800043u,+ 0x00800044u, 0x018200c3u,+ 0x00a10000u, 0x00000480u,+ 0xc0800000u, 0x00000480u,+ 0x00800010u, 0x00000480u,+ 0x00801000u, 0x00000480u,+ 0x00b10000u, 0x00000400u,+ 0x00804010u, 0x00000400u,+ 0x00a00000u, 0x00000400u,+ 0x00000000u, 0x00000400u,+ 0x008003c4u, 0x00100000u,+ 0x00a103c4u, 0x00100000u,+ 0x00800d44u, 0x00000040u,+ 0x00b10000u, 0x00000480u,+ 0x00a00000u, 0x00000480u,+ 0x00a90000u, 0x00000400u,+ 0x00b90000u, 0x00000400u,+ 0x03000020u, 0x00800009u,+ 0x00808024u, 0x00000400u,+ 0x00800000u, 0x00040400u,+ 0x00800000u, 0x00004000u,+ 0x08800000u, 0x00000000u,+ 0x10800000u, 0x00000000u,+ 0x20800000u, 0x00000000u,+ 0x00800004u, 0x01800007u,+ 0x01008000u, 0x00800009u,+ 0x00a11000u, 0x00000400u,+ 0x00808020u, 0x00000003u,+ 0x00800004u, 0x01880007u,+ 0x00808004u, 0x01800003u,+ 0x00800004u, 0x00000003u,+ 0x00000000u, 0x00000200u,+ 0x01022020u, 0x00a00009u,+ 0x00800000u, 0x00002000u,+ 0x00800020u, 0x00050000u,+ 0x00800020u, 0x00040000u,+ 0x00801000u, 0x00000080u,+ 0x00800010u, 0x00000080u,+ 0x00800020u, 0x00002000u,+ 0x04800000u, 0x00800001u,+ 0x048003c4u, 0x01900003u,+ 0x00808020u, 0x00000080u,+ 0x04800d44u, 0x01800043u,+ 0x00800010u, 0x00002000u,+ 0x01008024u, 0x0080000bu,+ 0x00000020u, 0x00000000u,+ 0x00c00004u, 0x01800003u,+ 0x00c08004u, 0x01800003u,+ 0x01400020u, 0x00800009u,+ 0x01000020u, 0x0080000du,+ 0x01008004u, 0x00800009u,+ 0x01000000u, 0x00800009u,+ 0xc0800000u, 0x00000080u,+ 0x00a00000u, 0x00000000u,+ 0x00b10000u, 0x00000000u,+ 0x00200000u, 0x00000000u,+ 0x00800044u, 0x00100000u,+ 0x00a10044u, 0x00100000u,+ 0x00930000u, 0x00008000u,+ 0x00b90000u, 0x00000000u,+ 0x00a90000u, 0x00000000u,+ 0x00970020u, 0x00000008u,+ 0x00b30000u, 0x00000000u,+ 0x01022020u, 0x00000008u,+};++/* 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)[] = { /* 18516 bytes, record size 12 */+ { 99, 0, 2, 0, 0, 6144, 2, }, /* 0 */+ { 99, 0, 2, 0, 0, 43008, 4, }, /* 1 */+ { 99, 0, 1, 0, 0, 4096, 4, }, /* 2 */+ { 99, 0, 2, 0, 0, 45056, 4, }, /* 3 */+ { 99, 0, 0, 0, 0, 4096, 4, }, /* 4 */+ { 99, 0, 2, 0, 0, 4096, 2, }, /* 5 */+ { 99, 0, 2, 0, 0, 43008, 2, }, /* 6 */+ { 99, 29, 12, 0, 0, 45056, 6, }, /* 7 */+ { 99, 21, 12, 0, 0, 28672, 8, }, /* 8 */+ { 99, 21, 12, 0, 0, 28672, 10, }, /* 9 */+ { 99, 21, 12, 0, 0, 14336, 12, }, /* 10 */+ { 99, 23, 12, 0, 0, 14336, 14, }, /* 11 */+ { 99, 21, 12, 0, 0, 14336, 14, }, /* 12 */+ { 99, 21, 12, 0, 0, 28672, 14, }, /* 13 */+ { 99, 21, 12, 0, 0, 28672, 16, }, /* 14 */+ { 99, 22, 12, 0, 0, 28672, 18, }, /* 15 */+ { 99, 18, 12, 0, 0, 28672, 18, }, /* 16 */+ { 99, 21, 12, 0, 0, 28672, 12, }, /* 17 */+ { 99, 25, 12, 0, 0, 12288, 20, }, /* 18 */+ { 99, 21, 12, 0, 0, 8192, 22, }, /* 19 */+ { 99, 17, 12, 0, 0, 12288, 24, }, /* 20 */+ { 99, 21, 12, 0, 0, 8192, 26, }, /* 21 */+ { 99, 21, 12, 0, 0, 8192, 14, }, /* 22 */+ { 99, 13, 12, 0, 0, 10240, 28, }, /* 23 */+ { 99, 21, 12, 0, 0, 8192, 30, }, /* 24 */+ { 99, 21, 12, 0, 0, 28672, 22, }, /* 25 */+ { 99, 25, 12, 0, 0, 28672, 32, }, /* 26 */+ { 99, 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 */+ { 99, 24, 12, 0, 0, 28672, 38, }, /* 32 */+ { 99, 16, 12, 0, 0, 28672, 40, }, /* 33 */+ { 99, 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 */+ { 99, 0, 2, 0, 0, 6144, 0, }, /* 40 */+ { 99, 0, 2, 0, 0, 4096, 50, }, /* 41 */+ { 99, 29, 12, 0, 0, 8192, 52, }, /* 42 */+ { 99, 21, 12, 0, 0, 28672, 54, }, /* 43 */+ { 99, 23, 12, 0, 0, 14336, 54, }, /* 44 */+ { 99, 26, 12, 0, 0, 28672, 54, }, /* 45 */+ { 99, 24, 12, 0, 0, 28672, 56, }, /* 46 */+ { 99, 26, 14, 0, 0, 28672, 58, }, /* 47 */+ { 0, 7, 12, 0, 0, 18432, 60, }, /* 48 */+ { 99, 20, 12, 0, 0, 28672, 62, }, /* 49 */+ { 99, 25, 12, 0, 0, 28672, 64, }, /* 50 */+ { 99, 1, 2, 0, 0, 6144, 66, }, /* 51 */+ { 99, 26, 12, 0, 0, 14336, 54, }, /* 52 */+ { 99, 25, 12, 0, 0, 14336, 64, }, /* 53 */+ { 99, 15, 12, 0, 0, 10240, 68, }, /* 54 */+ { 99, 5, 12, 26, 775, 18432, 70, }, /* 55 */+ { 99, 21, 12, 0, 0, 28676, 72, }, /* 56 */+ { 99, 19, 12, 0, 0, 28672, 62, }, /* 57 */+ { 99, 15, 12, 0, 0, 28672, 74, }, /* 58 */+ { 0, 9, 12, 0, 32, 18432, 76, }, /* 59 */+ { 0, 9, 12, 104, 32, 18432, 76, }, /* 60 */+ { 0, 5, 12, 0, 7615, 18432, 70, }, /* 61 */+ { 0, 5, 12, 0, -32, 18432, 78, }, /* 62 */+ { 0, 5, 12, 104, -32, 18432, 78, }, /* 63 */+ { 0, 5, 12, 0, 121, 18432, 78, }, /* 64 */+ { 0, 9, 12, 0, 1, 18432, 76, }, /* 65 */+ { 0, 5, 12, 0, -1, 18432, 78, }, /* 66 */+ { 0, 5, 12, 0, -1, 18432, 80, }, /* 67 */+ { 0, 9, 12, 0, 0, 18432, 76, }, /* 68 */+ { 0, 5, 12, 0, 0, 18432, 78, }, /* 69 */+ { 0, 5, 12, 0, 0, 18432, 60, }, /* 70 */+ { 0, 5, 12, 0, 0, 18432, 82, }, /* 71 */+ { 0, 9, 12, 0, -121, 18432, 76, }, /* 72 */+ { 0, 5, 12, 1, 0, 18432, 70, }, /* 73 */+ { 0, 5, 12, 0, 195, 18432, 78, }, /* 74 */+ { 0, 9, 12, 0, 210, 18432, 76, }, /* 75 */+ { 0, 9, 12, 0, 206, 18432, 76, }, /* 76 */+ { 0, 9, 12, 0, 205, 18432, 76, }, /* 77 */+ { 0, 9, 12, 0, 79, 18432, 76, }, /* 78 */+ { 0, 9, 12, 0, 202, 18432, 76, }, /* 79 */+ { 0, 9, 12, 0, 203, 18432, 76, }, /* 80 */+ { 0, 9, 12, 0, 207, 18432, 76, }, /* 81 */+ { 0, 5, 12, 0, 97, 18432, 78, }, /* 82 */+ { 0, 9, 12, 0, 211, 18432, 76, }, /* 83 */+ { 0, 9, 12, 0, 209, 18432, 76, }, /* 84 */+ { 0, 5, 12, 0, 163, 18432, 78, }, /* 85 */+ { 0, 5, 12, 0, 42561, 18432, 78, }, /* 86 */+ { 0, 9, 12, 0, 213, 18432, 76, }, /* 87 */+ { 0, 5, 12, 0, 130, 18432, 78, }, /* 88 */+ { 0, 9, 12, 0, 214, 18432, 76, }, /* 89 */+ { 0, 9, 12, 0, 218, 18432, 76, }, /* 90 */+ { 0, 9, 12, 0, 217, 18432, 76, }, /* 91 */+ { 0, 9, 12, 0, 219, 18432, 76, }, /* 92 */+ { 0, 7, 12, 0, 0, 18432, 84, }, /* 93 */+ { 0, 5, 12, 0, 56, 18432, 78, }, /* 94 */+ { 0, 9, 12, 5, 2, 18432, 86, }, /* 95 */+ { 0, 8, 12, 5, 1, 18432, 88, }, /* 96 */+ { 0, 5, 12, 5, -2, 18432, 78, }, /* 97 */+ { 0, 9, 12, 9, 2, 18432, 86, }, /* 98 */+ { 0, 8, 12, 9, 1, 18432, 88, }, /* 99 */+ { 0, 5, 12, 9, -2, 18432, 78, }, /* 100 */+ { 0, 9, 12, 13, 2, 18432, 86, }, /* 101 */+ { 0, 8, 12, 13, 1, 18432, 88, }, /* 102 */+ { 0, 5, 12, 13, -2, 18432, 78, }, /* 103 */+ { 0, 5, 12, 0, -79, 18432, 78, }, /* 104 */+ { 0, 9, 12, 17, 2, 18432, 86, }, /* 105 */+ { 0, 8, 12, 17, 1, 18432, 88, }, /* 106 */+ { 0, 5, 12, 17, -2, 18432, 78, }, /* 107 */+ { 0, 9, 12, 0, -97, 18432, 76, }, /* 108 */+ { 0, 9, 12, 0, -56, 18432, 76, }, /* 109 */+ { 0, 9, 12, 0, -130, 18432, 76, }, /* 110 */+ { 0, 9, 12, 0, 10795, 18432, 76, }, /* 111 */+ { 0, 9, 12, 0, -163, 18432, 76, }, /* 112 */+ { 0, 9, 12, 0, 10792, 18432, 76, }, /* 113 */+ { 0, 5, 12, 0, 10815, 18432, 78, }, /* 114 */+ { 0, 9, 12, 0, -195, 18432, 76, }, /* 115 */+ { 0, 9, 12, 0, 69, 18432, 76, }, /* 116 */+ { 0, 9, 12, 0, 71, 18432, 76, }, /* 117 */+ { 0, 5, 12, 0, 10783, 18432, 78, }, /* 118 */+ { 0, 5, 12, 0, 10780, 18432, 78, }, /* 119 */+ { 0, 5, 12, 0, 10782, 18432, 78, }, /* 120 */+ { 0, 5, 12, 0, -210, 18432, 78, }, /* 121 */+ { 0, 5, 12, 0, -206, 18432, 78, }, /* 122 */+ { 0, 5, 12, 0, -205, 18432, 78, }, /* 123 */+ { 0, 5, 12, 0, -202, 18432, 78, }, /* 124 */+ { 0, 5, 12, 0, -203, 18432, 78, }, /* 125 */+ { 0, 5, 12, 0, 42319, 18432, 78, }, /* 126 */+ { 0, 5, 12, 0, 42315, 18432, 78, }, /* 127 */+ { 0, 5, 12, 0, -207, 18432, 78, }, /* 128 */+ { 0, 5, 12, 0, 42343, 18432, 78, }, /* 129 */+ { 0, 5, 12, 0, 42280, 18432, 78, }, /* 130 */+ { 0, 5, 12, 0, 42308, 18432, 78, }, /* 131 */+ { 0, 5, 12, 0, -209, 18432, 80, }, /* 132 */+ { 0, 5, 12, 0, -211, 18432, 78, }, /* 133 */+ { 0, 5, 12, 0, 10743, 18432, 78, }, /* 134 */+ { 0, 5, 12, 0, 42305, 18432, 78, }, /* 135 */+ { 0, 5, 12, 0, 10749, 18432, 78, }, /* 136 */+ { 0, 5, 12, 0, -213, 18432, 78, }, /* 137 */+ { 0, 5, 12, 0, -214, 18432, 78, }, /* 138 */+ { 0, 5, 12, 0, 10727, 18432, 78, }, /* 139 */+ { 0, 5, 12, 0, -218, 18432, 78, }, /* 140 */+ { 0, 5, 12, 0, 42307, 18432, 78, }, /* 141 */+ { 0, 5, 12, 0, 42282, 18432, 78, }, /* 142 */+ { 0, 5, 12, 0, -69, 18432, 78, }, /* 143 */+ { 0, 5, 12, 0, -217, 18432, 78, }, /* 144 */+ { 0, 5, 12, 0, -71, 18432, 78, }, /* 145 */+ { 0, 5, 12, 0, -219, 18432, 78, }, /* 146 */+ { 0, 5, 12, 0, 42261, 18432, 80, }, /* 147 */+ { 0, 5, 12, 0, 42258, 18432, 78, }, /* 148 */+ { 0, 6, 12, 0, 0, 18432, 90, }, /* 149 */+ { 0, 6, 12, 0, 0, 18432, 92, }, /* 150 */+ { 99, 6, 12, 0, 0, 28672, 94, }, /* 151 */+ { 99, 6, 12, 0, 0, 18432, 94, }, /* 152 */+ { 99, 6, 12, 0, 0, 18440, 94, }, /* 153 */+ { 99, 6, 12, 0, 0, 18432, 90, }, /* 154 */+ { 99, 6, 12, 0, 0, 28684, 94, }, /* 155 */+ { 99, 6, 12, 0, 0, 28688, 94, }, /* 156 */+ { 99, 6, 12, 0, 0, 18432, 96, }, /* 157 */+ { 99, 24, 12, 0, 0, 28692, 56, }, /* 158 */+ { 99, 24, 12, 0, 0, 28684, 56, }, /* 159 */+ { 29, 24, 12, 0, 0, 28672, 56, }, /* 160 */+ { 106, 12, 3, 0, 0, 26648, 98, }, /* 161 */+ { 106, 12, 3, 0, 0, 26652, 98, }, /* 162 */+ { 106, 12, 3, 0, 0, 26656, 98, }, /* 163 */+ { 106, 12, 3, 0, 0, 26660, 98, }, /* 164 */+ { 106, 12, 3, 0, 0, 26664, 98, }, /* 165 */+ { 106, 12, 3, 0, 0, 26668, 98, }, /* 166 */+ { 106, 12, 3, 0, 0, 26672, 98, }, /* 167 */+ { 106, 12, 3, 0, 0, 26676, 98, }, /* 168 */+ { 106, 12, 3, 0, 0, 26680, 98, }, /* 169 */+ { 106, 12, 3, 0, 0, 26684, 98, }, /* 170 */+ { 106, 12, 3, 0, 0, 26688, 98, }, /* 171 */+ { 106, 12, 3, 0, 0, 26692, 98, }, /* 172 */+ { 106, 12, 3, 0, 0, 26696, 98, }, /* 173 */+ { 106, 12, 3, 0, 0, 26700, 98, }, /* 174 */+ { 106, 12, 3, 0, 0, 26704, 98, }, /* 175 */+ { 106, 12, 3, 0, 0, 26624, 98, }, /* 176 */+ { 106, 12, 3, 0, 0, 26708, 98, }, /* 177 */+ { 106, 12, 3, 0, 0, 26712, 98, }, /* 178 */+ { 106, 12, 3, 0, 0, 26716, 98, }, /* 179 */+ { 106, 12, 3, 0, 0, 26720, 98, }, /* 180 */+ { 106, 12, 3, 0, 0, 26724, 98, }, /* 181 */+ { 106, 12, 3, 0, 0, 26728, 98, }, /* 182 */+ { 106, 12, 3, 0, 0, 26732, 98, }, /* 183 */+ { 106, 12, 3, 0, 0, 26736, 98, }, /* 184 */+ { 106, 12, 3, 0, 0, 26740, 98, }, /* 185 */+ { 106, 12, 3, 21, 116, 26740, 100, }, /* 186 */+ { 106, 12, 3, 0, 0, 26624, 102, }, /* 187 */+ { 106, 12, 3, 0, 0, 26744, 104, }, /* 188 */+ { 106, 12, 3, 0, 0, 26624, 104, }, /* 189 */+ { 106, 12, 3, 0, 0, 26748, 98, }, /* 190 */+ { 106, 12, 3, 0, 0, 26752, 106, }, /* 191 */+ { 1, 9, 12, 0, 1, 18432, 76, }, /* 192 */+ { 1, 5, 12, 0, -1, 18432, 78, }, /* 193 */+ { 99, 6, 12, 0, 0, 28804, 94, }, /* 194 */+ { 1, 24, 12, 0, 0, 28804, 56, }, /* 195 */+ { 98, 2, 12, 0, 0, 18432, 0, }, /* 196 */+ { 1, 6, 12, 0, 0, 18432, 108, }, /* 197 */+ { 1, 5, 12, 0, 130, 18432, 78, }, /* 198 */+ { 99, 21, 12, 0, 0, 28672, 110, }, /* 199 */+ { 1, 9, 12, 0, 116, 18432, 76, }, /* 200 */+ { 1, 24, 12, 0, 0, 28672, 56, }, /* 201 */+ { 1, 9, 12, 0, 38, 18432, 76, }, /* 202 */+ { 99, 21, 12, 0, 0, 28672, 112, }, /* 203 */+ { 1, 9, 12, 0, 37, 18432, 76, }, /* 204 */+ { 1, 9, 12, 0, 64, 18432, 76, }, /* 205 */+ { 1, 9, 12, 0, 63, 18432, 76, }, /* 206 */+ { 1, 5, 12, 0, 7235, 18432, 78, }, /* 207 */+ { 1, 9, 12, 0, 32, 18432, 76, }, /* 208 */+ { 1, 9, 12, 34, 32, 18432, 76, }, /* 209 */+ { 1, 9, 12, 59, 32, 18432, 76, }, /* 210 */+ { 1, 9, 12, 38, 32, 18432, 76, }, /* 211 */+ { 1, 9, 12, 21, 32, 18432, 76, }, /* 212 */+ { 1, 9, 12, 51, 32, 18432, 76, }, /* 213 */+ { 1, 9, 12, 26, 32, 18432, 76, }, /* 214 */+ { 1, 9, 12, 47, 32, 18432, 76, }, /* 215 */+ { 1, 9, 12, 55, 32, 18432, 76, }, /* 216 */+ { 1, 9, 12, 30, 32, 18432, 76, }, /* 217 */+ { 1, 9, 12, 43, 32, 18432, 76, }, /* 218 */+ { 1, 9, 12, 96, 32, 18432, 76, }, /* 219 */+ { 1, 5, 12, 0, -38, 18432, 78, }, /* 220 */+ { 1, 5, 12, 0, -37, 18432, 78, }, /* 221 */+ { 1, 5, 12, 0, 7219, 18432, 78, }, /* 222 */+ { 1, 5, 12, 0, -32, 18432, 78, }, /* 223 */+ { 1, 5, 12, 34, -32, 18432, 78, }, /* 224 */+ { 1, 5, 12, 59, -32, 18432, 78, }, /* 225 */+ { 1, 5, 12, 38, -32, 18432, 78, }, /* 226 */+ { 1, 5, 12, 21, -116, 18432, 78, }, /* 227 */+ { 1, 5, 12, 51, -32, 18432, 78, }, /* 228 */+ { 1, 5, 12, 26, -775, 18432, 78, }, /* 229 */+ { 1, 5, 12, 47, -32, 18432, 78, }, /* 230 */+ { 1, 5, 12, 55, -32, 18432, 78, }, /* 231 */+ { 1, 5, 12, 30, 1, 18432, 70, }, /* 232 */+ { 1, 5, 12, 30, -32, 18432, 78, }, /* 233 */+ { 1, 5, 12, 43, -32, 18432, 78, }, /* 234 */+ { 1, 5, 12, 96, -32, 18432, 78, }, /* 235 */+ { 1, 5, 12, 0, -64, 18432, 78, }, /* 236 */+ { 1, 5, 12, 0, -63, 18432, 78, }, /* 237 */+ { 1, 9, 12, 0, 8, 18432, 76, }, /* 238 */+ { 1, 5, 12, 34, -30, 18432, 114, }, /* 239 */+ { 1, 5, 12, 38, -25, 18432, 114, }, /* 240 */+ { 1, 9, 12, 0, 0, 18432, 116, }, /* 241 */+ { 1, 9, 12, 0, 0, 18432, 118, }, /* 242 */+ { 1, 5, 12, 43, -15, 18432, 114, }, /* 243 */+ { 1, 5, 12, 47, -22, 18432, 70, }, /* 244 */+ { 1, 5, 12, 0, -8, 18432, 78, }, /* 245 */+ { 43, 9, 12, 0, 1, 18432, 76, }, /* 246 */+ { 43, 5, 12, 0, -1, 18432, 78, }, /* 247 */+ { 1, 5, 12, 51, -54, 18432, 114, }, /* 248 */+ { 1, 5, 12, 55, -48, 18432, 114, }, /* 249 */+ { 1, 5, 12, 0, 7, 18432, 78, }, /* 250 */+ { 1, 5, 12, 0, -116, 18432, 80, }, /* 251 */+ { 1, 9, 12, 38, -60, 18432, 120, }, /* 252 */+ { 1, 5, 12, 59, -64, 18432, 114, }, /* 253 */+ { 1, 25, 12, 0, 0, 28672, 122, }, /* 254 */+ { 1, 9, 12, 0, -7, 18432, 76, }, /* 255 */+ { 1, 5, 12, 0, 0, 18432, 60, }, /* 256 */+ { 1, 9, 12, 0, -130, 18432, 76, }, /* 257 */+ { 2, 9, 12, 0, 80, 18432, 76, }, /* 258 */+ { 2, 9, 12, 0, 32, 18432, 76, }, /* 259 */+ { 2, 9, 12, 63, 32, 18432, 76, }, /* 260 */+ { 2, 9, 12, 67, 32, 18432, 76, }, /* 261 */+ { 2, 9, 12, 71, 32, 18432, 76, }, /* 262 */+ { 2, 9, 12, 75, 32, 18432, 76, }, /* 263 */+ { 2, 9, 12, 79, 32, 18432, 76, }, /* 264 */+ { 2, 9, 12, 84, 32, 18432, 76, }, /* 265 */+ { 2, 5, 12, 0, -32, 18432, 78, }, /* 266 */+ { 2, 5, 12, 63, -32, 18432, 78, }, /* 267 */+ { 2, 5, 12, 67, -32, 18432, 78, }, /* 268 */+ { 2, 5, 12, 71, -32, 18432, 78, }, /* 269 */+ { 2, 5, 12, 75, -32, 18432, 78, }, /* 270 */+ { 2, 5, 12, 79, -32, 18432, 78, }, /* 271 */+ { 2, 5, 12, 84, -32, 18432, 78, }, /* 272 */+ { 2, 5, 12, 0, -80, 18432, 78, }, /* 273 */+ { 2, 5, 12, 0, -80, 18432, 80, }, /* 274 */+ { 2, 9, 12, 0, 1, 18432, 76, }, /* 275 */+ { 2, 5, 12, 0, -1, 18432, 78, }, /* 276 */+ { 2, 9, 12, 88, 1, 18432, 76, }, /* 277 */+ { 2, 5, 12, 88, -1, 18432, 78, }, /* 278 */+ { 2, 26, 12, 0, 0, 18432, 74, }, /* 279 */+ { 2, 12, 3, 0, 0, 26760, 98, }, /* 280 */+ { 2, 12, 3, 0, 0, 26764, 98, }, /* 281 */+ { 106, 12, 3, 0, 0, 26768, 98, }, /* 282 */+ { 2, 11, 3, 0, 0, 26624, 124, }, /* 283 */+ { 2, 9, 12, 0, 15, 18432, 76, }, /* 284 */+ { 2, 5, 12, 0, -15, 18432, 78, }, /* 285 */+ { 3, 9, 12, 0, 48, 18432, 76, }, /* 286 */+ { 3, 6, 12, 0, 0, 18432, 94, }, /* 287 */+ { 3, 21, 12, 0, 0, 18432, 74, }, /* 288 */+ { 3, 21, 12, 0, 0, 18432, 126, }, /* 289 */+ { 3, 5, 12, 0, 0, 18432, 60, }, /* 290 */+ { 3, 5, 12, 0, -48, 18432, 78, }, /* 291 */+ { 3, 5, 12, 0, 0, 18432, 70, }, /* 292 */+ { 3, 21, 12, 0, 0, 18580, 128, }, /* 293 */+ { 3, 17, 12, 0, 0, 28672, 130, }, /* 294 */+ { 3, 26, 12, 0, 0, 28672, 74, }, /* 295 */+ { 3, 23, 12, 0, 0, 14336, 74, }, /* 296 */+ { 98, 2, 12, 0, 0, 34816, 0, }, /* 297 */+ { 4, 12, 3, 0, 0, 26624, 98, }, /* 298 */+ { 4, 12, 3, 0, 0, 26624, 104, }, /* 299 */+ { 4, 12, 3, 0, 0, 26624, 132, }, /* 300 */+ { 4, 17, 12, 0, 0, 34816, 130, }, /* 301 */+ { 4, 21, 12, 0, 0, 34816, 74, }, /* 302 */+ { 4, 21, 12, 0, 0, 34816, 110, }, /* 303 */+ { 4, 12, 3, 0, 0, 26624, 106, }, /* 304 */+ { 4, 7, 12, 0, 0, 34816, 84, }, /* 305 */+ { 4, 21, 12, 0, 0, 34816, 126, }, /* 306 */+ { 5, 1, 4, 0, 0, 2048, 134, }, /* 307 */+ { 99, 1, 4, 0, 0, 2048, 134, }, /* 308 */+ { 5, 25, 12, 0, 0, 28672, 122, }, /* 309 */+ { 5, 25, 12, 0, 0, 0, 122, }, /* 310 */+ { 5, 21, 12, 0, 0, 14336, 74, }, /* 311 */+ { 5, 23, 12, 0, 0, 0, 74, }, /* 312 */+ { 99, 21, 12, 0, 0, 8344, 110, }, /* 313 */+ { 5, 21, 12, 0, 0, 0, 74, }, /* 314 */+ { 5, 26, 12, 0, 0, 28672, 74, }, /* 315 */+ { 5, 12, 3, 0, 0, 26624, 106, }, /* 316 */+ { 99, 21, 12, 0, 0, 152, 110, }, /* 317 */+ { 5, 1, 2, 0, 0, 156, 136, }, /* 318 */+ { 5, 21, 12, 0, 0, 0, 128, }, /* 319 */+ { 99, 21, 12, 0, 0, 160, 128, }, /* 320 */+ { 5, 7, 12, 0, 0, 0, 84, }, /* 321 */+ { 99, 6, 12, 0, 0, 164, 138, }, /* 322 */+ { 106, 12, 3, 0, 0, 26792, 132, }, /* 323 */+ { 106, 12, 3, 0, 0, 26792, 106, }, /* 324 */+ { 106, 12, 3, 0, 0, 26792, 140, }, /* 325 */+ { 5, 12, 3, 0, 0, 26624, 132, }, /* 326 */+ { 5, 12, 3, 0, 0, 26624, 142, }, /* 327 */+ { 5, 13, 12, 0, 0, 2220, 144, }, /* 328 */+ { 5, 21, 12, 0, 0, 2048, 74, }, /* 329 */+ { 5, 7, 12, 0, 0, 0, 146, }, /* 330 */+ { 5, 21, 12, 0, 0, 176, 128, }, /* 331 */+ { 5, 12, 3, 0, 0, 26624, 140, }, /* 332 */+ { 5, 12, 3, 0, 0, 26624, 98, }, /* 333 */+ { 5, 6, 12, 0, 0, 0, 94, }, /* 334 */+ { 5, 13, 12, 0, 0, 10240, 144, }, /* 335 */+ { 5, 26, 12, 0, 0, 0, 74, }, /* 336 */+ { 6, 21, 12, 0, 0, 0, 128, }, /* 337 */+ { 6, 21, 12, 0, 0, 0, 110, }, /* 338 */+ { 6, 21, 12, 0, 0, 0, 74, }, /* 339 */+ { 98, 2, 12, 0, 0, 0, 0, }, /* 340 */+ { 6, 1, 4, 0, 0, 0, 134, }, /* 341 */+ { 6, 7, 12, 0, 0, 0, 84, }, /* 342 */+ { 6, 12, 3, 0, 0, 26624, 106, }, /* 343 */+ { 6, 12, 3, 0, 0, 26624, 132, }, /* 344 */+ { 6, 12, 3, 0, 0, 26624, 98, }, /* 345 */+ { 7, 7, 12, 0, 0, 0, 84, }, /* 346 */+ { 7, 12, 3, 0, 0, 26624, 132, }, /* 347 */+ { 48, 13, 12, 0, 0, 34816, 144, }, /* 348 */+ { 48, 7, 12, 0, 0, 34816, 84, }, /* 349 */+ { 48, 12, 3, 0, 0, 26624, 98, }, /* 350 */+ { 48, 6, 12, 0, 0, 34816, 94, }, /* 351 */+ { 48, 26, 12, 0, 0, 28672, 74, }, /* 352 */+ { 48, 21, 12, 0, 0, 28672, 74, }, /* 353 */+ { 48, 21, 12, 0, 0, 28672, 110, }, /* 354 */+ { 48, 21, 12, 0, 0, 28672, 128, }, /* 355 */+ { 48, 6, 12, 0, 0, 34816, 138, }, /* 356 */+ { 48, 12, 3, 0, 0, 26624, 104, }, /* 357 */+ { 48, 23, 12, 0, 0, 34816, 74, }, /* 358 */+ { 54, 7, 12, 0, 0, 34816, 84, }, /* 359 */+ { 54, 12, 3, 0, 0, 26624, 106, }, /* 360 */+ { 54, 12, 3, 0, 0, 26624, 98, }, /* 361 */+ { 54, 6, 12, 0, 0, 34816, 148, }, /* 362 */+ { 54, 12, 3, 0, 0, 26624, 104, }, /* 363 */+ { 54, 21, 12, 0, 0, 34816, 110, }, /* 364 */+ { 54, 21, 12, 0, 0, 34816, 74, }, /* 365 */+ { 54, 21, 12, 0, 0, 34816, 128, }, /* 366 */+ { 59, 7, 12, 0, 0, 34816, 84, }, /* 367 */+ { 59, 12, 3, 0, 0, 26624, 104, }, /* 368 */+ { 59, 21, 12, 0, 0, 34816, 110, }, /* 369 */+ { 5, 24, 12, 0, 0, 0, 126, }, /* 370 */+ { 5, 12, 3, 0, 0, 26624, 150, }, /* 371 */+ { 5, 12, 3, 0, 0, 26624, 104, }, /* 372 */+ { 5, 12, 3, 0, 0, 26624, 152, }, /* 373 */+ { 8, 12, 3, 0, 0, 26624, 106, }, /* 374 */+ { 8, 10, 5, 0, 0, 18432, 154, }, /* 375 */+ { 8, 7, 12, 0, 0, 18432, 84, }, /* 376 */+ { 8, 7, 12, 0, 0, 18432, 156, }, /* 377 */+ { 8, 12, 3, 0, 0, 26624, 98, }, /* 378 */+ { 8, 12, 3, 0, 0, 26624, 158, }, /* 379 */+ { 106, 12, 3, 0, 0, 26804, 98, }, /* 380 */+ { 106, 12, 3, 0, 0, 26808, 98, }, /* 381 */+ { 99, 21, 12, 0, 0, 18620, 128, }, /* 382 */+ { 99, 21, 12, 0, 0, 18624, 128, }, /* 383 */+ { 8, 13, 12, 0, 0, 18628, 144, }, /* 384 */+ { 8, 21, 12, 0, 0, 18432, 74, }, /* 385 */+ { 8, 6, 12, 0, 0, 18432, 94, }, /* 386 */+ { 9, 7, 12, 0, 0, 18432, 84, }, /* 387 */+ { 9, 12, 3, 0, 0, 26624, 106, }, /* 388 */+ { 9, 10, 5, 0, 0, 18432, 154, }, /* 389 */+ { 9, 7, 12, 0, 0, 18432, 156, }, /* 390 */+ { 9, 12, 3, 0, 0, 26624, 98, }, /* 391 */+ { 9, 10, 3, 0, 0, 18432, 160, }, /* 392 */+ { 9, 12, 3, 0, 0, 26624, 158, }, /* 393 */+ { 9, 13, 12, 0, 0, 18632, 144, }, /* 394 */+ { 9, 23, 12, 0, 0, 14336, 74, }, /* 395 */+ { 9, 15, 12, 0, 0, 18432, 74, }, /* 396 */+ { 9, 26, 12, 0, 0, 18432, 74, }, /* 397 */+ { 9, 21, 12, 0, 0, 18432, 74, }, /* 398 */+ { 9, 12, 3, 0, 0, 26624, 104, }, /* 399 */+ { 10, 12, 3, 0, 0, 26624, 106, }, /* 400 */+ { 10, 10, 5, 0, 0, 18432, 154, }, /* 401 */+ { 10, 7, 12, 0, 0, 18432, 84, }, /* 402 */+ { 10, 12, 3, 0, 0, 26624, 98, }, /* 403 */+ { 10, 12, 3, 0, 0, 26624, 158, }, /* 404 */+ { 10, 13, 12, 0, 0, 18636, 144, }, /* 405 */+ { 10, 12, 3, 0, 0, 26624, 162, }, /* 406 */+ { 10, 21, 12, 0, 0, 18432, 74, }, /* 407 */+ { 11, 12, 3, 0, 0, 26624, 106, }, /* 408 */+ { 11, 10, 5, 0, 0, 18432, 154, }, /* 409 */+ { 11, 7, 12, 0, 0, 18432, 84, }, /* 410 */+ { 11, 7, 12, 0, 0, 18432, 156, }, /* 411 */+ { 11, 12, 3, 0, 0, 26624, 98, }, /* 412 */+ { 11, 12, 3, 0, 0, 26624, 158, }, /* 413 */+ { 11, 13, 12, 0, 0, 18640, 144, }, /* 414 */+ { 11, 21, 12, 0, 0, 18432, 74, }, /* 415 */+ { 11, 23, 12, 0, 0, 14336, 74, }, /* 416 */+ { 11, 12, 3, 0, 0, 26624, 162, }, /* 417 */+ { 12, 12, 3, 0, 0, 26624, 106, }, /* 418 */+ { 12, 10, 5, 0, 0, 18432, 154, }, /* 419 */+ { 12, 7, 12, 0, 0, 18432, 84, }, /* 420 */+ { 12, 7, 12, 0, 0, 18432, 156, }, /* 421 */+ { 12, 12, 3, 0, 0, 26624, 98, }, /* 422 */+ { 12, 10, 3, 0, 0, 18432, 160, }, /* 423 */+ { 12, 12, 3, 0, 0, 26624, 158, }, /* 424 */+ { 12, 12, 3, 0, 0, 26624, 164, }, /* 425 */+ { 12, 13, 12, 0, 0, 18432, 144, }, /* 426 */+ { 12, 26, 12, 0, 0, 18432, 74, }, /* 427 */+ { 12, 15, 12, 0, 0, 18432, 74, }, /* 428 */+ { 13, 12, 3, 0, 0, 26624, 106, }, /* 429 */+ { 13, 7, 12, 0, 0, 18432, 84, }, /* 430 */+ { 13, 10, 3, 0, 0, 18432, 160, }, /* 431 */+ { 13, 10, 5, 0, 0, 18432, 154, }, /* 432 */+ { 13, 12, 3, 0, 0, 26624, 158, }, /* 433 */+ { 13, 13, 12, 0, 0, 18644, 144, }, /* 434 */+ { 13, 15, 12, 0, 0, 18644, 74, }, /* 435 */+ { 13, 26, 12, 0, 0, 28884, 74, }, /* 436 */+ { 13, 26, 12, 0, 0, 28672, 74, }, /* 437 */+ { 13, 23, 12, 0, 0, 14336, 74, }, /* 438 */+ { 14, 12, 3, 0, 0, 26624, 106, }, /* 439 */+ { 14, 10, 5, 0, 0, 18432, 154, }, /* 440 */+ { 14, 7, 12, 0, 0, 18432, 84, }, /* 441 */+ { 14, 7, 12, 0, 0, 18432, 156, }, /* 442 */+ { 14, 12, 3, 0, 0, 26624, 98, }, /* 443 */+ { 14, 12, 3, 0, 0, 26624, 158, }, /* 444 */+ { 14, 13, 12, 0, 0, 18432, 144, }, /* 445 */+ { 14, 21, 12, 0, 0, 18432, 74, }, /* 446 */+ { 14, 15, 12, 0, 0, 28672, 74, }, /* 447 */+ { 14, 26, 12, 0, 0, 18432, 74, }, /* 448 */+ { 15, 7, 12, 0, 0, 18432, 84, }, /* 449 */+ { 15, 12, 3, 0, 0, 26624, 106, }, /* 450 */+ { 15, 10, 5, 0, 0, 18432, 154, }, /* 451 */+ { 15, 21, 12, 0, 0, 18432, 74, }, /* 452 */+ { 15, 12, 3, 0, 0, 26624, 98, }, /* 453 */+ { 15, 12, 3, 0, 0, 18432, 106, }, /* 454 */+ { 15, 10, 3, 0, 0, 18432, 160, }, /* 455 */+ { 15, 12, 3, 0, 0, 26624, 158, }, /* 456 */+ { 15, 13, 12, 0, 0, 18648, 144, }, /* 457 */+ { 16, 12, 3, 0, 0, 26624, 106, }, /* 458 */+ { 16, 10, 5, 0, 0, 18432, 154, }, /* 459 */+ { 16, 7, 12, 0, 0, 18432, 84, }, /* 460 */+ { 16, 7, 12, 0, 0, 18432, 156, }, /* 461 */+ { 16, 12, 3, 0, 0, 26624, 158, }, /* 462 */+ { 16, 10, 3, 0, 0, 18432, 160, }, /* 463 */+ { 16, 7, 4, 0, 0, 18432, 84, }, /* 464 */+ { 16, 26, 12, 0, 0, 18432, 74, }, /* 465 */+ { 16, 15, 12, 0, 0, 18432, 74, }, /* 466 */+ { 16, 13, 12, 0, 0, 18432, 144, }, /* 467 */+ { 17, 12, 3, 0, 0, 26624, 106, }, /* 468 */+ { 17, 10, 5, 0, 0, 18432, 154, }, /* 469 */+ { 17, 7, 12, 0, 0, 18432, 84, }, /* 470 */+ { 17, 12, 3, 0, 0, 26624, 158, }, /* 471 */+ { 17, 10, 3, 0, 0, 18432, 160, }, /* 472 */+ { 17, 13, 12, 0, 0, 18432, 144, }, /* 473 */+ { 17, 21, 12, 0, 0, 18432, 74, }, /* 474 */+ { 18, 7, 12, 0, 0, 18432, 84, }, /* 475 */+ { 18, 12, 3, 0, 0, 26624, 106, }, /* 476 */+ { 18, 7, 5, 0, 0, 18432, 166, }, /* 477 */+ { 18, 12, 3, 0, 0, 26624, 168, }, /* 478 */+ { 99, 23, 12, 0, 0, 14336, 74, }, /* 479 */+ { 18, 7, 12, 0, 0, 18432, 170, }, /* 480 */+ { 18, 6, 12, 0, 0, 18432, 138, }, /* 481 */+ { 18, 12, 3, 0, 0, 26624, 98, }, /* 482 */+ { 18, 21, 12, 0, 0, 18432, 74, }, /* 483 */+ { 18, 13, 12, 0, 0, 18432, 144, }, /* 484 */+ { 18, 21, 12, 0, 0, 18432, 110, }, /* 485 */+ { 100, 7, 12, 0, 0, 18432, 84, }, /* 486 */+ { 100, 12, 3, 0, 0, 26624, 106, }, /* 487 */+ { 100, 7, 5, 0, 0, 18432, 166, }, /* 488 */+ { 100, 12, 3, 0, 0, 26624, 158, }, /* 489 */+ { 100, 7, 12, 0, 0, 18432, 170, }, /* 490 */+ { 100, 6, 12, 0, 0, 18432, 138, }, /* 491 */+ { 100, 12, 3, 0, 0, 26624, 98, }, /* 492 */+ { 100, 12, 3, 0, 0, 26624, 104, }, /* 493 */+ { 100, 13, 12, 0, 0, 18432, 144, }, /* 494 */+ { 19, 7, 12, 0, 0, 18432, 84, }, /* 495 */+ { 19, 26, 12, 0, 0, 18432, 74, }, /* 496 */+ { 19, 21, 12, 0, 0, 18432, 74, }, /* 497 */+ { 19, 21, 12, 0, 0, 18432, 110, }, /* 498 */+ { 19, 12, 3, 0, 0, 26624, 98, }, /* 499 */+ { 19, 13, 12, 0, 0, 18432, 144, }, /* 500 */+ { 19, 15, 12, 0, 0, 18432, 74, }, /* 501 */+ { 19, 22, 12, 0, 0, 28672, 172, }, /* 502 */+ { 19, 18, 12, 0, 0, 28672, 172, }, /* 503 */+ { 19, 10, 5, 0, 0, 18432, 174, }, /* 504 */+ { 19, 12, 3, 0, 0, 26624, 106, }, /* 505 */+ { 19, 12, 3, 0, 0, 26624, 176, }, /* 506 */+ { 19, 10, 5, 0, 0, 18432, 154, }, /* 507 */+ { 19, 12, 3, 0, 0, 26624, 132, }, /* 508 */+ { 19, 12, 3, 0, 0, 26624, 158, }, /* 509 */+ { 99, 26, 12, 0, 0, 18432, 74, }, /* 510 */+ { 20, 7, 12, 0, 0, 18432, 84, }, /* 511 */+ { 20, 10, 12, 0, 0, 18432, 154, }, /* 512 */+ { 20, 12, 3, 0, 0, 26624, 106, }, /* 513 */+ { 20, 10, 5, 0, 0, 18432, 154, }, /* 514 */+ { 20, 12, 3, 0, 0, 26624, 98, }, /* 515 */+ { 20, 12, 3, 0, 0, 26624, 158, }, /* 516 */+ { 20, 13, 12, 0, 0, 18652, 144, }, /* 517 */+ { 20, 21, 12, 0, 0, 18432, 128, }, /* 518 */+ { 20, 21, 12, 0, 0, 18432, 74, }, /* 519 */+ { 20, 10, 12, 0, 0, 18432, 178, }, /* 520 */+ { 20, 12, 3, 0, 0, 26624, 132, }, /* 521 */+ { 20, 13, 12, 0, 0, 18432, 144, }, /* 522 */+ { 20, 26, 12, 0, 0, 18432, 74, }, /* 523 */+ { 21, 9, 12, 0, 7264, 18432, 76, }, /* 524 */+ { 21, 5, 12, 0, 3008, 18432, 180, }, /* 525 */+ { 99, 21, 12, 0, 0, 18656, 74, }, /* 526 */+ { 21, 6, 12, 0, 0, 18432, 182, }, /* 527 */+ { 22, 7, 6, 0, 0, 18432, 84, }, /* 528 */+ { 22, 7, 6, 0, 0, 18432, 184, }, /* 529 */+ { 22, 7, 7, 0, 0, 18432, 184, }, /* 530 */+ { 22, 7, 7, 0, 0, 18432, 84, }, /* 531 */+ { 22, 7, 8, 0, 0, 18432, 84, }, /* 532 */+ { 23, 7, 12, 0, 0, 18432, 84, }, /* 533 */+ { 23, 12, 3, 0, 0, 26624, 98, }, /* 534 */+ { 23, 21, 12, 0, 0, 18432, 74, }, /* 535 */+ { 23, 21, 12, 0, 0, 18432, 110, }, /* 536 */+ { 23, 21, 12, 0, 0, 18432, 128, }, /* 537 */+ { 23, 15, 12, 0, 0, 18432, 144, }, /* 538 */+ { 23, 15, 12, 0, 0, 18432, 74, }, /* 539 */+ { 23, 26, 12, 0, 0, 28672, 74, }, /* 540 */+ { 24, 9, 12, 0, 38864, 18432, 186, }, /* 541 */+ { 24, 9, 12, 0, 8, 18432, 186, }, /* 542 */+ { 24, 5, 12, 0, -8, 18432, 70, }, /* 543 */+ { 101, 17, 12, 0, 0, 28672, 130, }, /* 544 */+ { 101, 7, 12, 0, 0, 18432, 84, }, /* 545 */+ { 101, 26, 12, 0, 0, 18432, 74, }, /* 546 */+ { 101, 21, 12, 0, 0, 18432, 128, }, /* 547 */+ { 102, 29, 12, 0, 0, 45056, 52, }, /* 548 */+ { 102, 7, 12, 0, 0, 18432, 84, }, /* 549 */+ { 102, 22, 12, 0, 0, 28672, 172, }, /* 550 */+ { 102, 18, 12, 0, 0, 28672, 172, }, /* 551 */+ { 25, 7, 12, 0, 0, 18432, 84, }, /* 552 */+ { 99, 21, 12, 0, 0, 18660, 110, }, /* 553 */+ { 25, 14, 12, 0, 0, 18432, 84, }, /* 554 */+ { 33, 7, 12, 0, 0, 18432, 84, }, /* 555 */+ { 33, 12, 3, 0, 0, 26624, 106, }, /* 556 */+ { 33, 12, 3, 0, 0, 26624, 158, }, /* 557 */+ { 33, 10, 3, 0, 0, 18432, 188, }, /* 558 */+ { 34, 7, 12, 0, 0, 18432, 84, }, /* 559 */+ { 34, 12, 3, 0, 0, 26624, 106, }, /* 560 */+ { 34, 10, 3, 0, 0, 18432, 188, }, /* 561 */+ { 99, 21, 12, 0, 0, 18664, 128, }, /* 562 */+ { 35, 7, 12, 0, 0, 18432, 84, }, /* 563 */+ { 35, 12, 3, 0, 0, 26624, 106, }, /* 564 */+ { 36, 7, 12, 0, 0, 18432, 84, }, /* 565 */+ { 36, 12, 3, 0, 0, 26624, 106, }, /* 566 */+ { 103, 7, 12, 0, 0, 18432, 84, }, /* 567 */+ { 103, 7, 12, 0, 0, 18432, 146, }, /* 568 */+ { 103, 12, 3, 0, 0, 26624, 102, }, /* 569 */+ { 103, 10, 5, 0, 0, 18432, 154, }, /* 570 */+ { 103, 12, 3, 0, 0, 26624, 106, }, /* 571 */+ { 103, 12, 3, 0, 0, 26624, 98, }, /* 572 */+ { 103, 12, 3, 0, 0, 26624, 158, }, /* 573 */+ { 103, 21, 12, 0, 0, 18432, 128, }, /* 574 */+ { 103, 21, 12, 0, 0, 18432, 110, }, /* 575 */+ { 103, 6, 12, 0, 0, 18432, 148, }, /* 576 */+ { 103, 21, 12, 0, 0, 18432, 74, }, /* 577 */+ { 103, 23, 12, 0, 0, 14336, 74, }, /* 578 */+ { 103, 13, 12, 0, 0, 18432, 144, }, /* 579 */+ { 103, 15, 12, 0, 0, 28672, 74, }, /* 580 */+ { 26, 21, 12, 0, 0, 28672, 74, }, /* 581 */+ { 99, 21, 12, 0, 0, 28908, 110, }, /* 582 */+ { 99, 21, 12, 0, 0, 28908, 128, }, /* 583 */+ { 26, 21, 12, 0, 0, 28672, 110, }, /* 584 */+ { 26, 17, 12, 0, 0, 28672, 130, }, /* 585 */+ { 26, 21, 12, 0, 0, 28672, 128, }, /* 586 */+ { 26, 21, 12, 0, 0, 28672, 190, }, /* 587 */+ { 26, 12, 3, 0, 0, 26624, 192, }, /* 588 */+ { 26, 1, 2, 0, 0, 6144, 66, }, /* 589 */+ { 26, 13, 12, 0, 0, 18432, 144, }, /* 590 */+ { 26, 7, 12, 0, 0, 18432, 84, }, /* 591 */+ { 26, 6, 12, 0, 0, 18432, 138, }, /* 592 */+ { 26, 12, 3, 0, 0, 26624, 194, }, /* 593 */+ { 26, 12, 3, 0, 0, 26624, 106, }, /* 594 */+ { 37, 7, 12, 0, 0, 18432, 84, }, /* 595 */+ { 37, 12, 3, 0, 0, 26624, 106, }, /* 596 */+ { 37, 10, 5, 0, 0, 18432, 154, }, /* 597 */+ { 37, 12, 3, 0, 0, 26624, 98, }, /* 598 */+ { 37, 26, 12, 0, 0, 28672, 74, }, /* 599 */+ { 37, 21, 12, 0, 0, 28672, 128, }, /* 600 */+ { 37, 13, 12, 0, 0, 18432, 144, }, /* 601 */+ { 38, 7, 12, 0, 0, 18432, 84, }, /* 602 */+ { 110, 7, 12, 0, 0, 18432, 84, }, /* 603 */+ { 110, 7, 12, 0, 0, 18432, 170, }, /* 604 */+ { 110, 13, 12, 0, 0, 18432, 144, }, /* 605 */+ { 110, 15, 12, 0, 0, 18432, 144, }, /* 606 */+ { 110, 26, 12, 0, 0, 28672, 74, }, /* 607 */+ { 103, 26, 12, 0, 0, 28672, 74, }, /* 608 */+ { 42, 7, 12, 0, 0, 18432, 84, }, /* 609 */+ { 42, 12, 3, 0, 0, 26624, 106, }, /* 610 */+ { 42, 10, 5, 0, 0, 18432, 154, }, /* 611 */+ { 42, 21, 12, 0, 0, 18432, 74, }, /* 612 */+ { 123, 7, 12, 0, 0, 18432, 84, }, /* 613 */+ { 123, 10, 5, 0, 0, 18432, 154, }, /* 614 */+ { 123, 12, 3, 0, 0, 26624, 106, }, /* 615 */+ { 123, 12, 3, 0, 0, 26624, 158, }, /* 616 */+ { 123, 10, 12, 0, 0, 18432, 154, }, /* 617 */+ { 123, 12, 3, 0, 0, 26624, 98, }, /* 618 */+ { 123, 13, 12, 0, 0, 18432, 144, }, /* 619 */+ { 123, 21, 12, 0, 0, 18432, 74, }, /* 620 */+ { 123, 6, 12, 0, 0, 18432, 138, }, /* 621 */+ { 123, 21, 12, 0, 0, 18432, 128, }, /* 622 */+ { 106, 11, 3, 0, 0, 26624, 196, }, /* 623 */+ { 106, 12, 3, 0, 0, 26624, 106, }, /* 624 */+ { 113, 12, 3, 0, 0, 26624, 106, }, /* 625 */+ { 113, 10, 5, 0, 0, 18432, 154, }, /* 626 */+ { 113, 7, 12, 0, 0, 18432, 84, }, /* 627 */+ { 113, 12, 3, 0, 0, 26624, 98, }, /* 628 */+ { 113, 10, 3, 0, 0, 18432, 160, }, /* 629 */+ { 113, 10, 3, 0, 0, 18432, 188, }, /* 630 */+ { 113, 21, 12, 0, 0, 18432, 128, }, /* 631 */+ { 113, 13, 12, 0, 0, 18432, 144, }, /* 632 */+ { 113, 21, 12, 0, 0, 18432, 74, }, /* 633 */+ { 113, 21, 12, 0, 0, 18432, 110, }, /* 634 */+ { 113, 26, 12, 0, 0, 18432, 74, }, /* 635 */+ { 116, 12, 3, 0, 0, 26624, 106, }, /* 636 */+ { 116, 10, 5, 0, 0, 18432, 154, }, /* 637 */+ { 116, 7, 12, 0, 0, 18432, 84, }, /* 638 */+ { 116, 10, 3, 0, 0, 18432, 188, }, /* 639 */+ { 116, 12, 3, 0, 0, 26624, 158, }, /* 640 */+ { 116, 13, 12, 0, 0, 18432, 144, }, /* 641 */+ { 132, 7, 12, 0, 0, 18432, 84, }, /* 642 */+ { 132, 12, 3, 0, 0, 26624, 98, }, /* 643 */+ { 132, 10, 5, 0, 0, 18432, 154, }, /* 644 */+ { 132, 12, 3, 0, 0, 26624, 106, }, /* 645 */+ { 132, 10, 3, 0, 0, 18432, 188, }, /* 646 */+ { 132, 21, 12, 0, 0, 18432, 74, }, /* 647 */+ { 117, 7, 12, 0, 0, 18432, 84, }, /* 648 */+ { 117, 10, 5, 0, 0, 18432, 154, }, /* 649 */+ { 117, 12, 3, 0, 0, 26624, 106, }, /* 650 */+ { 117, 12, 3, 0, 0, 26624, 198, }, /* 651 */+ { 117, 12, 3, 0, 0, 26624, 98, }, /* 652 */+ { 117, 21, 12, 0, 0, 18432, 128, }, /* 653 */+ { 117, 21, 12, 0, 0, 18432, 110, }, /* 654 */+ { 117, 13, 12, 0, 0, 18432, 144, }, /* 655 */+ { 118, 13, 12, 0, 0, 18432, 144, }, /* 656 */+ { 118, 7, 12, 0, 0, 18432, 84, }, /* 657 */+ { 118, 6, 12, 0, 0, 18432, 94, }, /* 658 */+ { 118, 6, 12, 0, 0, 18432, 96, }, /* 659 */+ { 118, 21, 12, 0, 0, 18432, 128, }, /* 660 */+ { 2, 5, 12, 63, -6222, 18432, 70, }, /* 661 */+ { 2, 5, 12, 67, -6221, 18432, 70, }, /* 662 */+ { 2, 5, 12, 71, -6212, 18432, 70, }, /* 663 */+ { 2, 5, 12, 75, -6210, 18432, 70, }, /* 664 */+ { 2, 5, 12, 79, -6210, 18432, 70, }, /* 665 */+ { 2, 5, 12, 79, -6211, 18432, 70, }, /* 666 */+ { 2, 5, 12, 84, -6204, 18432, 70, }, /* 667 */+ { 2, 5, 12, 88, -6180, 18432, 70, }, /* 668 */+ { 2, 5, 12, 108, 35267, 18432, 70, }, /* 669 */+ { 21, 9, 12, 0, -3008, 18432, 76, }, /* 670 */+ { 116, 21, 12, 0, 0, 18432, 74, }, /* 671 */+ { 106, 12, 3, 0, 0, 26864, 98, }, /* 672 */+ { 106, 12, 3, 0, 0, 26868, 98, }, /* 673 */+ { 99, 21, 12, 0, 0, 18680, 200, }, /* 674 */+ { 106, 12, 3, 0, 0, 26876, 98, }, /* 675 */+ { 106, 12, 3, 0, 0, 26880, 98, }, /* 676 */+ { 106, 12, 3, 0, 0, 26884, 98, }, /* 677 */+ { 99, 10, 5, 0, 0, 18684, 174, }, /* 678 */+ { 99, 7, 12, 0, 0, 18696, 84, }, /* 679 */+ { 99, 7, 12, 0, 0, 18684, 84, }, /* 680 */+ { 99, 7, 12, 0, 0, 18676, 84, }, /* 681 */+ { 99, 7, 12, 0, 0, 18700, 84, }, /* 682 */+ { 99, 7, 12, 0, 0, 18704, 84, }, /* 683 */+ { 106, 12, 3, 0, 0, 26900, 98, }, /* 684 */+ { 99, 10, 5, 0, 0, 18712, 174, }, /* 685 */+ { 106, 12, 3, 0, 0, 26896, 98, }, /* 686 */+ { 99, 7, 12, 0, 0, 18716, 84, }, /* 687 */+ { 2, 5, 12, 0, 0, 18432, 60, }, /* 688 */+ { 1, 6, 12, 0, 0, 18432, 90, }, /* 689 */+ { 2, 6, 12, 0, 0, 18432, 182, }, /* 690 */+ { 0, 5, 12, 0, 35332, 18432, 78, }, /* 691 */+ { 0, 5, 12, 0, 3814, 18432, 78, }, /* 692 */+ { 0, 5, 12, 0, 35384, 18432, 78, }, /* 693 */+ { 0, 5, 12, 0, 0, 18432, 202, }, /* 694 */+ { 0, 6, 12, 0, 0, 18432, 182, }, /* 695 */+ { 0, 6, 12, 0, 0, 18432, 204, }, /* 696 */+ { 1, 6, 12, 0, 0, 18432, 182, }, /* 697 */+ { 106, 12, 3, 0, 0, 26740, 104, }, /* 698 */+ { 106, 12, 3, 0, 0, 26912, 98, }, /* 699 */+ { 106, 12, 3, 0, 0, 26916, 98, }, /* 700 */+ { 0, 9, 12, 92, 1, 18432, 76, }, /* 701 */+ { 0, 5, 12, 92, -1, 18432, 78, }, /* 702 */+ { 0, 5, 12, 0, 0, 18432, 70, }, /* 703 */+ { 0, 5, 12, 92, -58, 18432, 70, }, /* 704 */+ { 0, 9, 12, 0, -7615, 18432, 76, }, /* 705 */+ { 1, 5, 12, 0, 8, 18432, 78, }, /* 706 */+ { 1, 9, 12, 0, -8, 18432, 76, }, /* 707 */+ { 1, 5, 12, 0, 0, 18432, 78, }, /* 708 */+ { 1, 5, 12, 0, 74, 18432, 78, }, /* 709 */+ { 1, 5, 12, 0, 86, 18432, 78, }, /* 710 */+ { 1, 5, 12, 0, 100, 18432, 78, }, /* 711 */+ { 1, 5, 12, 0, 128, 18432, 78, }, /* 712 */+ { 1, 5, 12, 0, 112, 18432, 78, }, /* 713 */+ { 1, 5, 12, 0, 126, 18432, 78, }, /* 714 */+ { 1, 5, 12, 0, 8, 18432, 70, }, /* 715 */+ { 1, 8, 12, 0, -8, 18432, 88, }, /* 716 */+ { 1, 5, 12, 0, 0, 18432, 70, }, /* 717 */+ { 1, 5, 12, 0, 9, 18432, 70, }, /* 718 */+ { 1, 9, 12, 0, -74, 18432, 76, }, /* 719 */+ { 1, 8, 12, 0, -9, 18432, 88, }, /* 720 */+ { 1, 5, 12, 21, -7173, 18432, 78, }, /* 721 */+ { 1, 9, 12, 0, -86, 18432, 76, }, /* 722 */+ { 1, 5, 12, 0, -7235, 18432, 78, }, /* 723 */+ { 1, 9, 12, 0, -100, 18432, 76, }, /* 724 */+ { 1, 5, 12, 0, -7219, 18432, 78, }, /* 725 */+ { 1, 9, 12, 0, -112, 18432, 76, }, /* 726 */+ { 1, 9, 12, 0, -128, 18432, 76, }, /* 727 */+ { 1, 9, 12, 0, -126, 18432, 76, }, /* 728 */+ { 99, 29, 12, 0, 0, 45056, 52, }, /* 729 */+ { 106, 1, 3, 0, 0, 6144, 206, }, /* 730 */+ { 106, 1, 13, 0, 0, 6144, 208, }, /* 731 */+ { 99, 1, 2, 0, 0, 18432, 210, }, /* 732 */+ { 99, 1, 2, 0, 0, 34816, 210, }, /* 733 */+ { 99, 17, 12, 0, 0, 28672, 212, }, /* 734 */+ { 99, 21, 12, 0, 0, 28672, 64, }, /* 735 */+ { 99, 20, 12, 0, 0, 28672, 214, }, /* 736 */+ { 99, 19, 12, 0, 0, 28672, 214, }, /* 737 */+ { 99, 22, 12, 0, 0, 28672, 216, }, /* 738 */+ { 99, 20, 12, 0, 0, 28672, 216, }, /* 739 */+ { 99, 19, 12, 0, 0, 28672, 216, }, /* 740 */+ { 99, 21, 12, 0, 0, 28672, 218, }, /* 741 */+ { 99, 21, 12, 0, 0, 28672, 220, }, /* 742 */+ { 99, 27, 2, 0, 0, 45056, 50, }, /* 743 */+ { 99, 28, 2, 0, 0, 4096, 50, }, /* 744 */+ { 99, 1, 2, 0, 0, 20480, 136, }, /* 745 */+ { 99, 1, 2, 0, 0, 36864, 136, }, /* 746 */+ { 99, 1, 2, 0, 0, 30720, 136, }, /* 747 */+ { 99, 1, 2, 0, 0, 24576, 136, }, /* 748 */+ { 99, 1, 2, 0, 0, 40960, 136, }, /* 749 */+ { 99, 29, 12, 0, 0, 8488, 52, }, /* 750 */+ { 99, 21, 12, 0, 0, 14336, 54, }, /* 751 */+ { 99, 21, 12, 0, 0, 14336, 64, }, /* 752 */+ { 99, 21, 14, 0, 0, 28672, 222, }, /* 753 */+ { 99, 21, 12, 0, 0, 28672, 224, }, /* 754 */+ { 99, 16, 12, 0, 0, 28672, 144, }, /* 755 */+ { 99, 16, 12, 0, 0, 28672, 226, }, /* 756 */+ { 99, 25, 12, 0, 0, 8192, 64, }, /* 757 */+ { 99, 22, 12, 0, 0, 28672, 228, }, /* 758 */+ { 99, 18, 12, 0, 0, 28672, 228, }, /* 759 */+ { 99, 21, 12, 0, 0, 28972, 54, }, /* 760 */+ { 99, 21, 12, 0, 0, 28672, 212, }, /* 761 */+ { 99, 21, 12, 0, 0, 28976, 54, }, /* 762 */+ { 99, 21, 12, 0, 0, 28980, 54, }, /* 763 */+ { 99, 1, 2, 0, 0, 6144, 230, }, /* 764 */+ { 98, 2, 2, 0, 0, 6144, 232, }, /* 765 */+ { 99, 1, 2, 0, 0, 22528, 136, }, /* 766 */+ { 99, 1, 2, 0, 0, 38912, 136, }, /* 767 */+ { 99, 1, 2, 0, 0, 16384, 136, }, /* 768 */+ { 99, 1, 2, 0, 0, 32768, 136, }, /* 769 */+ { 99, 1, 2, 0, 0, 6144, 234, }, /* 770 */+ { 99, 25, 12, 0, 0, 12288, 236, }, /* 771 */+ { 99, 25, 12, 0, 0, 12288, 238, }, /* 772 */+ { 99, 25, 12, 0, 0, 28672, 236, }, /* 773 */+ { 99, 22, 12, 0, 0, 28672, 240, }, /* 774 */+ { 99, 18, 12, 0, 0, 28672, 240, }, /* 775 */+ { 98, 2, 12, 0, 0, 14336, 0, }, /* 776 */+ { 106, 12, 3, 0, 0, 26624, 242, }, /* 777 */+ { 106, 11, 3, 0, 0, 26624, 124, }, /* 778 */+ { 106, 11, 3, 0, 0, 26624, 244, }, /* 779 */+ { 106, 12, 3, 0, 0, 26936, 104, }, /* 780 */+ { 99, 26, 12, 0, 0, 28672, 74, }, /* 781 */+ { 99, 9, 12, 0, 0, 18432, 116, }, /* 782 */+ { 99, 5, 12, 0, 0, 18432, 246, }, /* 783 */+ { 99, 25, 12, 0, 0, 28672, 248, }, /* 784 */+ { 99, 26, 14, 0, 0, 28672, 250, }, /* 785 */+ { 1, 9, 12, 96, -7517, 18432, 76, }, /* 786 */+ { 99, 26, 12, 0, 0, 28672, 122, }, /* 787 */+ { 0, 9, 12, 100, 0, 18432, 76, }, /* 788 */+ { 0, 9, 12, 104, -8262, 18432, 76, }, /* 789 */+ { 99, 26, 12, 0, 0, 14336, 252, }, /* 790 */+ { 0, 9, 12, 0, 28, 18432, 76, }, /* 791 */+ { 99, 7, 12, 0, 0, 18432, 254, }, /* 792 */+ { 99, 5, 14, 0, 0, 18432, 256, }, /* 793 */+ { 99, 25, 12, 0, 0, 28672, 122, }, /* 794 */+ { 99, 5, 12, 0, 0, 18432, 258, }, /* 795 */+ { 0, 5, 12, 0, -28, 18432, 78, }, /* 796 */+ { 0, 14, 12, 0, 16, 18432, 76, }, /* 797 */+ { 0, 14, 12, 0, -16, 18432, 78, }, /* 798 */+ { 0, 14, 12, 0, 0, 18432, 84, }, /* 799 */+ { 99, 25, 14, 0, 0, 28672, 260, }, /* 800 */+ { 99, 26, 14, 0, 0, 28672, 260, }, /* 801 */+ { 99, 26, 12, 0, 0, 28672, 64, }, /* 802 */+ { 99, 25, 12, 0, 0, 28672, 262, }, /* 803 */+ { 99, 25, 12, 0, 0, 28672, 264, }, /* 804 */+ { 99, 25, 12, 0, 0, 12288, 266, }, /* 805 */+ { 99, 22, 12, 0, 0, 28672, 264, }, /* 806 */+ { 99, 18, 12, 0, 0, 28672, 264, }, /* 807 */+ { 99, 26, 14, 0, 0, 28672, 268, }, /* 808 */+ { 99, 22, 12, 0, 0, 28672, 270, }, /* 809 */+ { 99, 18, 12, 0, 0, 28672, 270, }, /* 810 */+ { 99, 26, 12, 0, 0, 18432, 54, }, /* 811 */+ { 99, 26, 14, 0, 0, 28672, 272, }, /* 812 */+ { 98, 2, 12, 0, 0, 18432, 274, }, /* 813 */+ { 99, 15, 12, 0, 0, 10240, 74, }, /* 814 */+ { 99, 26, 12, 0, 26, 18432, 276, }, /* 815 */+ { 99, 26, 14, 0, 26, 18432, 278, }, /* 816 */+ { 99, 26, 12, 0, -26, 18432, 280, }, /* 817 */+ { 99, 25, 14, 0, 0, 28672, 282, }, /* 818 */+ { 99, 26, 14, 0, 0, 28672, 284, }, /* 819 */+ { 99, 26, 14, 0, 0, 28672, 286, }, /* 820 */+ { 99, 25, 14, 0, 0, 28672, 284, }, /* 821 */+ { 99, 26, 14, 0, 0, 18432, 272, }, /* 822 */+ { 99, 26, 14, 0, 0, 28672, 288, }, /* 823 */+ { 109, 26, 12, 0, 0, 18432, 54, }, /* 824 */+ { 99, 26, 12, 0, 0, 28672, 228, }, /* 825 */+ { 44, 9, 12, 0, 48, 18432, 76, }, /* 826 */+ { 44, 5, 12, 0, -48, 18432, 78, }, /* 827 */+ { 0, 9, 12, 0, -10743, 18432, 76, }, /* 828 */+ { 0, 9, 12, 0, -3814, 18432, 76, }, /* 829 */+ { 0, 9, 12, 0, -10727, 18432, 76, }, /* 830 */+ { 0, 5, 12, 0, -10795, 18432, 78, }, /* 831 */+ { 0, 5, 12, 0, -10792, 18432, 78, }, /* 832 */+ { 0, 9, 12, 0, -10780, 18432, 76, }, /* 833 */+ { 0, 9, 12, 0, -10749, 18432, 76, }, /* 834 */+ { 0, 9, 12, 0, -10783, 18432, 76, }, /* 835 */+ { 0, 9, 12, 0, -10782, 18432, 76, }, /* 836 */+ { 0, 9, 12, 0, -10815, 18432, 76, }, /* 837 */+ { 43, 5, 12, 0, 0, 18432, 60, }, /* 838 */+ { 43, 26, 12, 0, 0, 28672, 74, }, /* 839 */+ { 43, 12, 3, 0, 0, 26624, 98, }, /* 840 */+ { 43, 21, 12, 0, 0, 28672, 128, }, /* 841 */+ { 43, 21, 12, 0, 0, 28672, 74, }, /* 842 */+ { 43, 15, 12, 0, 0, 28672, 74, }, /* 843 */+ { 21, 5, 12, 0, -7264, 18432, 78, }, /* 844 */+ { 45, 7, 12, 0, 0, 18432, 84, }, /* 845 */+ { 45, 6, 12, 0, 0, 18432, 148, }, /* 846 */+ { 45, 21, 12, 0, 0, 18432, 74, }, /* 847 */+ { 45, 12, 3, 0, 0, 26624, 290, }, /* 848 */+ { 2, 12, 3, 0, 0, 26624, 106, }, /* 849 */+ { 99, 20, 12, 0, 0, 28672, 228, }, /* 850 */+ { 99, 19, 12, 0, 0, 28672, 228, }, /* 851 */+ { 99, 17, 12, 0, 0, 28988, 212, }, /* 852 */+ { 99, 6, 12, 0, 0, 28672, 292, }, /* 853 */+ { 99, 21, 12, 0, 0, 28992, 54, }, /* 854 */+ { 99, 21, 12, 0, 0, 28996, 54, }, /* 855 */+ { 99, 21, 12, 0, 0, 29000, 224, }, /* 856 */+ { 99, 21, 12, 0, 0, 29004, 294, }, /* 857 */+ { 99, 21, 12, 0, 0, 28812, 54, }, /* 858 */+ { 99, 21, 12, 0, 0, 28672, 294, }, /* 859 */+ { 30, 26, 12, 0, 0, 28672, 296, }, /* 860 */+ { 99, 26, 12, 0, 0, 29008, 298, }, /* 861 */+ { 99, 26, 12, 0, 0, 29008, 300, }, /* 862 */+ { 99, 26, 12, 0, 0, 29008, 302, }, /* 863 */+ { 99, 21, 12, 0, 0, 29012, 294, }, /* 864 */+ { 99, 21, 12, 0, 0, 29016, 224, }, /* 865 */+ { 99, 21, 12, 0, 0, 29020, 54, }, /* 866 */+ { 30, 6, 12, 0, 0, 18432, 138, }, /* 867 */+ { 99, 7, 12, 0, 0, 18784, 304, }, /* 868 */+ { 30, 14, 12, 0, 0, 18432, 304, }, /* 869 */+ { 99, 22, 12, 0, 0, 29028, 228, }, /* 870 */+ { 99, 18, 12, 0, 0, 29028, 228, }, /* 871 */+ { 99, 22, 12, 0, 0, 29032, 228, }, /* 872 */+ { 99, 18, 12, 0, 0, 29032, 228, }, /* 873 */+ { 99, 22, 12, 0, 0, 29036, 62, }, /* 874 */+ { 99, 18, 12, 0, 0, 29036, 62, }, /* 875 */+ { 99, 22, 12, 0, 0, 29036, 228, }, /* 876 */+ { 99, 18, 12, 0, 0, 29036, 228, }, /* 877 */+ { 99, 26, 12, 0, 0, 29020, 54, }, /* 878 */+ { 99, 17, 12, 0, 0, 29020, 212, }, /* 879 */+ { 99, 22, 12, 0, 0, 29020, 216, }, /* 880 */+ { 99, 18, 12, 0, 0, 29020, 216, }, /* 881 */+ { 106, 12, 3, 0, 0, 26992, 98, }, /* 882 */+ { 22, 10, 3, 0, 0, 18432, 306, }, /* 883 */+ { 99, 17, 14, 0, 0, 29020, 308, }, /* 884 */+ { 99, 6, 12, 0, 0, 18804, 138, }, /* 885 */+ { 99, 26, 12, 0, 0, 29020, 74, }, /* 886 */+ { 30, 6, 12, 0, 0, 18432, 148, }, /* 887 */+ { 99, 7, 12, 0, 0, 18808, 84, }, /* 888 */+ { 99, 21, 14, 0, 0, 29048, 250, }, /* 889 */+ { 99, 26, 12, 0, 0, 29024, 74, }, /* 890 */+ { 27, 7, 12, 0, 0, 18432, 84, }, /* 891 */+ { 106, 12, 3, 0, 0, 26996, 98, }, /* 892 */+ { 99, 24, 12, 0, 0, 29044, 310, }, /* 893 */+ { 27, 6, 12, 0, 0, 18432, 138, }, /* 894 */+ { 99, 17, 12, 0, 0, 29044, 130, }, /* 895 */+ { 28, 7, 12, 0, 0, 18432, 84, }, /* 896 */+ { 99, 21, 12, 0, 0, 29036, 144, }, /* 897 */+ { 99, 6, 12, 0, 0, 18804, 96, }, /* 898 */+ { 28, 6, 12, 0, 0, 18432, 138, }, /* 899 */+ { 29, 7, 12, 0, 0, 18432, 84, }, /* 900 */+ { 22, 7, 12, 0, 0, 18432, 84, }, /* 901 */+ { 22, 7, 12, 0, 0, 18432, 184, }, /* 902 */+ { 99, 26, 12, 0, 0, 18784, 74, }, /* 903 */+ { 99, 15, 12, 0, 0, 18784, 74, }, /* 904 */+ { 22, 26, 12, 0, 0, 18432, 74, }, /* 905 */+ { 22, 26, 12, 0, 0, 28672, 74, }, /* 906 */+ { 99, 15, 12, 0, 0, 18432, 74, }, /* 907 */+ { 99, 26, 14, 0, 0, 18784, 250, }, /* 908 */+ { 28, 26, 12, 0, 0, 18432, 74, }, /* 909 */+ { 30, 7, 12, 0, 0, 18432, 312, }, /* 910 */+ { 31, 7, 12, 0, 0, 18432, 84, }, /* 911 */+ { 31, 6, 12, 0, 0, 18432, 138, }, /* 912 */+ { 31, 26, 12, 0, 0, 28672, 74, }, /* 913 */+ { 55, 7, 12, 0, 0, 18432, 84, }, /* 914 */+ { 55, 6, 12, 0, 0, 18432, 148, }, /* 915 */+ { 55, 21, 12, 0, 0, 18432, 110, }, /* 916 */+ { 55, 21, 12, 0, 0, 18432, 128, }, /* 917 */+ { 119, 7, 12, 0, 0, 18432, 84, }, /* 918 */+ { 119, 6, 12, 0, 0, 18432, 138, }, /* 919 */+ { 119, 21, 12, 0, 0, 28672, 110, }, /* 920 */+ { 119, 21, 12, 0, 0, 28672, 128, }, /* 921 */+ { 119, 13, 12, 0, 0, 18432, 144, }, /* 922 */+ { 2, 9, 12, 108, 1, 18432, 76, }, /* 923 */+ { 2, 5, 12, 108, -35267, 18432, 78, }, /* 924 */+ { 2, 7, 12, 0, 0, 18432, 84, }, /* 925 */+ { 2, 21, 12, 0, 0, 28672, 74, }, /* 926 */+ { 2, 12, 3, 0, 0, 26624, 98, }, /* 927 */+ { 2, 6, 12, 0, 0, 28672, 94, }, /* 928 */+ { 2, 6, 12, 0, 0, 18432, 90, }, /* 929 */+ { 126, 7, 12, 0, 0, 18432, 84, }, /* 930 */+ { 126, 14, 12, 0, 0, 18432, 84, }, /* 931 */+ { 126, 12, 3, 0, 0, 26624, 98, }, /* 932 */+ { 126, 21, 12, 0, 0, 18432, 74, }, /* 933 */+ { 126, 21, 12, 0, 0, 18432, 128, }, /* 934 */+ { 126, 21, 12, 0, 0, 18432, 110, }, /* 935 */+ { 99, 24, 12, 0, 0, 29052, 56, }, /* 936 */+ { 0, 9, 12, 0, -35332, 18432, 76, }, /* 937 */+ { 99, 24, 12, 0, 0, 18432, 56, }, /* 938 */+ { 0, 9, 12, 0, -42280, 18432, 76, }, /* 939 */+ { 0, 5, 12, 0, 48, 18432, 78, }, /* 940 */+ { 0, 9, 12, 0, -42308, 18432, 76, }, /* 941 */+ { 0, 9, 12, 0, -42319, 18432, 76, }, /* 942 */+ { 0, 9, 12, 0, -42315, 18432, 76, }, /* 943 */+ { 0, 9, 12, 0, -42305, 18432, 76, }, /* 944 */+ { 0, 9, 12, 0, -42258, 18432, 76, }, /* 945 */+ { 0, 9, 12, 0, -42282, 18432, 76, }, /* 946 */+ { 0, 9, 12, 0, -42261, 18432, 76, }, /* 947 */+ { 0, 9, 12, 0, 928, 18432, 76, }, /* 948 */+ { 0, 9, 12, 0, -48, 18432, 76, }, /* 949 */+ { 0, 9, 12, 0, -42307, 18432, 76, }, /* 950 */+ { 0, 9, 12, 0, -35384, 18432, 76, }, /* 951 */+ { 0, 9, 12, 0, -42343, 18432, 76, }, /* 952 */+ { 0, 9, 12, 0, -42561, 18432, 76, }, /* 953 */+ { 46, 7, 12, 0, 0, 18432, 84, }, /* 954 */+ { 46, 12, 3, 0, 0, 26624, 106, }, /* 955 */+ { 46, 12, 3, 0, 0, 26624, 158, }, /* 956 */+ { 46, 10, 5, 0, 0, 18432, 154, }, /* 957 */+ { 46, 26, 12, 0, 0, 28672, 74, }, /* 958 */+ { 99, 15, 12, 0, 0, 18816, 74, }, /* 959 */+ { 99, 15, 12, 0, 0, 18820, 74, }, /* 960 */+ { 99, 26, 12, 0, 0, 18824, 74, }, /* 961 */+ { 99, 23, 12, 0, 0, 14732, 74, }, /* 962 */+ { 99, 26, 12, 0, 0, 14728, 74, }, /* 963 */+ { 47, 7, 12, 0, 0, 18432, 84, }, /* 964 */+ { 47, 21, 12, 0, 0, 28672, 74, }, /* 965 */+ { 47, 21, 12, 0, 0, 28672, 128, }, /* 966 */+ { 120, 10, 5, 0, 0, 18432, 154, }, /* 967 */+ { 120, 7, 12, 0, 0, 18432, 84, }, /* 968 */+ { 120, 12, 3, 0, 0, 26624, 158, }, /* 969 */+ { 120, 12, 3, 0, 0, 26624, 106, }, /* 970 */+ { 120, 21, 12, 0, 0, 18432, 128, }, /* 971 */+ { 120, 13, 12, 0, 0, 18432, 144, }, /* 972 */+ { 8, 12, 3, 0, 0, 27024, 98, }, /* 973 */+ { 8, 7, 12, 0, 0, 18836, 84, }, /* 974 */+ { 49, 13, 12, 0, 0, 18432, 144, }, /* 975 */+ { 49, 7, 12, 0, 0, 18432, 84, }, /* 976 */+ { 49, 12, 3, 0, 0, 26624, 106, }, /* 977 */+ { 49, 12, 3, 0, 0, 26624, 98, }, /* 978 */+ { 99, 21, 12, 0, 0, 18840, 200, }, /* 979 */+ { 49, 21, 12, 0, 0, 18432, 128, }, /* 980 */+ { 121, 7, 12, 0, 0, 18432, 84, }, /* 981 */+ { 121, 12, 3, 0, 0, 26624, 106, }, /* 982 */+ { 121, 10, 5, 0, 0, 18432, 154, }, /* 983 */+ { 121, 10, 3, 0, 0, 18432, 188, }, /* 984 */+ { 121, 21, 12, 0, 0, 18432, 74, }, /* 985 */+ { 56, 12, 3, 0, 0, 26624, 106, }, /* 986 */+ { 56, 10, 5, 0, 0, 18432, 154, }, /* 987 */+ { 56, 7, 12, 0, 0, 18432, 84, }, /* 988 */+ { 56, 12, 3, 0, 0, 26624, 98, }, /* 989 */+ { 56, 10, 3, 0, 0, 18432, 188, }, /* 990 */+ { 56, 21, 12, 0, 0, 18432, 74, }, /* 991 */+ { 56, 21, 12, 0, 0, 18432, 110, }, /* 992 */+ { 56, 21, 12, 0, 0, 18432, 128, }, /* 993 */+ { 99, 6, 12, 0, 0, 18844, 138, }, /* 994 */+ { 56, 13, 12, 0, 0, 18432, 144, }, /* 995 */+ { 20, 6, 12, 0, 0, 18432, 138, }, /* 996 */+ { 122, 7, 12, 0, 0, 18432, 84, }, /* 997 */+ { 122, 12, 3, 0, 0, 26624, 106, }, /* 998 */+ { 122, 10, 5, 0, 0, 18432, 154, }, /* 999 */+ { 122, 13, 12, 0, 0, 18432, 144, }, /* 1000 */+ { 122, 21, 12, 0, 0, 18432, 74, }, /* 1001 */+ { 122, 21, 12, 0, 0, 18432, 128, }, /* 1002 */+ { 124, 7, 12, 0, 0, 18432, 84, }, /* 1003 */+ { 124, 12, 3, 0, 0, 26624, 106, }, /* 1004 */+ { 124, 7, 12, 0, 0, 18432, 170, }, /* 1005 */+ { 124, 12, 3, 0, 0, 26624, 98, }, /* 1006 */+ { 124, 7, 12, 0, 0, 18432, 314, }, /* 1007 */+ { 124, 6, 12, 0, 0, 18432, 138, }, /* 1008 */+ { 124, 21, 12, 0, 0, 18432, 74, }, /* 1009 */+ { 124, 21, 12, 0, 0, 18432, 110, }, /* 1010 */+ { 127, 7, 12, 0, 0, 18432, 84, }, /* 1011 */+ { 127, 10, 5, 0, 0, 18432, 154, }, /* 1012 */+ { 127, 12, 3, 0, 0, 26624, 106, }, /* 1013 */+ { 127, 21, 12, 0, 0, 18432, 128, }, /* 1014 */+ { 127, 6, 12, 0, 0, 18432, 138, }, /* 1015 */+ { 127, 12, 3, 0, 0, 26624, 158, }, /* 1016 */+ { 0, 5, 12, 0, -928, 18432, 78, }, /* 1017 */+ { 24, 5, 12, 0, -38864, 18432, 70, }, /* 1018 */+ { 127, 10, 5, 0, 0, 18432, 174, }, /* 1019 */+ { 127, 13, 12, 0, 0, 18432, 144, }, /* 1020 */+ { 22, 7, 9, 0, 0, 18432, 84, }, /* 1021 */+ { 22, 7, 10, 0, 0, 18432, 84, }, /* 1022 */+ { 98, 4, 12, 0, 0, 18432, 0, }, /* 1023 */+ { 98, 3, 12, 0, 0, 18432, 0, }, /* 1024 */+ { 30, 7, 12, 0, 0, 18432, 304, }, /* 1025 */+ { 0, 5, 12, 0, 1, 18432, 70, }, /* 1026 */+ { 0, 5, 12, 0, -1, 18432, 70, }, /* 1027 */+ { 4, 25, 12, 0, 0, 12288, 122, }, /* 1028 */+ { 5, 7, 12, 0, 0, 0, 316, }, /* 1029 */+ { 99, 18, 12, 0, 0, 29088, 54, }, /* 1030 */+ { 99, 22, 12, 0, 0, 29088, 54, }, /* 1031 */+ { 98, 2, 12, 0, 0, 6144, 318, }, /* 1032 */+ { 5, 7, 12, 0, 0, 420, 84, }, /* 1033 */+ { 5, 26, 12, 0, 0, 29092, 74, }, /* 1034 */+ { 106, 12, 3, 0, 0, 26624, 192, }, /* 1035 */+ { 106, 12, 3, 0, 0, 26624, 320, }, /* 1036 */+ { 99, 21, 12, 0, 0, 28672, 74, }, /* 1037 */+ { 99, 21, 12, 0, 0, 28672, 128, }, /* 1038 */+ { 99, 21, 12, 0, 0, 28672, 126, }, /* 1039 */+ { 99, 22, 12, 0, 0, 28672, 74, }, /* 1040 */+ { 99, 18, 12, 0, 0, 28672, 74, }, /* 1041 */+ { 99, 17, 12, 0, 0, 28672, 130, }, /* 1042 */+ { 99, 22, 12, 0, 0, 28672, 322, }, /* 1043 */+ { 99, 18, 12, 0, 0, 28672, 322, }, /* 1044 */+ { 99, 21, 12, 0, 0, 8192, 110, }, /* 1045 */+ { 99, 21, 12, 0, 0, 8192, 324, }, /* 1046 */+ { 99, 21, 12, 0, 0, 8192, 326, }, /* 1047 */+ { 99, 22, 12, 0, 0, 28672, 172, }, /* 1048 */+ { 99, 18, 12, 0, 0, 28672, 172, }, /* 1049 */+ { 99, 21, 12, 0, 0, 14336, 74, }, /* 1050 */+ { 99, 21, 12, 0, 0, 28672, 122, }, /* 1051 */+ { 99, 25, 12, 0, 0, 12288, 122, }, /* 1052 */+ { 99, 17, 12, 0, 0, 12288, 328, }, /* 1053 */+ { 99, 25, 12, 0, 0, 28672, 330, }, /* 1054 */+ { 99, 21, 12, 0, 0, 28672, 322, }, /* 1055 */+ { 99, 21, 12, 0, 0, 28672, 332, }, /* 1056 */+ { 99, 17, 12, 0, 0, 12288, 130, }, /* 1057 */+ { 99, 21, 12, 0, 0, 8192, 74, }, /* 1058 */+ { 99, 13, 12, 0, 0, 10240, 334, }, /* 1059 */+ { 0, 9, 12, 0, 32, 18432, 336, }, /* 1060 */+ { 99, 24, 12, 0, 0, 28672, 338, }, /* 1061 */+ { 0, 5, 12, 0, -32, 18432, 340, }, /* 1062 */+ { 99, 21, 12, 0, 0, 29036, 128, }, /* 1063 */+ { 99, 22, 12, 0, 0, 29036, 342, }, /* 1064 */+ { 99, 18, 12, 0, 0, 29036, 342, }, /* 1065 */+ { 99, 21, 12, 0, 0, 29036, 110, }, /* 1066 */+ { 99, 6, 3, 0, 0, 18804, 344, }, /* 1067 */+ { 99, 1, 2, 0, 0, 28672, 346, }, /* 1068 */+ { 39, 7, 12, 0, 0, 18432, 84, }, /* 1069 */+ { 99, 21, 12, 0, 0, 18856, 74, }, /* 1070 */+ { 99, 21, 12, 0, 0, 29096, 74, }, /* 1071 */+ { 99, 21, 12, 0, 0, 18860, 74, }, /* 1072 */+ { 99, 15, 12, 0, 0, 18864, 74, }, /* 1073 */+ { 99, 26, 12, 0, 0, 18860, 74, }, /* 1074 */+ { 1, 14, 12, 0, 0, 28672, 84, }, /* 1075 */+ { 1, 15, 12, 0, 0, 28672, 74, }, /* 1076 */+ { 1, 26, 12, 0, 0, 28672, 74, }, /* 1077 */+ { 1, 26, 12, 0, 0, 18432, 74, }, /* 1078 */+ { 50, 7, 12, 0, 0, 18432, 84, }, /* 1079 */+ { 51, 7, 12, 0, 0, 18432, 84, }, /* 1080 */+ { 106, 12, 3, 0, 0, 27060, 98, }, /* 1081 */+ { 99, 15, 12, 0, 0, 10676, 74, }, /* 1082 */+ { 104, 7, 12, 0, 0, 18432, 84, }, /* 1083 */+ { 104, 15, 12, 0, 0, 18432, 74, }, /* 1084 */+ { 32, 7, 12, 0, 0, 18432, 84, }, /* 1085 */+ { 32, 14, 12, 0, 0, 18432, 84, }, /* 1086 */+ { 73, 7, 12, 0, 0, 18432, 84, }, /* 1087 */+ { 73, 12, 3, 0, 0, 26624, 106, }, /* 1088 */+ { 107, 7, 12, 0, 0, 18432, 84, }, /* 1089 */+ { 107, 21, 12, 0, 0, 18432, 110, }, /* 1090 */+ { 111, 7, 12, 0, 0, 18432, 84, }, /* 1091 */+ { 111, 21, 12, 0, 0, 18432, 110, }, /* 1092 */+ { 111, 14, 12, 0, 0, 18432, 84, }, /* 1093 */+ { 105, 9, 12, 0, 40, 18432, 76, }, /* 1094 */+ { 105, 5, 12, 0, -40, 18432, 78, }, /* 1095 */+ { 40, 7, 12, 0, 0, 18432, 84, }, /* 1096 */+ { 108, 7, 12, 0, 0, 18432, 84, }, /* 1097 */+ { 108, 13, 12, 0, 0, 18432, 144, }, /* 1098 */+ { 80, 9, 12, 0, 40, 18432, 76, }, /* 1099 */+ { 80, 5, 12, 0, -40, 18432, 78, }, /* 1100 */+ { 66, 7, 12, 0, 0, 18432, 84, }, /* 1101 */+ { 64, 7, 12, 0, 0, 18432, 84, }, /* 1102 */+ { 64, 21, 12, 0, 0, 18432, 74, }, /* 1103 */+ { 167, 9, 12, 0, 39, 18432, 76, }, /* 1104 */+ { 167, 5, 12, 0, -39, 18432, 78, }, /* 1105 */+ { 96, 7, 12, 0, 0, 18432, 84, }, /* 1106 */+ { 69, 7, 12, 0, 0, 18432, 84, }, /* 1107 */+ { 0, 6, 12, 0, 0, 18432, 96, }, /* 1108 */+ { 41, 7, 12, 0, 0, 34816, 84, }, /* 1109 */+ { 128, 7, 12, 0, 0, 34816, 84, }, /* 1110 */+ { 128, 21, 12, 0, 0, 34816, 110, }, /* 1111 */+ { 128, 15, 12, 0, 0, 34816, 74, }, /* 1112 */+ { 143, 7, 12, 0, 0, 34816, 84, }, /* 1113 */+ { 143, 26, 12, 0, 0, 34816, 74, }, /* 1114 */+ { 143, 15, 12, 0, 0, 34816, 74, }, /* 1115 */+ { 142, 7, 12, 0, 0, 34816, 84, }, /* 1116 */+ { 142, 15, 12, 0, 0, 34816, 74, }, /* 1117 */+ { 149, 7, 12, 0, 0, 34816, 84, }, /* 1118 */+ { 149, 15, 12, 0, 0, 34816, 74, }, /* 1119 */+ { 115, 7, 12, 0, 0, 34816, 84, }, /* 1120 */+ { 115, 15, 12, 0, 0, 34816, 74, }, /* 1121 */+ { 115, 21, 12, 0, 0, 28672, 110, }, /* 1122 */+ { 52, 7, 12, 0, 0, 34816, 84, }, /* 1123 */+ { 52, 21, 12, 0, 0, 34816, 74, }, /* 1124 */+ { 61, 7, 12, 0, 0, 34816, 84, }, /* 1125 */+ { 134, 7, 12, 0, 0, 34816, 84, }, /* 1126 */+ { 134, 15, 12, 0, 0, 34816, 74, }, /* 1127 */+ { 112, 7, 12, 0, 0, 34816, 84, }, /* 1128 */+ { 112, 12, 3, 0, 0, 26624, 106, }, /* 1129 */+ { 112, 12, 3, 0, 0, 26624, 98, }, /* 1130 */+ { 112, 12, 3, 0, 0, 26624, 158, }, /* 1131 */+ { 112, 15, 12, 0, 0, 34816, 74, }, /* 1132 */+ { 112, 21, 12, 0, 0, 34816, 74, }, /* 1133 */+ { 112, 21, 12, 0, 0, 34816, 128, }, /* 1134 */+ { 129, 7, 12, 0, 0, 34816, 84, }, /* 1135 */+ { 129, 15, 12, 0, 0, 34816, 74, }, /* 1136 */+ { 129, 21, 12, 0, 0, 34816, 74, }, /* 1137 */+ { 141, 7, 12, 0, 0, 34816, 84, }, /* 1138 */+ { 141, 15, 12, 0, 0, 34816, 74, }, /* 1139 */+ { 71, 7, 12, 0, 0, 34816, 84, }, /* 1140 */+ { 71, 26, 12, 0, 0, 34816, 74, }, /* 1141 */+ { 71, 12, 3, 0, 0, 26624, 98, }, /* 1142 */+ { 71, 15, 12, 0, 0, 34816, 74, }, /* 1143 */+ { 71, 21, 12, 0, 0, 34816, 110, }, /* 1144 */+ { 71, 21, 12, 0, 0, 35256, 110, }, /* 1145 */+ { 71, 21, 12, 0, 0, 34816, 74, }, /* 1146 */+ { 53, 7, 12, 0, 0, 34816, 84, }, /* 1147 */+ { 53, 21, 12, 0, 0, 28672, 74, }, /* 1148 */+ { 53, 21, 12, 0, 0, 28672, 110, }, /* 1149 */+ { 130, 7, 12, 0, 0, 34816, 84, }, /* 1150 */+ { 130, 15, 12, 0, 0, 34816, 74, }, /* 1151 */+ { 131, 7, 12, 0, 0, 34816, 84, }, /* 1152 */+ { 131, 15, 12, 0, 0, 34816, 74, }, /* 1153 */+ { 74, 7, 12, 0, 0, 34816, 84, }, /* 1154 */+ { 74, 21, 12, 0, 0, 34816, 110, }, /* 1155 */+ { 74, 15, 12, 0, 0, 34816, 74, }, /* 1156 */+ { 57, 7, 12, 0, 0, 34816, 84, }, /* 1157 */+ { 78, 9, 12, 0, 64, 34816, 76, }, /* 1158 */+ { 78, 5, 12, 0, -64, 34816, 78, }, /* 1159 */+ { 78, 15, 12, 0, 0, 34816, 74, }, /* 1160 */+ { 85, 7, 12, 0, 0, 0, 84, }, /* 1161 */+ { 85, 7, 12, 0, 0, 0, 314, }, /* 1162 */+ { 85, 12, 3, 0, 0, 26624, 132, }, /* 1163 */+ { 85, 13, 12, 0, 0, 2048, 144, }, /* 1164 */+ { 92, 13, 12, 0, 0, 2048, 144, }, /* 1165 */+ { 92, 7, 12, 0, 0, 34816, 84, }, /* 1166 */+ { 92, 6, 12, 0, 0, 34816, 96, }, /* 1167 */+ { 92, 9, 12, 0, 32, 34816, 76, }, /* 1168 */+ { 92, 12, 3, 0, 0, 26624, 132, }, /* 1169 */+ { 92, 12, 3, 0, 0, 26624, 164, }, /* 1170 */+ { 92, 12, 3, 0, 0, 26624, 98, }, /* 1171 */+ { 92, 17, 12, 0, 0, 28672, 130, }, /* 1172 */+ { 92, 6, 12, 0, 0, 34816, 138, }, /* 1173 */+ { 92, 5, 12, 0, -32, 34816, 78, }, /* 1174 */+ { 92, 25, 12, 0, 0, 34816, 122, }, /* 1175 */+ { 5, 15, 12, 0, 0, 2048, 74, }, /* 1176 */+ { 88, 7, 12, 0, 0, 34816, 84, }, /* 1177 */+ { 88, 12, 3, 0, 0, 26624, 106, }, /* 1178 */+ { 88, 17, 12, 0, 0, 34816, 130, }, /* 1179 */+ { 159, 7, 12, 0, 0, 34816, 84, }, /* 1180 */+ { 159, 15, 12, 0, 0, 34816, 74, }, /* 1181 */+ { 86, 7, 12, 0, 0, 0, 84, }, /* 1182 */+ { 86, 12, 3, 0, 0, 26624, 98, }, /* 1183 */+ { 86, 15, 12, 0, 0, 0, 74, }, /* 1184 */+ { 86, 21, 12, 0, 0, 0, 128, }, /* 1185 */+ { 90, 7, 12, 0, 0, 34816, 84, }, /* 1186 */+ { 90, 12, 3, 0, 0, 26624, 98, }, /* 1187 */+ { 90, 21, 12, 0, 0, 34816, 128, }, /* 1188 */+ { 163, 7, 12, 0, 0, 34816, 84, }, /* 1189 */+ { 163, 15, 12, 0, 0, 34816, 74, }, /* 1190 */+ { 160, 7, 12, 0, 0, 34816, 84, }, /* 1191 */+ { 133, 10, 5, 0, 0, 18432, 154, }, /* 1192 */+ { 133, 12, 3, 0, 0, 26624, 106, }, /* 1193 */+ { 133, 7, 12, 0, 0, 18432, 84, }, /* 1194 */+ { 133, 12, 3, 0, 0, 26624, 158, }, /* 1195 */+ { 133, 21, 12, 0, 0, 18432, 128, }, /* 1196 */+ { 133, 21, 12, 0, 0, 18432, 110, }, /* 1197 */+ { 133, 15, 12, 0, 0, 28672, 74, }, /* 1198 */+ { 133, 13, 12, 0, 0, 18432, 144, }, /* 1199 */+ { 133, 12, 3, 0, 0, 26624, 290, }, /* 1200 */+ { 58, 12, 3, 0, 0, 26624, 106, }, /* 1201 */+ { 58, 10, 5, 0, 0, 18432, 154, }, /* 1202 */+ { 58, 7, 12, 0, 0, 18432, 84, }, /* 1203 */+ { 58, 12, 3, 0, 0, 26624, 158, }, /* 1204 */+ { 58, 12, 3, 0, 0, 26624, 98, }, /* 1205 */+ { 58, 21, 12, 0, 0, 18432, 74, }, /* 1206 */+ { 58, 1, 4, 0, 0, 18432, 134, }, /* 1207 */+ { 58, 21, 12, 0, 0, 18432, 128, }, /* 1208 */+ { 136, 7, 12, 0, 0, 18432, 84, }, /* 1209 */+ { 136, 13, 12, 0, 0, 18432, 144, }, /* 1210 */+ { 60, 12, 3, 0, 0, 26624, 106, }, /* 1211 */+ { 60, 7, 12, 0, 0, 18432, 84, }, /* 1212 */+ { 60, 10, 5, 0, 0, 18432, 154, }, /* 1213 */+ { 60, 12, 3, 0, 0, 26624, 158, }, /* 1214 */+ { 60, 13, 12, 0, 0, 18432, 144, }, /* 1215 */+ { 60, 21, 12, 0, 0, 18432, 74, }, /* 1216 */+ { 60, 21, 12, 0, 0, 18432, 128, }, /* 1217 */+ { 70, 7, 12, 0, 0, 18432, 84, }, /* 1218 */+ { 70, 12, 3, 0, 0, 26624, 98, }, /* 1219 */+ { 70, 21, 12, 0, 0, 18432, 74, }, /* 1220 */+ { 62, 12, 3, 0, 0, 26624, 106, }, /* 1221 */+ { 62, 10, 5, 0, 0, 18432, 154, }, /* 1222 */+ { 62, 7, 12, 0, 0, 18432, 84, }, /* 1223 */+ { 62, 10, 3, 0, 0, 18432, 188, }, /* 1224 */+ { 62, 7, 4, 0, 0, 18432, 84, }, /* 1225 */+ { 62, 21, 12, 0, 0, 18432, 128, }, /* 1226 */+ { 62, 21, 12, 0, 0, 18432, 74, }, /* 1227 */+ { 62, 12, 3, 0, 0, 26624, 104, }, /* 1228 */+ { 62, 12, 3, 0, 0, 26624, 98, }, /* 1229 */+ { 62, 13, 12, 0, 0, 18432, 144, }, /* 1230 */+ { 17, 15, 12, 0, 0, 18432, 74, }, /* 1231 */+ { 68, 7, 12, 0, 0, 18432, 84, }, /* 1232 */+ { 68, 10, 5, 0, 0, 18432, 154, }, /* 1233 */+ { 68, 12, 3, 0, 0, 26624, 106, }, /* 1234 */+ { 68, 10, 3, 0, 0, 18432, 188, }, /* 1235 */+ { 68, 12, 3, 0, 0, 26624, 98, }, /* 1236 */+ { 68, 12, 3, 0, 0, 26624, 162, }, /* 1237 */+ { 68, 21, 12, 0, 0, 18432, 128, }, /* 1238 */+ { 68, 21, 12, 0, 0, 18432, 110, }, /* 1239 */+ { 68, 21, 12, 0, 0, 18432, 74, }, /* 1240 */+ { 77, 7, 12, 0, 0, 18432, 84, }, /* 1241 */+ { 77, 21, 12, 0, 0, 18432, 128, }, /* 1242 */+ { 75, 7, 12, 0, 0, 18432, 84, }, /* 1243 */+ { 75, 12, 3, 0, 0, 26624, 106, }, /* 1244 */+ { 75, 10, 5, 0, 0, 18432, 154, }, /* 1245 */+ { 75, 12, 3, 0, 0, 26624, 98, }, /* 1246 */+ { 75, 12, 3, 0, 0, 26624, 158, }, /* 1247 */+ { 75, 13, 12, 0, 0, 18432, 144, }, /* 1248 */+ { 67, 12, 3, 0, 0, 26624, 106, }, /* 1249 */+ { 67, 12, 3, 0, 0, 26836, 106, }, /* 1250 */+ { 67, 10, 5, 0, 0, 18432, 154, }, /* 1251 */+ { 67, 10, 5, 0, 0, 18644, 154, }, /* 1252 */+ { 67, 7, 12, 0, 0, 18432, 84, }, /* 1253 */+ { 106, 12, 3, 0, 0, 26836, 98, }, /* 1254 */+ { 67, 12, 3, 0, 0, 26836, 98, }, /* 1255 */+ { 67, 10, 3, 0, 0, 18432, 160, }, /* 1256 */+ { 67, 10, 3, 0, 0, 18432, 188, }, /* 1257 */+ { 67, 7, 12, 0, 0, 18432, 348, }, /* 1258 */+ { 67, 12, 3, 0, 0, 26624, 98, }, /* 1259 */+ { 97, 7, 12, 0, 0, 18432, 84, }, /* 1260 */+ { 97, 10, 3, 0, 0, 18432, 160, }, /* 1261 */+ { 97, 10, 5, 0, 0, 18432, 154, }, /* 1262 */+ { 97, 12, 3, 0, 0, 26624, 106, }, /* 1263 */+ { 97, 12, 3, 0, 0, 26624, 158, }, /* 1264 */+ { 97, 10, 3, 0, 0, 18432, 188, }, /* 1265 */+ { 97, 7, 4, 0, 0, 18432, 84, }, /* 1266 */+ { 97, 12, 3, 0, 0, 26624, 164, }, /* 1267 */+ { 97, 7, 12, 0, 0, 18432, 350, }, /* 1268 */+ { 97, 21, 12, 0, 0, 18432, 128, }, /* 1269 */+ { 97, 21, 12, 0, 0, 18432, 74, }, /* 1270 */+ { 97, 12, 3, 0, 0, 26624, 98, }, /* 1271 */+ { 153, 7, 12, 0, 0, 18432, 84, }, /* 1272 */+ { 153, 10, 5, 0, 0, 18432, 154, }, /* 1273 */+ { 153, 12, 3, 0, 0, 26624, 106, }, /* 1274 */+ { 153, 12, 3, 0, 0, 26624, 158, }, /* 1275 */+ { 153, 12, 3, 0, 0, 26624, 98, }, /* 1276 */+ { 153, 21, 12, 0, 0, 18432, 128, }, /* 1277 */+ { 153, 21, 12, 0, 0, 18432, 110, }, /* 1278 */+ { 153, 21, 12, 0, 0, 18432, 74, }, /* 1279 */+ { 153, 13, 12, 0, 0, 18432, 144, }, /* 1280 */+ { 153, 12, 3, 0, 0, 26624, 104, }, /* 1281 */+ { 76, 7, 12, 0, 0, 18432, 84, }, /* 1282 */+ { 76, 10, 3, 0, 0, 18432, 160, }, /* 1283 */+ { 76, 10, 5, 0, 0, 18432, 154, }, /* 1284 */+ { 76, 12, 3, 0, 0, 26624, 106, }, /* 1285 */+ { 76, 12, 3, 0, 0, 26624, 158, }, /* 1286 */+ { 76, 12, 3, 0, 0, 26624, 98, }, /* 1287 */+ { 76, 21, 12, 0, 0, 18432, 74, }, /* 1288 */+ { 76, 13, 12, 0, 0, 18432, 144, }, /* 1289 */+ { 145, 7, 12, 0, 0, 18432, 84, }, /* 1290 */+ { 145, 10, 3, 0, 0, 18432, 160, }, /* 1291 */+ { 145, 10, 5, 0, 0, 18432, 154, }, /* 1292 */+ { 145, 12, 3, 0, 0, 26624, 106, }, /* 1293 */+ { 145, 12, 3, 0, 0, 26624, 158, }, /* 1294 */+ { 145, 12, 3, 0, 0, 26624, 98, }, /* 1295 */+ { 145, 21, 12, 0, 0, 18432, 74, }, /* 1296 */+ { 145, 21, 12, 0, 0, 18432, 128, }, /* 1297 */+ { 145, 21, 12, 0, 0, 18432, 110, }, /* 1298 */+ { 145, 21, 12, 0, 0, 18432, 190, }, /* 1299 */+ { 72, 7, 12, 0, 0, 18432, 84, }, /* 1300 */+ { 72, 10, 5, 0, 0, 18432, 154, }, /* 1301 */+ { 72, 12, 3, 0, 0, 26624, 106, }, /* 1302 */+ { 72, 12, 3, 0, 0, 26624, 158, }, /* 1303 */+ { 72, 21, 12, 0, 0, 18432, 128, }, /* 1304 */+ { 72, 21, 12, 0, 0, 18432, 74, }, /* 1305 */+ { 72, 13, 12, 0, 0, 18432, 144, }, /* 1306 */+ { 63, 7, 12, 0, 0, 18432, 84, }, /* 1307 */+ { 63, 12, 3, 0, 0, 26624, 106, }, /* 1308 */+ { 63, 10, 5, 0, 0, 18432, 154, }, /* 1309 */+ { 63, 10, 3, 0, 0, 18432, 188, }, /* 1310 */+ { 63, 12, 3, 0, 0, 26624, 98, }, /* 1311 */+ { 63, 21, 12, 0, 0, 18432, 74, }, /* 1312 */+ { 63, 13, 12, 0, 0, 18432, 144, }, /* 1313 */+ { 147, 7, 12, 0, 0, 18432, 84, }, /* 1314 */+ { 147, 12, 3, 0, 0, 26624, 106, }, /* 1315 */+ { 147, 10, 5, 0, 0, 18432, 154, }, /* 1316 */+ { 147, 10, 12, 0, 0, 18432, 154, }, /* 1317 */+ { 147, 12, 3, 0, 0, 26624, 158, }, /* 1318 */+ { 147, 13, 12, 0, 0, 18432, 144, }, /* 1319 */+ { 147, 15, 12, 0, 0, 18432, 74, }, /* 1320 */+ { 147, 21, 12, 0, 0, 18432, 128, }, /* 1321 */+ { 147, 26, 12, 0, 0, 18432, 74, }, /* 1322 */+ { 83, 7, 12, 0, 0, 18432, 84, }, /* 1323 */+ { 83, 10, 5, 0, 0, 18432, 154, }, /* 1324 */+ { 83, 12, 3, 0, 0, 26624, 106, }, /* 1325 */+ { 83, 12, 3, 0, 0, 26624, 158, }, /* 1326 */+ { 83, 12, 3, 0, 0, 26624, 98, }, /* 1327 */+ { 83, 21, 12, 0, 0, 18432, 74, }, /* 1328 */+ { 146, 9, 12, 0, 32, 18432, 76, }, /* 1329 */+ { 146, 5, 12, 0, -32, 18432, 78, }, /* 1330 */+ { 146, 13, 12, 0, 0, 18432, 144, }, /* 1331 */+ { 146, 15, 12, 0, 0, 18432, 74, }, /* 1332 */+ { 146, 7, 12, 0, 0, 18432, 84, }, /* 1333 */+ { 164, 7, 12, 0, 0, 18432, 84, }, /* 1334 */+ { 164, 10, 3, 0, 0, 18432, 160, }, /* 1335 */+ { 164, 10, 5, 0, 0, 18432, 154, }, /* 1336 */+ { 164, 12, 3, 0, 0, 26624, 106, }, /* 1337 */+ { 164, 10, 3, 0, 0, 18432, 188, }, /* 1338 */+ { 164, 12, 3, 0, 0, 26624, 158, }, /* 1339 */+ { 164, 7, 4, 0, 0, 18432, 84, }, /* 1340 */+ { 164, 12, 3, 0, 0, 26624, 98, }, /* 1341 */+ { 164, 21, 12, 0, 0, 18432, 128, }, /* 1342 */+ { 164, 21, 12, 0, 0, 18432, 74, }, /* 1343 */+ { 164, 13, 12, 0, 0, 18432, 144, }, /* 1344 */+ { 87, 7, 12, 0, 0, 18432, 84, }, /* 1345 */+ { 87, 10, 5, 0, 0, 18432, 154, }, /* 1346 */+ { 87, 12, 3, 0, 0, 26624, 106, }, /* 1347 */+ { 87, 12, 3, 0, 0, 26624, 158, }, /* 1348 */+ { 87, 21, 12, 0, 0, 18432, 74, }, /* 1349 */+ { 156, 7, 12, 0, 0, 18432, 84, }, /* 1350 */+ { 156, 12, 3, 0, 0, 26624, 106, }, /* 1351 */+ { 156, 12, 3, 0, 0, 18432, 106, }, /* 1352 */+ { 156, 12, 3, 0, 0, 26624, 104, }, /* 1353 */+ { 156, 12, 3, 0, 0, 26624, 158, }, /* 1354 */+ { 156, 10, 5, 0, 0, 18432, 154, }, /* 1355 */+ { 156, 7, 4, 0, 0, 18432, 84, }, /* 1356 */+ { 156, 21, 12, 0, 0, 18432, 74, }, /* 1357 */+ { 156, 21, 12, 0, 0, 18432, 128, }, /* 1358 */+ { 155, 7, 12, 0, 0, 18432, 84, }, /* 1359 */+ { 155, 12, 3, 0, 0, 26624, 106, }, /* 1360 */+ { 155, 10, 5, 0, 0, 18432, 154, }, /* 1361 */+ { 155, 7, 4, 0, 0, 18432, 84, }, /* 1362 */+ { 155, 12, 3, 0, 0, 26624, 352, }, /* 1363 */+ { 155, 12, 3, 0, 0, 26624, 158, }, /* 1364 */+ { 155, 21, 12, 0, 0, 18432, 74, }, /* 1365 */+ { 155, 21, 12, 0, 0, 18432, 128, }, /* 1366 */+ { 155, 21, 12, 0, 0, 18432, 110, }, /* 1367 */+ { 144, 7, 12, 0, 0, 18432, 84, }, /* 1368 */+ { 95, 7, 12, 0, 0, 18432, 84, }, /* 1369 */+ { 95, 21, 12, 0, 0, 18432, 74, }, /* 1370 */+ { 95, 13, 12, 0, 0, 18432, 144, }, /* 1371 */+ { 151, 7, 12, 0, 0, 18432, 84, }, /* 1372 */+ { 151, 10, 5, 0, 0, 18432, 154, }, /* 1373 */+ { 151, 12, 3, 0, 0, 26624, 106, }, /* 1374 */+ { 151, 12, 3, 0, 0, 18432, 158, }, /* 1375 */+ { 151, 21, 12, 0, 0, 18432, 128, }, /* 1376 */+ { 151, 21, 12, 0, 0, 18432, 110, }, /* 1377 */+ { 151, 21, 12, 0, 0, 18432, 74, }, /* 1378 */+ { 151, 13, 12, 0, 0, 18432, 144, }, /* 1379 */+ { 151, 15, 12, 0, 0, 18432, 74, }, /* 1380 */+ { 152, 21, 12, 0, 0, 18432, 74, }, /* 1381 */+ { 152, 21, 12, 0, 0, 18432, 110, }, /* 1382 */+ { 152, 7, 12, 0, 0, 18432, 84, }, /* 1383 */+ { 152, 12, 3, 0, 0, 26624, 106, }, /* 1384 */+ { 152, 10, 5, 0, 0, 18432, 154, }, /* 1385 */+ { 82, 7, 12, 0, 0, 18432, 84, }, /* 1386 */+ { 82, 12, 3, 0, 0, 26624, 106, }, /* 1387 */+ { 82, 12, 3, 0, 0, 26624, 98, }, /* 1388 */+ { 82, 12, 3, 0, 0, 26624, 158, }, /* 1389 */+ { 82, 7, 4, 0, 0, 18432, 84, }, /* 1390 */+ { 82, 13, 12, 0, 0, 18432, 144, }, /* 1391 */+ { 84, 7, 12, 0, 0, 18432, 84, }, /* 1392 */+ { 84, 10, 5, 0, 0, 18432, 154, }, /* 1393 */+ { 84, 12, 3, 0, 0, 26624, 106, }, /* 1394 */+ { 84, 12, 3, 0, 0, 26624, 158, }, /* 1395 */+ { 84, 13, 12, 0, 0, 18432, 144, }, /* 1396 */+ { 157, 7, 12, 0, 0, 18432, 84, }, /* 1397 */+ { 157, 12, 3, 0, 0, 26624, 106, }, /* 1398 */+ { 157, 10, 5, 0, 0, 18432, 154, }, /* 1399 */+ { 157, 21, 12, 0, 0, 18432, 128, }, /* 1400 */+ { 168, 12, 3, 0, 0, 26624, 106, }, /* 1401 */+ { 168, 7, 4, 0, 0, 18432, 84, }, /* 1402 */+ { 168, 10, 5, 0, 0, 18432, 154, }, /* 1403 */+ { 168, 7, 12, 0, 0, 18432, 84, }, /* 1404 */+ { 168, 10, 3, 0, 0, 18432, 188, }, /* 1405 */+ { 168, 12, 3, 0, 0, 26624, 158, }, /* 1406 */+ { 168, 21, 12, 0, 0, 18432, 128, }, /* 1407 */+ { 168, 21, 12, 0, 0, 18432, 74, }, /* 1408 */+ { 168, 13, 12, 0, 0, 18432, 144, }, /* 1409 */+ { 168, 12, 3, 0, 0, 26624, 98, }, /* 1410 */+ { 13, 15, 12, 0, 0, 18432, 74, }, /* 1411 */+ { 13, 21, 12, 0, 0, 18432, 74, }, /* 1412 */+ { 114, 7, 12, 0, 0, 18432, 84, }, /* 1413 */+ { 114, 14, 12, 0, 0, 18432, 84, }, /* 1414 */+ { 114, 21, 12, 0, 0, 18432, 110, }, /* 1415 */+ { 89, 7, 12, 0, 0, 18432, 84, }, /* 1416 */+ { 89, 21, 12, 0, 0, 18432, 74, }, /* 1417 */+ { 125, 7, 12, 0, 0, 18432, 84, }, /* 1418 */+ { 125, 1, 2, 0, 0, 18432, 346, }, /* 1419 */+ { 125, 12, 3, 0, 0, 26624, 104, }, /* 1420 */+ { 125, 12, 3, 0, 0, 26624, 98, }, /* 1421 */+ { 148, 7, 12, 0, 0, 18432, 84, }, /* 1422 */+ { 93, 7, 12, 0, 0, 18432, 84, }, /* 1423 */+ { 93, 12, 3, 0, 0, 26624, 106, }, /* 1424 */+ { 93, 10, 5, 0, 0, 18432, 154, }, /* 1425 */+ { 93, 12, 3, 0, 0, 26624, 158, }, /* 1426 */+ { 93, 13, 12, 0, 0, 18432, 144, }, /* 1427 */+ { 140, 7, 12, 0, 0, 18432, 84, }, /* 1428 */+ { 140, 13, 12, 0, 0, 18432, 144, }, /* 1429 */+ { 140, 21, 12, 0, 0, 18432, 128, }, /* 1430 */+ { 166, 7, 12, 0, 0, 18432, 84, }, /* 1431 */+ { 166, 13, 12, 0, 0, 18432, 144, }, /* 1432 */+ { 137, 7, 12, 0, 0, 18432, 84, }, /* 1433 */+ { 137, 12, 3, 0, 0, 26624, 98, }, /* 1434 */+ { 137, 21, 12, 0, 0, 18432, 128, }, /* 1435 */+ { 138, 7, 12, 0, 0, 18432, 84, }, /* 1436 */+ { 138, 12, 3, 0, 0, 26624, 98, }, /* 1437 */+ { 138, 21, 12, 0, 0, 18432, 128, }, /* 1438 */+ { 138, 21, 12, 0, 0, 18432, 110, }, /* 1439 */+ { 138, 21, 12, 0, 0, 18432, 74, }, /* 1440 */+ { 138, 26, 12, 0, 0, 18432, 74, }, /* 1441 */+ { 138, 6, 12, 0, 0, 18432, 148, }, /* 1442 */+ { 138, 6, 12, 0, 0, 18432, 138, }, /* 1443 */+ { 138, 13, 12, 0, 0, 18432, 144, }, /* 1444 */+ { 138, 15, 12, 0, 0, 18432, 74, }, /* 1445 */+ { 170, 6, 12, 0, 0, 18432, 148, }, /* 1446 */+ { 170, 7, 12, 0, 0, 18432, 84, }, /* 1447 */+ { 170, 7, 7, 0, 0, 18432, 84, }, /* 1448 */+ { 170, 6, 12, 0, 0, 18432, 94, }, /* 1449 */+ { 170, 21, 12, 0, 0, 18432, 74, }, /* 1450 */+ { 170, 21, 12, 0, 0, 18432, 128, }, /* 1451 */+ { 170, 13, 12, 0, 0, 18432, 144, }, /* 1452 */+ { 158, 9, 12, 0, 32, 18432, 76, }, /* 1453 */+ { 158, 5, 12, 0, -32, 18432, 78, }, /* 1454 */+ { 158, 15, 12, 0, 0, 18432, 74, }, /* 1455 */+ { 158, 21, 12, 0, 0, 18432, 110, }, /* 1456 */+ { 158, 21, 12, 0, 0, 18432, 128, }, /* 1457 */+ { 158, 21, 12, 0, 0, 18432, 74, }, /* 1458 */+ { 135, 7, 12, 0, 0, 18432, 84, }, /* 1459 */+ { 135, 12, 3, 0, 0, 26624, 106, }, /* 1460 */+ { 135, 10, 5, 0, 0, 18432, 154, }, /* 1461 */+ { 135, 12, 3, 0, 0, 26624, 132, }, /* 1462 */+ { 135, 6, 12, 0, 0, 18432, 94, }, /* 1463 */+ { 81, 6, 12, 0, 0, 18432, 138, }, /* 1464 */+ { 154, 6, 12, 0, 0, 18432, 138, }, /* 1465 */+ { 30, 21, 12, 0, 0, 28672, 74, }, /* 1466 */+ { 165, 12, 3, 0, 0, 26624, 354, }, /* 1467 */+ { 30, 10, 3, 0, 0, 18432, 356, }, /* 1468 */+ { 81, 7, 12, 0, 0, 18432, 304, }, /* 1469 */+ { 165, 7, 12, 0, 0, 18432, 304, }, /* 1470 */+ { 28, 6, 12, 0, 0, 18432, 94, }, /* 1471 */+ { 154, 7, 12, 0, 0, 18432, 304, }, /* 1472 */+ { 65, 7, 12, 0, 0, 18432, 84, }, /* 1473 */+ { 65, 26, 12, 0, 0, 18432, 74, }, /* 1474 */+ { 65, 12, 3, 0, 0, 26624, 104, }, /* 1475 */+ { 65, 12, 3, 0, 0, 26624, 106, }, /* 1476 */+ { 65, 21, 12, 0, 0, 18432, 128, }, /* 1477 */+ { 99, 1, 2, 0, 0, 6472, 66, }, /* 1478 */+ { 99, 13, 12, 0, 0, 10240, 144, }, /* 1479 */+ { 99, 10, 3, 0, 0, 18432, 358, }, /* 1480 */+ { 99, 10, 3, 0, 0, 18432, 306, }, /* 1481 */+ { 1, 12, 3, 0, 0, 26624, 104, }, /* 1482 */+ { 99, 25, 12, 0, 0, 28672, 360, }, /* 1483 */+ { 99, 13, 12, 0, 0, 10240, 226, }, /* 1484 */+ { 150, 26, 12, 0, 0, 18432, 74, }, /* 1485 */+ { 150, 12, 3, 0, 0, 26624, 104, }, /* 1486 */+ { 150, 21, 12, 0, 0, 18432, 110, }, /* 1487 */+ { 150, 21, 12, 0, 0, 18432, 128, }, /* 1488 */+ { 150, 21, 12, 0, 0, 18432, 74, }, /* 1489 */+ { 44, 12, 3, 0, 0, 26624, 106, }, /* 1490 */+ { 2, 6, 12, 0, 0, 18432, 92, }, /* 1491 */+ { 161, 7, 12, 0, 0, 18432, 84, }, /* 1492 */+ { 161, 12, 3, 0, 0, 26624, 98, }, /* 1493 */+ { 161, 6, 12, 0, 0, 18432, 148, }, /* 1494 */+ { 161, 6, 12, 0, 0, 18432, 138, }, /* 1495 */+ { 161, 13, 12, 0, 0, 18432, 144, }, /* 1496 */+ { 161, 26, 12, 0, 0, 18432, 74, }, /* 1497 */+ { 91, 7, 12, 0, 0, 18432, 84, }, /* 1498 */+ { 91, 12, 3, 0, 0, 26624, 98, }, /* 1499 */+ { 162, 7, 12, 0, 0, 18432, 84, }, /* 1500 */+ { 162, 12, 3, 0, 0, 26624, 98, }, /* 1501 */+ { 162, 13, 12, 0, 0, 18432, 144, }, /* 1502 */+ { 162, 23, 12, 0, 0, 14336, 74, }, /* 1503 */+ { 169, 7, 12, 0, 0, 18432, 84, }, /* 1504 */+ { 169, 6, 12, 0, 0, 18432, 148, }, /* 1505 */+ { 169, 12, 3, 0, 0, 26624, 104, }, /* 1506 */+ { 169, 13, 12, 0, 0, 18432, 144, }, /* 1507 */+ { 94, 7, 12, 0, 0, 18432, 84, }, /* 1508 */+ { 94, 12, 3, 0, 0, 26624, 98, }, /* 1509 */+ { 94, 12, 3, 0, 0, 26624, 164, }, /* 1510 */+ { 94, 13, 12, 0, 0, 18432, 144, }, /* 1511 */+ { 94, 21, 12, 0, 0, 18432, 74, }, /* 1512 */+ { 139, 7, 12, 0, 0, 34816, 84, }, /* 1513 */+ { 139, 15, 12, 0, 0, 34816, 74, }, /* 1514 */+ { 139, 12, 3, 0, 0, 26624, 98, }, /* 1515 */+ { 79, 9, 12, 0, 34, 34816, 76, }, /* 1516 */+ { 79, 5, 12, 0, -34, 34816, 78, }, /* 1517 */+ { 79, 12, 3, 0, 0, 26624, 164, }, /* 1518 */+ { 79, 12, 3, 0, 0, 26624, 106, }, /* 1519 */+ { 79, 12, 3, 0, 0, 26624, 98, }, /* 1520 */+ { 79, 6, 12, 0, 0, 34816, 148, }, /* 1521 */+ { 79, 13, 12, 0, 0, 34816, 144, }, /* 1522 */+ { 79, 21, 12, 0, 0, 34816, 74, }, /* 1523 */+ { 99, 15, 12, 0, 0, 0, 74, }, /* 1524 */+ { 99, 26, 12, 0, 0, 0, 74, }, /* 1525 */+ { 99, 23, 12, 0, 0, 0, 74, }, /* 1526 */+ { 5, 7, 12, 0, 0, 0, 254, }, /* 1527 */+ { 99, 26, 14, 0, 0, 28672, 362, }, /* 1528 */+ { 99, 26, 14, 0, 0, 28672, 364, }, /* 1529 */+ { 98, 2, 14, 0, 0, 18432, 366, }, /* 1530 */+ { 99, 26, 12, 0, 0, 18432, 368, }, /* 1531 */+ { 99, 26, 14, 0, 0, 18432, 370, }, /* 1532 */+ { 99, 26, 14, 0, 0, 18432, 364, }, /* 1533 */+ { 99, 26, 11, 0, 0, 18432, 372, }, /* 1534 */+ { 27, 26, 12, 0, 0, 18432, 74, }, /* 1535 */+ { 99, 26, 14, 0, 0, 18432, 250, }, /* 1536 */+ { 99, 26, 14, 0, 0, 18784, 364, }, /* 1537 */+ { 99, 26, 14, 0, 0, 28672, 374, }, /* 1538 */+ { 99, 26, 14, 0, 0, 28672, 376, }, /* 1539 */+ { 99, 24, 3, 0, 0, 28672, 378, }, /* 1540 */+ { 99, 26, 14, 0, 0, 28672, 380, }, /* 1541 */+ { 99, 1, 3, 0, 0, 6144, 382, }, /* 1542 */+};++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,180,181,182,146,183,184,185,186,146, /* U+11000 */+187,188,189,190,191,192,193,194,195,196,197,198,146,199,200,201, /* U+11800 */+202,202,202,202,202,202,202,203,204,202,205,146,146,146,146,146, /* U+12000 */+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,206, /* U+12800 */+207,207,207,207,207,207,207,207,208,207,207,207,207,207,207,207, /* U+13000 */+207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, /* U+13800 */+207,207,207,207,207,207,207,209,210,210,210,210,211,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,212,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+16000 */+213,213,213,213,214,215,216,217,146,146,218,146,219,220,221,222, /* U+16800 */+223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, /* U+17000 */+223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, /* U+17800 */+223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,224, /* U+18000 */+223,223,223,223,223,223,225,225,225,226,227,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,228, /* U+1A800 */+229,230,231,232,232,233,146,146,146,146,146,146,146,146,146,146, /* U+1B000 */+146,146,146,146,146,146,146,146,234,235,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,236,237,236,236,236,238,239,240, /* U+1C800 */+241,242,243,244,245,246,247,146,248,249,250,251,252,253,254,255, /* U+1D000 */+256,256,256,256,257,258,146,146,146,146,146,146,146,146,259,146, /* U+1D800 */+260,261,262,146,146,263,146,146,146,264,146,265,146,146,146,266, /* U+1E000 */+267,268,269,270,270,270,270,270,271,272,273,270,274,275,270,270, /* U+1E800 */+276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291, /* U+1F000 */+292,293,294,295,296,297,236,298,281,281,281,281,281,281,281,299, /* 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,300,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,301,101, /* U+2B000 */+302,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,303,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,304,101,101,101,101,305,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,306,146,146,146,146,146,146,146,146,146,146,307, /* 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,308,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,309,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,307, /* 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,307, /* 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,307, /* 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,307, /* 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,307, /* 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,307, /* 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,307, /* 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,307, /* 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,307, /* 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,307, /* 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,307, /* U+DF800 */+310,311,312,313,311,311,311,311,311,311,311,311,311,311,311,311, /* U+E0000 */+311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311, /* 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,307, /* 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,314, /* 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,314, /* U+10F800 */+};++const uint16_t PRIV(ucd_stage2)[] = { /* 80640 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, 86, 83, 87, 88, 89,+ 65, 66, 65, 66, 65, 66, 90, 65, 66, 90, 70, 70, 65, 66, 90, 65,+ 66, 91, 91, 65, 66, 65, 66, 92, 65, 66, 70, 93, 65, 66, 70, 94,+ 93, 93, 93, 93, 95, 96, 97, 98, 99,100,101,102,103, 65, 66, 65,+ 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,104, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 69,105,106,107, 65, 66,108,109, 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,+110, 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,111, 65, 66,112,113,114,+114, 65, 66,115,116,117, 65, 66, 65, 67, 65, 66, 65, 66, 65, 66,+118,119,120,121,122, 70,123,123, 70,124, 70,125,126, 70, 70, 70,+123,127, 70,128,129,130,131, 70,132,133,131,134,135, 70, 70,133,+ 70,136,137, 70, 70,138, 70, 70, 70, 70, 70, 70, 70,139, 70, 70,++/* block 5 */+140, 70,141,140, 70, 70, 70,142,140,143,144,144,145, 70, 70, 70,+ 70, 70,146, 70, 93, 70, 70, 70, 70, 70, 70, 70, 70,147,148, 70,+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,+149,149,150,149,149,149,149,149,149,151,151,152,153,152,152,152,+154,154, 46, 46, 46, 46,151,155,151,155,155,155,151,156,151,151,+157,157, 46, 46, 46, 46, 46,158, 46,159, 46, 46, 46, 46, 46, 46,+149,149,149,149,149, 46, 46, 46, 46, 46,160,160,151, 46,152, 46,+ 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,++/* block 6 */+161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,+174,177,176,178,176,176,176,176,176,176,176,176,176,176,176,176,+179,176,176,180,181,179,176,176,176,176,176,176,176,182,179,176,+183,184,176,176,176,176,176,176,176,176,176,176,176,176,176,176,+176,176,185,176,176,186,176,176,176,176,176,176,176,176,176,187,+176,176,176,176,176,176,176,176,188,189,189,189,189,176,190,176,+176,176,176,191,191,191,191,191,191,191,191,191,191,191,191,191,+192,193,192,193,194,195,192,193,196,196,197,198,198,198,199,200,++/* block 7 */+196,196,196,196,201, 46,202,203,204,204,204,196,205,196,206,206,+207,208,209,208,208,210,208,208,211,212,213,208,214,208,208,208,+215,216,196,217,208,208,218,208,208,219,208,208,220,221,221,221,+222,223,224,223,223,225,223,223,226,227,228,223,229,223,223,223,+230,231,232,233,223,223,234,223,223,235,223,223,236,237,237,238,+239,240,241,242,242,243,244,245,192,193,192,193,192,193,192,193,+192,193,246,247,246,247,246,247,246,247,246,247,246,247,246,247,+248,249,250,251,252,253,254,192,193,255,192,193,256,257,257,257,++/* block 8 */+258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,+259,259,260,259,261,259,259,259,259,259,259,259,259,259,262,259,+259,263,264,259,259,259,259,259,259,259,265,259,259,259,259,259,+266,266,267,266,268,266,266,266,266,266,266,266,266,266,269,266,+266,270,271,266,266,266,266,266,266,266,272,266,266,266,266,266,+273,273,273,273,273,273,274,273,274,273,273,273,273,273,273,273,+275,276,277,278,275,276,275,276,275,276,275,276,275,276,275,276,+275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276,++/* block 9 */+275,276,279,280,281,282,282,281,283,283,275,276,275,276,275,276,+275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276,+275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276,+275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276,+284,275,276,275,276,275,276,275,276,275,276,275,276,275,276,285,+275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276,+275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276,+275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276,++/* block 10 */+275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276,+275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276,+275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276,+196,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,+286,286,286,286,286,286,286,196,196,287,288,288,288,288,288,289,+290,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,+291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,++/* block 11 */+291,291,291,291,291,291,291,292,290,293,294,196,196,295,295,296,+297,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,+298,298,299,298,298,298,298,298,298,298,298,298,298,298,298,298,+300,300,300,300,300,300,300,300,300,300,300,300,300,300,301,300,+302,300,300,303,300,304,302,304,297,297,297,297,297,297,297,297,+305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,+305,305,305,305,305,305,305,305,305,305,305,297,297,297,297,305,+305,305,305,302,306,297,297,297,297,297,297,297,297,297,297,297,++/* block 12 */+307,307,307,307,307,308,309,309,310,311,311,312,313,314,315,315,+316,316,316,316,316,316,316,316,316,316,316,317,318,319,319,320,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+322,321,321,321,321,321,321,321,321,321,321,323,323,323,323,323,+323,323,323,324,325,325,316,326,327,316,316,316,316,316,316,316,+328,328,328,328,328,328,328,328,328,328,311,329,329,314,321,321,+324,321,321,330,321,321,321,321,321,321,321,321,321,321,321,321,++/* block 13 */+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,331,321,316,316,316,316,316,316,332,308,315,333,+333,316,316,332,316,334,334,332,332,315,333,333,333,316,321,321,+335,335,335,335,335,335,335,335,335,335,321,321,321,336,336,321,++/* block 14 */+337,337,337,338,338,338,338,338,338,338,338,339,338,339,340,341,+342,343,342,342,342,342,342,342,342,342,342,342,342,342,342,342,+342,342,342,342,342,342,342,342,342,342,342,342,342,342,342,342,+344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,+345,345,345,345,345,345,345,345,345,345,345,340,340,342,342,342,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,++/* block 15 */+346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,+346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,+346,346,346,346,346,346,347,347,347,347,347,347,347,347,347,347,+347,346,340,340,340,340,340,340,340,340,340,340,340,340,340,340,+348,348,348,348,348,348,348,348,348,348,349,349,349,349,349,349,+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,+349,349,349,349,349,349,349,349,349,349,349,350,350,350,350,350,+350,350,350,350,351,351,352,353,354,355,356,297,297,357,358,358,++/* block 16 */+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,+359,359,359,359,359,359,360,360,361,361,362,360,360,360,360,360,+360,360,360,360,362,360,360,360,362,360,360,360,360,363,297,297,+364,364,364,364,364,364,365,366,364,366,364,364,364,366,366,297,+367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,+367,367,367,367,367,367,367,367,367,368,368,368,297,297,369,297,+342,342,342,342,342,342,342,342,342,342,342,340,340,340,340,340,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,++/* block 17 */+321,321,321,321,321,321,321,321,370,321,321,321,321,321,321,340,+307,307,340,340,340,340,340,316,333,333,333,333,333,333,333,333,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,334,327,327,333,327,327,327,+333,333,333,371,316,316,316,316,316,316,316,316,316,316,316,316,+372,372,308,326,326,326,326,326,326,326,333,333,333,333,333,333,+326,326,326,373,326,326,326,326,326,326,326,326,326,326,326,316,++/* block 18 */+374,374,374,375,376,376,376,376,376,376,376,376,376,376,376,376,+376,376,376,376,376,377,377,377,377,377,377,377,377,377,377,377,+377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,+377,377,377,377,377,377,377,377,377,377,374,375,378,376,375,375,+375,374,374,374,374,374,374,374,374,375,375,375,375,379,375,375,+376,380,381,176,176,374,374,374,377,377,377,377,377,377,377,377,+376,376,374,374,382,383,384,384,384,384,384,384,384,384,384,384,+385,386,376,376,376,376,376,376,377,377,377,377,377,377,377,377,++/* block 19 */+387,388,389,389,196,387,387,387,387,387,387,387,387,196,196,387,+387,196,196,387,387,390,390,390,390,390,390,390,390,390,390,390,+390,390,390,390,390,390,390,390,390,196,390,390,390,390,390,390,+390,196,390,196,196,196,390,390,390,390,196,196,391,387,392,389,+389,388,388,388,388,196,196,389,389,196,196,389,389,393,387,196,+196,196,196,196,196,196,196,392,196,196,196,196,390,390,196,390,+387,387,388,388,196,196,394,394,394,394,394,394,394,394,394,394,+390,390,395,395,396,396,396,396,396,396,397,395,387,398,399,196,++/* block 20 */+196,400,400,401,196,402,402,402,402,402,402,196,196,196,196,402,+402,196,196,402,402,402,402,402,402,402,402,402,402,402,402,402,+402,402,402,402,402,402,402,402,402,196,402,402,402,402,402,402,+402,196,402,402,196,402,402,196,402,402,196,196,403,196,401,401,+401,400,400,196,196,196,196,400,400,196,196,400,400,404,196,196,+196,400,196,196,196,196,196,196,196,402,402,402,402,196,402,196,+196,196,196,196,196,196,405,405,405,405,405,405,405,405,405,405,+400,406,402,402,402,400,407,196,196,196,196,196,196,196,196,196,++/* block 21 */+196,408,408,409,196,410,410,410,410,410,410,410,410,410,196,410,+410,410,196,410,410,411,411,411,411,411,411,411,411,411,411,411,+411,411,411,411,411,411,411,411,411,196,411,411,411,411,411,411,+411,196,411,411,196,411,411,411,411,411,196,196,412,410,409,409,+409,408,408,408,408,408,196,408,408,409,196,409,409,413,196,196,+410,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+410,410,408,408,196,196,414,414,414,414,414,414,414,414,414,414,+415,416,196,196,196,196,196,196,196,411,408,417,408,412,412,412,++/* block 22 */+196,418,419,419,196,420,420,420,420,420,420,420,420,196,196,420,+420,196,196,420,420,421,421,421,421,421,421,421,421,421,421,421,+421,421,421,421,421,421,421,421,421,196,421,421,421,421,421,421,+421,196,421,421,196,421,421,421,421,421,196,196,422,420,423,418,+419,418,418,418,418,196,196,419,419,196,196,419,419,424,196,196,+196,196,196,196,196,425,418,423,196,196,196,196,421,421,196,421,+420,420,418,418,196,196,426,426,426,426,426,426,426,426,426,426,+427,421,428,428,428,428,428,428,196,196,196,196,196,196,196,196,++/* block 23 */+196,196,429,430,196,430,430,430,430,430,430,196,196,196,430,430,+430,196,430,430,430,430,196,196,196,430,430,196,430,196,430,430,+196,196,196,430,430,196,196,196,430,430,430,196,196,196,430,430,+430,430,430,430,430,430,430,430,430,430,196,196,196,196,431,432,+429,432,432,196,196,196,432,432,432,196,432,432,432,433,196,196,+430,196,196,196,196,196,196,431,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,434,434,434,434,434,434,434,434,434,434,+435,435,435,436,437,437,437,437,437,438,437,196,196,196,196,196,++/* block 24 */+439,440,440,440,439,441,441,441,441,441,441,441,441,196,441,441,+441,196,441,441,441,442,442,442,442,442,442,442,442,442,442,442,+442,442,442,442,442,442,442,442,442,196,442,442,442,442,442,442,+442,442,442,442,442,442,442,442,442,442,196,196,443,441,439,439,+439,440,440,440,440,196,439,439,439,196,439,439,439,444,196,196,+196,196,196,196,196,439,439,196,442,442,442,196,196,441,196,196,+441,441,439,439,196,196,445,445,445,445,445,445,445,445,445,445,+196,196,196,196,196,196,196,446,447,447,447,447,447,447,447,448,++/* block 25 */+449,450,451,451,452,449,449,449,449,449,449,449,449,196,449,449,+449,196,449,449,449,449,449,449,449,449,449,449,449,449,449,449,+449,449,449,449,449,449,449,449,449,196,449,449,449,449,449,449,+449,449,449,449,196,449,449,449,449,449,196,196,453,449,451,454,+455,451,455,451,451,196,454,455,455,196,455,455,450,456,196,196,+196,196,196,196,196,455,455,196,196,196,196,196,196,449,449,196,+449,449,450,450,196,196,457,457,457,457,457,457,457,457,457,457,+196,449,449,451,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 26 */+458,458,459,459,460,460,460,460,460,460,460,460,460,196,460,460,+460,196,460,460,460,461,461,461,461,461,461,461,461,461,461,461,+461,461,461,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,460,463,459,+459,458,458,458,458,196,459,459,459,196,459,459,459,462,464,465,+196,196,196,196,460,460,460,463,466,466,466,466,466,466,466,460,+460,460,458,458,196,196,467,467,467,467,467,467,467,467,467,467,+466,466,466,466,466,466,466,466,466,465,460,460,460,460,460,460,++/* block 27 */+196,468,469,469,196,470,470,470,470,470,470,470,470,470,470,470,+470,470,470,470,470,470,470,196,196,196,470,470,470,470,470,470,+470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,+470,470,196,470,470,470,470,470,470,470,470,470,196,470,196,196,+470,470,470,470,470,470,470,196,196,196,471,196,196,196,196,472,+469,469,468,468,468,196,468,196,469,469,469,469,469,469,469,472,+196,196,196,196,196,196,473,473,473,473,473,473,473,473,473,473,+196,196,469,469,474,196,196,196,196,196,196,196,196,196,196,196,++/* block 28 */+196,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,475,475,475,475,+475,476,475,477,476,476,476,476,476,476,478,196,196,196,196,479,+480,480,480,480,480,475,481,482,482,482,482,482,482,476,482,483,+484,484,484,484,484,484,484,484,484,484,485,485,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 29 */+196,486,486,196,486,196,486,486,486,486,486,196,486,486,486,486,+486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,+486,486,486,486,196,486,196,486,486,486,486,486,486,486,486,486,+486,487,486,488,487,487,487,487,487,487,489,487,487,486,196,196,+490,490,490,490,490,196,491,196,492,492,492,492,492,487,493,196,+494,494,494,494,494,494,494,494,494,494,196,196,486,486,486,486,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 30 */+495,496,496,496,497,497,497,497,498,497,497,497,497,498,498,498,+498,498,498,496,497,496,496,496,499,499,496,496,496,496,496,496,+500,500,500,500,500,500,500,500,500,500,501,501,501,501,501,501,+501,501,501,501,496,499,496,499,496,499,502,503,502,503,504,504,+495,495,495,495,495,495,495,495,196,495,495,495,495,495,495,495,+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,+495,495,495,495,495,495,495,495,495,495,495,495,495,196,196,196,+196,505,505,505,505,505,505,506,505,506,505,505,505,505,505,507,++/* block 31 */+505,505,508,508,509,497,499,499,495,495,495,495,495,505,505,505,+505,505,505,505,505,505,505,505,196,505,505,505,505,505,505,505,+505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,+505,505,505,505,505,505,505,505,505,505,505,505,505,196,496,496,+496,496,496,496,496,496,499,496,496,496,496,496,496,196,496,496,+497,497,497,497,497,510,510,510,510,497,497,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 32 */+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,+511,511,511,511,511,511,511,511,511,511,511,512,512,513,513,513,+513,514,513,513,513,513,513,515,512,516,516,514,514,513,513,511,+517,517,517,517,517,517,517,517,517,517,518,518,519,519,519,519,+511,511,511,511,511,511,514,514,513,513,511,511,511,511,513,513,+513,511,512,520,520,511,511,512,512,520,520,520,520,520,511,511,+511,513,513,513,513,511,511,511,511,511,511,511,511,511,511,511,++/* block 33 */+511,511,513,512,514,513,513,520,520,520,520,520,520,521,511,520,+522,522,522,522,522,522,522,522,522,522,520,520,512,513,523,523,+524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,+524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,+524,524,524,524,524,524,196,524,196,196,196,196,196,524,196,196,+525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,+525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,+525,525,525,525,525,525,525,525,525,525,525,526,527,525,525,525,++/* block 34 */+528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,+528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,+528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,+528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,+528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,+528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,529,+530,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,+531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,++/* block 35 */+531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,+531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,+531,531,531,531,531,531,531,531,532,532,532,532,532,532,532,532,+532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,+532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,+532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,+532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,+532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,++/* block 36 */+533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,+533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,+533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,+533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,+533,533,533,533,533,533,533,533,533,196,533,533,533,533,196,196,+533,533,533,533,533,533,533,196,533,196,533,533,533,533,196,196,+533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,+533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,++/* block 37 */+533,533,533,533,533,533,533,533,533,196,533,533,533,533,196,196,+533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,+533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,+533,196,533,533,533,533,196,196,533,533,533,533,533,533,533,196,+533,196,533,533,533,533,196,196,533,533,533,533,533,533,533,533,+533,533,533,533,533,533,533,196,533,533,533,533,533,533,533,533,+533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,+533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,++/* block 38 */+533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,+533,196,533,533,533,533,196,196,533,533,533,533,533,533,533,533,+533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,+533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,+533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,+533,533,533,533,533,533,533,533,533,533,533,196,196,534,534,534,+535,536,537,536,536,536,536,537,537,538,538,538,538,538,538,538,+538,538,539,539,539,539,539,539,539,539,539,539,539,196,196,196,++/* block 39 */+533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,+540,540,540,540,540,540,540,540,540,540,196,196,196,196,196,196,+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,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,542,542,542,542,542,196,196,543,543,543,543,543,543,196,196,++/* block 40 */+544,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,+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,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,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,545,545,545,++/* block 41 */+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,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,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,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,545,545,545,545,++/* block 42 */+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,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,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,545,545,545,+545,545,545,545,545,545,545,545,545,545,545,545,545,546,547,545,+545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,++/* block 43 */+548,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,+549,549,549,549,549,549,549,549,549,549,549,550,551,196,196,196,+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,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,553,553,553,554,554,+554,552,552,552,552,552,552,552,552,196,196,196,196,196,196,196,++/* block 44 */+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,+555,555,556,556,557,558,196,196,196,196,196,196,196,196,196,555,+559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,+559,559,560,560,561,562,562,196,196,196,196,196,196,196,196,196,+563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,+563,563,564,564,196,196,196,196,196,196,196,196,196,196,196,196,+565,565,565,565,565,565,565,565,565,565,565,565,565,196,565,565,+565,196,566,566,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 45 */+567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,+567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,+567,567,567,568,568,567,567,567,567,567,567,567,567,567,567,567,+567,567,567,567,569,569,570,571,571,571,571,571,571,571,570,570,+570,570,570,570,570,570,571,570,570,572,572,572,572,572,572,572,+572,572,573,572,574,574,575,576,577,577,575,578,567,572,196,196,+579,579,579,579,579,579,579,579,579,579,196,196,196,196,196,196,+580,580,580,580,580,580,580,580,580,580,196,196,196,196,196,196,++/* block 46 */+581,581,582,583,584,582,585,581,584,586,587,588,588,588,589,588,+590,590,590,590,590,590,590,590,590,590,196,196,196,196,196,196,+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,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,591,591,591,591,591,591,+591,591,591,591,591,591,591,591,591,196,196,196,196,196,196,196,++/* block 47 */+591,591,591,591,591,593,593,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,594,591,196,196,196,196,196,+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,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,545,545,+545,545,545,545,545,545,196,196,196,196,196,196,196,196,196,196,++/* block 48 */+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,196,+596,596,596,597,597,597,597,596,596,597,597,597,196,196,196,196,+597,597,596,597,597,597,597,597,597,598,598,598,196,196,196,196,+599,196,196,196,600,600,601,601,601,601,601,601,601,601,601,601,+602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,+602,602,602,602,602,602,602,602,602,602,602,602,602,602,196,196,+602,602,602,602,602,196,196,196,196,196,196,196,196,196,196,196,++/* block 49 */+603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,+603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,+603,603,603,603,603,603,603,603,603,603,603,603,196,196,196,196,+603,603,603,603,603,604,604,604,603,603,604,603,603,603,603,603,+603,603,603,603,603,603,603,603,603,603,196,196,196,196,196,196,+605,605,605,605,605,605,605,605,605,605,606,196,196,196,607,607,+608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,+608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,++/* block 50 */+609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,+609,609,609,609,609,609,609,610,610,611,611,610,196,196,612,612,+613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,+613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,+613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,+613,613,613,613,613,614,615,614,615,615,615,615,615,615,615,196,+616,617,615,617,617,615,615,615,615,615,615,615,615,614,614,614,+614,614,614,615,615,618,618,618,618,618,618,618,618,196,196,618,++/* block 51 */+619,619,619,619,619,619,619,619,619,619,196,196,196,196,196,196,+619,619,619,619,619,619,619,619,619,619,196,196,196,196,196,196,+620,620,620,620,620,620,620,621,622,622,622,622,620,620,196,196,+176,176,176,176,176,176,176,176,176,176,176,176,176,176,623,624,+624,176,176,176,176,176,176,176,176,176,176,176,624,624,624,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 52 */+625,625,625,625,626,627,627,627,627,627,627,627,627,627,627,627,+627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,+627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,+627,627,627,627,628,629,625,625,625,625,625,629,625,629,626,626,+626,626,625,629,630,627,627,627,627,627,627,627,627,196,631,631,+632,632,632,632,632,632,632,632,632,632,631,631,633,634,631,631,+633,635,635,635,635,635,635,635,635,635,635,628,628,628,628,628,+628,628,628,628,635,635,635,635,635,635,635,635,635,631,631,631,++/* block 53 */+636,636,637,638,638,638,638,638,638,638,638,638,638,638,638,638,+638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,+638,637,636,636,636,636,637,637,636,636,639,640,636,636,638,638,+641,641,641,641,641,641,641,641,641,641,638,638,638,638,638,638,+642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,+642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,+642,642,642,642,642,642,643,644,645,645,644,644,644,645,644,645,+645,645,646,646,196,196,196,196,196,196,196,196,647,647,647,647,++/* block 54 */+648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,+648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,+648,648,648,648,649,649,649,649,649,649,649,649,650,650,650,650,+650,650,650,650,649,649,651,652,196,196,196,653,653,654,654,654,+655,655,655,655,655,655,655,655,655,655,196,196,196,648,648,648,+656,656,656,656,656,656,656,656,656,656,657,657,657,657,657,657,+657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,+657,657,657,657,657,657,657,657,658,658,658,659,658,658,660,660,++/* block 55 */+661,662,663,664,665,666,667,668,669,275,276,196,196,196,196,196,+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,+670,670,670,670,670,670,670,670,670,670,670,196,196,670,670,670,+671,671,671,671,671,671,671,671,196,196,196,196,196,196,196,196,+672,673,672,674,673,675,675,676,675,676,677,673,676,676,673,673,+676,678,673,673,673,673,673,673,673,679,680,681,681,675,681,681,+681,681,682,683,684,680,680,685,686,686,687,196,196,196,196,196,++/* 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,256,256,256,256,256,688,149,149,149,149,+149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,+149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,+149,149,149,149,149,149,149,149,149,149,149,149,149,689,689,689,+689,689,150,149,149,149,689,689,689,689,689, 70, 70, 70, 70, 70,+ 70, 70, 70, 70, 70, 70, 70, 70,690,691, 70, 70, 70,692, 70, 70,++/* block 57 */+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,693, 70,+ 70, 70, 70, 70, 70, 70,694, 70, 70, 70, 70,695,695,695,695,695,+695,695,695,695,696,695,695,695,696,695,695,695,695,695,695,695,+695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,697,+698,698,189,189,176,176,176,176,176,176,176,176,176,176,176,176,+189,189,189,624,624,624,624,624,624,624,624,624,624,624,624,624,+624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,+624,624,624,624,624,176,176,176,699,176,700,176,176,176,176,176,++/* 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,+701,702, 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,703,704, 70, 70,705, 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 */+706,706,706,706,706,706,706,706,707,707,707,707,707,707,707,707,+706,706,706,706,706,706,196,196,707,707,707,707,707,707,196,196,+706,706,706,706,706,706,706,706,707,707,707,707,707,707,707,707,+706,706,706,706,706,706,706,706,707,707,707,707,707,707,707,707,+706,706,706,706,706,706,196,196,707,707,707,707,707,707,196,196,+708,706,708,706,708,706,708,706,196,707,196,707,196,707,196,707,+706,706,706,706,706,706,706,706,707,707,707,707,707,707,707,707,+709,709,710,710,710,710,711,711,712,712,713,713,714,714,196,196,++/* block 61 */+715,715,715,715,715,715,715,715,716,716,716,716,716,716,716,716,+715,715,715,715,715,715,715,715,716,716,716,716,716,716,716,716,+715,715,715,715,715,715,715,715,716,716,716,716,716,716,716,716,+706,706,717,718,717,196,708,717,707,707,719,719,720,201,721,201,+201,201,717,718,717,196,708,717,722,722,722,722,720,201,201,201,+706,706,708,723,196,196,708,708,707,707,724,724,196,201,201,201,+706,706,708,725,708,250,708,708,707,707,726,726,255,201,201,201,+196,196,717,718,717,196,708,717,727,727,728,728,720,201,201,196,++/* block 62 */+729,729,729,729,729,729,729,729,729,729,729, 51,730,731,732,733,+734,734,734,734,734,734,735, 43,736,737,738,739,739,740,738,739,+ 43, 43, 43, 43,741, 43, 43,742,743,744,745,746,747,748,749,750,+751,751,752,752,752, 43, 43, 43, 43, 49, 57, 43,753,754, 43,755,+756, 43, 43, 43,757,758,759,754,754,753, 43, 43, 43, 43, 43,760,+ 43, 43, 50,761,755, 43, 43, 43, 43, 43,762, 43, 43,763, 43,729,+ 51,764,764,764,764,765,766,767,768,769,770,770,770,770,770,770,+ 54,696,196,196, 54, 54, 54, 54, 54, 54,771,772,773,774,775,695,++/* block 63 */+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,771,772,773,774,775,196,+695,695,695,695,695,695,695,695,695,695,695,695,695,196,196,196,+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,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,+777,777,777,777,777,777,777,777,777,777,777,777,777,778,778,778,+778,777,778,779,778,777,777,189,189,189,189,777,777,777,777,777,+780,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 64 */+781,781,782,781,781,781,781,782,781,781,783,782,782,782,783,783,+782,782,782,783,781,782,781,781,784,782,782,782,782,782,781,781,+781,781,785,781,782,781,786,781,782,787,788,789,782,782,790,783,+782,782,791,782,783,792,792,792,792,793,781,781,783,783,782,782,+794,794,794,794,794,782,783,783,795,795,781,794,781,781,796,510,+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,+797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,+798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,++/* block 65 */+799,799,799, 65, 66,799,799,799,799, 58,781,781,196,196,196,196,+ 50, 50, 50, 50,800,801,801,801,801,801, 50, 50,802,802,802,802,+ 50,802,802, 50,802,802, 50,802, 45,801,801,802,802,802, 50, 45,+802,802, 45, 45, 45, 45,802,802, 45, 45, 45, 45,802,802,802,802,+802,802,802,802,802,802,802,802,802,802,802,802,802,802, 50, 50,+802,802, 50,802, 50,802,802,802,802,802,802,802, 45,802, 45, 45,+ 45, 45, 45, 45,802,802, 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,803, 50, 50, 50, 50,803,804,804,804,804,804,804, 50, 50,+ 50, 50,805, 53, 50,804, 50, 50, 50, 50, 50, 50, 50, 50,803,804,+804,804,804, 50,804, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,804,804, 50, 50,+ 50, 50, 50,804, 50,804, 50, 50, 50, 50, 50, 50,804, 50, 50, 50,+ 50, 50,804,804,804,804, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50,804,804,804,804,804,804,804,804, 50, 50,804,804,+804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,++/* block 67 */+804,804,804,804,804,804,804,804,804,804,804,804, 50, 50, 50,804,+804,804,804, 50, 50, 50, 50, 50,804, 50, 50, 50, 50, 50, 50, 50,+ 50, 50,804,804, 50, 50,804, 50,804,804, 50,804, 50, 50, 50, 50,+804,804,804,804,804,804,804,804,804, 50, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50, 50, 50, 50, 50, 50,804,804,804,804,804, 50, 50,+804,804, 50, 50, 50, 50,804,804,804,804,804,804,804,804,804,804,+804,804,804,804,804,804,804,804,804,804,804,804,804,804, 50, 50,+804,804,804,804,804, 50,804,804, 50, 50,804,804,804,804,804, 50,++/* block 68 */+ 45, 45, 45, 45, 45, 45, 45, 45,806,807,806,807, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,808,808, 45, 45, 45, 45,+ 50, 50, 45, 45, 45, 45, 45, 45, 47,809,810, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45,811,811,811,811,811,811,811,811,811,811,+811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,+811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,+811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,+811,811,811,811,811,811,811,811,811,811,811, 45, 50, 45, 45, 45,++/* block 69 */+ 45, 45, 45, 45, 45, 45, 45, 45,812, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45,811, 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,802,802, 45,802, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 47,+802, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 50, 50, 50, 50,+ 50, 50,802, 45, 45, 45, 45, 45, 45,808,808,808,808, 47, 47, 47,+808, 47, 47,808, 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, 45, 45, 45,813,813,813,813,813,813,+813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,813,813,813,813,813,+813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,+ 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,814,814,814,814,814,814,814,814,+814,814,814,814,814,814,814,814,814,814,814,814,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,815,815,815,815,815,815,815,815,815,815,+815,815,816,815,815,815,815,815,815,815,815,815,815,815,815,815,+817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,+817,817,817,817,817,817,817,817,817,817, 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,+802,802, 45, 45, 45, 45, 45, 45, 45, 45, 47, 47, 45, 45,802,802,+802,802,802,802,802,802,801, 50, 45, 45, 45, 45,802,802,802,802,+801, 50, 45, 45, 45, 45,802,802, 45, 45,802,802, 45, 45, 45,802,+802,802,802,802, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45,802, 45,802, 45, 45,802,802,802,802,802,802, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 50, 50, 50,800,800,818,818, 50,++/* block 74 */+ 47, 47, 47, 47, 47,819,802,812,812,812,812,812,812,812, 47,812,+812, 47,812, 45,808,808,812,812, 47,812,812,812,812,820,812,812,+ 47,812, 47, 47,812,812, 47,812,812,812, 47,812,812,812, 47, 47,+812,812,812,812,812,812,812,812, 47, 47, 47,812,812,812,812,812,+801,812,801,812,812,812,812,812,808,808,808,808,808,808,808,808,+808,808,808,808,812,812,812,812,812,812,812,812,812,812,812, 47,+801,819,819,801,812, 47, 47,812, 47,812,812,812,812,819,819,821,+812,812,812,812,812,812,812,812,812,812,812, 47,812,812, 47,808,++/* block 75 */+812,812,812,812,812,812, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+812,812, 47,808, 47, 47, 47, 47,812, 47,812, 47, 47,812,812,812,+ 47,808,812,812,812,812,812, 47,812,812,808,808,822,812,812,812,+ 47, 47,812,812,812,812,812,812,812,812,812,812,812,808,808,812,+812,812,812,812,808,808,812,812, 47,812,812,812,812,812,808, 47,+812, 47,812, 47,808,812,812,812,812,812,812,812,812,812,812,812,+812,812,812,812,812,812,812,812,812, 47,808,812,812,812,812,812,+ 47, 47,808,808, 47,808,812, 47, 47,820,808,812,812,808,812,812,++/* block 76 */+812,812, 47,812,812,808, 45, 45, 47, 47,823,823,820,820,812, 47,+812,812, 47, 45, 47, 45, 47, 45, 45, 45, 45, 45, 45, 47, 45, 45,+ 45, 47, 45, 45, 45, 45, 45, 45,808, 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,808, 45,808, 45,+ 45, 45, 45,808,808,808, 45,808, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 47, 47,812,812,812,758,759,758,759,758,759,758,759,+758,759,758,759,758,759, 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,808,808,808, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 47, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+808, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,808,+ 50, 50, 50,804,804,806,807, 50,804,804, 50,804, 50,804, 50, 50,+ 50, 50, 50, 50, 50,804,804, 50, 50, 50, 50, 50,804,804,804, 50,+ 50, 50,804,804,804,804,806,807,806,807,806,807,806,807,806,807,+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,++/* block 78 */+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,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,++/* 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,800,800, 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,806,807,806,807,806,807,806,807,806,807,806,807,806,+807,806,807,806,807,806,807,806,807, 50, 50,804, 50, 50, 50, 50,+804, 50, 50,804,804,804, 50, 50,804,804,804,804,804,804,804,804,+ 50, 50, 50, 50, 50, 50, 50, 50,804, 50, 50, 50, 50, 50, 50, 50,+804,804, 50, 50,804,804, 50, 50, 50, 50, 50, 50, 50, 50, 50,804,+804,804,804, 50,804,804, 50, 50,806,807,806,807, 50, 50, 50, 50,+ 50, 50, 50, 50, 50, 50, 50, 50,804,804, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50, 50,804, 50, 50,804,804, 50, 50,806,807, 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,804,804,804,804, 50,+ 50, 50, 50, 50,804,804, 50, 50, 50, 50, 50, 50,804,804, 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,804,804, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,+ 50, 50, 50, 50, 50, 50, 50, 50, 50,804,804,804,804,804,804,804,++/* block 82 */+804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,+804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,+804,804,804, 50, 50, 50,804,804,804,804,804,804,804,804, 50,804,+804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,+804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,+804,804,804,804,804,804,804, 50, 50, 50, 50, 50, 50, 50,804, 50,+ 50, 50, 50,804,804,804, 50, 50, 50, 50, 50, 50,804,804,804, 50,+ 50, 50, 50, 50, 50, 50, 50,804,804,804,804, 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,808,808, 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,+808, 45, 45, 45, 45,808, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45,813,813, 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,813, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,825, 45,++/* block 85 */+826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,+826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,+826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,+827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,+827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,+827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,+ 65, 66,828,829,830,831,832, 65, 66, 65, 66, 65, 66,833,834,835,+836, 70, 65, 66, 70, 65, 66, 70, 70, 70, 70, 70,696,695,837,837,++/* block 86 */+246,247,246,247,246,247,246,247,246,247,246,247,246,247,246,247,+246,247,246,247,246,247,246,247,246,247,246,247,246,247,246,247,+246,247,246,247,246,247,246,247,246,247,246,247,246,247,246,247,+246,247,246,247,246,247,246,247,246,247,246,247,246,247,246,247,+246,247,246,247,246,247,246,247,246,247,246,247,246,247,246,247,+246,247,246,247,246,247,246,247,246,247,246,247,246,247,246,247,+246,247,246,247,838,839,839,839,839,839,839,246,247,246,247,840,+840,840,246,247,196,196,196,196,196,841,841,841,842,843,842,842,++/* block 87 */+844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,+844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,+844,844,844,844,844,844,196,844,196,196,196,196,196,844,196,196,+845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,+845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,+845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,+845,845,845,845,845,845,845,845,196,196,196,196,196,196,196,846,+847,196,196,196,196,196,196,196,196,196,196,196,196,196,196,848,++/* block 88 */+533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,+533,533,533,533,533,533,533,196,196,196,196,196,196,196,196,196,+533,533,533,533,533,533,533,196,533,533,533,533,533,533,533,196,+533,533,533,533,533,533,533,196,533,533,533,533,533,533,533,196,+533,533,533,533,533,533,533,196,533,533,533,533,533,533,533,196,+533,533,533,533,533,533,533,196,533,533,533,533,533,533,533,196,+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,++/* block 89 */+ 43, 43,850,851,850,851, 43, 43, 43,850,851, 43,850,851, 43, 43,+ 43, 43, 43, 43, 43, 43, 43,852, 43, 43,734, 43,850,851, 43, 43,+850,851,758,759,758,759,758,759,758,759, 43, 43, 43, 43,754,853,+854,855, 43, 43, 43, 43, 43, 43, 43, 43,734,734,856, 43, 43, 43,+734,857,738,858, 43, 43, 43, 43, 43, 43, 43, 43,859, 43,859,859,+ 45, 45, 43,754,754,758,759,758,759,758,759,758,759,734,813,813,+813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,+813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,++/* block 90 */+860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,+860,860,860,860,860,860,860,860,860,860,196,860,860,860,860,860,+860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,+860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,+860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,+860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,+860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,+860,860,860,860,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 91 */+860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,+860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,+860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,+860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,+860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,+860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,+860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,+860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,++/* block 92 */+860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,+860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,+860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,+860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,+860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,+860,860,860,860,860,860,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+861,861,862,862,861,861,861,861,861,861,861,861,861,861,863,863,++/* block 93 */+729,864,865,866,781,867,868,869,870,871,872,873,874,875,874,875,+876,877, 45,878,876,877,876,877,876,877,876,877,879,880,881,881,+ 45,869,869,869,869,869,869,869,869,869,882,882,882,882,883,883,+884,885,885,885,885,885,781,886,869,869,869,887,888,889,890,890,+196,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,891,891,891,891,891,891,891,891,891,891,891,++/* block 94 */+891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,+891,891,891,891,891,891,891,196,196,892,892,893,893,894,894,891,+895,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,+896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,+896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,+896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,+896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,+896,896,896,896,896,896,896,896,896,896,896,897,898,899,899,896,++/* block 95 */+196,196,196,196,196,900,900,900,900,900,900,900,900,900,900,900,+900,900,900,900,900,900,900,900,900,900,900,900,900,900,900,900,+900,900,900,900,900,900,900,900,900,900,900,900,900,900,900,900,+196,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,+901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,+901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,+901,901,901,901,902,901,901,901,901,901,901,901,901,901,901,901,+901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,++/* block 96 */+901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,196,+903,903,904,904,904,904,903,903,903,903,903,903,903,903,903,903,+900,900,900,900,900,900,900,900,900,900,900,900,900,900,900,900,+900,900,900,900,900,900,900,900,900,900,900,900,900,900,900,900,+890,890,890,890,890,890,890,890,890,890,890,890,890,890,890,890,+890,890,890,890,890,890,890,890,890,890,890,890,890,890,890,890,+890,890,890,890,890,890,196,196,196,196,196,196,196,196,196,861,+896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,++/* block 97 */+905,905,905,905,905,905,905,905,905,905,905,905,905,905,905,905,+905,905,905,905,905,905,905,905,905,905,905,905,905,906,906,196,+904,904,904,904,904,904,904,904,904,904,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,903,903,907,907,907,907,907,907,907,907,+781, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,+905,905,905,905,905,905,905,905,905,905,905,905,905,905,905,905,+905,905,905,905,905,905,905,905,905,905,905,905,906,906,906,510,++/* block 98 */+904,904,904,904,904,904,904,904,904,904,903,903,903,903,903,903,+903,903,903,903,903,903,903,908,903,908,903,903,903,903,903,903,+903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,+903, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,+903,903,903,903,903,903,903,903,903,903,903,903,781,781,781,781,+909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,+909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,+909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,903,++/* block 99 */+909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,+909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,+909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,+909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,+909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,+909,909,909,909,909,909,909,909,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,510,510,510,510,510,510,781,781,781,781,903,903,903,903,903,++/* block 100 */+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,781,781,+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,903,903,903,781,++/* block 101 */+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,++/* block 102 */+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,++/* block 103 */+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,912,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,++/* block 104 */+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,+911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,++/* block 105 */+911,911,911,911,911,911,911,911,911,911,911,911,911,196,196,196,+913,913,913,913,913,913,913,913,913,913,913,913,913,913,913,913,+913,913,913,913,913,913,913,913,913,913,913,913,913,913,913,913,+913,913,913,913,913,913,913,913,913,913,913,913,913,913,913,913,+913,913,913,913,913,913,913,196,196,196,196,196,196,196,196,196,+914,914,914,914,914,914,914,914,914,914,914,914,914,914,914,914,+914,914,914,914,914,914,914,914,914,914,914,914,914,914,914,914,+914,914,914,914,914,914,914,914,915,915,915,915,915,915,916,917,++/* block 106 */+918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,+918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,+918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,+918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,+918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,+918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,+918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,+918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,++/* block 107 */+918,918,918,918,918,918,918,918,918,918,918,918,919,920,921,921,+918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,+922,922,922,922,922,922,922,922,922,922,918,918,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+275,276,275,276,275,276,275,276,275,276,923,924,275,276,275,276,+275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276,+275,276,275,276,275,276,275,276,275,276,275,276,275,276,925,281,+283,283,283,926,849,849,849,849,849,849,849,849,927,927,926,928,++/* block 108 */+275,276,275,276,275,276,275,276,275,276,275,276,275,276,275,276,+275,276,275,276,275,276,275,276,275,276,275,276,929,929,849,849,+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,+930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,+930,930,930,930,930,930,931,931,931,931,931,931,931,931,931,931,+932,932,933,934,935,935,935,934,196,196,196,196,196,196,196,196,++/* block 109 */+936,936,936,936,936,936,936,936, 46, 46, 46, 46, 46, 46, 46, 46,+ 46, 46, 46, 46, 46, 46, 46,151,151,151,151,151,151,151,151,151,+ 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,+695, 70, 70, 70, 70, 70, 70, 70, 70, 65, 66, 65, 66,937, 65, 66,++/* block 110 */+ 65, 66, 65, 66, 65, 66, 65, 66,151,938,938, 65, 66,939, 70, 93,+ 65, 66, 65, 66,940, 70, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,941,942,943,944,941, 70,+945,946,947,948, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,+ 65, 66, 65, 66,949,950,951, 65, 66, 65, 66,952, 65, 66,196,196,+ 65, 66,196, 70,196, 70, 65, 66, 65, 66, 65, 66,953,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,695,695,695, 65, 66, 93,149,149, 70, 93, 93, 93, 93, 93,++/* block 111 */+954,954,955,954,954,954,956,954,954,954,954,955,954,954,954,954,+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,+954,954,954,957,957,955,955,957,958,958,958,958,956,196,196,196,+959,959,959,960,960,960,961,961,962,963,196,196,196,196,196,196,+964,964,964,964,964,964,964,964,964,964,964,964,964,964,964,964,+964,964,964,964,964,964,964,964,964,964,964,964,964,964,964,964,+964,964,964,964,964,964,964,964,964,964,964,964,964,964,964,964,+964,964,964,964,965,965,966,966,196,196,196,196,196,196,196,196,++/* block 112 */+967,967,968,968,968,968,968,968,968,968,968,968,968,968,968,968,+968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,+968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,+968,968,968,968,967,967,967,967,967,967,967,967,967,967,967,967,+967,967,967,967,969,970,196,196,196,196,196,196,196,196,971,971,+972,972,972,972,972,972,972,972,972,972,196,196,196,196,196,196,+378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,+378,973,376,974,376,376,376,376,385,385,385,376,385,376,376,374,++/* block 113 */+975,975,975,975,975,975,975,975,975,975,976,976,976,976,976,976,+976,976,976,976,976,976,976,976,976,976,976,976,976,976,976,976,+976,976,976,976,976,976,977,977,977,977,977,978,978,978,979,980,+981,981,981,981,981,981,981,981,981,981,981,981,981,981,981,981,+981,981,981,981,981,981,981,982,982,982,982,982,982,982,982,982,+982,982,983,984,196,196,196,196,196,196,196,196,196,196,196,985,+528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,+528,528,528,528,528,528,528,528,528,528,528,528,528,196,196,196,++/* block 114 */+986,986,986,987,988,988,988,988,988,988,988,988,988,988,988,988,+988,988,988,988,988,988,988,988,988,988,988,988,988,988,988,988,+988,988,988,988,988,988,988,988,988,988,988,988,988,988,988,988,+988,988,988,989,987,987,986,986,986,986,987,987,986,986,987,987,+990,991,991,991,991,991,991,992,993,993,991,991,991,991,196,994,+995,995,995,995,995,995,995,995,995,995,196,196,196,196,991,991,+511,511,511,511,511,521,996,511,511,511,511,511,511,511,511,511,+522,522,522,522,522,522,522,522,522,522,511,511,511,511,511,196,++/* block 115 */+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,998,998,998,998,998,998,999,+999,998,998,999,999,998,998,196,196,196,196,196,196,196,196,196,+997,997,997,998,997,997,997,997,997,997,997,997,998,999,196,196,+1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,196,196,1001,1002,1002,1002,+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,+996,511,511,511,511,511,511,523,523,523,511,520,521,520,511,511,++/* block 116 */+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,1003,1003,1003,+1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,1003,+1004,1003,1004,1004,1004,1005,1005,1004,1004,1005,1003,1005,1005,1003,1004,1006,+1007,1006,1007,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,1003,1003,1008,1009,1010,+1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1011,1012,1013,1013,1012,1012,+1014,1014,1011,1015,1015,1012,1016,196,196,196,196,196,196,196,196,196,++/* block 117 */+196,533,533,533,533,533,533,196,196,533,533,533,533,533,533,196,+196,533,533,533,533,533,533,196,196,196,196,196,196,196,196,196,+533,533,533,533,533,533,533,196,533,533,533,533,533,533,533,196,+ 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,1017, 70, 70, 70, 70, 70, 70, 70,938,149,149,149,149,+ 70, 70, 70, 70, 70,256, 70, 70, 70,149, 46, 46,196,196,196,196,+1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,++/* block 118 */+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,1018,1018,1018,1018,1018,1018,1018,1018,+1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,1018,+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,1013,1012,1012,1013,1012,1012,1014,1019,1016,196,196,+1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,196,196,196,196,196,196,++/* block 119 */+1021,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,1021,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,1021,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,1021,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,+1021,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,++/* block 120 */+1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1021,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,1021,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,1021,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,+1021,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,1021,1022,1022,1022,++/* block 121 */+1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,+1022,1022,1022,1022,1022,1022,1022,1022,1021,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,1021,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,+1021,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,1021,1022,1022,1022,+1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,++/* block 122 */+1022,1022,1022,1022,1022,1022,1022,1022,1021,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,1021,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,+1021,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,1021,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,1021,1022,1022,1022,1022,1022,1022,1022,++/* block 123 */+1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,+1022,1022,1022,1022,1021,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,+1021,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,1021,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,1021,1022,1022,1022,1022,1022,1022,1022,+1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,++/* block 124 */+1022,1022,1022,1022,1021,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,+1021,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,1021,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,1021,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,1021,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,++/* block 125 */+1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,+1021,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,1021,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,1021,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,1021,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,++/* block 126 */+1022,1022,1022,1022,1022,1022,1022,1022,1021,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,196,196,196,196,196,196,196,196,196,196,196,196,+531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,+531,531,531,531,531,531,531,196,196,196,196,532,532,532,532,532,+532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,+532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,+532,532,532,532,532,532,532,532,532,532,532,532,196,196,196,196,++/* block 127 */+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,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,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,1023,1023,1023,1023,+1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,++/* block 128 */+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,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,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,1024,1024,1024,1024,+1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,++/* block 129 */+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,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,+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,1025,1025,1025,1025,1025,1025,1025,1025,++/* block 130 */+1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,910,910,+1025,910,1025,910,910,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,910,+1025,910,1025,910,910,1025,1025,910,910,910,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,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,196,196,+1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,++/* block 131 */+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,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,+1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 132 */+703,703,703,703,703,1026,1027,196,196,196,196,196,196,196,196,196,+196,196,196,292,292,292,292,292,196,196,196,196,196,305,300,305,+305,305,305,305,305,305,305,305,305,1028,305,305,305,305,305,305,+305,305,305,305,305,305,305,297,305,305,305,305,305,297,305,297,+305,305,297,305,305,297,305,305,305,305,305,305,305,305,305,305,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,++/* block 133 */+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,370,370,370,370,370,370,370,370,370,370,370,370,370,370,+370,370,370,340,340,340,340,340,340,340,340,340,340,340,340,340,+340,340,340,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,++/* block 134 */+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,1029,1029,+1029,1029,1029,1029,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,++/* block 135 */+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,++/* block 136 */+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,1030,1031,+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,++/* block 137 */+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+340,340,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,340,340,340,340,340,340,340,315,+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,+321,321,1033,321,321,321,321,321,321,321,1029,1029,312,1034,315,315,++/* block 138 */+1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1036,+1037,1037,1038,1039,1037,1038,1038,1040,1041,1037,196,196,196,196,196,196,+176,176,176,176,176,176,176,176,176,176,176,176,176,176,927,927,+1037,1042,1042,755,755,1040,1041,1040,1041,1040,1041,1040,1041,1040,1041,1040,+1041,1043,1044,1043,1044,866,866,1040,1041,1037,1037,1037,1037,755,755,755,+1045,199,1046,196,199,1047,1038,1038,1042,1048,1049,1048,1049,1048,1049,1050,+1037,1051,1052,1053,1054,1054,794,196,1051,479,1050,1037,196,196,196,196,+1029,321,1029,321,1029,340,1029,321,1029,321,1029,321,1029,321,1029,321,++/* block 139 */+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,+321,321,321,321,321,321,321,321,321,321,321,321,321,340,340, 51,++/* block 140 */+196,1038,1055,1050,479,1050,1037,1056,1048,1049,1037,1052,1045,1057,1046,1058,+1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1047,199,1054,794,1054,1038,+1037,1060,1060,1060,1060,1060,1060, 59, 59, 59, 59, 59, 59, 59, 59, 59,+ 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,1048,1051,1049,1061,755,+ 46,1062,1062,1062,1062,1062,1062, 62, 62, 62, 62, 62, 62, 62, 62, 62,+ 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,1048,794,1049,794,1048,+1049,1063,1064,1065,1066,897,896,896,896,896,896,896,896,896,896,896,+898,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,++/* block 141 */+896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,+896,896,896,896,896,896,896,896,896,896,896,896,896,896,1067,1067,+902,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,+901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,196,+196,196,901,901,901,901,901,901,196,196,901,901,901,901,901,901,+196,196,901,901,901,901,901,901,196,196,901,901,901,196,196,196,+479,479,794, 46,781,479,479,196,781,794,794,794,794,781,781,196,+765,765,765,765,765,765,765,765,765,1068,1068,1068,781,781,1032,1032,++/* block 142 */+1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,196,1069,1069,1069,+1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,+1069,1069,1069,1069,1069,1069,1069,196,1069,1069,1069,1069,1069,1069,1069,1069,+1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,196,1069,1069,196,1069,+1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,196,196,+1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 143 */+1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,+1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,+1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,+1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,+1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,+1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,+1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,+1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,1069,196,196,196,196,196,++/* block 144 */+1070,1071,1072,196,196,196,196,1073,1073,1073,1073,1073,1073,1073,1073,1073,+1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,+1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,1073,+1073,1073,1073,1073,196,196,196,1074,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,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,+1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,1075,+1075,1075,1075,1075,1075,1076,1076,1076,1076,1077,1077,1077,1077,1077,1077,1077,++/* block 145 */+1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1076,1076,1077,1078,1078,196,+781,781,781,781,781,781,781,781,781,781,781,781,781,196,196,196,+1077,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,189,196,196,++/* block 146 */+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 147 */+1079,1079,1079,1079,1079,1079,1079,1079,1079,1079,1079,1079,1079,1079,1079,1079,+1079,1079,1079,1079,1079,1079,1079,1079,1079,1079,1079,1079,1079,196,196,196,+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,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+1081,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,196,196,196,196,++/* block 148 */+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,+1084,1084,1084,1084,196,196,196,196,196,196,196,196,196,1083,1083,1083,+1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,+1085,1086,1085,1085,1085,1085,1085,1085,1085,1085,1086,196,196,196,196,196,+1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,+1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,1087,+1087,1087,1087,1087,1087,1087,1088,1088,1088,1088,1088,196,196,196,196,196,++/* block 149 */+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,196,1090,+1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,+1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,1091,+1091,1091,1091,1091,196,196,196,196,1091,1091,1091,1091,1091,1091,1091,1091,+1092,1093,1093,1093,1093,1093,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 150 */+1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,1094,+1094,1094,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,1095,1095,1095,1095,1095,1095,1095,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,1096,1096,1096,1096,1096,+1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,+1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,++/* block 151 */+1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,+1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,1097,196,196,+1098,1098,1098,1098,1098,1098,1098,1098,1098,1098,196,196,196,196,196,196,+1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,+1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,+1099,1099,1099,1099,196,196,196,196,1100,1100,1100,1100,1100,1100,1100,1100,+1100,1100,1100,1100,1100,1100,1100,1100,1100,1100,1100,1100,1100,1100,1100,1100,+1100,1100,1100,1100,1100,1100,1100,1100,1100,1100,1100,1100,196,196,196,196,++/* block 152 */+1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,+1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,1101,+1101,1101,1101,1101,1101,1101,1101,1101,196,196,196,196,196,196,196,196,+1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,+1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,+1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,+1102,1102,1102,1102,196,196,196,196,196,196,196,196,196,196,196,1103,+1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,196,1104,1104,1104,1104,++/* block 153 */+1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,196,1104,1104,1104,1104,+1104,1104,1104,196,1104,1104,196,1105,1105,1105,1105,1105,1105,1105,1105,1105,+1105,1105,196,1105,1105,1105,1105,1105,1105,1105,1105,1105,1105,1105,1105,1105,+1105,1105,196,1105,1105,1105,1105,1105,1105,1105,196,1105,1105,196,196,196,+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,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 154 */+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,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,1107,1107,1107,1107,1107,1107,+1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,++/* block 155 */+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,1107,1107,196,196,196,196,196,196,196,196,196,+1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,+1107,1107,1107,1107,1107,1107,196,196,196,196,196,196,196,196,196,196,+1107,1107,1107,1107,1107,1107,1107,1107,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 156 */+149,1108,1108,149,149,149,196,149,149,149,149,149,149,149,149,149,+149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,+149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,+149,196,149,149,149,149,149,149,149,149,149,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 157 */+1109,1109,1109,1109,1109,1109,297,297,1109,297,1109,1109,1109,1109,1109,1109,+1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,+1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,1109,+1109,1109,1109,1109,1109,1109,297,1109,1109,297,297,297,1109,297,297,1109,+1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,1110,+1110,1110,1110,1110,1110,1110,297,1111,1112,1112,1112,1112,1112,1112,1112,1112,+1113,1113,1113,1113,1113,1113,1113,1113,1113,1113,1113,1113,1113,1113,1113,1113,+1113,1113,1113,1113,1113,1113,1113,1114,1114,1115,1115,1115,1115,1115,1115,1115,++/* block 158 */+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,297,+297,297,297,297,297,297,297,1117,1117,1117,1117,1117,1117,1117,1117,1117,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+1118,1118,1118,1118,1118,1118,1118,1118,1118,1118,1118,1118,1118,1118,1118,1118,+1118,1118,1118,297,1118,1118,297,297,297,297,297,1119,1119,1119,1119,1119,++/* block 159 */+1120,1120,1120,1120,1120,1120,1120,1120,1120,1120,1120,1120,1120,1120,1120,1120,+1120,1120,1120,1120,1120,1120,1121,1121,1121,1121,1121,1121,297,297,297,1122,+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,1123,297,297,297,297,297,1124,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,++/* block 160 */+1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,+1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,1125,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,297,297,297,297,1127,1127,1126,1126,+1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,+297,297,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,+1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,+1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,1127,++/* block 161 */+1128,1129,1129,1129,297,1129,1129,297,297,297,297,297,1129,1129,1129,1129,+1128,1128,1128,1128,297,1128,1128,1128,297,1128,1128,1128,1128,1128,1128,1128,+1128,1128,1128,1128,1128,1128,1128,1128,1128,1128,1128,1128,1128,1128,1128,1128,+1128,1128,1128,1128,1128,1128,297,297,1130,1130,1130,297,297,297,297,1131,+1132,1132,1132,1132,1132,1132,1132,1132,1132,297,297,297,297,297,297,297,+1133,1133,1133,1133,1133,1133,1134,1134,1133,297,297,297,297,297,297,297,+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,1136,1136,1137,++/* block 162 */+1138,1138,1138,1138,1138,1138,1138,1138,1138,1138,1138,1138,1138,1138,1138,1138,+1138,1138,1138,1138,1138,1138,1138,1138,1138,1138,1138,1138,1138,1139,1139,1139,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+1140,1140,1140,1140,1140,1140,1140,1140,1141,1140,1140,1140,1140,1140,1140,1140,+1140,1140,1140,1140,1140,1140,1140,1140,1140,1140,1140,1140,1140,1140,1140,1140,+1140,1140,1140,1140,1140,1142,1142,297,297,297,297,1143,1143,1143,1143,1143,+1144,1144,1145,1144,1144,1144,1146,297,297,297,297,297,297,297,297,297,++/* block 163 */+1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,+1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,+1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,1147,+1147,1147,1147,1147,1147,1147,297,297,297,1148,1149,1149,1149,1149,1149,1149,+1150,1150,1150,1150,1150,1150,1150,1150,1150,1150,1150,1150,1150,1150,1150,1150,+1150,1150,1150,1150,1150,1150,297,297,1151,1151,1151,1151,1151,1151,1151,1151,+1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,1152,+1152,1152,1152,297,297,297,297,297,1153,1153,1153,1153,1153,1153,1153,1153,++/* block 164 */+1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,+1154,1154,297,297,297,297,297,297,297,1155,1155,1155,1155,297,297,297,+297,297,297,297,297,297,297,297,297,1156,1156,1156,1156,1156,1156,1156,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,++/* block 165 */+1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,+1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,+1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,+1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,1157,+1157,1157,1157,1157,1157,1157,1157,1157,1157,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,++/* block 166 */+1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,+1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,+1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,1158,+1158,1158,1158,297,297,297,297,297,297,297,297,297,297,297,297,297,+1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,+1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,+1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,1159,+1159,1159,1159,297,297,297,297,297,297,297,1160,1160,1160,1160,1160,1160,++/* block 167 */+1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,+1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,+1161,1161,1162,1162,1163,1163,1163,1163,340,340,340,340,340,340,340,340,+1164,1164,1164,1164,1164,1164,1164,1164,1164,1164,340,340,340,340,340,340,+1165,1165,1165,1165,1165,1165,1165,1165,1165,1165,1166,1166,1166,1166,1167,1166,+1168,1168,1168,1168,1168,1168,1168,1168,1168,1168,1168,1168,1168,1168,1168,1168,+1168,1168,1168,1168,1168,1168,297,297,297,1169,1170,1171,1171,1171,1172,1173,+1174,1174,1174,1174,1174,1174,1174,1174,1174,1174,1174,1174,1174,1174,1174,1174,++/* block 168 */+1174,1174,1174,1174,1174,1174,297,297,297,297,297,297,297,297,1175,1175,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,++/* block 169 */+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,+1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,1176,297,++/* block 170 */+1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,+1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,+1177,1177,1177,1177,1177,1177,1177,1177,1177,1177,297,1178,1178,1179,297,297,+1177,1177,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+340,340,321,321,321,340,340,340,340,340,340,340,340,340,340,340,+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,+340,340,340,340,340,340,340,340,340,340,340,340,316,333,333,333,++/* block 171 */+1180,1180,1180,1180,1180,1180,1180,1180,1180,1180,1180,1180,1180,1180,1180,1180,+1180,1180,1180,1180,1180,1180,1180,1180,1180,1180,1180,1180,1180,1181,1181,1181,+1181,1181,1181,1181,1181,1181,1181,1180,297,297,297,297,297,297,297,297,+1182,1182,1182,1182,1182,1182,1182,1182,1182,1182,1182,1182,1182,1182,1182,1182,+1182,1182,1182,1182,1182,1182,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,+1183,1184,1184,1184,1184,1185,1185,1185,1185,1185,340,340,340,340,340,340,+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,+1186,1186,1186,1186,1186,1186,1186,1186,1186,1186,1186,1186,1186,1186,1186,1186,++/* block 172 */+1186,1186,1187,1187,1187,1187,1188,1188,1188,1188,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,1189,+1189,1189,1189,1189,1189,1190,1190,1190,1190,1190,1190,1190,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,+1191,1191,1191,1191,1191,1191,1191,297,297,297,297,297,297,297,297,297,++/* block 173 */+1192,1193,1192,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,+1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,+1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,1194,+1194,1194,1194,1194,1194,1194,1194,1194,1193,1193,1193,1193,1193,1193,1193,1193,+1193,1193,1193,1193,1193,1193,1195,1196,1196,1197,1197,1197,1197,1197,196,196,+196,196,1198,1198,1198,1198,1198,1198,1198,1198,1198,1198,1198,1198,1198,1198,+1198,1198,1198,1198,1198,1198,1199,1199,1199,1199,1199,1199,1199,1199,1199,1199,+1195,1194,1194,1193,1193,1194,196,196,196,196,196,196,196,196,196,1200,++/* block 174 */+1201,1201,1202,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,+1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,+1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,+1202,1202,1202,1201,1201,1201,1201,1202,1202,1204,1205,1206,1206,1207,1208,1208,+1208,1208,1201,196,196,196,196,196,196,196,196,196,196,1207,196,196,+1209,1209,1209,1209,1209,1209,1209,1209,1209,1209,1209,1209,1209,1209,1209,1209,+1209,1209,1209,1209,1209,1209,1209,1209,1209,196,196,196,196,196,196,196,+1210,1210,1210,1210,1210,1210,1210,1210,1210,1210,196,196,196,196,196,196,++/* block 175 */+1211,1211,1211,1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,+1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,1212,+1212,1212,1212,1212,1212,1212,1212,1211,1211,1211,1211,1211,1213,1211,1211,1211,+1211,1211,1211,1214,1214,196,1215,1215,1215,1215,1215,1215,1215,1215,1215,1215,+1216,1217,1217,1217,1212,1213,1213,1212,196,196,196,196,196,196,196,196,+1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,+1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,1218,+1218,1218,1218,1219,1220,1220,1218,196,196,196,196,196,196,196,196,196,++/* block 176 */+1221,1221,1222,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,+1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,+1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,1223,+1223,1223,1223,1222,1222,1222,1221,1221,1221,1221,1221,1221,1221,1221,1221,1222,+1224,1223,1225,1225,1223,1226,1226,1227,1227,1228,1229,1229,1229,1226,1222,1221,+1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1223,1227,1223,1227,1226,1226,+196,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,+1231,1231,1231,1231,1231,196,196,196,196,196,196,196,196,196,196,196,++/* block 177 */+1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,+1232,1232,196,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,+1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1233,1233,1233,1234,+1234,1234,1233,1233,1234,1235,1236,1237,1238,1238,1239,1238,1238,1240,1234,1232,+1232,1234,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 178 */+1241,1241,1241,1241,1241,1241,1241,196,1241,196,1241,1241,1241,1241,196,1241,+1241,1241,1241,1241,1241,1241,1241,1241,1241,1241,1241,1241,1241,1241,196,1241,+1241,1241,1241,1241,1241,1241,1241,1241,1241,1242,196,196,196,196,196,196,+1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,+1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,+1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1243,1244,+1245,1245,1245,1244,1244,1244,1244,1244,1244,1246,1247,196,196,196,196,196,+1248,1248,1248,1248,1248,1248,1248,1248,1248,1248,196,196,196,196,196,196,++/* block 179 */+1249,1250,1251,1252,196,1253,1253,1253,1253,1253,1253,1253,1253,196,196,1253,+1253,196,196,1253,1253,1253,1253,1253,1253,1253,1253,1253,1253,1253,1253,1253,+1253,1253,1253,1253,1253,1253,1253,1253,1253,196,1253,1253,1253,1253,1253,1253,+1253,196,1253,1253,196,1253,1253,1253,1253,1253,196,1254,1255,1253,1256,1251,+1249,1251,1251,1251,1251,196,196,1251,1251,196,196,1251,1251,1257,196,196,+1253,196,196,196,196,196,196,1256,196,196,196,196,196,1258,1253,1253,+1253,1253,1251,1251,196,196,1259,1259,1259,1259,1259,1259,1259,196,196,196,+1259,1259,1259,1259,1259,196,196,196,196,196,196,196,196,196,196,196,++/* block 180 */+1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,196,1260,196,196,1260,196,+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,1260,1260,196,1260,1261,1262,1262,1263,1263,1263,1263,1263,+1263,196,1261,196,196,1261,196,1261,1261,1261,1262,196,1262,1262,1264,1265,+1264,1266,1267,1268,1269,1269,196,1270,1270,196,196,196,196,196,196,196,+196,1271,1271,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 181 */+1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,+1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,+1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,1272,+1272,1272,1272,1272,1272,1273,1273,1273,1274,1274,1274,1274,1274,1274,1274,1274,+1273,1273,1275,1274,1274,1273,1276,1272,1272,1272,1272,1277,1277,1278,1279,1279,+1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1278,1278,196,1279,1281,1272,+1272,1272,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 182 */+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,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,+1283,1284,1284,1285,1285,1285,1285,1285,1285,1284,1285,1284,1284,1283,1284,1285,+1285,1284,1286,1287,1282,1282,1288,1282,196,196,196,196,196,196,196,196,+1289,1289,1289,1289,1289,1289,1289,1289,1289,1289,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 183 */+1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,+1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,+1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1291,+1292,1292,1293,1293,1293,1293,196,196,1292,1292,1292,1292,1293,1293,1292,1294,+1295,1296,1297,1297,1298,1298,1299,1299,1299,1297,1297,1297,1297,1297,1297,1297,+1297,1297,1297,1297,1297,1297,1297,1297,1290,1290,1290,1290,1293,1293,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 184 */+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,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,1300,+1301,1301,1301,1302,1302,1302,1302,1302,1302,1302,1302,1301,1301,1302,1301,1303,+1302,1304,1304,1305,1300,196,196,196,196,196,196,196,196,196,196,196,+1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,196,196,196,196,196,196,+581,581,581,581,581,581,581,581,581,581,581,581,581,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 185 */+1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,+1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,+1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1307,1308,1309,1308,1309,1309,+1308,1308,1308,1308,1308,1308,1310,1311,1307,1312,196,196,196,196,196,196,+1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,196,196,196,196,196,196,+522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,+522,522,522,522,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 186 */+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,196,196,1315,1316,1315,+1317,1317,1315,1315,1315,1315,1316,1315,1315,1315,1315,1318,196,196,196,196,+1319,1319,1319,1319,1319,1319,1319,1319,1319,1319,1320,1320,1321,1321,1321,1322,+1314,1314,1314,1314,1314,1314,1314,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 187 */+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,1323,1323,+1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1323,1324,1324,1324,1325,+1325,1325,1325,1325,1325,1325,1325,1325,1324,1326,1327,1328,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 188 */+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,+1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,+1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,+1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,1330,+1331,1331,1331,1331,1331,1331,1331,1331,1331,1331,1332,1332,1332,1332,1332,1332,+1332,1332,1332,196,196,196,196,196,196,196,196,196,196,196,196,1333,++/* block 189 */+1334,1334,1334,1334,1334,1334,1334,196,196,1334,196,196,1334,1334,1334,1334,+1334,1334,1334,1334,196,1334,1334,196,1334,1334,1334,1334,1334,1334,1334,1334,+1334,1334,1334,1334,1334,1334,1334,1334,1334,1334,1334,1334,1334,1334,1334,1334,+1335,1336,1336,1336,1336,1336,196,1336,1336,196,196,1337,1337,1338,1339,1340,+1336,1340,1336,1341,1342,1343,1342,196,196,196,196,196,196,196,196,196,+1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 190 */+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+1345,1345,1345,1345,1345,1345,1345,1345,196,196,1345,1345,1345,1345,1345,1345,+1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,+1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,+1345,1346,1346,1346,1347,1347,1347,1347,196,196,1347,1347,1346,1346,1346,1346,+1348,1345,1349,1345,1346,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 191 */+1350,1351,1351,1351,1351,1351,1351,1352,1352,1351,1351,1350,1350,1350,1350,1350,+1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,+1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,1350,+1350,1350,1350,1353,1354,1351,1351,1351,1351,1355,1356,1351,1351,1351,1351,1357,+1357,1357,1358,1358,1357,1357,1357,1354,196,196,196,196,196,196,196,196,+1359,1360,1360,1360,1360,1360,1360,1361,1361,1360,1360,1360,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 192 */+1359,1359,1359,1359,1362,1362,1362,1362,1362,1362,1360,1360,1360,1360,1360,1360,+1360,1360,1360,1360,1360,1360,1360,1361,1363,1364,1365,1366,1366,1359,1365,1365,+1365,1367,1367,196,196,196,196,196,196,196,196,196,196,196,196,196,+545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,+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,1368,1368,1368,1368,1368,1368,1368,196,196,196,196,196,196,196,++/* block 193 */+385,385,385,385,385,385,385,385,385,385,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 194 */+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+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,1370,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+1371,1371,1371,1371,1371,1371,1371,1371,1371,1371,196,196,196,196,196,196,++/* block 195 */+1372,1372,1372,1372,1372,1372,1372,1372,1372,196,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,1372,1372,1372,1372,1372,1372,1372,1373,+1374,1374,1374,1374,1374,1374,1374,196,1374,1374,1374,1374,1374,1374,1373,1375,+1372,1376,1376,1377,1378,1378,196,196,196,196,196,196,196,196,196,196,+1379,1379,1379,1379,1379,1379,1379,1379,1379,1379,1380,1380,1380,1380,1380,1380,+1380,1380,1380,1380,1380,1380,1380,1380,1380,1380,1380,1380,1380,196,196,196,+1381,1382,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,++/* block 196 */+1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,1383,+196,196,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,1384,+1384,1384,1384,1384,1384,1384,1384,1384,196,1385,1384,1384,1384,1384,1384,1384,+1384,1385,1384,1384,1385,1384,1384,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 197 */+1386,1386,1386,1386,1386,1386,1386,196,1386,1386,196,1386,1386,1386,1386,1386,+1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,+1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,1386,+1386,1387,1387,1387,1387,1387,1387,196,196,196,1387,196,1387,1387,196,1387,+1387,1387,1388,1387,1389,1389,1390,1387,196,196,196,196,196,196,196,196,+1391,1391,1391,1391,1391,1391,1391,1391,1391,1391,196,196,196,196,196,196,+1392,1392,1392,1392,1392,1392,196,1392,1392,196,1392,1392,1392,1392,1392,1392,+1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,++/* block 198 */+1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1393,1393,1393,1393,1393,196,+1394,1394,196,1393,1393,1394,1393,1395,1392,196,196,196,196,196,196,196,+1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 199 */+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+1397,1397,1397,1397,1397,1397,1397,1397,1397,1397,1397,1397,1397,1397,1397,1397,+1397,1397,1397,1398,1398,1399,1399,1400,1400,196,196,196,196,196,196,196,++/* block 200 */+1401,1401,1402,1403,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,+1404,196,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,+1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,1404,+1404,1404,1404,1404,1403,1403,1401,1401,1401,1401,1401,196,196,196,1403,1403,+1401,1405,1406,1407,1407,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,+1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1410,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 201 */+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+914,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+1411,1411,1411,1411,1411,1411,1411,1411,1411,1411,1411,1411,1411,1411,1411,1411,+435,435,1411,435,1411,437,437,437,437,437,437,437,437,438,438,438,+438,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,+437,437,196,196,196,196,196,196,196,196,196,196,196,196,196,1412,++/* block 202 */+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,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,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,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,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 203 */+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,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 204 */+1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,+1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,+1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,+1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,+1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,+1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,+1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,1414,196,+1415,1415,1415,1415,1415,196,196,196,196,196,196,196,196,196,196,196,++/* block 205 */+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,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,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,1413,+1413,1413,1413,1413,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 206 */+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,+1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,+1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,+1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,+1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,+1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,1416,+1416,1417,1417,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 207 */+1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,+1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,+1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,+1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,+1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,+1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,+1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,+1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,++/* block 208 */+1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,+1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,+1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,+1419,1419,1419,1419,1419,1419,1419,1419,1419,1419,1419,1419,1419,1419,1419,1419,+1420,1418,1418,1418,1418,1418,1418,1421,1421,1421,1421,1421,1421,1421,1421,1421,+1421,1421,1421,1421,1421,1421,196,196,196,196,196,196,196,196,196,196,+1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,+1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,++/* block 209 */+1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,+1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,+1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,+1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,+1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,+1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,+1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,+1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,1418,196,196,196,196,196,++/* block 210 */+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,+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 211 */+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,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 212 */+1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,+1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1423,1424,1424,+1424,1424,1424,1424,1424,1424,1424,1424,1424,1424,1425,1425,1425,1424,1424,1426,+1427,1427,1427,1427,1427,1427,1427,1427,1427,1427,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 213 */+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,+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,+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,++/* block 214 */+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,+930,930,930,930,930,930,930,930,930,196,196,196,196,196,196,196,+1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,+1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,1428,196,+1429,1429,1429,1429,1429,1429,1429,1429,1429,1429,196,196,196,196,1430,1430,+1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,++/* block 215 */+1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,+1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,+1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,+1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,1431,196,+1432,1432,1432,1432,1432,1432,1432,1432,1432,1432,196,196,196,196,196,196,+1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,+1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,1433,196,196,+1434,1434,1434,1434,1434,1435,196,196,196,196,196,196,196,196,196,196,++/* block 216 */+1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,+1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,+1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,+1437,1437,1437,1437,1437,1437,1437,1438,1438,1439,1440,1440,1441,1441,1441,1441,+1442,1442,1443,1443,1438,1441,196,196,196,196,196,196,196,196,196,196,+1444,1444,1444,1444,1444,1444,1444,1444,1444,1444,196,1445,1445,1445,1445,1445,+1445,1445,196,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,+1436,1436,1436,1436,1436,1436,1436,1436,196,196,196,196,196,1436,1436,1436,++/* block 217 */+1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,1436,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 218 */+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+1446,1446,1446,1447,1447,1447,1447,1447,1447,1447,1447,1447,1447,1447,1447,1447,+1447,1447,1447,1447,1447,1447,1447,1447,1447,1447,1447,1447,1447,1447,1447,1447,+1447,1447,1447,1448,1447,1447,1447,1448,1448,1448,1448,1449,1449,1450,1451,1451,+1452,1452,1452,1452,1452,1452,1452,1452,1452,1452,196,196,196,196,196,196,++/* block 219 */+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,+1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,1453,+1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,+1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,1454,++/* block 220 */+1455,1455,1455,1455,1455,1455,1455,1455,1455,1455,1455,1455,1455,1455,1455,1455,+1455,1455,1455,1455,1455,1455,1455,1456,1457,1458,1458,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 221 */+1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,+1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,+1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,+1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,+1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,1459,196,196,196,196,1460,+1459,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,+1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,+1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,1461,++/* block 222 */+1461,1461,1461,1461,1461,1461,1461,1461,196,196,196,196,196,196,196,1462,+1462,1462,1462,1463,1463,1463,1463,1463,1463,1463,1463,1463,1463,1463,1463,1463,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+1464,1465,1466,867,1467,196,196,196,196,196,196,196,196,196,196,196,+1468,1468,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 223 */+1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,+1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,+1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,+1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,+1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,+1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,+1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,+1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,++/* block 224 */+1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,+1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,+1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,+1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,+1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,+1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,+1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,1469,+1469,1469,1469,1469,1469,1469,1469,1469,196,196,196,196,196,196,196,196,++/* block 225 */+1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,+1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,+1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,+1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,+1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,+1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,+1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,+1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,++/* block 226 */+1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,+1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,+1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,+1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,+1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,+1470,1470,1470,1470,1470,1470,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,1470,++/* block 227 */+1469,1469,1469,1469,1469,1469,1469,1469,1469,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 228 */+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+1471,1471,1471,1471,196,1471,1471,1471,1471,1471,1471,1471,196,1471,1471,196,++/* block 229 */+896,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,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,891,891,891,891,891,891,891,+891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,++/* block 230 */+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,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,891,891,891,891,891,891,891,891,+891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,++/* block 231 */+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,+896,896,896,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,891,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+891,891,891,196,196,896,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,896,896,896,896,196,196,196,196,196,196,196,196,+1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,++/* block 232 */+1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,+1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,+1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,+1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,+1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,+1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,+1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,+1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,++/* block 233 */+1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,+1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,+1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,+1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,+1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,+1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,+1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,+1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,1472,196,196,196,196,++/* block 234 */+1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,+1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,+1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,+1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,+1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,+1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,+1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,196,196,196,196,196,+1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,196,196,196,++/* block 235 */+1473,1473,1473,1473,1473,1473,1473,1473,1473,196,196,196,196,196,196,196,+1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,196,196,1474,1475,1476,1477,+1478,1478,1478,1478,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 236 */+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,++/* block 237 */+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+1479,1479,1479,1479,1479,1479,1479,1479,1479,1479,196,196,196,196,196,196,++/* block 238 */+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 239 */+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,+176,176,176,176,176,176,176,176,176,176,176,176,176,176,196,196,+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,+176,176,176,176,176,176,176,196,196,196,196,196,196,196,196,196,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,++/* block 240 */+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 241 */+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,++/* block 242 */+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,196,196,196,196,196,196,196,196,196,196,++/* block 243 */+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,196,196,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,1480,1480,176,176,176,510,510,510,1481,1481,1481,+1481,1481,1481, 51, 51, 51, 51, 51, 51, 51, 51,176,176,176,176,176,++/* block 244 */+176,176,176,510,510,176,176,176,176,176,176,176,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,176,176,176,176,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,781,781,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 245 */+1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,+1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,+1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,+1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,1077,+1077,1077,1482,1482,1482,1077,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 246 */+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,+907,907,907,907,196,196,196,196,196,196,196,196,196,196,196,196,+907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,+907,907,907,907,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 247 */+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,196,196,196,196,196,196,196,196,196,+904,904,904,904,904,904,904,904,904,904,904,904,904,904,904,904,+904,904,907,907,907,907,907,907,907,196,196,196,196,196,196,196,++/* block 248 */+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,783,783,783,783,783,783,+783,783,795,795,783,783,783,783,783,783,783,783,783,783,783,783,+783,783,783,783,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,783,783,+783,783,783,783,783,196,795,795,783,783,783,783,783,783,783,783,+783,783,783,783,783,783,783,783,782,782,782,782,782,782,782,782,+782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,++/* block 249 */+782,782,783,783,783,783,783,783,783,783,795,795,783,783,783,783,+783,783,783,783,783,783,783,783,783,783,783,783,782,196,782,782,+196,196,782,196,196,782,782,196,196,782,782,782,782,196,782,782,+782,782,782,782,782,782,783,783,783,783,196,783,196,783,795,795,+783,783,783,783,196,783,783,783,783,783,783,783,783,783,783,783,+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,783,783,783,783,783,783,+783,783,795,795,783,783,783,783,783,783,783,783,783,783,783,783,++/* block 250 */+783,783,783,783,782,782,196,782,782,782,782,196,196,782,782,782,+782,782,782,782,782,196,782,782,782,782,782,782,782,196,783,783,+783,783,783,783,783,783,795,795,783,783,783,783,783,783,783,783,+783,783,783,783,783,783,783,783,782,782,196,782,782,782,782,196,+782,782,782,782,782,196,782,196,196,196,782,782,782,782,782,782,+782,196,783,783,783,783,783,783,783,783,795,795,783,783,783,783,+783,783,783,783,783,783,783,783,783,783,783,783,782,782,782,782,+782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,++/* block 251 */+782,782,782,782,782,782,783,783,783,783,783,783,783,783,795,795,+783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,+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,783,783,783,783,783,783,+783,783,795,795,783,783,783,783,783,783,783,783,783,783,783,783,+783,783,783,783,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,783,783,+783,783,783,783,783,783,795,795,783,783,783,783,783,783,783,783,++/* block 252 */+783,783,783,783,783,783,783,783,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,783,783,783,783,783,783,783,783,795,795,783,783,783,783,+783,783,783,783,783,783,783,783,783,783,783,783,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,783,783,783,783,783,783,783,783,795,795,+783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,+782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,++/* block 253 */+782,782,782,782,782,782,782,782,782,782,783,783,783,783,783,783,+783,783,795,795,783,783,783,783,783,783,783,783,783,783,783,783,+783,783,783,783,783,783,196,196,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,1483,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,1483,783,783,783,783,+783,783,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,1483,783,783,783,783,++/* block 254 */+783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,+783,783,783,783,783,1483,783,783,783,783,783,783,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,1483,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,1483,+783,783,783,783,783,783,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,1483,+783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,++/* block 255 */+783,783,783,783,783,783,783,783,783,1483,783,783,783,783,783,783,+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,1483,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,1483,783,783,783,783,783,783,782,783,196,196,1484,1484,+1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,+1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,+1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,1484,++/* block 256 */+1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,+1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,+1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,+1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,+1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,+1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,+1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,+1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,++/* block 257 */+1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,+1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,+1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,+1486,1486,1486,1486,1486,1486,1486,1485,1485,1485,1485,1486,1486,1486,1486,1486,+1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,+1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,+1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1485,1485,1485,+1485,1485,1485,1485,1485,1486,1485,1485,1485,1485,1485,1485,1485,1485,1485,1485,++/* block 258 */+1485,1485,1485,1485,1486,1485,1485,1487,1488,1487,1487,1489,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,1486,1486,1486,1486,1486,+196,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,1486,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 259 */+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 93, 70, 70, 70, 70, 70,+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,694, 70, 70, 70, 70,196,+196,196,196,196,196, 70, 70, 70, 70, 70, 70,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 260 */+1490,1490,1490,1490,1490,1490,1490,196,1490,1490,1490,1490,1490,1490,1490,1490,+1490,1490,1490,1490,1490,1490,1490,1490,1490,196,196,1490,1490,1490,1490,1490,+1490,1490,196,1490,1490,196,1490,1490,1490,1490,1490,196,196,196,196,196,+929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,+929,929,929,929,929,929,929,929,929,929,929,929,1491,1491,929,929,+929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,+929,929,929,929,929,929,929,929,1491,929,929,929,929,929,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 261 */+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,849,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 262 */+1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,+1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,+1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,1492,196,196,196,+1493,1493,1493,1493,1493,1493,1493,1494,1494,1494,1494,1494,1495,1495,196,196,+1496,1496,1496,1496,1496,1496,1496,1496,1496,1496,196,196,196,196,1492,1497,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 263 */+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,+1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1498,1499,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,+1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,+1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1501,1501,1501,1501,+1502,1502,1502,1502,1502,1502,1502,1502,1502,1502,196,196,196,196,196,1503,++/* block 264 */+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+1504,1504,1504,1504,1504,1504,1504,1504,1504,1504,1504,1504,1504,1504,1504,1504,+1504,1504,1504,1504,1504,1504,1504,1504,1504,1504,1504,1505,1506,1506,1506,1506,+1507,1507,1507,1507,1507,1507,1507,1507,1507,1507,196,196,196,196,196,196,++/* block 265 */+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,+1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1508,1509,1510,+1508,1511,1511,1511,1511,1511,1511,1511,1511,1511,1511,196,196,196,196,1512,++/* block 266 */+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+533,533,533,533,533,533,533,196,533,533,533,533,196,533,533,196,+533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,196,++/* block 267 */+1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,+1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,+1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,+1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,+1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,+1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,+1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,+1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,++/* block 268 */+1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,+1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,+1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,+1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,1513,+1513,1513,1513,1513,1513,297,297,1514,1514,1514,1514,1514,1514,1514,1514,1514,+1515,1515,1515,1515,1515,1515,1515,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,++/* block 269 */+1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,+1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,1516,+1516,1516,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,+1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,1517,+1517,1517,1517,1517,1518,1518,1518,1519,1520,1520,1520,1521,297,297,297,297,+1522,1522,1522,1522,1522,1522,1522,1522,1522,1522,297,297,297,297,1523,1523,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,++/* block 270 */+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,++/* block 271 */+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+340,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,++/* block 272 */+1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,+1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,+1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1525,1524,1524,1524,+1526,1524,1524,1524,1524,340,340,340,340,340,340,340,340,340,340,340,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,++/* block 273 */+340,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,+1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,+1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1525,1524,+1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,1524,340,340,+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,+297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,++/* block 274 */+1527,1527,1527,1527,340,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,+1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,+340,1527,1527,340,1527,340,340,1527,340,1527,1527,1527,1527,1527,1527,1527,+1527,1527,1527,340,1527,1527,1527,1527,340,1527,340,1527,340,340,340,340,+340,340,1527,340,340,340,340,1527,340,1527,340,1527,340,1527,1527,1527,+340,1527,1527,340,1527,340,340,1527,340,1527,340,1527,340,1527,340,1527,+340,1527,1527,340,1527,340,340,1527,1527,1527,1527,340,1527,1527,1527,1527,+1527,1527,1527,340,1527,1527,1527,1527,340,1527,1527,1527,1527,340,1527,340,++/* block 275 */+1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,340,1527,1527,1527,1527,1527,+1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,340,340,340,340,+340,1527,1527,1527,340,1527,1527,1527,1527,1527,340,1527,1527,1527,1527,1527,+1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,1527,340,340,340,340,+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,+340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,+309,309,340,340,340,340,340,340,340,340,340,340,340,340,340,340,++/* block 276 */+1528,1528,1528,1528,1529,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,+1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,+1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1530,1530,1530,1530,+1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,+1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,+1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,+1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,+1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,++/* block 277 */+1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,+1528,1528,1528,1528,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1530,+1530,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,+1530,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1529,+1530,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,+1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,+1528,1528,1528,1528,1528,1528,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,++/* block 278 */+814,814,814,814,814,814,814,814,814,814,814, 58, 58,1528,1528,1528,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,1528,+1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,+1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,510,510,510,510,510,510,+1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,+1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,781,781,1528,1528,1528,1528,+1532,1532,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,1532,1532,++/* block 279 */+1531,1531,1531,1531,1531,1531,1531,1531,1531,1531,510,510,510,510,1533,510,+510,1533,1533,1533,1533,1533,1533,1533,1533,1533,1533,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,1528,1530,1530,+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1530,1530,1530,1530,1530,1530,1534,1534,1534,1534,1534,1534,1534,1534,1534,1534,+1534,1534,1534,1534,1534,1534,1534,1534,1534,1534,1534,1534,1534,1534,1534,1534,++/* block 280 */+1535,1533,1536,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+510,510,510,510,510,510,510,510,510,510,1533,510,510,510,510,510,+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,1533,+510,510,1533,1533,1533,1533,1533,1536,1533,1533,1533,510,1530,1530,1530,1530,+510,510,510,510,510,510,510,510,510,1530,1530,1530,1530,1530,1530,1530,+1537,1537,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1528,1528,1528,1528,1528,1528,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,++/* block 281 */+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,++/* block 282 */+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,785,1528,1528,785,785,785,785,785,785,785,785,785,1529,1529,1529,+1529,1529,1529,1529,1529,1529,785,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,785,1529,1529,++/* block 283 */+1529,1529,1529,1529,1529,1538,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1528,1528,785,785,1528,785,785,785,1528,1528,785,785,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1538,1538,1538,1529,1529,1538,1529,1529,1538,1539,1539,785,785,1529,+1529,1529,1529,1529,785,785,785,785,785,785,785,785,785,785,785,785,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1528,1528,785,1529,785,1528,785,1529,1529,1529,1540,1540,1540,1540,1540,++/* block 284 */+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,785,+1529,785,1538,1538,1529,1529,1538,1538,1538,1538,1538,1538,1538,1538,1538,1538,+1538,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1538,1538,1538,1538,1538,1538,1538,1538,1538,1538,+1538,1538,1538,1538,1538,1538,1538,1538,1538,1529,1529,1529,1538,1529,1529,1529,++/* block 285 */+1529,1538,1538,1538,1529,1538,1538,1538,1529,1529,1529,1529,1529,1529,1529,1538,+1529,1538,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1538,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,785,1528,1529,++/* block 286 */+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,781,781,+781,781,781,781,781,781,1528,1528,1528,785,785,1529,1529,1529,1529,1528,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1528,1528,1528,1528,1528,1528,1528,785,+785,1528,1528,785,1539,1539,785,785,785,785,1538,1528,1528,1528,1528,1528,++/* block 287 */+1528,1528,1528,1528,1528,1528,1528,785,1528,1528,785,785,785,785,1528,1528,+1539,1528,1528,1528,1528,1538,1538,1528,1528,1528,1528,1528,1528,1528,1528,1528,+1528,1528,1528,1528,1529,785,1528,1528,785,1528,1528,1528,1528,1528,1528,1528,+1528,785,785,1528,1528,1528,1528,1528,1528,1528,1528,1528,785,1528,1528,1528,+1528,1528,785,785,785,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,+1528,785,785,785,1528,1528,1528,1528,1528,1528,1528,1528,785,785,785,1528,+1528,785,1528,785,1528,1528,1528,1528,785,1528,1528,1528,1528,1528,1528,785,+1528,1528,1528,785,1528,1528,1528,1528,1528,1528,785,1529,1529,1529,1529,1529,++/* block 288 */+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1538,1538,1538,1529,1529,1529,1538,1538,1538,1538,1538,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,++/* block 289 */+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1538,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1538,1538,1538,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1538,1529,1529,1529,1529,1529,1528,1528,1528,1528,1528,785,1538,785,785,785,+1529,1529,1529,1528,1528,1529,1529,1529,1530,1530,1530,1530,1529,1529,1529,1529,+785,785,785,785,785,785,1528,1528,1528,785,1528,1529,1529,1530,1530,1530,+785,1528,1528,785,1529,1529,1529,1529,1529,1529,1529,1529,1529,1530,1530,1530,++/* block 290 */+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,1528,1528,1528,1530,1530,1530,1530,1528,1528,1528,1528,1528,++/* block 291 */+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,1528,1528,1528,1528,1528,1530,1530,1530,1530,1530,1530,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1530,1530,1530,1530,+1529,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,++/* block 292 */+781,781,781,781,781,781,781,781,781,781,781,781,1530,1530,1530,1530,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,1530,1530,1530,1530,1530,1530,1530,1530,+781,781,781,781,781,781,781,781,781,781,1530,1530,1530,1530,1530,1530,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,++/* block 293 */+781,781,781,781,781,781,781,781,1530,1530,1530,1530,1530,1530,1530,1530,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,1530,1530,+1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1530,1530,1530,1530,+1528,1528,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,++/* block 294 */+781,781,781,781,781,781,781,781,781,781,781,781,1538,1529,1529,1538,+1529,1529,1529,1529,1529,1529,1529,1529,1538,1538,1538,1538,1538,1538,1538,1538,+1529,1529,1529,1529,1529,1529,1538,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1538,1538,1538,1538,1538,1538,1538,1538,1538,1538,1529,781,1538,1538,1538,1529,+1529,1529,1529,1529,1529,1529,781,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1538,1529,1529,1529,1529,1529,1529,1529,1529,++/* block 295 */+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1541,1541,1541,1541,1529,1538,1538,1529,1538,1538,1529,1538,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1538,1538,1538,+1529,1538,1538,1538,1538,1538,1538,1538,1538,1538,1538,1538,1538,1538,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,++/* block 296 */+1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,+1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,+1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,+1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,+1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,+1528,1528,1528,1528,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1528,1530,1530,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1530,1530,1530,++/* block 297 */+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1530,1530,1530,1530,1530,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,+1529,1529,1529,1538,1538,1538,1529,1530,1530,1530,1530,1530,1530,1530,1529,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1530,1530,1529,+1529,1529,1529,1529,1529,1529,1529,1529,1529,1529,1530,1530,1530,1530,1530,1530,+1538,1538,1538,1538,1538,1538,1538,1538,1538,1530,1530,1530,1530,1530,1530,1530,++/* block 298 */+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,196,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,+1479,1479,1479,1479,1479,1479,1479,1479,1479,1479,196,196,196,196,196,196,++/* block 299 */+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,+1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1530,1032,1032,++/* block 300 */+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 301 */+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,196,196,196,196,196,196,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,++/* block 302 */+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,196,196,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,++/* block 303 */+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,++/* block 304 */+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,++/* block 305 */+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 306 */+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,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 307 */+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,1032,1032,++/* block 308 */+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,196,196,196,196,196,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,++/* block 309 */+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,910,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,++/* block 310 */+765,770,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,+1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,+1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,+1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,+1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,+1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,+1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,1542,++/* block 311 */+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,+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,+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,++/* block 312 */+1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,+1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,+1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,+1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,+1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,+1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,+1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,+1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,++/* block 313 */+1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,+1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,+1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,+1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,+1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,+1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,+1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,1035,+765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,++/* block 314 */+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,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,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,1024,1024,1024,1024,+1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1032,1032, }; #if UCD_BLOCK_SIZE != 128
src/c/pcre2/src/pcre2_ucp.h view
@@ -132,13 +132,18 @@ ucp_Hex_Digit, ucp_IDS_Binary_Operator, ucp_IDS_Trinary_Operator,+ ucp_IDS_Unary_Operator,+ ucp_ID_Compat_Math_Continue,+ ucp_ID_Compat_Math_Start, ucp_ID_Continue, ucp_ID_Start, ucp_Ideographic,+ ucp_InCB, ucp_Join_Control, ucp_Logical_Order_Exception, ucp_Lowercase, ucp_Math,+ ucp_Modifier_Combining_Mark, ucp_Noncharacter_Code_Point, ucp_Pattern_Syntax, ucp_Pattern_White_Space,@@ -219,6 +224,8 @@ ucp_Latin, ucp_Greek, ucp_Cyrillic,+ ucp_Armenian,+ ucp_Hebrew, ucp_Arabic, ucp_Syriac, ucp_Thaana,@@ -232,15 +239,21 @@ ucp_Kannada, ucp_Malayalam, ucp_Sinhala,+ ucp_Thai,+ ucp_Tibetan, ucp_Myanmar, ucp_Georgian, ucp_Hangul,+ ucp_Ethiopic,+ ucp_Cherokee,+ ucp_Runic, ucp_Mongolian, ucp_Hiragana, ucp_Katakana, ucp_Bopomofo, ucp_Han, ucp_Yi,+ ucp_Gothic, ucp_Tagalog, ucp_Hanunoo, ucp_Buhid,@@ -248,21 +261,33 @@ ucp_Limbu, ucp_Tai_Le, ucp_Linear_B,+ ucp_Shavian, ucp_Cypriot, ucp_Buginese, ucp_Coptic, ucp_Glagolitic,+ ucp_Tifinagh, ucp_Syloti_Nagri, ucp_Phags_Pa, ucp_Nko, ucp_Kayah_Li,+ ucp_Lycian,+ ucp_Carian,+ ucp_Lydian,+ ucp_Avestan,+ ucp_Samaritan,+ ucp_Lisu, ucp_Javanese,+ ucp_Old_Turkic, ucp_Kaithi, ucp_Mandaic, ucp_Chakma,+ ucp_Meroitic_Hieroglyphs, ucp_Sharada, ucp_Takri,+ ucp_Caucasian_Albanian, ucp_Duployan,+ ucp_Elbasan, ucp_Grantha, ucp_Khojki, ucp_Linear_A,@@ -274,7 +299,10 @@ ucp_Khudawadi, ucp_Tirhuta, ucp_Multani,+ ucp_Old_Hungarian, ucp_Adlam,+ ucp_Osage,+ ucp_Tangut, ucp_Masaram_Gondi, ucp_Dogra, ucp_Gunjala_Gondi,@@ -284,31 +312,28 @@ ucp_Yezidi, ucp_Cypro_Minoan, ucp_Old_Uyghur,+ ucp_Toto,+ ucp_Garay,+ ucp_Gurung_Khema,+ ucp_Ol_Onal,+ ucp_Sunuwar,+ ucp_Todhri,+ ucp_Tulu_Tigalari, /* Scripts which has no characters in other scripts. */ ucp_Unknown, ucp_Common,- ucp_Armenian,- ucp_Hebrew,- ucp_Thai, ucp_Lao,- ucp_Tibetan,- ucp_Ethiopic,- ucp_Cherokee, ucp_Canadian_Aboriginal, ucp_Ogham,- ucp_Runic, ucp_Khmer, ucp_Old_Italic,- ucp_Gothic, ucp_Deseret, ucp_Inherited, ucp_Ugaritic,- ucp_Shavian, ucp_Osmanya, ucp_Braille, ucp_New_Tai_Lue,- ucp_Tifinagh, ucp_Old_Persian, ucp_Kharoshthi, ucp_Balinese,@@ -320,32 +345,22 @@ ucp_Vai, ucp_Saurashtra, ucp_Rejang,- ucp_Lycian,- ucp_Carian,- ucp_Lydian, ucp_Cham, ucp_Tai_Tham, ucp_Tai_Viet,- ucp_Avestan, ucp_Egyptian_Hieroglyphs,- ucp_Samaritan,- ucp_Lisu, ucp_Bamum, ucp_Meetei_Mayek, ucp_Imperial_Aramaic, ucp_Old_South_Arabian, ucp_Inscriptional_Parthian, ucp_Inscriptional_Pahlavi,- ucp_Old_Turkic, ucp_Batak, ucp_Brahmi, ucp_Meroitic_Cursive,- ucp_Meroitic_Hieroglyphs, ucp_Miao, ucp_Sora_Sompeng,- ucp_Caucasian_Albanian, ucp_Bassa_Vah,- ucp_Elbasan, ucp_Pahawh_Hmong, ucp_Mende_Kikakui, ucp_Mro,@@ -358,13 +373,10 @@ ucp_Ahom, ucp_Anatolian_Hieroglyphs, ucp_Hatran,- ucp_Old_Hungarian, ucp_SignWriting, ucp_Bhaiksuki, ucp_Marchen, ucp_Newa,- ucp_Osage,- ucp_Tangut, ucp_Nushu, ucp_Soyombo, ucp_Zanabazar_Square,@@ -378,10 +390,10 @@ ucp_Dives_Akuru, ucp_Khitan_Small_Script, ucp_Tangsa,- ucp_Toto, ucp_Vithkuqi, ucp_Kawi, ucp_Nag_Mundari,+ ucp_Kirat_Rai, /* This must be last */ ucp_Script_Count@@ -389,7 +401,7 @@ /* Size of entries in ucd_script_sets[] */ -#define ucd_script_sets_item_size 3+#define ucd_script_sets_item_size 4 #endif /* PCRE2_UCP_H_IDEMPOTENT_GUARD */
− src/c/pcre2/src/pcre2_ucptables.c
@@ -1,1533 +0,0 @@-/*************************************************-* 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- Original API code Copyright (c) 1997-2012 University of Cambridge- New API code Copyright (c) 2016-2022 University of Cambridge--This module is auto-generated from Unicode data files. DO NOT EDIT MANUALLY!-Instead, modify the maint/GenerateUcpTables.py script and run it to generate-a new version of this code.--------------------------------------------------------------------------------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 SUPPORT_UNICODE--/* The PRIV(utt)[] table below translates Unicode property names into type and-code values. It is searched by binary chop, so must be in collating sequence of-name. Originally, the table contained pointers to the name strings in the first-field of each entry. However, that leads to a large number of relocations when-a shared library is dynamically loaded. A significant reduction is made by-putting all the names into a single, large string and using offsets instead.-All letters are lower cased, and underscores are removed, in accordance with-the "loose matching" rules that Unicode advises and Perl uses. */--#define STRING_adlam0 STR_a STR_d STR_l STR_a STR_m "\0"-#define STRING_adlm0 STR_a STR_d STR_l STR_m "\0"-#define STRING_aghb0 STR_a STR_g STR_h STR_b "\0"-#define STRING_ahex0 STR_a STR_h STR_e STR_x "\0"-#define STRING_ahom0 STR_a STR_h STR_o STR_m "\0"-#define STRING_alpha0 STR_a STR_l STR_p STR_h STR_a "\0"-#define STRING_alphabetic0 STR_a STR_l STR_p STR_h STR_a STR_b STR_e STR_t STR_i STR_c "\0"-#define STRING_anatolianhieroglyphs0 STR_a STR_n STR_a STR_t STR_o STR_l STR_i STR_a STR_n STR_h STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"-#define STRING_any0 STR_a STR_n STR_y "\0"-#define STRING_arab0 STR_a STR_r STR_a STR_b "\0"-#define STRING_arabic0 STR_a STR_r STR_a STR_b STR_i STR_c "\0"-#define STRING_armenian0 STR_a STR_r STR_m STR_e STR_n STR_i STR_a STR_n "\0"-#define STRING_armi0 STR_a STR_r STR_m STR_i "\0"-#define STRING_armn0 STR_a STR_r STR_m STR_n "\0"-#define STRING_ascii0 STR_a STR_s STR_c STR_i STR_i "\0"-#define STRING_asciihexdigit0 STR_a STR_s STR_c STR_i STR_i STR_h STR_e STR_x STR_d STR_i STR_g STR_i STR_t "\0"-#define STRING_avestan0 STR_a STR_v STR_e STR_s STR_t STR_a STR_n "\0"-#define STRING_avst0 STR_a STR_v STR_s STR_t "\0"-#define STRING_bali0 STR_b STR_a STR_l STR_i "\0"-#define STRING_balinese0 STR_b STR_a STR_l STR_i STR_n STR_e STR_s STR_e "\0"-#define STRING_bamu0 STR_b STR_a STR_m STR_u "\0"-#define STRING_bamum0 STR_b STR_a STR_m STR_u STR_m "\0"-#define STRING_bass0 STR_b STR_a STR_s STR_s "\0"-#define STRING_bassavah0 STR_b STR_a STR_s STR_s STR_a STR_v STR_a STR_h "\0"-#define STRING_batak0 STR_b STR_a STR_t STR_a STR_k "\0"-#define STRING_batk0 STR_b STR_a STR_t STR_k "\0"-#define STRING_beng0 STR_b STR_e STR_n STR_g "\0"-#define STRING_bengali0 STR_b STR_e STR_n STR_g STR_a STR_l STR_i "\0"-#define STRING_bhaiksuki0 STR_b STR_h STR_a STR_i STR_k STR_s STR_u STR_k STR_i "\0"-#define STRING_bhks0 STR_b STR_h STR_k STR_s "\0"-#define STRING_bidial0 STR_b STR_i STR_d STR_i STR_a STR_l "\0"-#define STRING_bidian0 STR_b STR_i STR_d STR_i STR_a STR_n "\0"-#define STRING_bidib0 STR_b STR_i STR_d STR_i STR_b "\0"-#define STRING_bidibn0 STR_b STR_i STR_d STR_i STR_b STR_n "\0"-#define STRING_bidic0 STR_b STR_i STR_d STR_i STR_c "\0"-#define STRING_bidicontrol0 STR_b STR_i STR_d STR_i STR_c STR_o STR_n STR_t STR_r STR_o STR_l "\0"-#define STRING_bidics0 STR_b STR_i STR_d STR_i STR_c STR_s "\0"-#define STRING_bidien0 STR_b STR_i STR_d STR_i STR_e STR_n "\0"-#define STRING_bidies0 STR_b STR_i STR_d STR_i STR_e STR_s "\0"-#define STRING_bidiet0 STR_b STR_i STR_d STR_i STR_e STR_t "\0"-#define STRING_bidifsi0 STR_b STR_i STR_d STR_i STR_f STR_s STR_i "\0"-#define STRING_bidil0 STR_b STR_i STR_d STR_i STR_l "\0"-#define STRING_bidilre0 STR_b STR_i STR_d STR_i STR_l STR_r STR_e "\0"-#define STRING_bidilri0 STR_b STR_i STR_d STR_i STR_l STR_r STR_i "\0"-#define STRING_bidilro0 STR_b STR_i STR_d STR_i STR_l STR_r STR_o "\0"-#define STRING_bidim0 STR_b STR_i STR_d STR_i STR_m "\0"-#define STRING_bidimirrored0 STR_b STR_i STR_d STR_i STR_m STR_i STR_r STR_r STR_o STR_r STR_e STR_d "\0"-#define STRING_bidinsm0 STR_b STR_i STR_d STR_i STR_n STR_s STR_m "\0"-#define STRING_bidion0 STR_b STR_i STR_d STR_i STR_o STR_n "\0"-#define STRING_bidipdf0 STR_b STR_i STR_d STR_i STR_p STR_d STR_f "\0"-#define STRING_bidipdi0 STR_b STR_i STR_d STR_i STR_p STR_d STR_i "\0"-#define STRING_bidir0 STR_b STR_i STR_d STR_i STR_r "\0"-#define STRING_bidirle0 STR_b STR_i STR_d STR_i STR_r STR_l STR_e "\0"-#define STRING_bidirli0 STR_b STR_i STR_d STR_i STR_r STR_l STR_i "\0"-#define STRING_bidirlo0 STR_b STR_i STR_d STR_i STR_r STR_l STR_o "\0"-#define STRING_bidis0 STR_b STR_i STR_d STR_i STR_s "\0"-#define STRING_bidiws0 STR_b STR_i STR_d STR_i STR_w STR_s "\0"-#define STRING_bopo0 STR_b STR_o STR_p STR_o "\0"-#define STRING_bopomofo0 STR_b STR_o STR_p STR_o STR_m STR_o STR_f STR_o "\0"-#define STRING_brah0 STR_b STR_r STR_a STR_h "\0"-#define STRING_brahmi0 STR_b STR_r STR_a STR_h STR_m STR_i "\0"-#define STRING_brai0 STR_b STR_r STR_a STR_i "\0"-#define STRING_braille0 STR_b STR_r STR_a STR_i STR_l STR_l STR_e "\0"-#define STRING_bugi0 STR_b STR_u STR_g STR_i "\0"-#define STRING_buginese0 STR_b STR_u STR_g STR_i STR_n STR_e STR_s STR_e "\0"-#define STRING_buhd0 STR_b STR_u STR_h STR_d "\0"-#define STRING_buhid0 STR_b STR_u STR_h STR_i STR_d "\0"-#define STRING_c0 STR_c "\0"-#define STRING_cakm0 STR_c STR_a STR_k STR_m "\0"-#define STRING_canadianaboriginal0 STR_c STR_a STR_n STR_a STR_d STR_i STR_a STR_n STR_a STR_b STR_o STR_r STR_i STR_g STR_i STR_n STR_a STR_l "\0"-#define STRING_cans0 STR_c STR_a STR_n STR_s "\0"-#define STRING_cari0 STR_c STR_a STR_r STR_i "\0"-#define STRING_carian0 STR_c STR_a STR_r STR_i STR_a STR_n "\0"-#define STRING_cased0 STR_c STR_a STR_s STR_e STR_d "\0"-#define STRING_caseignorable0 STR_c STR_a STR_s STR_e STR_i STR_g STR_n STR_o STR_r STR_a STR_b STR_l STR_e "\0"-#define STRING_caucasianalbanian0 STR_c STR_a STR_u STR_c STR_a STR_s STR_i STR_a STR_n STR_a STR_l STR_b STR_a STR_n STR_i STR_a STR_n "\0"-#define STRING_cc0 STR_c STR_c "\0"-#define STRING_cf0 STR_c STR_f "\0"-#define STRING_chakma0 STR_c STR_h STR_a STR_k STR_m STR_a "\0"-#define STRING_cham0 STR_c STR_h STR_a STR_m "\0"-#define STRING_changeswhencasefolded0 STR_c STR_h STR_a STR_n STR_g STR_e STR_s STR_w STR_h STR_e STR_n STR_c STR_a STR_s STR_e STR_f STR_o STR_l STR_d STR_e STR_d "\0"-#define STRING_changeswhencasemapped0 STR_c STR_h STR_a STR_n STR_g STR_e STR_s STR_w STR_h STR_e STR_n STR_c STR_a STR_s STR_e STR_m STR_a STR_p STR_p STR_e STR_d "\0"-#define STRING_changeswhenlowercased0 STR_c STR_h STR_a STR_n STR_g STR_e STR_s STR_w STR_h STR_e STR_n STR_l STR_o STR_w STR_e STR_r STR_c STR_a STR_s STR_e STR_d "\0"-#define STRING_changeswhentitlecased0 STR_c STR_h STR_a STR_n STR_g STR_e STR_s STR_w STR_h STR_e STR_n STR_t STR_i STR_t STR_l STR_e STR_c STR_a STR_s STR_e STR_d "\0"-#define STRING_changeswhenuppercased0 STR_c STR_h STR_a STR_n STR_g STR_e STR_s STR_w STR_h STR_e STR_n STR_u STR_p STR_p STR_e STR_r STR_c STR_a STR_s STR_e STR_d "\0"-#define STRING_cher0 STR_c STR_h STR_e STR_r "\0"-#define STRING_cherokee0 STR_c STR_h STR_e STR_r STR_o STR_k STR_e STR_e "\0"-#define STRING_chorasmian0 STR_c STR_h STR_o STR_r STR_a STR_s STR_m STR_i STR_a STR_n "\0"-#define STRING_chrs0 STR_c STR_h STR_r STR_s "\0"-#define STRING_ci0 STR_c STR_i "\0"-#define STRING_cn0 STR_c STR_n "\0"-#define STRING_co0 STR_c STR_o "\0"-#define STRING_common0 STR_c STR_o STR_m STR_m STR_o STR_n "\0"-#define STRING_copt0 STR_c STR_o STR_p STR_t "\0"-#define STRING_coptic0 STR_c STR_o STR_p STR_t STR_i STR_c "\0"-#define STRING_cpmn0 STR_c STR_p STR_m STR_n "\0"-#define STRING_cprt0 STR_c STR_p STR_r STR_t "\0"-#define STRING_cs0 STR_c STR_s "\0"-#define STRING_cuneiform0 STR_c STR_u STR_n STR_e STR_i STR_f STR_o STR_r STR_m "\0"-#define STRING_cwcf0 STR_c STR_w STR_c STR_f "\0"-#define STRING_cwcm0 STR_c STR_w STR_c STR_m "\0"-#define STRING_cwl0 STR_c STR_w STR_l "\0"-#define STRING_cwt0 STR_c STR_w STR_t "\0"-#define STRING_cwu0 STR_c STR_w STR_u "\0"-#define STRING_cypriot0 STR_c STR_y STR_p STR_r STR_i STR_o STR_t "\0"-#define STRING_cyprominoan0 STR_c STR_y STR_p STR_r STR_o STR_m STR_i STR_n STR_o STR_a STR_n "\0"-#define STRING_cyrillic0 STR_c STR_y STR_r STR_i STR_l STR_l STR_i STR_c "\0"-#define STRING_cyrl0 STR_c STR_y STR_r STR_l "\0"-#define STRING_dash0 STR_d STR_a STR_s STR_h "\0"-#define STRING_defaultignorablecodepoint0 STR_d STR_e STR_f STR_a STR_u STR_l STR_t STR_i STR_g STR_n STR_o STR_r STR_a STR_b STR_l STR_e STR_c STR_o STR_d STR_e STR_p STR_o STR_i STR_n STR_t "\0"-#define STRING_dep0 STR_d STR_e STR_p "\0"-#define STRING_deprecated0 STR_d STR_e STR_p STR_r STR_e STR_c STR_a STR_t STR_e STR_d "\0"-#define STRING_deseret0 STR_d STR_e STR_s STR_e STR_r STR_e STR_t "\0"-#define STRING_deva0 STR_d STR_e STR_v STR_a "\0"-#define STRING_devanagari0 STR_d STR_e STR_v STR_a STR_n STR_a STR_g STR_a STR_r STR_i "\0"-#define STRING_di0 STR_d STR_i "\0"-#define STRING_dia0 STR_d STR_i STR_a "\0"-#define STRING_diacritic0 STR_d STR_i STR_a STR_c STR_r STR_i STR_t STR_i STR_c "\0"-#define STRING_diak0 STR_d STR_i STR_a STR_k "\0"-#define STRING_divesakuru0 STR_d STR_i STR_v STR_e STR_s STR_a STR_k STR_u STR_r STR_u "\0"-#define STRING_dogr0 STR_d STR_o STR_g STR_r "\0"-#define STRING_dogra0 STR_d STR_o STR_g STR_r STR_a "\0"-#define STRING_dsrt0 STR_d STR_s STR_r STR_t "\0"-#define STRING_dupl0 STR_d STR_u STR_p STR_l "\0"-#define STRING_duployan0 STR_d STR_u STR_p STR_l STR_o STR_y STR_a STR_n "\0"-#define STRING_ebase0 STR_e STR_b STR_a STR_s STR_e "\0"-#define STRING_ecomp0 STR_e STR_c STR_o STR_m STR_p "\0"-#define STRING_egyp0 STR_e STR_g STR_y STR_p "\0"-#define STRING_egyptianhieroglyphs0 STR_e STR_g STR_y STR_p STR_t STR_i STR_a STR_n STR_h STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"-#define STRING_elba0 STR_e STR_l STR_b STR_a "\0"-#define STRING_elbasan0 STR_e STR_l STR_b STR_a STR_s STR_a STR_n "\0"-#define STRING_elym0 STR_e STR_l STR_y STR_m "\0"-#define STRING_elymaic0 STR_e STR_l STR_y STR_m STR_a STR_i STR_c "\0"-#define STRING_emod0 STR_e STR_m STR_o STR_d "\0"-#define STRING_emoji0 STR_e STR_m STR_o STR_j STR_i "\0"-#define STRING_emojicomponent0 STR_e STR_m STR_o STR_j STR_i STR_c STR_o STR_m STR_p STR_o STR_n STR_e STR_n STR_t "\0"-#define STRING_emojimodifier0 STR_e STR_m STR_o STR_j STR_i STR_m STR_o STR_d STR_i STR_f STR_i STR_e STR_r "\0"-#define STRING_emojimodifierbase0 STR_e STR_m STR_o STR_j STR_i STR_m STR_o STR_d STR_i STR_f STR_i STR_e STR_r STR_b STR_a STR_s STR_e "\0"-#define STRING_emojipresentation0 STR_e STR_m STR_o STR_j STR_i STR_p STR_r STR_e STR_s STR_e STR_n STR_t STR_a STR_t STR_i STR_o STR_n "\0"-#define STRING_epres0 STR_e STR_p STR_r STR_e STR_s "\0"-#define STRING_ethi0 STR_e STR_t STR_h STR_i "\0"-#define STRING_ethiopic0 STR_e STR_t STR_h STR_i STR_o STR_p STR_i STR_c "\0"-#define STRING_ext0 STR_e STR_x STR_t "\0"-#define STRING_extendedpictographic0 STR_e STR_x STR_t STR_e STR_n STR_d STR_e STR_d STR_p STR_i STR_c STR_t STR_o STR_g STR_r STR_a STR_p STR_h STR_i STR_c "\0"-#define STRING_extender0 STR_e STR_x STR_t STR_e STR_n STR_d STR_e STR_r "\0"-#define STRING_extpict0 STR_e STR_x STR_t STR_p STR_i STR_c STR_t "\0"-#define STRING_geor0 STR_g STR_e STR_o STR_r "\0"-#define STRING_georgian0 STR_g STR_e STR_o STR_r STR_g STR_i STR_a STR_n "\0"-#define STRING_glag0 STR_g STR_l STR_a STR_g "\0"-#define STRING_glagolitic0 STR_g STR_l STR_a STR_g STR_o STR_l STR_i STR_t STR_i STR_c "\0"-#define STRING_gong0 STR_g STR_o STR_n STR_g "\0"-#define STRING_gonm0 STR_g STR_o STR_n STR_m "\0"-#define STRING_goth0 STR_g STR_o STR_t STR_h "\0"-#define STRING_gothic0 STR_g STR_o STR_t STR_h STR_i STR_c "\0"-#define STRING_gran0 STR_g STR_r STR_a STR_n "\0"-#define STRING_grantha0 STR_g STR_r STR_a STR_n STR_t STR_h STR_a "\0"-#define STRING_graphemebase0 STR_g STR_r STR_a STR_p STR_h STR_e STR_m STR_e STR_b STR_a STR_s STR_e "\0"-#define STRING_graphemeextend0 STR_g STR_r STR_a STR_p STR_h STR_e STR_m STR_e STR_e STR_x STR_t STR_e STR_n STR_d "\0"-#define STRING_graphemelink0 STR_g STR_r STR_a STR_p STR_h STR_e STR_m STR_e STR_l STR_i STR_n STR_k "\0"-#define STRING_grbase0 STR_g STR_r STR_b STR_a STR_s STR_e "\0"-#define STRING_greek0 STR_g STR_r STR_e STR_e STR_k "\0"-#define STRING_grek0 STR_g STR_r STR_e STR_k "\0"-#define STRING_grext0 STR_g STR_r STR_e STR_x STR_t "\0"-#define STRING_grlink0 STR_g STR_r STR_l STR_i STR_n STR_k "\0"-#define STRING_gujarati0 STR_g STR_u STR_j STR_a STR_r STR_a STR_t STR_i "\0"-#define STRING_gujr0 STR_g STR_u STR_j STR_r "\0"-#define STRING_gunjalagondi0 STR_g STR_u STR_n STR_j STR_a STR_l STR_a STR_g STR_o STR_n STR_d STR_i "\0"-#define STRING_gurmukhi0 STR_g STR_u STR_r STR_m STR_u STR_k STR_h STR_i "\0"-#define STRING_guru0 STR_g STR_u STR_r STR_u "\0"-#define STRING_han0 STR_h STR_a STR_n "\0"-#define STRING_hang0 STR_h STR_a STR_n STR_g "\0"-#define STRING_hangul0 STR_h STR_a STR_n STR_g STR_u STR_l "\0"-#define STRING_hani0 STR_h STR_a STR_n STR_i "\0"-#define STRING_hanifirohingya0 STR_h STR_a STR_n STR_i STR_f STR_i STR_r STR_o STR_h STR_i STR_n STR_g STR_y STR_a "\0"-#define STRING_hano0 STR_h STR_a STR_n STR_o "\0"-#define STRING_hanunoo0 STR_h STR_a STR_n STR_u STR_n STR_o STR_o "\0"-#define STRING_hatr0 STR_h STR_a STR_t STR_r "\0"-#define STRING_hatran0 STR_h STR_a STR_t STR_r STR_a STR_n "\0"-#define STRING_hebr0 STR_h STR_e STR_b STR_r "\0"-#define STRING_hebrew0 STR_h STR_e STR_b STR_r STR_e STR_w "\0"-#define STRING_hex0 STR_h STR_e STR_x "\0"-#define STRING_hexdigit0 STR_h STR_e STR_x STR_d STR_i STR_g STR_i STR_t "\0"-#define STRING_hira0 STR_h STR_i STR_r STR_a "\0"-#define STRING_hiragana0 STR_h STR_i STR_r STR_a STR_g STR_a STR_n STR_a "\0"-#define STRING_hluw0 STR_h STR_l STR_u STR_w "\0"-#define STRING_hmng0 STR_h STR_m STR_n STR_g "\0"-#define STRING_hmnp0 STR_h STR_m STR_n STR_p "\0"-#define STRING_hung0 STR_h STR_u STR_n STR_g "\0"-#define STRING_idc0 STR_i STR_d STR_c "\0"-#define STRING_idcontinue0 STR_i STR_d STR_c STR_o STR_n STR_t STR_i STR_n STR_u STR_e "\0"-#define STRING_ideo0 STR_i STR_d STR_e STR_o "\0"-#define STRING_ideographic0 STR_i STR_d STR_e STR_o STR_g STR_r STR_a STR_p STR_h STR_i STR_c "\0"-#define STRING_ids0 STR_i STR_d STR_s "\0"-#define STRING_idsb0 STR_i STR_d STR_s STR_b "\0"-#define STRING_idsbinaryoperator0 STR_i STR_d STR_s STR_b STR_i STR_n STR_a STR_r STR_y STR_o STR_p STR_e STR_r STR_a STR_t STR_o STR_r "\0"-#define STRING_idst0 STR_i STR_d STR_s STR_t "\0"-#define STRING_idstart0 STR_i STR_d STR_s STR_t STR_a STR_r STR_t "\0"-#define STRING_idstrinaryoperator0 STR_i STR_d STR_s STR_t STR_r STR_i STR_n STR_a STR_r STR_y STR_o STR_p STR_e STR_r STR_a STR_t STR_o STR_r "\0"-#define STRING_imperialaramaic0 STR_i STR_m STR_p STR_e STR_r STR_i STR_a STR_l STR_a STR_r STR_a STR_m STR_a STR_i STR_c "\0"-#define STRING_inherited0 STR_i STR_n STR_h STR_e STR_r STR_i STR_t STR_e STR_d "\0"-#define STRING_inscriptionalpahlavi0 STR_i STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_p STR_a STR_h STR_l STR_a STR_v STR_i "\0"-#define STRING_inscriptionalparthian0 STR_i STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_p STR_a STR_r STR_t STR_h STR_i STR_a STR_n "\0"-#define STRING_ital0 STR_i STR_t STR_a STR_l "\0"-#define STRING_java0 STR_j STR_a STR_v STR_a "\0"-#define STRING_javanese0 STR_j STR_a STR_v STR_a STR_n STR_e STR_s STR_e "\0"-#define STRING_joinc0 STR_j STR_o STR_i STR_n STR_c "\0"-#define STRING_joincontrol0 STR_j STR_o STR_i STR_n STR_c STR_o STR_n STR_t STR_r STR_o STR_l "\0"-#define STRING_kaithi0 STR_k STR_a STR_i STR_t STR_h STR_i "\0"-#define STRING_kali0 STR_k STR_a STR_l STR_i "\0"-#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"-#define STRING_khitansmallscript0 STR_k STR_h STR_i STR_t STR_a STR_n STR_s STR_m STR_a STR_l STR_l STR_s STR_c STR_r STR_i STR_p STR_t "\0"-#define STRING_khmer0 STR_k STR_h STR_m STR_e STR_r "\0"-#define STRING_khmr0 STR_k STR_h STR_m STR_r "\0"-#define STRING_khoj0 STR_k STR_h STR_o STR_j "\0"-#define STRING_khojki0 STR_k STR_h STR_o STR_j STR_k STR_i "\0"-#define STRING_khudawadi0 STR_k STR_h STR_u STR_d STR_a STR_w STR_a STR_d STR_i "\0"-#define STRING_kits0 STR_k STR_i STR_t STR_s "\0"-#define STRING_knda0 STR_k STR_n STR_d STR_a "\0"-#define STRING_kthi0 STR_k STR_t STR_h STR_i "\0"-#define STRING_l0 STR_l "\0"-#define STRING_l_AMPERSAND0 STR_l STR_AMPERSAND "\0"-#define STRING_lana0 STR_l STR_a STR_n STR_a "\0"-#define STRING_lao0 STR_l STR_a STR_o "\0"-#define STRING_laoo0 STR_l STR_a STR_o STR_o "\0"-#define STRING_latin0 STR_l STR_a STR_t STR_i STR_n "\0"-#define STRING_latn0 STR_l STR_a STR_t STR_n "\0"-#define STRING_lc0 STR_l STR_c "\0"-#define STRING_lepc0 STR_l STR_e STR_p STR_c "\0"-#define STRING_lepcha0 STR_l STR_e STR_p STR_c STR_h STR_a "\0"-#define STRING_limb0 STR_l STR_i STR_m STR_b "\0"-#define STRING_limbu0 STR_l STR_i STR_m STR_b STR_u "\0"-#define STRING_lina0 STR_l STR_i STR_n STR_a "\0"-#define STRING_linb0 STR_l STR_i STR_n STR_b "\0"-#define STRING_lineara0 STR_l STR_i STR_n STR_e STR_a STR_r STR_a "\0"-#define STRING_linearb0 STR_l STR_i STR_n STR_e STR_a STR_r STR_b "\0"-#define STRING_lisu0 STR_l STR_i STR_s STR_u "\0"-#define STRING_ll0 STR_l STR_l "\0"-#define STRING_lm0 STR_l STR_m "\0"-#define STRING_lo0 STR_l STR_o "\0"-#define STRING_loe0 STR_l STR_o STR_e "\0"-#define STRING_logicalorderexception0 STR_l STR_o STR_g STR_i STR_c STR_a STR_l STR_o STR_r STR_d STR_e STR_r STR_e STR_x STR_c STR_e STR_p STR_t STR_i STR_o STR_n "\0"-#define STRING_lower0 STR_l STR_o STR_w STR_e STR_r "\0"-#define STRING_lowercase0 STR_l STR_o STR_w STR_e STR_r STR_c STR_a STR_s STR_e "\0"-#define STRING_lt0 STR_l STR_t "\0"-#define STRING_lu0 STR_l STR_u "\0"-#define STRING_lyci0 STR_l STR_y STR_c STR_i "\0"-#define STRING_lycian0 STR_l STR_y STR_c STR_i STR_a STR_n "\0"-#define STRING_lydi0 STR_l STR_y STR_d STR_i "\0"-#define STRING_lydian0 STR_l STR_y STR_d STR_i STR_a STR_n "\0"-#define STRING_m0 STR_m "\0"-#define STRING_mahajani0 STR_m STR_a STR_h STR_a STR_j STR_a STR_n STR_i "\0"-#define STRING_mahj0 STR_m STR_a STR_h STR_j "\0"-#define STRING_maka0 STR_m STR_a STR_k STR_a "\0"-#define STRING_makasar0 STR_m STR_a STR_k STR_a STR_s STR_a STR_r "\0"-#define STRING_malayalam0 STR_m STR_a STR_l STR_a STR_y STR_a STR_l STR_a STR_m "\0"-#define STRING_mand0 STR_m STR_a STR_n STR_d "\0"-#define STRING_mandaic0 STR_m STR_a STR_n STR_d STR_a STR_i STR_c "\0"-#define STRING_mani0 STR_m STR_a STR_n STR_i "\0"-#define STRING_manichaean0 STR_m STR_a STR_n STR_i STR_c STR_h STR_a STR_e STR_a STR_n "\0"-#define STRING_marc0 STR_m STR_a STR_r STR_c "\0"-#define STRING_marchen0 STR_m STR_a STR_r STR_c STR_h STR_e STR_n "\0"-#define STRING_masaramgondi0 STR_m STR_a STR_s STR_a STR_r STR_a STR_m STR_g STR_o STR_n STR_d STR_i "\0"-#define STRING_math0 STR_m STR_a STR_t STR_h "\0"-#define STRING_mc0 STR_m STR_c "\0"-#define STRING_me0 STR_m STR_e "\0"-#define STRING_medefaidrin0 STR_m STR_e STR_d STR_e STR_f STR_a STR_i STR_d STR_r STR_i STR_n "\0"-#define STRING_medf0 STR_m STR_e STR_d STR_f "\0"-#define STRING_meeteimayek0 STR_m STR_e STR_e STR_t STR_e STR_i STR_m STR_a STR_y STR_e STR_k "\0"-#define STRING_mend0 STR_m STR_e STR_n STR_d "\0"-#define STRING_mendekikakui0 STR_m STR_e STR_n STR_d STR_e STR_k STR_i STR_k STR_a STR_k STR_u STR_i "\0"-#define STRING_merc0 STR_m STR_e STR_r STR_c "\0"-#define STRING_mero0 STR_m STR_e STR_r STR_o "\0"-#define STRING_meroiticcursive0 STR_m STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_c STR_u STR_r STR_s STR_i STR_v STR_e "\0"-#define STRING_meroitichieroglyphs0 STR_m STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_h STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"-#define STRING_miao0 STR_m STR_i STR_a STR_o "\0"-#define STRING_mlym0 STR_m STR_l STR_y STR_m "\0"-#define STRING_mn0 STR_m STR_n "\0"-#define STRING_modi0 STR_m STR_o STR_d STR_i "\0"-#define STRING_mong0 STR_m STR_o STR_n STR_g "\0"-#define STRING_mongolian0 STR_m STR_o STR_n STR_g STR_o STR_l STR_i STR_a STR_n "\0"-#define STRING_mro0 STR_m STR_r STR_o "\0"-#define STRING_mroo0 STR_m STR_r STR_o STR_o "\0"-#define STRING_mtei0 STR_m STR_t STR_e STR_i "\0"-#define STRING_mult0 STR_m STR_u STR_l STR_t "\0"-#define STRING_multani0 STR_m STR_u STR_l STR_t STR_a STR_n STR_i "\0"-#define STRING_myanmar0 STR_m STR_y STR_a STR_n STR_m STR_a STR_r "\0"-#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"-#define STRING_nbat0 STR_n STR_b STR_a STR_t "\0"-#define STRING_nchar0 STR_n STR_c STR_h STR_a STR_r "\0"-#define STRING_nd0 STR_n STR_d "\0"-#define STRING_newa0 STR_n STR_e STR_w STR_a "\0"-#define STRING_newtailue0 STR_n STR_e STR_w STR_t STR_a STR_i STR_l STR_u STR_e "\0"-#define STRING_nko0 STR_n STR_k STR_o "\0"-#define STRING_nkoo0 STR_n STR_k STR_o STR_o "\0"-#define STRING_nl0 STR_n STR_l "\0"-#define STRING_no0 STR_n STR_o "\0"-#define STRING_noncharactercodepoint0 STR_n STR_o STR_n STR_c STR_h STR_a STR_r STR_a STR_c STR_t STR_e STR_r STR_c STR_o STR_d STR_e STR_p STR_o STR_i STR_n STR_t "\0"-#define STRING_nshu0 STR_n STR_s STR_h STR_u "\0"-#define STRING_nushu0 STR_n STR_u STR_s STR_h STR_u "\0"-#define STRING_nyiakengpuachuehmong0 STR_n STR_y STR_i STR_a STR_k STR_e STR_n STR_g STR_p STR_u STR_a STR_c STR_h STR_u STR_e STR_h STR_m STR_o STR_n STR_g "\0"-#define STRING_ogam0 STR_o STR_g STR_a STR_m "\0"-#define STRING_ogham0 STR_o STR_g STR_h STR_a STR_m "\0"-#define STRING_olchiki0 STR_o STR_l STR_c STR_h STR_i STR_k STR_i "\0"-#define STRING_olck0 STR_o STR_l STR_c STR_k "\0"-#define STRING_oldhungarian0 STR_o STR_l STR_d STR_h STR_u STR_n STR_g STR_a STR_r STR_i STR_a STR_n "\0"-#define STRING_olditalic0 STR_o STR_l STR_d STR_i STR_t STR_a STR_l STR_i STR_c "\0"-#define STRING_oldnortharabian0 STR_o STR_l STR_d STR_n STR_o STR_r STR_t STR_h STR_a STR_r STR_a STR_b STR_i STR_a STR_n "\0"-#define STRING_oldpermic0 STR_o STR_l STR_d STR_p STR_e STR_r STR_m STR_i STR_c "\0"-#define STRING_oldpersian0 STR_o STR_l STR_d STR_p STR_e STR_r STR_s STR_i STR_a STR_n "\0"-#define STRING_oldsogdian0 STR_o STR_l STR_d STR_s STR_o STR_g STR_d STR_i STR_a STR_n "\0"-#define STRING_oldsoutharabian0 STR_o STR_l STR_d STR_s STR_o STR_u STR_t STR_h STR_a STR_r STR_a STR_b STR_i STR_a STR_n "\0"-#define STRING_oldturkic0 STR_o STR_l STR_d STR_t STR_u STR_r STR_k STR_i STR_c "\0"-#define STRING_olduyghur0 STR_o STR_l STR_d STR_u STR_y STR_g STR_h STR_u STR_r "\0"-#define STRING_oriya0 STR_o STR_r STR_i STR_y STR_a "\0"-#define STRING_orkh0 STR_o STR_r STR_k STR_h "\0"-#define STRING_orya0 STR_o STR_r STR_y STR_a "\0"-#define STRING_osage0 STR_o STR_s STR_a STR_g STR_e "\0"-#define STRING_osge0 STR_o STR_s STR_g STR_e "\0"-#define STRING_osma0 STR_o STR_s STR_m STR_a "\0"-#define STRING_osmanya0 STR_o STR_s STR_m STR_a STR_n STR_y STR_a "\0"-#define STRING_ougr0 STR_o STR_u STR_g STR_r "\0"-#define STRING_p0 STR_p "\0"-#define STRING_pahawhhmong0 STR_p STR_a STR_h STR_a STR_w STR_h STR_h STR_m STR_o STR_n STR_g "\0"-#define STRING_palm0 STR_p STR_a STR_l STR_m "\0"-#define STRING_palmyrene0 STR_p STR_a STR_l STR_m STR_y STR_r STR_e STR_n STR_e "\0"-#define STRING_patsyn0 STR_p STR_a STR_t STR_s STR_y STR_n "\0"-#define STRING_patternsyntax0 STR_p STR_a STR_t STR_t STR_e STR_r STR_n STR_s STR_y STR_n STR_t STR_a STR_x "\0"-#define STRING_patternwhitespace0 STR_p STR_a STR_t STR_t STR_e STR_r STR_n STR_w STR_h STR_i STR_t STR_e STR_s STR_p STR_a STR_c STR_e "\0"-#define STRING_patws0 STR_p STR_a STR_t STR_w STR_s "\0"-#define STRING_pauc0 STR_p STR_a STR_u STR_c "\0"-#define STRING_paucinhau0 STR_p STR_a STR_u STR_c STR_i STR_n STR_h STR_a STR_u "\0"-#define STRING_pc0 STR_p STR_c "\0"-#define STRING_pcm0 STR_p STR_c STR_m "\0"-#define STRING_pd0 STR_p STR_d "\0"-#define STRING_pe0 STR_p STR_e "\0"-#define STRING_perm0 STR_p STR_e STR_r STR_m "\0"-#define STRING_pf0 STR_p STR_f "\0"-#define STRING_phag0 STR_p STR_h STR_a STR_g "\0"-#define STRING_phagspa0 STR_p STR_h STR_a STR_g STR_s STR_p STR_a "\0"-#define STRING_phli0 STR_p STR_h STR_l STR_i "\0"-#define STRING_phlp0 STR_p STR_h STR_l STR_p "\0"-#define STRING_phnx0 STR_p STR_h STR_n STR_x "\0"-#define STRING_phoenician0 STR_p STR_h STR_o STR_e STR_n STR_i STR_c STR_i STR_a STR_n "\0"-#define STRING_pi0 STR_p STR_i "\0"-#define STRING_plrd0 STR_p STR_l STR_r STR_d "\0"-#define STRING_po0 STR_p STR_o "\0"-#define STRING_prependedconcatenationmark0 STR_p STR_r STR_e STR_p STR_e STR_n STR_d STR_e STR_d STR_c STR_o STR_n STR_c STR_a STR_t STR_e STR_n STR_a STR_t STR_i STR_o STR_n STR_m STR_a STR_r STR_k "\0"-#define STRING_prti0 STR_p STR_r STR_t STR_i "\0"-#define STRING_ps0 STR_p STR_s "\0"-#define STRING_psalterpahlavi0 STR_p STR_s STR_a STR_l STR_t STR_e STR_r STR_p STR_a STR_h STR_l STR_a STR_v STR_i "\0"-#define STRING_qaac0 STR_q STR_a STR_a STR_c "\0"-#define STRING_qaai0 STR_q STR_a STR_a STR_i "\0"-#define STRING_qmark0 STR_q STR_m STR_a STR_r STR_k "\0"-#define STRING_quotationmark0 STR_q STR_u STR_o STR_t STR_a STR_t STR_i STR_o STR_n STR_m STR_a STR_r STR_k "\0"-#define STRING_radical0 STR_r STR_a STR_d STR_i STR_c STR_a STR_l "\0"-#define STRING_regionalindicator0 STR_r STR_e STR_g STR_i STR_o STR_n STR_a STR_l STR_i STR_n STR_d STR_i STR_c STR_a STR_t STR_o STR_r "\0"-#define STRING_rejang0 STR_r STR_e STR_j STR_a STR_n STR_g "\0"-#define STRING_ri0 STR_r STR_i "\0"-#define STRING_rjng0 STR_r STR_j STR_n STR_g "\0"-#define STRING_rohg0 STR_r STR_o STR_h STR_g "\0"-#define STRING_runic0 STR_r STR_u STR_n STR_i STR_c "\0"-#define STRING_runr0 STR_r STR_u STR_n STR_r "\0"-#define STRING_s0 STR_s "\0"-#define STRING_samaritan0 STR_s STR_a STR_m STR_a STR_r STR_i STR_t STR_a STR_n "\0"-#define STRING_samr0 STR_s STR_a STR_m STR_r "\0"-#define STRING_sarb0 STR_s STR_a STR_r STR_b "\0"-#define STRING_saur0 STR_s STR_a STR_u STR_r "\0"-#define STRING_saurashtra0 STR_s STR_a STR_u STR_r STR_a STR_s STR_h STR_t STR_r STR_a "\0"-#define STRING_sc0 STR_s STR_c "\0"-#define STRING_sd0 STR_s STR_d "\0"-#define STRING_sentenceterminal0 STR_s STR_e STR_n STR_t STR_e STR_n STR_c STR_e STR_t STR_e STR_r STR_m STR_i STR_n STR_a STR_l "\0"-#define STRING_sgnw0 STR_s STR_g STR_n STR_w "\0"-#define STRING_sharada0 STR_s STR_h STR_a STR_r STR_a STR_d STR_a "\0"-#define STRING_shavian0 STR_s STR_h STR_a STR_v STR_i STR_a STR_n "\0"-#define STRING_shaw0 STR_s STR_h STR_a STR_w "\0"-#define STRING_shrd0 STR_s STR_h STR_r STR_d "\0"-#define STRING_sidd0 STR_s STR_i STR_d STR_d "\0"-#define STRING_siddham0 STR_s STR_i STR_d STR_d STR_h STR_a STR_m "\0"-#define STRING_signwriting0 STR_s STR_i STR_g STR_n STR_w STR_r STR_i STR_t STR_i STR_n STR_g "\0"-#define STRING_sind0 STR_s STR_i STR_n STR_d "\0"-#define STRING_sinh0 STR_s STR_i STR_n STR_h "\0"-#define STRING_sinhala0 STR_s STR_i STR_n STR_h STR_a STR_l STR_a "\0"-#define STRING_sk0 STR_s STR_k "\0"-#define STRING_sm0 STR_s STR_m "\0"-#define STRING_so0 STR_s STR_o "\0"-#define STRING_softdotted0 STR_s STR_o STR_f STR_t STR_d STR_o STR_t STR_t STR_e STR_d "\0"-#define STRING_sogd0 STR_s STR_o STR_g STR_d "\0"-#define STRING_sogdian0 STR_s STR_o STR_g STR_d STR_i STR_a STR_n "\0"-#define STRING_sogo0 STR_s STR_o STR_g STR_o "\0"-#define STRING_sora0 STR_s STR_o STR_r STR_a "\0"-#define STRING_sorasompeng0 STR_s STR_o STR_r STR_a STR_s STR_o STR_m STR_p STR_e STR_n STR_g "\0"-#define STRING_soyo0 STR_s STR_o STR_y STR_o "\0"-#define STRING_soyombo0 STR_s STR_o STR_y STR_o STR_m STR_b STR_o "\0"-#define STRING_space0 STR_s STR_p STR_a STR_c STR_e "\0"-#define STRING_sterm0 STR_s STR_t STR_e STR_r STR_m "\0"-#define STRING_sund0 STR_s STR_u STR_n STR_d "\0"-#define STRING_sundanese0 STR_s STR_u STR_n STR_d STR_a STR_n STR_e STR_s STR_e "\0"-#define STRING_sylo0 STR_s STR_y STR_l STR_o "\0"-#define STRING_sylotinagri0 STR_s STR_y STR_l STR_o STR_t STR_i STR_n STR_a STR_g STR_r STR_i "\0"-#define STRING_syrc0 STR_s STR_y STR_r STR_c "\0"-#define STRING_syriac0 STR_s STR_y STR_r STR_i STR_a STR_c "\0"-#define STRING_tagalog0 STR_t STR_a STR_g STR_a STR_l STR_o STR_g "\0"-#define STRING_tagb0 STR_t STR_a STR_g STR_b "\0"-#define STRING_tagbanwa0 STR_t STR_a STR_g STR_b STR_a STR_n STR_w STR_a "\0"-#define STRING_taile0 STR_t STR_a STR_i STR_l STR_e "\0"-#define STRING_taitham0 STR_t STR_a STR_i STR_t STR_h STR_a STR_m "\0"-#define STRING_taiviet0 STR_t STR_a STR_i STR_v STR_i STR_e STR_t "\0"-#define STRING_takr0 STR_t STR_a STR_k STR_r "\0"-#define STRING_takri0 STR_t STR_a STR_k STR_r STR_i "\0"-#define STRING_tale0 STR_t STR_a STR_l STR_e "\0"-#define STRING_talu0 STR_t STR_a STR_l STR_u "\0"-#define STRING_tamil0 STR_t STR_a STR_m STR_i STR_l "\0"-#define STRING_taml0 STR_t STR_a STR_m STR_l "\0"-#define STRING_tang0 STR_t STR_a STR_n STR_g "\0"-#define STRING_tangsa0 STR_t STR_a STR_n STR_g STR_s STR_a "\0"-#define STRING_tangut0 STR_t STR_a STR_n STR_g STR_u STR_t "\0"-#define STRING_tavt0 STR_t STR_a STR_v STR_t "\0"-#define STRING_telu0 STR_t STR_e STR_l STR_u "\0"-#define STRING_telugu0 STR_t STR_e STR_l STR_u STR_g STR_u "\0"-#define STRING_term0 STR_t STR_e STR_r STR_m "\0"-#define STRING_terminalpunctuation0 STR_t STR_e STR_r STR_m STR_i STR_n STR_a STR_l STR_p STR_u STR_n STR_c STR_t STR_u STR_a STR_t STR_i STR_o STR_n "\0"-#define STRING_tfng0 STR_t STR_f STR_n STR_g "\0"-#define STRING_tglg0 STR_t STR_g STR_l STR_g "\0"-#define STRING_thaa0 STR_t STR_h STR_a STR_a "\0"-#define STRING_thaana0 STR_t STR_h STR_a STR_a STR_n STR_a "\0"-#define STRING_thai0 STR_t STR_h STR_a STR_i "\0"-#define STRING_tibetan0 STR_t STR_i STR_b STR_e STR_t STR_a STR_n "\0"-#define STRING_tibt0 STR_t STR_i STR_b STR_t "\0"-#define STRING_tifinagh0 STR_t STR_i STR_f STR_i STR_n STR_a STR_g STR_h "\0"-#define STRING_tirh0 STR_t STR_i STR_r STR_h "\0"-#define STRING_tirhuta0 STR_t STR_i STR_r STR_h STR_u STR_t STR_a "\0"-#define STRING_tnsa0 STR_t STR_n STR_s STR_a "\0"-#define STRING_toto0 STR_t STR_o STR_t STR_o "\0"-#define STRING_ugar0 STR_u STR_g STR_a STR_r "\0"-#define STRING_ugaritic0 STR_u STR_g STR_a STR_r STR_i STR_t STR_i STR_c "\0"-#define STRING_uideo0 STR_u STR_i STR_d STR_e STR_o "\0"-#define STRING_unifiedideograph0 STR_u STR_n STR_i STR_f STR_i STR_e STR_d STR_i STR_d STR_e STR_o STR_g STR_r STR_a STR_p STR_h "\0"-#define STRING_unknown0 STR_u STR_n STR_k STR_n STR_o STR_w STR_n "\0"-#define STRING_upper0 STR_u STR_p STR_p STR_e STR_r "\0"-#define STRING_uppercase0 STR_u STR_p STR_p STR_e STR_r STR_c STR_a STR_s STR_e "\0"-#define STRING_vai0 STR_v STR_a STR_i "\0"-#define STRING_vaii0 STR_v STR_a STR_i STR_i "\0"-#define STRING_variationselector0 STR_v STR_a STR_r STR_i STR_a STR_t STR_i STR_o STR_n STR_s STR_e STR_l STR_e STR_c STR_t STR_o STR_r "\0"-#define STRING_vith0 STR_v STR_i STR_t STR_h "\0"-#define STRING_vithkuqi0 STR_v STR_i STR_t STR_h STR_k STR_u STR_q STR_i "\0"-#define STRING_vs0 STR_v STR_s "\0"-#define STRING_wancho0 STR_w STR_a STR_n STR_c STR_h STR_o "\0"-#define STRING_wara0 STR_w STR_a STR_r STR_a "\0"-#define STRING_warangciti0 STR_w STR_a STR_r STR_a STR_n STR_g STR_c STR_i STR_t STR_i "\0"-#define STRING_wcho0 STR_w STR_c STR_h STR_o "\0"-#define STRING_whitespace0 STR_w STR_h STR_i STR_t STR_e STR_s STR_p STR_a STR_c STR_e "\0"-#define STRING_wspace0 STR_w STR_s STR_p STR_a STR_c STR_e "\0"-#define STRING_xan0 STR_x STR_a STR_n "\0"-#define STRING_xidc0 STR_x STR_i STR_d STR_c "\0"-#define STRING_xidcontinue0 STR_x STR_i STR_d STR_c STR_o STR_n STR_t STR_i STR_n STR_u STR_e "\0"-#define STRING_xids0 STR_x STR_i STR_d STR_s "\0"-#define STRING_xidstart0 STR_x STR_i STR_d STR_s STR_t STR_a STR_r STR_t "\0"-#define STRING_xpeo0 STR_x STR_p STR_e STR_o "\0"-#define STRING_xps0 STR_x STR_p STR_s "\0"-#define STRING_xsp0 STR_x STR_s STR_p "\0"-#define STRING_xsux0 STR_x STR_s STR_u STR_x "\0"-#define STRING_xuc0 STR_x STR_u STR_c "\0"-#define STRING_xwd0 STR_x STR_w STR_d "\0"-#define STRING_yezi0 STR_y STR_e STR_z STR_i "\0"-#define STRING_yezidi0 STR_y STR_e STR_z STR_i STR_d STR_i "\0"-#define STRING_yi0 STR_y STR_i "\0"-#define STRING_yiii0 STR_y STR_i STR_i STR_i "\0"-#define STRING_z0 STR_z "\0"-#define STRING_zanabazarsquare0 STR_z STR_a STR_n STR_a STR_b STR_a STR_z STR_a STR_r STR_s STR_q STR_u STR_a STR_r STR_e "\0"-#define STRING_zanb0 STR_z STR_a STR_n STR_b "\0"-#define STRING_zinh0 STR_z STR_i STR_n STR_h "\0"-#define STRING_zl0 STR_z STR_l "\0"-#define STRING_zp0 STR_z STR_p "\0"-#define STRING_zs0 STR_z STR_s "\0"-#define STRING_zyyy0 STR_z STR_y STR_y STR_y "\0"-#define STRING_zzzz0 STR_z STR_z STR_z STR_z "\0"--const char PRIV(utt_names)[] =- STRING_adlam0- STRING_adlm0- STRING_aghb0- STRING_ahex0- STRING_ahom0- STRING_alpha0- STRING_alphabetic0- STRING_anatolianhieroglyphs0- STRING_any0- STRING_arab0- STRING_arabic0- STRING_armenian0- STRING_armi0- STRING_armn0- STRING_ascii0- STRING_asciihexdigit0- STRING_avestan0- STRING_avst0- STRING_bali0- STRING_balinese0- STRING_bamu0- STRING_bamum0- STRING_bass0- STRING_bassavah0- STRING_batak0- STRING_batk0- STRING_beng0- STRING_bengali0- STRING_bhaiksuki0- STRING_bhks0- STRING_bidial0- STRING_bidian0- STRING_bidib0- STRING_bidibn0- STRING_bidic0- STRING_bidicontrol0- STRING_bidics0- STRING_bidien0- STRING_bidies0- STRING_bidiet0- STRING_bidifsi0- STRING_bidil0- STRING_bidilre0- STRING_bidilri0- STRING_bidilro0- STRING_bidim0- STRING_bidimirrored0- STRING_bidinsm0- STRING_bidion0- STRING_bidipdf0- STRING_bidipdi0- STRING_bidir0- STRING_bidirle0- STRING_bidirli0- STRING_bidirlo0- STRING_bidis0- STRING_bidiws0- STRING_bopo0- STRING_bopomofo0- STRING_brah0- STRING_brahmi0- STRING_brai0- STRING_braille0- STRING_bugi0- STRING_buginese0- STRING_buhd0- STRING_buhid0- STRING_c0- STRING_cakm0- STRING_canadianaboriginal0- STRING_cans0- STRING_cari0- STRING_carian0- STRING_cased0- STRING_caseignorable0- STRING_caucasianalbanian0- STRING_cc0- STRING_cf0- STRING_chakma0- STRING_cham0- STRING_changeswhencasefolded0- STRING_changeswhencasemapped0- STRING_changeswhenlowercased0- STRING_changeswhentitlecased0- STRING_changeswhenuppercased0- STRING_cher0- STRING_cherokee0- STRING_chorasmian0- STRING_chrs0- STRING_ci0- STRING_cn0- STRING_co0- STRING_common0- STRING_copt0- STRING_coptic0- STRING_cpmn0- STRING_cprt0- STRING_cs0- STRING_cuneiform0- STRING_cwcf0- STRING_cwcm0- STRING_cwl0- STRING_cwt0- STRING_cwu0- STRING_cypriot0- STRING_cyprominoan0- STRING_cyrillic0- STRING_cyrl0- STRING_dash0- STRING_defaultignorablecodepoint0- STRING_dep0- STRING_deprecated0- STRING_deseret0- STRING_deva0- STRING_devanagari0- STRING_di0- STRING_dia0- STRING_diacritic0- STRING_diak0- STRING_divesakuru0- STRING_dogr0- STRING_dogra0- STRING_dsrt0- STRING_dupl0- STRING_duployan0- STRING_ebase0- STRING_ecomp0- STRING_egyp0- STRING_egyptianhieroglyphs0- STRING_elba0- STRING_elbasan0- STRING_elym0- STRING_elymaic0- STRING_emod0- STRING_emoji0- STRING_emojicomponent0- STRING_emojimodifier0- STRING_emojimodifierbase0- STRING_emojipresentation0- STRING_epres0- STRING_ethi0- STRING_ethiopic0- STRING_ext0- STRING_extendedpictographic0- STRING_extender0- STRING_extpict0- STRING_geor0- STRING_georgian0- STRING_glag0- STRING_glagolitic0- STRING_gong0- STRING_gonm0- STRING_goth0- STRING_gothic0- STRING_gran0- STRING_grantha0- STRING_graphemebase0- STRING_graphemeextend0- STRING_graphemelink0- STRING_grbase0- STRING_greek0- STRING_grek0- STRING_grext0- STRING_grlink0- STRING_gujarati0- STRING_gujr0- STRING_gunjalagondi0- STRING_gurmukhi0- STRING_guru0- STRING_han0- STRING_hang0- STRING_hangul0- STRING_hani0- STRING_hanifirohingya0- STRING_hano0- STRING_hanunoo0- STRING_hatr0- STRING_hatran0- STRING_hebr0- STRING_hebrew0- STRING_hex0- STRING_hexdigit0- STRING_hira0- STRING_hiragana0- STRING_hluw0- STRING_hmng0- STRING_hmnp0- STRING_hung0- STRING_idc0- STRING_idcontinue0- STRING_ideo0- STRING_ideographic0- STRING_ids0- STRING_idsb0- STRING_idsbinaryoperator0- STRING_idst0- STRING_idstart0- STRING_idstrinaryoperator0- STRING_imperialaramaic0- STRING_inherited0- STRING_inscriptionalpahlavi0- STRING_inscriptionalparthian0- STRING_ital0- STRING_java0- STRING_javanese0- STRING_joinc0- STRING_joincontrol0- STRING_kaithi0- STRING_kali0- STRING_kana0- STRING_kannada0- STRING_katakana0- STRING_kawi0- STRING_kayahli0- STRING_khar0- STRING_kharoshthi0- STRING_khitansmallscript0- STRING_khmer0- STRING_khmr0- STRING_khoj0- STRING_khojki0- STRING_khudawadi0- STRING_kits0- STRING_knda0- STRING_kthi0- STRING_l0- STRING_l_AMPERSAND0- STRING_lana0- STRING_lao0- STRING_laoo0- STRING_latin0- STRING_latn0- STRING_lc0- STRING_lepc0- STRING_lepcha0- STRING_limb0- STRING_limbu0- STRING_lina0- STRING_linb0- STRING_lineara0- STRING_linearb0- STRING_lisu0- STRING_ll0- STRING_lm0- STRING_lo0- STRING_loe0- STRING_logicalorderexception0- STRING_lower0- STRING_lowercase0- STRING_lt0- STRING_lu0- STRING_lyci0- STRING_lycian0- STRING_lydi0- STRING_lydian0- STRING_m0- STRING_mahajani0- STRING_mahj0- STRING_maka0- STRING_makasar0- STRING_malayalam0- STRING_mand0- STRING_mandaic0- STRING_mani0- STRING_manichaean0- STRING_marc0- STRING_marchen0- STRING_masaramgondi0- STRING_math0- STRING_mc0- STRING_me0- STRING_medefaidrin0- STRING_medf0- STRING_meeteimayek0- STRING_mend0- STRING_mendekikakui0- STRING_merc0- STRING_mero0- STRING_meroiticcursive0- STRING_meroitichieroglyphs0- STRING_miao0- STRING_mlym0- STRING_mn0- STRING_modi0- STRING_mong0- STRING_mongolian0- STRING_mro0- STRING_mroo0- STRING_mtei0- STRING_mult0- STRING_multani0- STRING_myanmar0- STRING_mymr0- STRING_n0- STRING_nabataean0- STRING_nagm0- STRING_nagmundari0- STRING_nand0- STRING_nandinagari0- STRING_narb0- STRING_nbat0- STRING_nchar0- STRING_nd0- STRING_newa0- STRING_newtailue0- STRING_nko0- STRING_nkoo0- STRING_nl0- STRING_no0- STRING_noncharactercodepoint0- STRING_nshu0- STRING_nushu0- STRING_nyiakengpuachuehmong0- STRING_ogam0- STRING_ogham0- STRING_olchiki0- STRING_olck0- STRING_oldhungarian0- STRING_olditalic0- STRING_oldnortharabian0- STRING_oldpermic0- STRING_oldpersian0- STRING_oldsogdian0- STRING_oldsoutharabian0- STRING_oldturkic0- STRING_olduyghur0- STRING_oriya0- STRING_orkh0- STRING_orya0- STRING_osage0- STRING_osge0- STRING_osma0- STRING_osmanya0- STRING_ougr0- STRING_p0- STRING_pahawhhmong0- STRING_palm0- STRING_palmyrene0- STRING_patsyn0- STRING_patternsyntax0- STRING_patternwhitespace0- STRING_patws0- STRING_pauc0- STRING_paucinhau0- STRING_pc0- STRING_pcm0- STRING_pd0- STRING_pe0- STRING_perm0- STRING_pf0- STRING_phag0- STRING_phagspa0- STRING_phli0- STRING_phlp0- STRING_phnx0- STRING_phoenician0- STRING_pi0- STRING_plrd0- STRING_po0- STRING_prependedconcatenationmark0- STRING_prti0- STRING_ps0- STRING_psalterpahlavi0- STRING_qaac0- STRING_qaai0- STRING_qmark0- STRING_quotationmark0- STRING_radical0- STRING_regionalindicator0- STRING_rejang0- STRING_ri0- STRING_rjng0- STRING_rohg0- STRING_runic0- STRING_runr0- STRING_s0- STRING_samaritan0- STRING_samr0- STRING_sarb0- STRING_saur0- STRING_saurashtra0- STRING_sc0- STRING_sd0- STRING_sentenceterminal0- STRING_sgnw0- STRING_sharada0- STRING_shavian0- STRING_shaw0- STRING_shrd0- STRING_sidd0- STRING_siddham0- STRING_signwriting0- STRING_sind0- STRING_sinh0- STRING_sinhala0- STRING_sk0- STRING_sm0- STRING_so0- STRING_softdotted0- STRING_sogd0- STRING_sogdian0- STRING_sogo0- STRING_sora0- STRING_sorasompeng0- STRING_soyo0- STRING_soyombo0- STRING_space0- STRING_sterm0- STRING_sund0- STRING_sundanese0- STRING_sylo0- STRING_sylotinagri0- STRING_syrc0- STRING_syriac0- STRING_tagalog0- STRING_tagb0- STRING_tagbanwa0- STRING_taile0- STRING_taitham0- STRING_taiviet0- STRING_takr0- STRING_takri0- STRING_tale0- STRING_talu0- STRING_tamil0- STRING_taml0- STRING_tang0- STRING_tangsa0- STRING_tangut0- STRING_tavt0- STRING_telu0- STRING_telugu0- STRING_term0- STRING_terminalpunctuation0- STRING_tfng0- STRING_tglg0- STRING_thaa0- STRING_thaana0- STRING_thai0- STRING_tibetan0- STRING_tibt0- STRING_tifinagh0- STRING_tirh0- STRING_tirhuta0- STRING_tnsa0- STRING_toto0- STRING_ugar0- STRING_ugaritic0- STRING_uideo0- STRING_unifiedideograph0- STRING_unknown0- STRING_upper0- STRING_uppercase0- STRING_vai0- STRING_vaii0- STRING_variationselector0- STRING_vith0- STRING_vithkuqi0- STRING_vs0- STRING_wancho0- STRING_wara0- STRING_warangciti0- STRING_wcho0- STRING_whitespace0- STRING_wspace0- STRING_xan0- STRING_xidc0- STRING_xidcontinue0- STRING_xids0- STRING_xidstart0- STRING_xpeo0- STRING_xps0- STRING_xsp0- STRING_xsux0- STRING_xuc0- STRING_xwd0- STRING_yezi0- STRING_yezidi0- STRING_yi0- STRING_yiii0- STRING_z0- STRING_zanabazarsquare0- STRING_zanb0- STRING_zinh0- STRING_zl0- STRING_zp0- STRING_zs0- STRING_zyyy0- STRING_zzzz0;--const ucp_type_table PRIV(utt)[] = {- { 0, PT_SCX, ucp_Adlam },- { 6, PT_SCX, ucp_Adlam },- { 11, PT_SC, ucp_Caucasian_Albanian },- { 16, PT_BOOL, ucp_ASCII_Hex_Digit },- { 21, PT_SC, ucp_Ahom },- { 26, PT_BOOL, ucp_Alphabetic },- { 32, PT_BOOL, ucp_Alphabetic },- { 43, PT_SC, ucp_Anatolian_Hieroglyphs },- { 64, PT_ANY, 0 },- { 68, PT_SCX, ucp_Arabic },- { 73, PT_SCX, ucp_Arabic },- { 80, PT_SC, ucp_Armenian },- { 89, PT_SC, ucp_Imperial_Aramaic },- { 94, PT_SC, ucp_Armenian },- { 99, PT_BOOL, ucp_ASCII },- { 105, PT_BOOL, ucp_ASCII_Hex_Digit },- { 119, PT_SC, ucp_Avestan },- { 127, PT_SC, ucp_Avestan },- { 132, PT_SC, ucp_Balinese },- { 137, PT_SC, ucp_Balinese },- { 146, PT_SC, ucp_Bamum },- { 151, PT_SC, ucp_Bamum },- { 157, PT_SC, ucp_Bassa_Vah },- { 162, PT_SC, ucp_Bassa_Vah },- { 171, PT_SC, ucp_Batak },- { 177, PT_SC, ucp_Batak },- { 182, PT_SCX, ucp_Bengali },- { 187, PT_SCX, ucp_Bengali },- { 195, PT_SC, ucp_Bhaiksuki },- { 205, PT_SC, ucp_Bhaiksuki },- { 210, PT_BIDICL, ucp_bidiAL },- { 217, PT_BIDICL, ucp_bidiAN },- { 224, PT_BIDICL, ucp_bidiB },- { 230, PT_BIDICL, ucp_bidiBN },- { 237, PT_BOOL, ucp_Bidi_Control },- { 243, PT_BOOL, ucp_Bidi_Control },- { 255, PT_BIDICL, ucp_bidiCS },- { 262, PT_BIDICL, ucp_bidiEN },- { 269, PT_BIDICL, ucp_bidiES },- { 276, PT_BIDICL, ucp_bidiET },- { 283, PT_BIDICL, ucp_bidiFSI },- { 291, PT_BIDICL, ucp_bidiL },- { 297, PT_BIDICL, ucp_bidiLRE },- { 305, PT_BIDICL, ucp_bidiLRI },- { 313, PT_BIDICL, ucp_bidiLRO },- { 321, PT_BOOL, ucp_Bidi_Mirrored },- { 327, PT_BOOL, ucp_Bidi_Mirrored },- { 340, PT_BIDICL, ucp_bidiNSM },- { 348, PT_BIDICL, ucp_bidiON },- { 355, PT_BIDICL, ucp_bidiPDF },- { 363, PT_BIDICL, ucp_bidiPDI },- { 371, PT_BIDICL, ucp_bidiR },- { 377, PT_BIDICL, ucp_bidiRLE },- { 385, PT_BIDICL, ucp_bidiRLI },- { 393, PT_BIDICL, ucp_bidiRLO },- { 401, PT_BIDICL, ucp_bidiS },- { 407, PT_BIDICL, ucp_bidiWS },- { 414, PT_SCX, ucp_Bopomofo },- { 419, PT_SCX, ucp_Bopomofo },- { 428, PT_SC, ucp_Brahmi },- { 433, PT_SC, ucp_Brahmi },- { 440, PT_SC, ucp_Braille },- { 445, PT_SC, ucp_Braille },- { 453, PT_SCX, ucp_Buginese },- { 458, PT_SCX, ucp_Buginese },- { 467, PT_SCX, ucp_Buhid },- { 472, PT_SCX, ucp_Buhid },- { 478, PT_GC, ucp_C },- { 480, PT_SCX, ucp_Chakma },- { 485, PT_SC, ucp_Canadian_Aboriginal },- { 504, PT_SC, ucp_Canadian_Aboriginal },- { 509, PT_SC, ucp_Carian },- { 514, PT_SC, ucp_Carian },- { 521, PT_BOOL, ucp_Cased },- { 527, PT_BOOL, ucp_Case_Ignorable },- { 541, PT_SC, ucp_Caucasian_Albanian },- { 559, PT_PC, ucp_Cc },- { 562, PT_PC, ucp_Cf },- { 565, PT_SCX, ucp_Chakma },- { 572, PT_SC, ucp_Cham },- { 577, PT_BOOL, ucp_Changes_When_Casefolded },- { 599, PT_BOOL, ucp_Changes_When_Casemapped },- { 621, PT_BOOL, ucp_Changes_When_Lowercased },- { 643, PT_BOOL, ucp_Changes_When_Titlecased },- { 665, PT_BOOL, ucp_Changes_When_Uppercased },- { 687, PT_SC, ucp_Cherokee },- { 692, PT_SC, ucp_Cherokee },- { 701, PT_SC, ucp_Chorasmian },- { 712, PT_SC, ucp_Chorasmian },- { 717, PT_BOOL, ucp_Case_Ignorable },- { 720, PT_PC, ucp_Cn },- { 723, PT_PC, ucp_Co },- { 726, PT_SC, ucp_Common },- { 733, PT_SCX, ucp_Coptic },- { 738, PT_SCX, ucp_Coptic },- { 745, PT_SCX, ucp_Cypro_Minoan },- { 750, PT_SCX, ucp_Cypriot },- { 755, PT_PC, ucp_Cs },- { 758, PT_SC, ucp_Cuneiform },- { 768, PT_BOOL, ucp_Changes_When_Casefolded },- { 773, PT_BOOL, ucp_Changes_When_Casemapped },- { 778, PT_BOOL, ucp_Changes_When_Lowercased },- { 782, PT_BOOL, ucp_Changes_When_Titlecased },- { 786, PT_BOOL, ucp_Changes_When_Uppercased },- { 790, PT_SCX, ucp_Cypriot },- { 798, PT_SCX, ucp_Cypro_Minoan },- { 810, PT_SCX, ucp_Cyrillic },- { 819, PT_SCX, ucp_Cyrillic },- { 824, PT_BOOL, ucp_Dash },- { 829, PT_BOOL, ucp_Default_Ignorable_Code_Point },- { 855, PT_BOOL, ucp_Deprecated },- { 859, PT_BOOL, ucp_Deprecated },- { 870, PT_SC, ucp_Deseret },- { 878, PT_SCX, ucp_Devanagari },- { 883, PT_SCX, ucp_Devanagari },- { 894, PT_BOOL, ucp_Default_Ignorable_Code_Point },- { 897, PT_BOOL, ucp_Diacritic },- { 901, PT_BOOL, ucp_Diacritic },- { 911, PT_SC, ucp_Dives_Akuru },- { 916, PT_SC, ucp_Dives_Akuru },- { 927, PT_SCX, ucp_Dogra },- { 932, PT_SCX, ucp_Dogra },- { 938, PT_SC, ucp_Deseret },- { 943, PT_SCX, ucp_Duployan },- { 948, PT_SCX, ucp_Duployan },- { 957, PT_BOOL, ucp_Emoji_Modifier_Base },- { 963, PT_BOOL, ucp_Emoji_Component },- { 969, PT_SC, ucp_Egyptian_Hieroglyphs },- { 974, PT_SC, ucp_Egyptian_Hieroglyphs },- { 994, PT_SC, ucp_Elbasan },- { 999, PT_SC, ucp_Elbasan },- { 1007, PT_SC, ucp_Elymaic },- { 1012, PT_SC, ucp_Elymaic },- { 1020, PT_BOOL, ucp_Emoji_Modifier },- { 1025, PT_BOOL, ucp_Emoji },- { 1031, PT_BOOL, ucp_Emoji_Component },- { 1046, PT_BOOL, ucp_Emoji_Modifier },- { 1060, PT_BOOL, ucp_Emoji_Modifier_Base },- { 1078, PT_BOOL, ucp_Emoji_Presentation },- { 1096, PT_BOOL, ucp_Emoji_Presentation },- { 1102, PT_SC, ucp_Ethiopic },- { 1107, PT_SC, ucp_Ethiopic },- { 1116, PT_BOOL, ucp_Extender },- { 1120, PT_BOOL, ucp_Extended_Pictographic },- { 1141, PT_BOOL, ucp_Extender },- { 1150, PT_BOOL, ucp_Extended_Pictographic },- { 1158, PT_SCX, ucp_Georgian },- { 1163, PT_SCX, ucp_Georgian },- { 1172, PT_SCX, ucp_Glagolitic },- { 1177, PT_SCX, ucp_Glagolitic },- { 1188, PT_SCX, ucp_Gunjala_Gondi },- { 1193, PT_SCX, ucp_Masaram_Gondi },- { 1198, PT_SC, ucp_Gothic },- { 1203, PT_SC, ucp_Gothic },- { 1210, PT_SCX, ucp_Grantha },- { 1215, PT_SCX, ucp_Grantha },- { 1223, PT_BOOL, ucp_Grapheme_Base },- { 1236, PT_BOOL, ucp_Grapheme_Extend },- { 1251, PT_BOOL, ucp_Grapheme_Link },- { 1264, PT_BOOL, ucp_Grapheme_Base },- { 1271, PT_SCX, ucp_Greek },- { 1277, PT_SCX, ucp_Greek },- { 1282, PT_BOOL, ucp_Grapheme_Extend },- { 1288, PT_BOOL, ucp_Grapheme_Link },- { 1295, PT_SCX, ucp_Gujarati },- { 1304, PT_SCX, ucp_Gujarati },- { 1309, PT_SCX, ucp_Gunjala_Gondi },- { 1322, PT_SCX, ucp_Gurmukhi },- { 1331, PT_SCX, ucp_Gurmukhi },- { 1336, PT_SCX, ucp_Han },- { 1340, PT_SCX, ucp_Hangul },- { 1345, PT_SCX, ucp_Hangul },- { 1352, PT_SCX, ucp_Han },- { 1357, PT_SCX, ucp_Hanifi_Rohingya },- { 1372, PT_SCX, ucp_Hanunoo },- { 1377, PT_SCX, ucp_Hanunoo },- { 1385, PT_SC, ucp_Hatran },- { 1390, PT_SC, ucp_Hatran },- { 1397, PT_SC, ucp_Hebrew },- { 1402, PT_SC, ucp_Hebrew },- { 1409, PT_BOOL, ucp_Hex_Digit },- { 1413, PT_BOOL, ucp_Hex_Digit },- { 1422, PT_SCX, ucp_Hiragana },- { 1427, PT_SCX, ucp_Hiragana },- { 1436, PT_SC, ucp_Anatolian_Hieroglyphs },- { 1441, PT_SC, ucp_Pahawh_Hmong },- { 1446, PT_SC, ucp_Nyiakeng_Puachue_Hmong },- { 1451, PT_SC, ucp_Old_Hungarian },- { 1456, PT_BOOL, ucp_ID_Continue },- { 1460, PT_BOOL, ucp_ID_Continue },- { 1471, PT_BOOL, ucp_Ideographic },- { 1476, PT_BOOL, ucp_Ideographic },- { 1488, PT_BOOL, ucp_ID_Start },- { 1492, PT_BOOL, ucp_IDS_Binary_Operator },- { 1497, PT_BOOL, ucp_IDS_Binary_Operator },- { 1515, PT_BOOL, ucp_IDS_Trinary_Operator },- { 1520, PT_BOOL, ucp_ID_Start },- { 1528, PT_BOOL, ucp_IDS_Trinary_Operator },- { 1547, PT_SC, ucp_Imperial_Aramaic },- { 1563, PT_SC, ucp_Inherited },- { 1573, PT_SC, ucp_Inscriptional_Pahlavi },- { 1594, PT_SC, ucp_Inscriptional_Parthian },- { 1616, PT_SC, ucp_Old_Italic },- { 1621, PT_SCX, ucp_Javanese },- { 1626, PT_SCX, ucp_Javanese },- { 1635, PT_BOOL, ucp_Join_Control },- { 1641, PT_BOOL, ucp_Join_Control },- { 1653, PT_SCX, ucp_Kaithi },- { 1660, PT_SCX, ucp_Kayah_Li },- { 1665, PT_SCX, ucp_Katakana },- { 1670, PT_SCX, ucp_Kannada },- { 1678, PT_SCX, ucp_Katakana },- { 1687, PT_SC, ucp_Kawi },- { 1692, PT_SCX, ucp_Kayah_Li },- { 1700, PT_SC, ucp_Kharoshthi },- { 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 },- { 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 },- { 1820, PT_SC, ucp_Lepcha },- { 1827, PT_SCX, ucp_Limbu },- { 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 },- { 1931, PT_SC, ucp_Lycian },- { 1938, PT_SC, ucp_Lydian },- { 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 },- { 1971, PT_SC, ucp_Makasar },- { 1979, PT_SCX, ucp_Malayalam },- { 1989, PT_SCX, ucp_Mandaic },- { 1994, PT_SCX, ucp_Mandaic },- { 2002, PT_SCX, ucp_Manichaean },- { 2007, PT_SCX, ucp_Manichaean },- { 2018, PT_SC, ucp_Marchen },- { 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 },- { 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 },- { 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 },- { 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 },- { 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);--#endif /* SUPPORT_UNICODE */--/* End of pcre2_ucptables.c */
+ src/c/pcre2/src/pcre2_ucptables_inc.h view
@@ -0,0 +1,1596 @@+/*************************************************+* 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+ Original API code Copyright (c) 1997-2012 University of Cambridge+ New API code Copyright (c) 2016-2022 University of Cambridge++This module is auto-generated from Unicode data files. DO NOT EDIT MANUALLY!+Instead, modify the maint/GenerateUcpTables.py script and run it to generate+a new version of this code.++-----------------------------------------------------------------------------+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 SUPPORT_UNICODE++/* The PRIV(utt)[] table below translates Unicode property names into type and+code values. It is searched by binary chop, so must be in collating sequence of+name. Originally, the table contained pointers to the name strings in the first+field of each entry. However, that leads to a large number of relocations when+a shared library is dynamically loaded. A significant reduction is made by+putting all the names into a single, large string and using offsets instead.+All letters are lower cased, and underscores are removed, in accordance with+the "loose matching" rules that Unicode advises and Perl uses. */++#define STRING_adlam0 STR_a STR_d STR_l STR_a STR_m "\0"+#define STRING_adlm0 STR_a STR_d STR_l STR_m "\0"+#define STRING_aghb0 STR_a STR_g STR_h STR_b "\0"+#define STRING_ahex0 STR_a STR_h STR_e STR_x "\0"+#define STRING_ahom0 STR_a STR_h STR_o STR_m "\0"+#define STRING_alpha0 STR_a STR_l STR_p STR_h STR_a "\0"+#define STRING_alphabetic0 STR_a STR_l STR_p STR_h STR_a STR_b STR_e STR_t STR_i STR_c "\0"+#define STRING_anatolianhieroglyphs0 STR_a STR_n STR_a STR_t STR_o STR_l STR_i STR_a STR_n STR_h STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"+#define STRING_any0 STR_a STR_n STR_y "\0"+#define STRING_arab0 STR_a STR_r STR_a STR_b "\0"+#define STRING_arabic0 STR_a STR_r STR_a STR_b STR_i STR_c "\0"+#define STRING_armenian0 STR_a STR_r STR_m STR_e STR_n STR_i STR_a STR_n "\0"+#define STRING_armi0 STR_a STR_r STR_m STR_i "\0"+#define STRING_armn0 STR_a STR_r STR_m STR_n "\0"+#define STRING_ascii0 STR_a STR_s STR_c STR_i STR_i "\0"+#define STRING_asciihexdigit0 STR_a STR_s STR_c STR_i STR_i STR_h STR_e STR_x STR_d STR_i STR_g STR_i STR_t "\0"+#define STRING_avestan0 STR_a STR_v STR_e STR_s STR_t STR_a STR_n "\0"+#define STRING_avst0 STR_a STR_v STR_s STR_t "\0"+#define STRING_bali0 STR_b STR_a STR_l STR_i "\0"+#define STRING_balinese0 STR_b STR_a STR_l STR_i STR_n STR_e STR_s STR_e "\0"+#define STRING_bamu0 STR_b STR_a STR_m STR_u "\0"+#define STRING_bamum0 STR_b STR_a STR_m STR_u STR_m "\0"+#define STRING_bass0 STR_b STR_a STR_s STR_s "\0"+#define STRING_bassavah0 STR_b STR_a STR_s STR_s STR_a STR_v STR_a STR_h "\0"+#define STRING_batak0 STR_b STR_a STR_t STR_a STR_k "\0"+#define STRING_batk0 STR_b STR_a STR_t STR_k "\0"+#define STRING_beng0 STR_b STR_e STR_n STR_g "\0"+#define STRING_bengali0 STR_b STR_e STR_n STR_g STR_a STR_l STR_i "\0"+#define STRING_bhaiksuki0 STR_b STR_h STR_a STR_i STR_k STR_s STR_u STR_k STR_i "\0"+#define STRING_bhks0 STR_b STR_h STR_k STR_s "\0"+#define STRING_bidial0 STR_b STR_i STR_d STR_i STR_a STR_l "\0"+#define STRING_bidian0 STR_b STR_i STR_d STR_i STR_a STR_n "\0"+#define STRING_bidib0 STR_b STR_i STR_d STR_i STR_b "\0"+#define STRING_bidibn0 STR_b STR_i STR_d STR_i STR_b STR_n "\0"+#define STRING_bidic0 STR_b STR_i STR_d STR_i STR_c "\0"+#define STRING_bidicontrol0 STR_b STR_i STR_d STR_i STR_c STR_o STR_n STR_t STR_r STR_o STR_l "\0"+#define STRING_bidics0 STR_b STR_i STR_d STR_i STR_c STR_s "\0"+#define STRING_bidien0 STR_b STR_i STR_d STR_i STR_e STR_n "\0"+#define STRING_bidies0 STR_b STR_i STR_d STR_i STR_e STR_s "\0"+#define STRING_bidiet0 STR_b STR_i STR_d STR_i STR_e STR_t "\0"+#define STRING_bidifsi0 STR_b STR_i STR_d STR_i STR_f STR_s STR_i "\0"+#define STRING_bidil0 STR_b STR_i STR_d STR_i STR_l "\0"+#define STRING_bidilre0 STR_b STR_i STR_d STR_i STR_l STR_r STR_e "\0"+#define STRING_bidilri0 STR_b STR_i STR_d STR_i STR_l STR_r STR_i "\0"+#define STRING_bidilro0 STR_b STR_i STR_d STR_i STR_l STR_r STR_o "\0"+#define STRING_bidim0 STR_b STR_i STR_d STR_i STR_m "\0"+#define STRING_bidimirrored0 STR_b STR_i STR_d STR_i STR_m STR_i STR_r STR_r STR_o STR_r STR_e STR_d "\0"+#define STRING_bidinsm0 STR_b STR_i STR_d STR_i STR_n STR_s STR_m "\0"+#define STRING_bidion0 STR_b STR_i STR_d STR_i STR_o STR_n "\0"+#define STRING_bidipdf0 STR_b STR_i STR_d STR_i STR_p STR_d STR_f "\0"+#define STRING_bidipdi0 STR_b STR_i STR_d STR_i STR_p STR_d STR_i "\0"+#define STRING_bidir0 STR_b STR_i STR_d STR_i STR_r "\0"+#define STRING_bidirle0 STR_b STR_i STR_d STR_i STR_r STR_l STR_e "\0"+#define STRING_bidirli0 STR_b STR_i STR_d STR_i STR_r STR_l STR_i "\0"+#define STRING_bidirlo0 STR_b STR_i STR_d STR_i STR_r STR_l STR_o "\0"+#define STRING_bidis0 STR_b STR_i STR_d STR_i STR_s "\0"+#define STRING_bidiws0 STR_b STR_i STR_d STR_i STR_w STR_s "\0"+#define STRING_bopo0 STR_b STR_o STR_p STR_o "\0"+#define STRING_bopomofo0 STR_b STR_o STR_p STR_o STR_m STR_o STR_f STR_o "\0"+#define STRING_brah0 STR_b STR_r STR_a STR_h "\0"+#define STRING_brahmi0 STR_b STR_r STR_a STR_h STR_m STR_i "\0"+#define STRING_brai0 STR_b STR_r STR_a STR_i "\0"+#define STRING_braille0 STR_b STR_r STR_a STR_i STR_l STR_l STR_e "\0"+#define STRING_bugi0 STR_b STR_u STR_g STR_i "\0"+#define STRING_buginese0 STR_b STR_u STR_g STR_i STR_n STR_e STR_s STR_e "\0"+#define STRING_buhd0 STR_b STR_u STR_h STR_d "\0"+#define STRING_buhid0 STR_b STR_u STR_h STR_i STR_d "\0"+#define STRING_c0 STR_c "\0"+#define STRING_cakm0 STR_c STR_a STR_k STR_m "\0"+#define STRING_canadianaboriginal0 STR_c STR_a STR_n STR_a STR_d STR_i STR_a STR_n STR_a STR_b STR_o STR_r STR_i STR_g STR_i STR_n STR_a STR_l "\0"+#define STRING_cans0 STR_c STR_a STR_n STR_s "\0"+#define STRING_cari0 STR_c STR_a STR_r STR_i "\0"+#define STRING_carian0 STR_c STR_a STR_r STR_i STR_a STR_n "\0"+#define STRING_cased0 STR_c STR_a STR_s STR_e STR_d "\0"+#define STRING_caseignorable0 STR_c STR_a STR_s STR_e STR_i STR_g STR_n STR_o STR_r STR_a STR_b STR_l STR_e "\0"+#define STRING_caucasianalbanian0 STR_c STR_a STR_u STR_c STR_a STR_s STR_i STR_a STR_n STR_a STR_l STR_b STR_a STR_n STR_i STR_a STR_n "\0"+#define STRING_cc0 STR_c STR_c "\0"+#define STRING_cf0 STR_c STR_f "\0"+#define STRING_chakma0 STR_c STR_h STR_a STR_k STR_m STR_a "\0"+#define STRING_cham0 STR_c STR_h STR_a STR_m "\0"+#define STRING_changeswhencasefolded0 STR_c STR_h STR_a STR_n STR_g STR_e STR_s STR_w STR_h STR_e STR_n STR_c STR_a STR_s STR_e STR_f STR_o STR_l STR_d STR_e STR_d "\0"+#define STRING_changeswhencasemapped0 STR_c STR_h STR_a STR_n STR_g STR_e STR_s STR_w STR_h STR_e STR_n STR_c STR_a STR_s STR_e STR_m STR_a STR_p STR_p STR_e STR_d "\0"+#define STRING_changeswhenlowercased0 STR_c STR_h STR_a STR_n STR_g STR_e STR_s STR_w STR_h STR_e STR_n STR_l STR_o STR_w STR_e STR_r STR_c STR_a STR_s STR_e STR_d "\0"+#define STRING_changeswhentitlecased0 STR_c STR_h STR_a STR_n STR_g STR_e STR_s STR_w STR_h STR_e STR_n STR_t STR_i STR_t STR_l STR_e STR_c STR_a STR_s STR_e STR_d "\0"+#define STRING_changeswhenuppercased0 STR_c STR_h STR_a STR_n STR_g STR_e STR_s STR_w STR_h STR_e STR_n STR_u STR_p STR_p STR_e STR_r STR_c STR_a STR_s STR_e STR_d "\0"+#define STRING_cher0 STR_c STR_h STR_e STR_r "\0"+#define STRING_cherokee0 STR_c STR_h STR_e STR_r STR_o STR_k STR_e STR_e "\0"+#define STRING_chorasmian0 STR_c STR_h STR_o STR_r STR_a STR_s STR_m STR_i STR_a STR_n "\0"+#define STRING_chrs0 STR_c STR_h STR_r STR_s "\0"+#define STRING_ci0 STR_c STR_i "\0"+#define STRING_cn0 STR_c STR_n "\0"+#define STRING_co0 STR_c STR_o "\0"+#define STRING_common0 STR_c STR_o STR_m STR_m STR_o STR_n "\0"+#define STRING_copt0 STR_c STR_o STR_p STR_t "\0"+#define STRING_coptic0 STR_c STR_o STR_p STR_t STR_i STR_c "\0"+#define STRING_cpmn0 STR_c STR_p STR_m STR_n "\0"+#define STRING_cprt0 STR_c STR_p STR_r STR_t "\0"+#define STRING_cs0 STR_c STR_s "\0"+#define STRING_cuneiform0 STR_c STR_u STR_n STR_e STR_i STR_f STR_o STR_r STR_m "\0"+#define STRING_cwcf0 STR_c STR_w STR_c STR_f "\0"+#define STRING_cwcm0 STR_c STR_w STR_c STR_m "\0"+#define STRING_cwl0 STR_c STR_w STR_l "\0"+#define STRING_cwt0 STR_c STR_w STR_t "\0"+#define STRING_cwu0 STR_c STR_w STR_u "\0"+#define STRING_cypriot0 STR_c STR_y STR_p STR_r STR_i STR_o STR_t "\0"+#define STRING_cyprominoan0 STR_c STR_y STR_p STR_r STR_o STR_m STR_i STR_n STR_o STR_a STR_n "\0"+#define STRING_cyrillic0 STR_c STR_y STR_r STR_i STR_l STR_l STR_i STR_c "\0"+#define STRING_cyrl0 STR_c STR_y STR_r STR_l "\0"+#define STRING_dash0 STR_d STR_a STR_s STR_h "\0"+#define STRING_defaultignorablecodepoint0 STR_d STR_e STR_f STR_a STR_u STR_l STR_t STR_i STR_g STR_n STR_o STR_r STR_a STR_b STR_l STR_e STR_c STR_o STR_d STR_e STR_p STR_o STR_i STR_n STR_t "\0"+#define STRING_dep0 STR_d STR_e STR_p "\0"+#define STRING_deprecated0 STR_d STR_e STR_p STR_r STR_e STR_c STR_a STR_t STR_e STR_d "\0"+#define STRING_deseret0 STR_d STR_e STR_s STR_e STR_r STR_e STR_t "\0"+#define STRING_deva0 STR_d STR_e STR_v STR_a "\0"+#define STRING_devanagari0 STR_d STR_e STR_v STR_a STR_n STR_a STR_g STR_a STR_r STR_i "\0"+#define STRING_di0 STR_d STR_i "\0"+#define STRING_dia0 STR_d STR_i STR_a "\0"+#define STRING_diacritic0 STR_d STR_i STR_a STR_c STR_r STR_i STR_t STR_i STR_c "\0"+#define STRING_diak0 STR_d STR_i STR_a STR_k "\0"+#define STRING_divesakuru0 STR_d STR_i STR_v STR_e STR_s STR_a STR_k STR_u STR_r STR_u "\0"+#define STRING_dogr0 STR_d STR_o STR_g STR_r "\0"+#define STRING_dogra0 STR_d STR_o STR_g STR_r STR_a "\0"+#define STRING_dsrt0 STR_d STR_s STR_r STR_t "\0"+#define STRING_dupl0 STR_d STR_u STR_p STR_l "\0"+#define STRING_duployan0 STR_d STR_u STR_p STR_l STR_o STR_y STR_a STR_n "\0"+#define STRING_ebase0 STR_e STR_b STR_a STR_s STR_e "\0"+#define STRING_ecomp0 STR_e STR_c STR_o STR_m STR_p "\0"+#define STRING_egyp0 STR_e STR_g STR_y STR_p "\0"+#define STRING_egyptianhieroglyphs0 STR_e STR_g STR_y STR_p STR_t STR_i STR_a STR_n STR_h STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"+#define STRING_elba0 STR_e STR_l STR_b STR_a "\0"+#define STRING_elbasan0 STR_e STR_l STR_b STR_a STR_s STR_a STR_n "\0"+#define STRING_elym0 STR_e STR_l STR_y STR_m "\0"+#define STRING_elymaic0 STR_e STR_l STR_y STR_m STR_a STR_i STR_c "\0"+#define STRING_emod0 STR_e STR_m STR_o STR_d "\0"+#define STRING_emoji0 STR_e STR_m STR_o STR_j STR_i "\0"+#define STRING_emojicomponent0 STR_e STR_m STR_o STR_j STR_i STR_c STR_o STR_m STR_p STR_o STR_n STR_e STR_n STR_t "\0"+#define STRING_emojimodifier0 STR_e STR_m STR_o STR_j STR_i STR_m STR_o STR_d STR_i STR_f STR_i STR_e STR_r "\0"+#define STRING_emojimodifierbase0 STR_e STR_m STR_o STR_j STR_i STR_m STR_o STR_d STR_i STR_f STR_i STR_e STR_r STR_b STR_a STR_s STR_e "\0"+#define STRING_emojipresentation0 STR_e STR_m STR_o STR_j STR_i STR_p STR_r STR_e STR_s STR_e STR_n STR_t STR_a STR_t STR_i STR_o STR_n "\0"+#define STRING_epres0 STR_e STR_p STR_r STR_e STR_s "\0"+#define STRING_ethi0 STR_e STR_t STR_h STR_i "\0"+#define STRING_ethiopic0 STR_e STR_t STR_h STR_i STR_o STR_p STR_i STR_c "\0"+#define STRING_ext0 STR_e STR_x STR_t "\0"+#define STRING_extendedpictographic0 STR_e STR_x STR_t STR_e STR_n STR_d STR_e STR_d STR_p STR_i STR_c STR_t STR_o STR_g STR_r STR_a STR_p STR_h STR_i STR_c "\0"+#define STRING_extender0 STR_e STR_x STR_t STR_e STR_n STR_d STR_e STR_r "\0"+#define STRING_extpict0 STR_e STR_x STR_t STR_p STR_i STR_c STR_t "\0"+#define STRING_gara0 STR_g STR_a STR_r STR_a "\0"+#define STRING_garay0 STR_g STR_a STR_r STR_a STR_y "\0"+#define STRING_geor0 STR_g STR_e STR_o STR_r "\0"+#define STRING_georgian0 STR_g STR_e STR_o STR_r STR_g STR_i STR_a STR_n "\0"+#define STRING_glag0 STR_g STR_l STR_a STR_g "\0"+#define STRING_glagolitic0 STR_g STR_l STR_a STR_g STR_o STR_l STR_i STR_t STR_i STR_c "\0"+#define STRING_gong0 STR_g STR_o STR_n STR_g "\0"+#define STRING_gonm0 STR_g STR_o STR_n STR_m "\0"+#define STRING_goth0 STR_g STR_o STR_t STR_h "\0"+#define STRING_gothic0 STR_g STR_o STR_t STR_h STR_i STR_c "\0"+#define STRING_gran0 STR_g STR_r STR_a STR_n "\0"+#define STRING_grantha0 STR_g STR_r STR_a STR_n STR_t STR_h STR_a "\0"+#define STRING_graphemebase0 STR_g STR_r STR_a STR_p STR_h STR_e STR_m STR_e STR_b STR_a STR_s STR_e "\0"+#define STRING_graphemeextend0 STR_g STR_r STR_a STR_p STR_h STR_e STR_m STR_e STR_e STR_x STR_t STR_e STR_n STR_d "\0"+#define STRING_graphemelink0 STR_g STR_r STR_a STR_p STR_h STR_e STR_m STR_e STR_l STR_i STR_n STR_k "\0"+#define STRING_grbase0 STR_g STR_r STR_b STR_a STR_s STR_e "\0"+#define STRING_greek0 STR_g STR_r STR_e STR_e STR_k "\0"+#define STRING_grek0 STR_g STR_r STR_e STR_k "\0"+#define STRING_grext0 STR_g STR_r STR_e STR_x STR_t "\0"+#define STRING_grlink0 STR_g STR_r STR_l STR_i STR_n STR_k "\0"+#define STRING_gujarati0 STR_g STR_u STR_j STR_a STR_r STR_a STR_t STR_i "\0"+#define STRING_gujr0 STR_g STR_u STR_j STR_r "\0"+#define STRING_gukh0 STR_g STR_u STR_k STR_h "\0"+#define STRING_gunjalagondi0 STR_g STR_u STR_n STR_j STR_a STR_l STR_a STR_g STR_o STR_n STR_d STR_i "\0"+#define STRING_gurmukhi0 STR_g STR_u STR_r STR_m STR_u STR_k STR_h STR_i "\0"+#define STRING_guru0 STR_g STR_u STR_r STR_u "\0"+#define STRING_gurungkhema0 STR_g STR_u STR_r STR_u STR_n STR_g STR_k STR_h STR_e STR_m STR_a "\0"+#define STRING_han0 STR_h STR_a STR_n "\0"+#define STRING_hang0 STR_h STR_a STR_n STR_g "\0"+#define STRING_hangul0 STR_h STR_a STR_n STR_g STR_u STR_l "\0"+#define STRING_hani0 STR_h STR_a STR_n STR_i "\0"+#define STRING_hanifirohingya0 STR_h STR_a STR_n STR_i STR_f STR_i STR_r STR_o STR_h STR_i STR_n STR_g STR_y STR_a "\0"+#define STRING_hano0 STR_h STR_a STR_n STR_o "\0"+#define STRING_hanunoo0 STR_h STR_a STR_n STR_u STR_n STR_o STR_o "\0"+#define STRING_hatr0 STR_h STR_a STR_t STR_r "\0"+#define STRING_hatran0 STR_h STR_a STR_t STR_r STR_a STR_n "\0"+#define STRING_hebr0 STR_h STR_e STR_b STR_r "\0"+#define STRING_hebrew0 STR_h STR_e STR_b STR_r STR_e STR_w "\0"+#define STRING_hex0 STR_h STR_e STR_x "\0"+#define STRING_hexdigit0 STR_h STR_e STR_x STR_d STR_i STR_g STR_i STR_t "\0"+#define STRING_hira0 STR_h STR_i STR_r STR_a "\0"+#define STRING_hiragana0 STR_h STR_i STR_r STR_a STR_g STR_a STR_n STR_a "\0"+#define STRING_hluw0 STR_h STR_l STR_u STR_w "\0"+#define STRING_hmng0 STR_h STR_m STR_n STR_g "\0"+#define STRING_hmnp0 STR_h STR_m STR_n STR_p "\0"+#define STRING_hung0 STR_h STR_u STR_n STR_g "\0"+#define STRING_idc0 STR_i STR_d STR_c "\0"+#define STRING_idcompatmathcontinue0 STR_i STR_d STR_c STR_o STR_m STR_p STR_a STR_t STR_m STR_a STR_t STR_h STR_c STR_o STR_n STR_t STR_i STR_n STR_u STR_e "\0"+#define STRING_idcompatmathstart0 STR_i STR_d STR_c STR_o STR_m STR_p STR_a STR_t STR_m STR_a STR_t STR_h STR_s STR_t STR_a STR_r STR_t "\0"+#define STRING_idcontinue0 STR_i STR_d STR_c STR_o STR_n STR_t STR_i STR_n STR_u STR_e "\0"+#define STRING_ideo0 STR_i STR_d STR_e STR_o "\0"+#define STRING_ideographic0 STR_i STR_d STR_e STR_o STR_g STR_r STR_a STR_p STR_h STR_i STR_c "\0"+#define STRING_ids0 STR_i STR_d STR_s "\0"+#define STRING_idsb0 STR_i STR_d STR_s STR_b "\0"+#define STRING_idsbinaryoperator0 STR_i STR_d STR_s STR_b STR_i STR_n STR_a STR_r STR_y STR_o STR_p STR_e STR_r STR_a STR_t STR_o STR_r "\0"+#define STRING_idst0 STR_i STR_d STR_s STR_t "\0"+#define STRING_idstart0 STR_i STR_d STR_s STR_t STR_a STR_r STR_t "\0"+#define STRING_idstrinaryoperator0 STR_i STR_d STR_s STR_t STR_r STR_i STR_n STR_a STR_r STR_y STR_o STR_p STR_e STR_r STR_a STR_t STR_o STR_r "\0"+#define STRING_idsu0 STR_i STR_d STR_s STR_u "\0"+#define STRING_idsunaryoperator0 STR_i STR_d STR_s STR_u STR_n STR_a STR_r STR_y STR_o STR_p STR_e STR_r STR_a STR_t STR_o STR_r "\0"+#define STRING_imperialaramaic0 STR_i STR_m STR_p STR_e STR_r STR_i STR_a STR_l STR_a STR_r STR_a STR_m STR_a STR_i STR_c "\0"+#define STRING_incb0 STR_i STR_n STR_c STR_b "\0"+#define STRING_inherited0 STR_i STR_n STR_h STR_e STR_r STR_i STR_t STR_e STR_d "\0"+#define STRING_inscriptionalpahlavi0 STR_i STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_p STR_a STR_h STR_l STR_a STR_v STR_i "\0"+#define STRING_inscriptionalparthian0 STR_i STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_p STR_a STR_r STR_t STR_h STR_i STR_a STR_n "\0"+#define STRING_ital0 STR_i STR_t STR_a STR_l "\0"+#define STRING_java0 STR_j STR_a STR_v STR_a "\0"+#define STRING_javanese0 STR_j STR_a STR_v STR_a STR_n STR_e STR_s STR_e "\0"+#define STRING_joinc0 STR_j STR_o STR_i STR_n STR_c "\0"+#define STRING_joincontrol0 STR_j STR_o STR_i STR_n STR_c STR_o STR_n STR_t STR_r STR_o STR_l "\0"+#define STRING_kaithi0 STR_k STR_a STR_i STR_t STR_h STR_i "\0"+#define STRING_kali0 STR_k STR_a STR_l STR_i "\0"+#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"+#define STRING_khitansmallscript0 STR_k STR_h STR_i STR_t STR_a STR_n STR_s STR_m STR_a STR_l STR_l STR_s STR_c STR_r STR_i STR_p STR_t "\0"+#define STRING_khmer0 STR_k STR_h STR_m STR_e STR_r "\0"+#define STRING_khmr0 STR_k STR_h STR_m STR_r "\0"+#define STRING_khoj0 STR_k STR_h STR_o STR_j "\0"+#define STRING_khojki0 STR_k STR_h STR_o STR_j STR_k STR_i "\0"+#define STRING_khudawadi0 STR_k STR_h STR_u STR_d STR_a STR_w STR_a STR_d STR_i "\0"+#define STRING_kiratrai0 STR_k STR_i STR_r STR_a STR_t STR_r STR_a STR_i "\0"+#define STRING_kits0 STR_k STR_i STR_t STR_s "\0"+#define STRING_knda0 STR_k STR_n STR_d STR_a "\0"+#define STRING_krai0 STR_k STR_r STR_a STR_i "\0"+#define STRING_kthi0 STR_k STR_t STR_h STR_i "\0"+#define STRING_l0 STR_l "\0"+#define STRING_l_AMPERSAND0 STR_l STR_AMPERSAND "\0"+#define STRING_lana0 STR_l STR_a STR_n STR_a "\0"+#define STRING_lao0 STR_l STR_a STR_o "\0"+#define STRING_laoo0 STR_l STR_a STR_o STR_o "\0"+#define STRING_latin0 STR_l STR_a STR_t STR_i STR_n "\0"+#define STRING_latn0 STR_l STR_a STR_t STR_n "\0"+#define STRING_lc0 STR_l STR_c "\0"+#define STRING_lepc0 STR_l STR_e STR_p STR_c "\0"+#define STRING_lepcha0 STR_l STR_e STR_p STR_c STR_h STR_a "\0"+#define STRING_limb0 STR_l STR_i STR_m STR_b "\0"+#define STRING_limbu0 STR_l STR_i STR_m STR_b STR_u "\0"+#define STRING_lina0 STR_l STR_i STR_n STR_a "\0"+#define STRING_linb0 STR_l STR_i STR_n STR_b "\0"+#define STRING_lineara0 STR_l STR_i STR_n STR_e STR_a STR_r STR_a "\0"+#define STRING_linearb0 STR_l STR_i STR_n STR_e STR_a STR_r STR_b "\0"+#define STRING_lisu0 STR_l STR_i STR_s STR_u "\0"+#define STRING_ll0 STR_l STR_l "\0"+#define STRING_lm0 STR_l STR_m "\0"+#define STRING_lo0 STR_l STR_o "\0"+#define STRING_loe0 STR_l STR_o STR_e "\0"+#define STRING_logicalorderexception0 STR_l STR_o STR_g STR_i STR_c STR_a STR_l STR_o STR_r STR_d STR_e STR_r STR_e STR_x STR_c STR_e STR_p STR_t STR_i STR_o STR_n "\0"+#define STRING_lower0 STR_l STR_o STR_w STR_e STR_r "\0"+#define STRING_lowercase0 STR_l STR_o STR_w STR_e STR_r STR_c STR_a STR_s STR_e "\0"+#define STRING_lt0 STR_l STR_t "\0"+#define STRING_lu0 STR_l STR_u "\0"+#define STRING_lyci0 STR_l STR_y STR_c STR_i "\0"+#define STRING_lycian0 STR_l STR_y STR_c STR_i STR_a STR_n "\0"+#define STRING_lydi0 STR_l STR_y STR_d STR_i "\0"+#define STRING_lydian0 STR_l STR_y STR_d STR_i STR_a STR_n "\0"+#define STRING_m0 STR_m "\0"+#define STRING_mahajani0 STR_m STR_a STR_h STR_a STR_j STR_a STR_n STR_i "\0"+#define STRING_mahj0 STR_m STR_a STR_h STR_j "\0"+#define STRING_maka0 STR_m STR_a STR_k STR_a "\0"+#define STRING_makasar0 STR_m STR_a STR_k STR_a STR_s STR_a STR_r "\0"+#define STRING_malayalam0 STR_m STR_a STR_l STR_a STR_y STR_a STR_l STR_a STR_m "\0"+#define STRING_mand0 STR_m STR_a STR_n STR_d "\0"+#define STRING_mandaic0 STR_m STR_a STR_n STR_d STR_a STR_i STR_c "\0"+#define STRING_mani0 STR_m STR_a STR_n STR_i "\0"+#define STRING_manichaean0 STR_m STR_a STR_n STR_i STR_c STR_h STR_a STR_e STR_a STR_n "\0"+#define STRING_marc0 STR_m STR_a STR_r STR_c "\0"+#define STRING_marchen0 STR_m STR_a STR_r STR_c STR_h STR_e STR_n "\0"+#define STRING_masaramgondi0 STR_m STR_a STR_s STR_a STR_r STR_a STR_m STR_g STR_o STR_n STR_d STR_i "\0"+#define STRING_math0 STR_m STR_a STR_t STR_h "\0"+#define STRING_mc0 STR_m STR_c "\0"+#define STRING_mcm0 STR_m STR_c STR_m "\0"+#define STRING_me0 STR_m STR_e "\0"+#define STRING_medefaidrin0 STR_m STR_e STR_d STR_e STR_f STR_a STR_i STR_d STR_r STR_i STR_n "\0"+#define STRING_medf0 STR_m STR_e STR_d STR_f "\0"+#define STRING_meeteimayek0 STR_m STR_e STR_e STR_t STR_e STR_i STR_m STR_a STR_y STR_e STR_k "\0"+#define STRING_mend0 STR_m STR_e STR_n STR_d "\0"+#define STRING_mendekikakui0 STR_m STR_e STR_n STR_d STR_e STR_k STR_i STR_k STR_a STR_k STR_u STR_i "\0"+#define STRING_merc0 STR_m STR_e STR_r STR_c "\0"+#define STRING_mero0 STR_m STR_e STR_r STR_o "\0"+#define STRING_meroiticcursive0 STR_m STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_c STR_u STR_r STR_s STR_i STR_v STR_e "\0"+#define STRING_meroitichieroglyphs0 STR_m STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_h STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"+#define STRING_miao0 STR_m STR_i STR_a STR_o "\0"+#define STRING_mlym0 STR_m STR_l STR_y STR_m "\0"+#define STRING_mn0 STR_m STR_n "\0"+#define STRING_modi0 STR_m STR_o STR_d STR_i "\0"+#define STRING_modifiercombiningmark0 STR_m STR_o STR_d STR_i STR_f STR_i STR_e STR_r STR_c STR_o STR_m STR_b STR_i STR_n STR_i STR_n STR_g STR_m STR_a STR_r STR_k "\0"+#define STRING_mong0 STR_m STR_o STR_n STR_g "\0"+#define STRING_mongolian0 STR_m STR_o STR_n STR_g STR_o STR_l STR_i STR_a STR_n "\0"+#define STRING_mro0 STR_m STR_r STR_o "\0"+#define STRING_mroo0 STR_m STR_r STR_o STR_o "\0"+#define STRING_mtei0 STR_m STR_t STR_e STR_i "\0"+#define STRING_mult0 STR_m STR_u STR_l STR_t "\0"+#define STRING_multani0 STR_m STR_u STR_l STR_t STR_a STR_n STR_i "\0"+#define STRING_myanmar0 STR_m STR_y STR_a STR_n STR_m STR_a STR_r "\0"+#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"+#define STRING_nbat0 STR_n STR_b STR_a STR_t "\0"+#define STRING_nchar0 STR_n STR_c STR_h STR_a STR_r "\0"+#define STRING_nd0 STR_n STR_d "\0"+#define STRING_newa0 STR_n STR_e STR_w STR_a "\0"+#define STRING_newtailue0 STR_n STR_e STR_w STR_t STR_a STR_i STR_l STR_u STR_e "\0"+#define STRING_nko0 STR_n STR_k STR_o "\0"+#define STRING_nkoo0 STR_n STR_k STR_o STR_o "\0"+#define STRING_nl0 STR_n STR_l "\0"+#define STRING_no0 STR_n STR_o "\0"+#define STRING_noncharactercodepoint0 STR_n STR_o STR_n STR_c STR_h STR_a STR_r STR_a STR_c STR_t STR_e STR_r STR_c STR_o STR_d STR_e STR_p STR_o STR_i STR_n STR_t "\0"+#define STRING_nshu0 STR_n STR_s STR_h STR_u "\0"+#define STRING_nushu0 STR_n STR_u STR_s STR_h STR_u "\0"+#define STRING_nyiakengpuachuehmong0 STR_n STR_y STR_i STR_a STR_k STR_e STR_n STR_g STR_p STR_u STR_a STR_c STR_h STR_u STR_e STR_h STR_m STR_o STR_n STR_g "\0"+#define STRING_ogam0 STR_o STR_g STR_a STR_m "\0"+#define STRING_ogham0 STR_o STR_g STR_h STR_a STR_m "\0"+#define STRING_olchiki0 STR_o STR_l STR_c STR_h STR_i STR_k STR_i "\0"+#define STRING_olck0 STR_o STR_l STR_c STR_k "\0"+#define STRING_oldhungarian0 STR_o STR_l STR_d STR_h STR_u STR_n STR_g STR_a STR_r STR_i STR_a STR_n "\0"+#define STRING_olditalic0 STR_o STR_l STR_d STR_i STR_t STR_a STR_l STR_i STR_c "\0"+#define STRING_oldnortharabian0 STR_o STR_l STR_d STR_n STR_o STR_r STR_t STR_h STR_a STR_r STR_a STR_b STR_i STR_a STR_n "\0"+#define STRING_oldpermic0 STR_o STR_l STR_d STR_p STR_e STR_r STR_m STR_i STR_c "\0"+#define STRING_oldpersian0 STR_o STR_l STR_d STR_p STR_e STR_r STR_s STR_i STR_a STR_n "\0"+#define STRING_oldsogdian0 STR_o STR_l STR_d STR_s STR_o STR_g STR_d STR_i STR_a STR_n "\0"+#define STRING_oldsoutharabian0 STR_o STR_l STR_d STR_s STR_o STR_u STR_t STR_h STR_a STR_r STR_a STR_b STR_i STR_a STR_n "\0"+#define STRING_oldturkic0 STR_o STR_l STR_d STR_t STR_u STR_r STR_k STR_i STR_c "\0"+#define STRING_olduyghur0 STR_o STR_l STR_d STR_u STR_y STR_g STR_h STR_u STR_r "\0"+#define STRING_olonal0 STR_o STR_l STR_o STR_n STR_a STR_l "\0"+#define STRING_onao0 STR_o STR_n STR_a STR_o "\0"+#define STRING_oriya0 STR_o STR_r STR_i STR_y STR_a "\0"+#define STRING_orkh0 STR_o STR_r STR_k STR_h "\0"+#define STRING_orya0 STR_o STR_r STR_y STR_a "\0"+#define STRING_osage0 STR_o STR_s STR_a STR_g STR_e "\0"+#define STRING_osge0 STR_o STR_s STR_g STR_e "\0"+#define STRING_osma0 STR_o STR_s STR_m STR_a "\0"+#define STRING_osmanya0 STR_o STR_s STR_m STR_a STR_n STR_y STR_a "\0"+#define STRING_ougr0 STR_o STR_u STR_g STR_r "\0"+#define STRING_p0 STR_p "\0"+#define STRING_pahawhhmong0 STR_p STR_a STR_h STR_a STR_w STR_h STR_h STR_m STR_o STR_n STR_g "\0"+#define STRING_palm0 STR_p STR_a STR_l STR_m "\0"+#define STRING_palmyrene0 STR_p STR_a STR_l STR_m STR_y STR_r STR_e STR_n STR_e "\0"+#define STRING_patsyn0 STR_p STR_a STR_t STR_s STR_y STR_n "\0"+#define STRING_patternsyntax0 STR_p STR_a STR_t STR_t STR_e STR_r STR_n STR_s STR_y STR_n STR_t STR_a STR_x "\0"+#define STRING_patternwhitespace0 STR_p STR_a STR_t STR_t STR_e STR_r STR_n STR_w STR_h STR_i STR_t STR_e STR_s STR_p STR_a STR_c STR_e "\0"+#define STRING_patws0 STR_p STR_a STR_t STR_w STR_s "\0"+#define STRING_pauc0 STR_p STR_a STR_u STR_c "\0"+#define STRING_paucinhau0 STR_p STR_a STR_u STR_c STR_i STR_n STR_h STR_a STR_u "\0"+#define STRING_pc0 STR_p STR_c "\0"+#define STRING_pcm0 STR_p STR_c STR_m "\0"+#define STRING_pd0 STR_p STR_d "\0"+#define STRING_pe0 STR_p STR_e "\0"+#define STRING_perm0 STR_p STR_e STR_r STR_m "\0"+#define STRING_pf0 STR_p STR_f "\0"+#define STRING_phag0 STR_p STR_h STR_a STR_g "\0"+#define STRING_phagspa0 STR_p STR_h STR_a STR_g STR_s STR_p STR_a "\0"+#define STRING_phli0 STR_p STR_h STR_l STR_i "\0"+#define STRING_phlp0 STR_p STR_h STR_l STR_p "\0"+#define STRING_phnx0 STR_p STR_h STR_n STR_x "\0"+#define STRING_phoenician0 STR_p STR_h STR_o STR_e STR_n STR_i STR_c STR_i STR_a STR_n "\0"+#define STRING_pi0 STR_p STR_i "\0"+#define STRING_plrd0 STR_p STR_l STR_r STR_d "\0"+#define STRING_po0 STR_p STR_o "\0"+#define STRING_prependedconcatenationmark0 STR_p STR_r STR_e STR_p STR_e STR_n STR_d STR_e STR_d STR_c STR_o STR_n STR_c STR_a STR_t STR_e STR_n STR_a STR_t STR_i STR_o STR_n STR_m STR_a STR_r STR_k "\0"+#define STRING_prti0 STR_p STR_r STR_t STR_i "\0"+#define STRING_ps0 STR_p STR_s "\0"+#define STRING_psalterpahlavi0 STR_p STR_s STR_a STR_l STR_t STR_e STR_r STR_p STR_a STR_h STR_l STR_a STR_v STR_i "\0"+#define STRING_qaac0 STR_q STR_a STR_a STR_c "\0"+#define STRING_qaai0 STR_q STR_a STR_a STR_i "\0"+#define STRING_qmark0 STR_q STR_m STR_a STR_r STR_k "\0"+#define STRING_quotationmark0 STR_q STR_u STR_o STR_t STR_a STR_t STR_i STR_o STR_n STR_m STR_a STR_r STR_k "\0"+#define STRING_radical0 STR_r STR_a STR_d STR_i STR_c STR_a STR_l "\0"+#define STRING_regionalindicator0 STR_r STR_e STR_g STR_i STR_o STR_n STR_a STR_l STR_i STR_n STR_d STR_i STR_c STR_a STR_t STR_o STR_r "\0"+#define STRING_rejang0 STR_r STR_e STR_j STR_a STR_n STR_g "\0"+#define STRING_ri0 STR_r STR_i "\0"+#define STRING_rjng0 STR_r STR_j STR_n STR_g "\0"+#define STRING_rohg0 STR_r STR_o STR_h STR_g "\0"+#define STRING_runic0 STR_r STR_u STR_n STR_i STR_c "\0"+#define STRING_runr0 STR_r STR_u STR_n STR_r "\0"+#define STRING_s0 STR_s "\0"+#define STRING_samaritan0 STR_s STR_a STR_m STR_a STR_r STR_i STR_t STR_a STR_n "\0"+#define STRING_samr0 STR_s STR_a STR_m STR_r "\0"+#define STRING_sarb0 STR_s STR_a STR_r STR_b "\0"+#define STRING_saur0 STR_s STR_a STR_u STR_r "\0"+#define STRING_saurashtra0 STR_s STR_a STR_u STR_r STR_a STR_s STR_h STR_t STR_r STR_a "\0"+#define STRING_sc0 STR_s STR_c "\0"+#define STRING_sd0 STR_s STR_d "\0"+#define STRING_sentenceterminal0 STR_s STR_e STR_n STR_t STR_e STR_n STR_c STR_e STR_t STR_e STR_r STR_m STR_i STR_n STR_a STR_l "\0"+#define STRING_sgnw0 STR_s STR_g STR_n STR_w "\0"+#define STRING_sharada0 STR_s STR_h STR_a STR_r STR_a STR_d STR_a "\0"+#define STRING_shavian0 STR_s STR_h STR_a STR_v STR_i STR_a STR_n "\0"+#define STRING_shaw0 STR_s STR_h STR_a STR_w "\0"+#define STRING_shrd0 STR_s STR_h STR_r STR_d "\0"+#define STRING_sidd0 STR_s STR_i STR_d STR_d "\0"+#define STRING_siddham0 STR_s STR_i STR_d STR_d STR_h STR_a STR_m "\0"+#define STRING_signwriting0 STR_s STR_i STR_g STR_n STR_w STR_r STR_i STR_t STR_i STR_n STR_g "\0"+#define STRING_sind0 STR_s STR_i STR_n STR_d "\0"+#define STRING_sinh0 STR_s STR_i STR_n STR_h "\0"+#define STRING_sinhala0 STR_s STR_i STR_n STR_h STR_a STR_l STR_a "\0"+#define STRING_sk0 STR_s STR_k "\0"+#define STRING_sm0 STR_s STR_m "\0"+#define STRING_so0 STR_s STR_o "\0"+#define STRING_softdotted0 STR_s STR_o STR_f STR_t STR_d STR_o STR_t STR_t STR_e STR_d "\0"+#define STRING_sogd0 STR_s STR_o STR_g STR_d "\0"+#define STRING_sogdian0 STR_s STR_o STR_g STR_d STR_i STR_a STR_n "\0"+#define STRING_sogo0 STR_s STR_o STR_g STR_o "\0"+#define STRING_sora0 STR_s STR_o STR_r STR_a "\0"+#define STRING_sorasompeng0 STR_s STR_o STR_r STR_a STR_s STR_o STR_m STR_p STR_e STR_n STR_g "\0"+#define STRING_soyo0 STR_s STR_o STR_y STR_o "\0"+#define STRING_soyombo0 STR_s STR_o STR_y STR_o STR_m STR_b STR_o "\0"+#define STRING_space0 STR_s STR_p STR_a STR_c STR_e "\0"+#define STRING_sterm0 STR_s STR_t STR_e STR_r STR_m "\0"+#define STRING_sund0 STR_s STR_u STR_n STR_d "\0"+#define STRING_sundanese0 STR_s STR_u STR_n STR_d STR_a STR_n STR_e STR_s STR_e "\0"+#define STRING_sunu0 STR_s STR_u STR_n STR_u "\0"+#define STRING_sunuwar0 STR_s STR_u STR_n STR_u STR_w STR_a STR_r "\0"+#define STRING_sylo0 STR_s STR_y STR_l STR_o "\0"+#define STRING_sylotinagri0 STR_s STR_y STR_l STR_o STR_t STR_i STR_n STR_a STR_g STR_r STR_i "\0"+#define STRING_syrc0 STR_s STR_y STR_r STR_c "\0"+#define STRING_syriac0 STR_s STR_y STR_r STR_i STR_a STR_c "\0"+#define STRING_tagalog0 STR_t STR_a STR_g STR_a STR_l STR_o STR_g "\0"+#define STRING_tagb0 STR_t STR_a STR_g STR_b "\0"+#define STRING_tagbanwa0 STR_t STR_a STR_g STR_b STR_a STR_n STR_w STR_a "\0"+#define STRING_taile0 STR_t STR_a STR_i STR_l STR_e "\0"+#define STRING_taitham0 STR_t STR_a STR_i STR_t STR_h STR_a STR_m "\0"+#define STRING_taiviet0 STR_t STR_a STR_i STR_v STR_i STR_e STR_t "\0"+#define STRING_takr0 STR_t STR_a STR_k STR_r "\0"+#define STRING_takri0 STR_t STR_a STR_k STR_r STR_i "\0"+#define STRING_tale0 STR_t STR_a STR_l STR_e "\0"+#define STRING_talu0 STR_t STR_a STR_l STR_u "\0"+#define STRING_tamil0 STR_t STR_a STR_m STR_i STR_l "\0"+#define STRING_taml0 STR_t STR_a STR_m STR_l "\0"+#define STRING_tang0 STR_t STR_a STR_n STR_g "\0"+#define STRING_tangsa0 STR_t STR_a STR_n STR_g STR_s STR_a "\0"+#define STRING_tangut0 STR_t STR_a STR_n STR_g STR_u STR_t "\0"+#define STRING_tavt0 STR_t STR_a STR_v STR_t "\0"+#define STRING_telu0 STR_t STR_e STR_l STR_u "\0"+#define STRING_telugu0 STR_t STR_e STR_l STR_u STR_g STR_u "\0"+#define STRING_term0 STR_t STR_e STR_r STR_m "\0"+#define STRING_terminalpunctuation0 STR_t STR_e STR_r STR_m STR_i STR_n STR_a STR_l STR_p STR_u STR_n STR_c STR_t STR_u STR_a STR_t STR_i STR_o STR_n "\0"+#define STRING_tfng0 STR_t STR_f STR_n STR_g "\0"+#define STRING_tglg0 STR_t STR_g STR_l STR_g "\0"+#define STRING_thaa0 STR_t STR_h STR_a STR_a "\0"+#define STRING_thaana0 STR_t STR_h STR_a STR_a STR_n STR_a "\0"+#define STRING_thai0 STR_t STR_h STR_a STR_i "\0"+#define STRING_tibetan0 STR_t STR_i STR_b STR_e STR_t STR_a STR_n "\0"+#define STRING_tibt0 STR_t STR_i STR_b STR_t "\0"+#define STRING_tifinagh0 STR_t STR_i STR_f STR_i STR_n STR_a STR_g STR_h "\0"+#define STRING_tirh0 STR_t STR_i STR_r STR_h "\0"+#define STRING_tirhuta0 STR_t STR_i STR_r STR_h STR_u STR_t STR_a "\0"+#define STRING_tnsa0 STR_t STR_n STR_s STR_a "\0"+#define STRING_todhri0 STR_t STR_o STR_d STR_h STR_r STR_i "\0"+#define STRING_todr0 STR_t STR_o STR_d STR_r "\0"+#define STRING_toto0 STR_t STR_o STR_t STR_o "\0"+#define STRING_tulutigalari0 STR_t STR_u STR_l STR_u STR_t STR_i STR_g STR_a STR_l STR_a STR_r STR_i "\0"+#define STRING_tutg0 STR_t STR_u STR_t STR_g "\0"+#define STRING_ugar0 STR_u STR_g STR_a STR_r "\0"+#define STRING_ugaritic0 STR_u STR_g STR_a STR_r STR_i STR_t STR_i STR_c "\0"+#define STRING_uideo0 STR_u STR_i STR_d STR_e STR_o "\0"+#define STRING_unifiedideograph0 STR_u STR_n STR_i STR_f STR_i STR_e STR_d STR_i STR_d STR_e STR_o STR_g STR_r STR_a STR_p STR_h "\0"+#define STRING_unknown0 STR_u STR_n STR_k STR_n STR_o STR_w STR_n "\0"+#define STRING_upper0 STR_u STR_p STR_p STR_e STR_r "\0"+#define STRING_uppercase0 STR_u STR_p STR_p STR_e STR_r STR_c STR_a STR_s STR_e "\0"+#define STRING_vai0 STR_v STR_a STR_i "\0"+#define STRING_vaii0 STR_v STR_a STR_i STR_i "\0"+#define STRING_variationselector0 STR_v STR_a STR_r STR_i STR_a STR_t STR_i STR_o STR_n STR_s STR_e STR_l STR_e STR_c STR_t STR_o STR_r "\0"+#define STRING_vith0 STR_v STR_i STR_t STR_h "\0"+#define STRING_vithkuqi0 STR_v STR_i STR_t STR_h STR_k STR_u STR_q STR_i "\0"+#define STRING_vs0 STR_v STR_s "\0"+#define STRING_wancho0 STR_w STR_a STR_n STR_c STR_h STR_o "\0"+#define STRING_wara0 STR_w STR_a STR_r STR_a "\0"+#define STRING_warangciti0 STR_w STR_a STR_r STR_a STR_n STR_g STR_c STR_i STR_t STR_i "\0"+#define STRING_wcho0 STR_w STR_c STR_h STR_o "\0"+#define STRING_whitespace0 STR_w STR_h STR_i STR_t STR_e STR_s STR_p STR_a STR_c STR_e "\0"+#define STRING_wspace0 STR_w STR_s STR_p STR_a STR_c STR_e "\0"+#define STRING_xan0 STR_x STR_a STR_n "\0"+#define STRING_xidc0 STR_x STR_i STR_d STR_c "\0"+#define STRING_xidcontinue0 STR_x STR_i STR_d STR_c STR_o STR_n STR_t STR_i STR_n STR_u STR_e "\0"+#define STRING_xids0 STR_x STR_i STR_d STR_s "\0"+#define STRING_xidstart0 STR_x STR_i STR_d STR_s STR_t STR_a STR_r STR_t "\0"+#define STRING_xpeo0 STR_x STR_p STR_e STR_o "\0"+#define STRING_xps0 STR_x STR_p STR_s "\0"+#define STRING_xsp0 STR_x STR_s STR_p "\0"+#define STRING_xsux0 STR_x STR_s STR_u STR_x "\0"+#define STRING_xuc0 STR_x STR_u STR_c "\0"+#define STRING_xwd0 STR_x STR_w STR_d "\0"+#define STRING_yezi0 STR_y STR_e STR_z STR_i "\0"+#define STRING_yezidi0 STR_y STR_e STR_z STR_i STR_d STR_i "\0"+#define STRING_yi0 STR_y STR_i "\0"+#define STRING_yiii0 STR_y STR_i STR_i STR_i "\0"+#define STRING_z0 STR_z "\0"+#define STRING_zanabazarsquare0 STR_z STR_a STR_n STR_a STR_b STR_a STR_z STR_a STR_r STR_s STR_q STR_u STR_a STR_r STR_e "\0"+#define STRING_zanb0 STR_z STR_a STR_n STR_b "\0"+#define STRING_zinh0 STR_z STR_i STR_n STR_h "\0"+#define STRING_zl0 STR_z STR_l "\0"+#define STRING_zp0 STR_z STR_p "\0"+#define STRING_zs0 STR_z STR_s "\0"+#define STRING_zyyy0 STR_z STR_y STR_y STR_y "\0"+#define STRING_zzzz0 STR_z STR_z STR_z STR_z "\0"++const char PRIV(utt_names)[] =+ STRING_adlam0+ STRING_adlm0+ STRING_aghb0+ STRING_ahex0+ STRING_ahom0+ STRING_alpha0+ STRING_alphabetic0+ STRING_anatolianhieroglyphs0+ STRING_any0+ STRING_arab0+ STRING_arabic0+ STRING_armenian0+ STRING_armi0+ STRING_armn0+ STRING_ascii0+ STRING_asciihexdigit0+ STRING_avestan0+ STRING_avst0+ STRING_bali0+ STRING_balinese0+ STRING_bamu0+ STRING_bamum0+ STRING_bass0+ STRING_bassavah0+ STRING_batak0+ STRING_batk0+ STRING_beng0+ STRING_bengali0+ STRING_bhaiksuki0+ STRING_bhks0+ STRING_bidial0+ STRING_bidian0+ STRING_bidib0+ STRING_bidibn0+ STRING_bidic0+ STRING_bidicontrol0+ STRING_bidics0+ STRING_bidien0+ STRING_bidies0+ STRING_bidiet0+ STRING_bidifsi0+ STRING_bidil0+ STRING_bidilre0+ STRING_bidilri0+ STRING_bidilro0+ STRING_bidim0+ STRING_bidimirrored0+ STRING_bidinsm0+ STRING_bidion0+ STRING_bidipdf0+ STRING_bidipdi0+ STRING_bidir0+ STRING_bidirle0+ STRING_bidirli0+ STRING_bidirlo0+ STRING_bidis0+ STRING_bidiws0+ STRING_bopo0+ STRING_bopomofo0+ STRING_brah0+ STRING_brahmi0+ STRING_brai0+ STRING_braille0+ STRING_bugi0+ STRING_buginese0+ STRING_buhd0+ STRING_buhid0+ STRING_c0+ STRING_cakm0+ STRING_canadianaboriginal0+ STRING_cans0+ STRING_cari0+ STRING_carian0+ STRING_cased0+ STRING_caseignorable0+ STRING_caucasianalbanian0+ STRING_cc0+ STRING_cf0+ STRING_chakma0+ STRING_cham0+ STRING_changeswhencasefolded0+ STRING_changeswhencasemapped0+ STRING_changeswhenlowercased0+ STRING_changeswhentitlecased0+ STRING_changeswhenuppercased0+ STRING_cher0+ STRING_cherokee0+ STRING_chorasmian0+ STRING_chrs0+ STRING_ci0+ STRING_cn0+ STRING_co0+ STRING_common0+ STRING_copt0+ STRING_coptic0+ STRING_cpmn0+ STRING_cprt0+ STRING_cs0+ STRING_cuneiform0+ STRING_cwcf0+ STRING_cwcm0+ STRING_cwl0+ STRING_cwt0+ STRING_cwu0+ STRING_cypriot0+ STRING_cyprominoan0+ STRING_cyrillic0+ STRING_cyrl0+ STRING_dash0+ STRING_defaultignorablecodepoint0+ STRING_dep0+ STRING_deprecated0+ STRING_deseret0+ STRING_deva0+ STRING_devanagari0+ STRING_di0+ STRING_dia0+ STRING_diacritic0+ STRING_diak0+ STRING_divesakuru0+ STRING_dogr0+ STRING_dogra0+ STRING_dsrt0+ STRING_dupl0+ STRING_duployan0+ STRING_ebase0+ STRING_ecomp0+ STRING_egyp0+ STRING_egyptianhieroglyphs0+ STRING_elba0+ STRING_elbasan0+ STRING_elym0+ STRING_elymaic0+ STRING_emod0+ STRING_emoji0+ STRING_emojicomponent0+ STRING_emojimodifier0+ STRING_emojimodifierbase0+ STRING_emojipresentation0+ STRING_epres0+ STRING_ethi0+ STRING_ethiopic0+ STRING_ext0+ STRING_extendedpictographic0+ STRING_extender0+ STRING_extpict0+ STRING_gara0+ STRING_garay0+ STRING_geor0+ STRING_georgian0+ STRING_glag0+ STRING_glagolitic0+ STRING_gong0+ STRING_gonm0+ STRING_goth0+ STRING_gothic0+ STRING_gran0+ STRING_grantha0+ STRING_graphemebase0+ STRING_graphemeextend0+ STRING_graphemelink0+ STRING_grbase0+ STRING_greek0+ STRING_grek0+ STRING_grext0+ STRING_grlink0+ STRING_gujarati0+ STRING_gujr0+ STRING_gukh0+ STRING_gunjalagondi0+ STRING_gurmukhi0+ STRING_guru0+ STRING_gurungkhema0+ STRING_han0+ STRING_hang0+ STRING_hangul0+ STRING_hani0+ STRING_hanifirohingya0+ STRING_hano0+ STRING_hanunoo0+ STRING_hatr0+ STRING_hatran0+ STRING_hebr0+ STRING_hebrew0+ STRING_hex0+ STRING_hexdigit0+ STRING_hira0+ STRING_hiragana0+ STRING_hluw0+ STRING_hmng0+ STRING_hmnp0+ STRING_hung0+ STRING_idc0+ STRING_idcompatmathcontinue0+ STRING_idcompatmathstart0+ STRING_idcontinue0+ STRING_ideo0+ STRING_ideographic0+ STRING_ids0+ STRING_idsb0+ STRING_idsbinaryoperator0+ STRING_idst0+ STRING_idstart0+ STRING_idstrinaryoperator0+ STRING_idsu0+ STRING_idsunaryoperator0+ STRING_imperialaramaic0+ STRING_incb0+ STRING_inherited0+ STRING_inscriptionalpahlavi0+ STRING_inscriptionalparthian0+ STRING_ital0+ STRING_java0+ STRING_javanese0+ STRING_joinc0+ STRING_joincontrol0+ STRING_kaithi0+ STRING_kali0+ STRING_kana0+ STRING_kannada0+ STRING_katakana0+ STRING_kawi0+ STRING_kayahli0+ STRING_khar0+ STRING_kharoshthi0+ STRING_khitansmallscript0+ STRING_khmer0+ STRING_khmr0+ STRING_khoj0+ STRING_khojki0+ STRING_khudawadi0+ STRING_kiratrai0+ STRING_kits0+ STRING_knda0+ STRING_krai0+ STRING_kthi0+ STRING_l0+ STRING_l_AMPERSAND0+ STRING_lana0+ STRING_lao0+ STRING_laoo0+ STRING_latin0+ STRING_latn0+ STRING_lc0+ STRING_lepc0+ STRING_lepcha0+ STRING_limb0+ STRING_limbu0+ STRING_lina0+ STRING_linb0+ STRING_lineara0+ STRING_linearb0+ STRING_lisu0+ STRING_ll0+ STRING_lm0+ STRING_lo0+ STRING_loe0+ STRING_logicalorderexception0+ STRING_lower0+ STRING_lowercase0+ STRING_lt0+ STRING_lu0+ STRING_lyci0+ STRING_lycian0+ STRING_lydi0+ STRING_lydian0+ STRING_m0+ STRING_mahajani0+ STRING_mahj0+ STRING_maka0+ STRING_makasar0+ STRING_malayalam0+ STRING_mand0+ STRING_mandaic0+ STRING_mani0+ STRING_manichaean0+ STRING_marc0+ STRING_marchen0+ STRING_masaramgondi0+ STRING_math0+ STRING_mc0+ STRING_mcm0+ STRING_me0+ STRING_medefaidrin0+ STRING_medf0+ STRING_meeteimayek0+ STRING_mend0+ STRING_mendekikakui0+ STRING_merc0+ STRING_mero0+ STRING_meroiticcursive0+ STRING_meroitichieroglyphs0+ STRING_miao0+ STRING_mlym0+ STRING_mn0+ STRING_modi0+ STRING_modifiercombiningmark0+ STRING_mong0+ STRING_mongolian0+ STRING_mro0+ STRING_mroo0+ STRING_mtei0+ STRING_mult0+ STRING_multani0+ STRING_myanmar0+ STRING_mymr0+ STRING_n0+ STRING_nabataean0+ STRING_nagm0+ STRING_nagmundari0+ STRING_nand0+ STRING_nandinagari0+ STRING_narb0+ STRING_nbat0+ STRING_nchar0+ STRING_nd0+ STRING_newa0+ STRING_newtailue0+ STRING_nko0+ STRING_nkoo0+ STRING_nl0+ STRING_no0+ STRING_noncharactercodepoint0+ STRING_nshu0+ STRING_nushu0+ STRING_nyiakengpuachuehmong0+ STRING_ogam0+ STRING_ogham0+ STRING_olchiki0+ STRING_olck0+ STRING_oldhungarian0+ STRING_olditalic0+ STRING_oldnortharabian0+ STRING_oldpermic0+ STRING_oldpersian0+ STRING_oldsogdian0+ STRING_oldsoutharabian0+ STRING_oldturkic0+ STRING_olduyghur0+ STRING_olonal0+ STRING_onao0+ STRING_oriya0+ STRING_orkh0+ STRING_orya0+ STRING_osage0+ STRING_osge0+ STRING_osma0+ STRING_osmanya0+ STRING_ougr0+ STRING_p0+ STRING_pahawhhmong0+ STRING_palm0+ STRING_palmyrene0+ STRING_patsyn0+ STRING_patternsyntax0+ STRING_patternwhitespace0+ STRING_patws0+ STRING_pauc0+ STRING_paucinhau0+ STRING_pc0+ STRING_pcm0+ STRING_pd0+ STRING_pe0+ STRING_perm0+ STRING_pf0+ STRING_phag0+ STRING_phagspa0+ STRING_phli0+ STRING_phlp0+ STRING_phnx0+ STRING_phoenician0+ STRING_pi0+ STRING_plrd0+ STRING_po0+ STRING_prependedconcatenationmark0+ STRING_prti0+ STRING_ps0+ STRING_psalterpahlavi0+ STRING_qaac0+ STRING_qaai0+ STRING_qmark0+ STRING_quotationmark0+ STRING_radical0+ STRING_regionalindicator0+ STRING_rejang0+ STRING_ri0+ STRING_rjng0+ STRING_rohg0+ STRING_runic0+ STRING_runr0+ STRING_s0+ STRING_samaritan0+ STRING_samr0+ STRING_sarb0+ STRING_saur0+ STRING_saurashtra0+ STRING_sc0+ STRING_sd0+ STRING_sentenceterminal0+ STRING_sgnw0+ STRING_sharada0+ STRING_shavian0+ STRING_shaw0+ STRING_shrd0+ STRING_sidd0+ STRING_siddham0+ STRING_signwriting0+ STRING_sind0+ STRING_sinh0+ STRING_sinhala0+ STRING_sk0+ STRING_sm0+ STRING_so0+ STRING_softdotted0+ STRING_sogd0+ STRING_sogdian0+ STRING_sogo0+ STRING_sora0+ STRING_sorasompeng0+ STRING_soyo0+ STRING_soyombo0+ STRING_space0+ STRING_sterm0+ STRING_sund0+ STRING_sundanese0+ STRING_sunu0+ STRING_sunuwar0+ STRING_sylo0+ STRING_sylotinagri0+ STRING_syrc0+ STRING_syriac0+ STRING_tagalog0+ STRING_tagb0+ STRING_tagbanwa0+ STRING_taile0+ STRING_taitham0+ STRING_taiviet0+ STRING_takr0+ STRING_takri0+ STRING_tale0+ STRING_talu0+ STRING_tamil0+ STRING_taml0+ STRING_tang0+ STRING_tangsa0+ STRING_tangut0+ STRING_tavt0+ STRING_telu0+ STRING_telugu0+ STRING_term0+ STRING_terminalpunctuation0+ STRING_tfng0+ STRING_tglg0+ STRING_thaa0+ STRING_thaana0+ STRING_thai0+ STRING_tibetan0+ STRING_tibt0+ STRING_tifinagh0+ STRING_tirh0+ STRING_tirhuta0+ STRING_tnsa0+ STRING_todhri0+ STRING_todr0+ STRING_toto0+ STRING_tulutigalari0+ STRING_tutg0+ STRING_ugar0+ STRING_ugaritic0+ STRING_uideo0+ STRING_unifiedideograph0+ STRING_unknown0+ STRING_upper0+ STRING_uppercase0+ STRING_vai0+ STRING_vaii0+ STRING_variationselector0+ STRING_vith0+ STRING_vithkuqi0+ STRING_vs0+ STRING_wancho0+ STRING_wara0+ STRING_warangciti0+ STRING_wcho0+ STRING_whitespace0+ STRING_wspace0+ STRING_xan0+ STRING_xidc0+ STRING_xidcontinue0+ STRING_xids0+ STRING_xidstart0+ STRING_xpeo0+ STRING_xps0+ STRING_xsp0+ STRING_xsux0+ STRING_xuc0+ STRING_xwd0+ STRING_yezi0+ STRING_yezidi0+ STRING_yi0+ STRING_yiii0+ STRING_z0+ STRING_zanabazarsquare0+ STRING_zanb0+ STRING_zinh0+ STRING_zl0+ STRING_zp0+ STRING_zs0+ STRING_zyyy0+ STRING_zzzz0;++const ucp_type_table PRIV(utt)[] = {+ { 0, PT_SCX, ucp_Adlam },+ { 6, PT_SCX, ucp_Adlam },+ { 11, PT_SCX, ucp_Caucasian_Albanian },+ { 16, PT_BOOL, ucp_ASCII_Hex_Digit },+ { 21, PT_SC, ucp_Ahom },+ { 26, PT_BOOL, ucp_Alphabetic },+ { 32, PT_BOOL, ucp_Alphabetic },+ { 43, PT_SC, ucp_Anatolian_Hieroglyphs },+ { 64, PT_ANY, 0 },+ { 68, PT_SCX, ucp_Arabic },+ { 73, PT_SCX, ucp_Arabic },+ { 80, PT_SCX, ucp_Armenian },+ { 89, PT_SC, ucp_Imperial_Aramaic },+ { 94, PT_SCX, ucp_Armenian },+ { 99, PT_BOOL, ucp_ASCII },+ { 105, PT_BOOL, ucp_ASCII_Hex_Digit },+ { 119, PT_SCX, ucp_Avestan },+ { 127, PT_SCX, ucp_Avestan },+ { 132, PT_SC, ucp_Balinese },+ { 137, PT_SC, ucp_Balinese },+ { 146, PT_SC, ucp_Bamum },+ { 151, PT_SC, ucp_Bamum },+ { 157, PT_SC, ucp_Bassa_Vah },+ { 162, PT_SC, ucp_Bassa_Vah },+ { 171, PT_SC, ucp_Batak },+ { 177, PT_SC, ucp_Batak },+ { 182, PT_SCX, ucp_Bengali },+ { 187, PT_SCX, ucp_Bengali },+ { 195, PT_SC, ucp_Bhaiksuki },+ { 205, PT_SC, ucp_Bhaiksuki },+ { 210, PT_BIDICL, ucp_bidiAL },+ { 217, PT_BIDICL, ucp_bidiAN },+ { 224, PT_BIDICL, ucp_bidiB },+ { 230, PT_BIDICL, ucp_bidiBN },+ { 237, PT_BOOL, ucp_Bidi_Control },+ { 243, PT_BOOL, ucp_Bidi_Control },+ { 255, PT_BIDICL, ucp_bidiCS },+ { 262, PT_BIDICL, ucp_bidiEN },+ { 269, PT_BIDICL, ucp_bidiES },+ { 276, PT_BIDICL, ucp_bidiET },+ { 283, PT_BIDICL, ucp_bidiFSI },+ { 291, PT_BIDICL, ucp_bidiL },+ { 297, PT_BIDICL, ucp_bidiLRE },+ { 305, PT_BIDICL, ucp_bidiLRI },+ { 313, PT_BIDICL, ucp_bidiLRO },+ { 321, PT_BOOL, ucp_Bidi_Mirrored },+ { 327, PT_BOOL, ucp_Bidi_Mirrored },+ { 340, PT_BIDICL, ucp_bidiNSM },+ { 348, PT_BIDICL, ucp_bidiON },+ { 355, PT_BIDICL, ucp_bidiPDF },+ { 363, PT_BIDICL, ucp_bidiPDI },+ { 371, PT_BIDICL, ucp_bidiR },+ { 377, PT_BIDICL, ucp_bidiRLE },+ { 385, PT_BIDICL, ucp_bidiRLI },+ { 393, PT_BIDICL, ucp_bidiRLO },+ { 401, PT_BIDICL, ucp_bidiS },+ { 407, PT_BIDICL, ucp_bidiWS },+ { 414, PT_SCX, ucp_Bopomofo },+ { 419, PT_SCX, ucp_Bopomofo },+ { 428, PT_SC, ucp_Brahmi },+ { 433, PT_SC, ucp_Brahmi },+ { 440, PT_SC, ucp_Braille },+ { 445, PT_SC, ucp_Braille },+ { 453, PT_SCX, ucp_Buginese },+ { 458, PT_SCX, ucp_Buginese },+ { 467, PT_SCX, ucp_Buhid },+ { 472, PT_SCX, ucp_Buhid },+ { 478, PT_GC, ucp_C },+ { 480, PT_SCX, ucp_Chakma },+ { 485, PT_SC, ucp_Canadian_Aboriginal },+ { 504, PT_SC, ucp_Canadian_Aboriginal },+ { 509, PT_SCX, ucp_Carian },+ { 514, PT_SCX, ucp_Carian },+ { 521, PT_BOOL, ucp_Cased },+ { 527, PT_BOOL, ucp_Case_Ignorable },+ { 541, PT_SCX, ucp_Caucasian_Albanian },+ { 559, PT_PC, ucp_Cc },+ { 562, PT_PC, ucp_Cf },+ { 565, PT_SCX, ucp_Chakma },+ { 572, PT_SC, ucp_Cham },+ { 577, PT_BOOL, ucp_Changes_When_Casefolded },+ { 599, PT_BOOL, ucp_Changes_When_Casemapped },+ { 621, PT_BOOL, ucp_Changes_When_Lowercased },+ { 643, PT_BOOL, ucp_Changes_When_Titlecased },+ { 665, PT_BOOL, ucp_Changes_When_Uppercased },+ { 687, PT_SCX, ucp_Cherokee },+ { 692, PT_SCX, ucp_Cherokee },+ { 701, PT_SC, ucp_Chorasmian },+ { 712, PT_SC, ucp_Chorasmian },+ { 717, PT_BOOL, ucp_Case_Ignorable },+ { 720, PT_PC, ucp_Cn },+ { 723, PT_PC, ucp_Co },+ { 726, PT_SC, ucp_Common },+ { 733, PT_SCX, ucp_Coptic },+ { 738, PT_SCX, ucp_Coptic },+ { 745, PT_SCX, ucp_Cypro_Minoan },+ { 750, PT_SCX, ucp_Cypriot },+ { 755, PT_PC, ucp_Cs },+ { 758, PT_SC, ucp_Cuneiform },+ { 768, PT_BOOL, ucp_Changes_When_Casefolded },+ { 773, PT_BOOL, ucp_Changes_When_Casemapped },+ { 778, PT_BOOL, ucp_Changes_When_Lowercased },+ { 782, PT_BOOL, ucp_Changes_When_Titlecased },+ { 786, PT_BOOL, ucp_Changes_When_Uppercased },+ { 790, PT_SCX, ucp_Cypriot },+ { 798, PT_SCX, ucp_Cypro_Minoan },+ { 810, PT_SCX, ucp_Cyrillic },+ { 819, PT_SCX, ucp_Cyrillic },+ { 824, PT_BOOL, ucp_Dash },+ { 829, PT_BOOL, ucp_Default_Ignorable_Code_Point },+ { 855, PT_BOOL, ucp_Deprecated },+ { 859, PT_BOOL, ucp_Deprecated },+ { 870, PT_SC, ucp_Deseret },+ { 878, PT_SCX, ucp_Devanagari },+ { 883, PT_SCX, ucp_Devanagari },+ { 894, PT_BOOL, ucp_Default_Ignorable_Code_Point },+ { 897, PT_BOOL, ucp_Diacritic },+ { 901, PT_BOOL, ucp_Diacritic },+ { 911, PT_SC, ucp_Dives_Akuru },+ { 916, PT_SC, ucp_Dives_Akuru },+ { 927, PT_SCX, ucp_Dogra },+ { 932, PT_SCX, ucp_Dogra },+ { 938, PT_SC, ucp_Deseret },+ { 943, PT_SCX, ucp_Duployan },+ { 948, PT_SCX, ucp_Duployan },+ { 957, PT_BOOL, ucp_Emoji_Modifier_Base },+ { 963, PT_BOOL, ucp_Emoji_Component },+ { 969, PT_SC, ucp_Egyptian_Hieroglyphs },+ { 974, PT_SC, ucp_Egyptian_Hieroglyphs },+ { 994, PT_SCX, ucp_Elbasan },+ { 999, PT_SCX, ucp_Elbasan },+ { 1007, PT_SC, ucp_Elymaic },+ { 1012, PT_SC, ucp_Elymaic },+ { 1020, PT_BOOL, ucp_Emoji_Modifier },+ { 1025, PT_BOOL, ucp_Emoji },+ { 1031, PT_BOOL, ucp_Emoji_Component },+ { 1046, PT_BOOL, ucp_Emoji_Modifier },+ { 1060, PT_BOOL, ucp_Emoji_Modifier_Base },+ { 1078, PT_BOOL, ucp_Emoji_Presentation },+ { 1096, PT_BOOL, ucp_Emoji_Presentation },+ { 1102, PT_SCX, ucp_Ethiopic },+ { 1107, PT_SCX, ucp_Ethiopic },+ { 1116, PT_BOOL, ucp_Extender },+ { 1120, PT_BOOL, ucp_Extended_Pictographic },+ { 1141, PT_BOOL, ucp_Extender },+ { 1150, PT_BOOL, ucp_Extended_Pictographic },+ { 1158, PT_SCX, ucp_Garay },+ { 1163, PT_SCX, ucp_Garay },+ { 1169, PT_SCX, ucp_Georgian },+ { 1174, PT_SCX, ucp_Georgian },+ { 1183, PT_SCX, ucp_Glagolitic },+ { 1188, PT_SCX, ucp_Glagolitic },+ { 1199, PT_SCX, ucp_Gunjala_Gondi },+ { 1204, PT_SCX, ucp_Masaram_Gondi },+ { 1209, PT_SCX, ucp_Gothic },+ { 1214, PT_SCX, ucp_Gothic },+ { 1221, PT_SCX, ucp_Grantha },+ { 1226, PT_SCX, ucp_Grantha },+ { 1234, PT_BOOL, ucp_Grapheme_Base },+ { 1247, PT_BOOL, ucp_Grapheme_Extend },+ { 1262, PT_BOOL, ucp_Grapheme_Link },+ { 1275, PT_BOOL, ucp_Grapheme_Base },+ { 1282, PT_SCX, ucp_Greek },+ { 1288, PT_SCX, ucp_Greek },+ { 1293, PT_BOOL, ucp_Grapheme_Extend },+ { 1299, PT_BOOL, ucp_Grapheme_Link },+ { 1306, PT_SCX, ucp_Gujarati },+ { 1315, PT_SCX, ucp_Gujarati },+ { 1320, PT_SCX, ucp_Gurung_Khema },+ { 1325, PT_SCX, ucp_Gunjala_Gondi },+ { 1338, PT_SCX, ucp_Gurmukhi },+ { 1347, PT_SCX, ucp_Gurmukhi },+ { 1352, PT_SCX, ucp_Gurung_Khema },+ { 1364, PT_SCX, ucp_Han },+ { 1368, PT_SCX, ucp_Hangul },+ { 1373, PT_SCX, ucp_Hangul },+ { 1380, PT_SCX, ucp_Han },+ { 1385, PT_SCX, ucp_Hanifi_Rohingya },+ { 1400, PT_SCX, ucp_Hanunoo },+ { 1405, PT_SCX, ucp_Hanunoo },+ { 1413, PT_SC, ucp_Hatran },+ { 1418, PT_SC, ucp_Hatran },+ { 1425, PT_SCX, ucp_Hebrew },+ { 1430, PT_SCX, ucp_Hebrew },+ { 1437, PT_BOOL, ucp_Hex_Digit },+ { 1441, PT_BOOL, ucp_Hex_Digit },+ { 1450, PT_SCX, ucp_Hiragana },+ { 1455, PT_SCX, ucp_Hiragana },+ { 1464, PT_SC, ucp_Anatolian_Hieroglyphs },+ { 1469, PT_SC, ucp_Pahawh_Hmong },+ { 1474, PT_SC, ucp_Nyiakeng_Puachue_Hmong },+ { 1479, PT_SCX, ucp_Old_Hungarian },+ { 1484, PT_BOOL, ucp_ID_Continue },+ { 1488, PT_BOOL, ucp_ID_Compat_Math_Continue },+ { 1509, PT_BOOL, ucp_ID_Compat_Math_Start },+ { 1527, PT_BOOL, ucp_ID_Continue },+ { 1538, PT_BOOL, ucp_Ideographic },+ { 1543, PT_BOOL, ucp_Ideographic },+ { 1555, PT_BOOL, ucp_ID_Start },+ { 1559, PT_BOOL, ucp_IDS_Binary_Operator },+ { 1564, PT_BOOL, ucp_IDS_Binary_Operator },+ { 1582, PT_BOOL, ucp_IDS_Trinary_Operator },+ { 1587, PT_BOOL, ucp_ID_Start },+ { 1595, PT_BOOL, ucp_IDS_Trinary_Operator },+ { 1614, PT_BOOL, ucp_IDS_Unary_Operator },+ { 1619, PT_BOOL, ucp_IDS_Unary_Operator },+ { 1636, PT_SC, ucp_Imperial_Aramaic },+ { 1652, PT_BOOL, ucp_InCB },+ { 1657, PT_SC, ucp_Inherited },+ { 1667, PT_SC, ucp_Inscriptional_Pahlavi },+ { 1688, PT_SC, ucp_Inscriptional_Parthian },+ { 1710, PT_SC, ucp_Old_Italic },+ { 1715, PT_SCX, ucp_Javanese },+ { 1720, PT_SCX, ucp_Javanese },+ { 1729, PT_BOOL, ucp_Join_Control },+ { 1735, PT_BOOL, ucp_Join_Control },+ { 1747, PT_SCX, ucp_Kaithi },+ { 1754, PT_SCX, ucp_Kayah_Li },+ { 1759, PT_SCX, ucp_Katakana },+ { 1764, PT_SCX, ucp_Kannada },+ { 1772, PT_SCX, ucp_Katakana },+ { 1781, PT_SC, ucp_Kawi },+ { 1786, PT_SCX, ucp_Kayah_Li },+ { 1794, PT_SC, ucp_Kharoshthi },+ { 1799, PT_SC, ucp_Kharoshthi },+ { 1810, PT_SC, ucp_Khitan_Small_Script },+ { 1828, PT_SC, ucp_Khmer },+ { 1834, PT_SC, ucp_Khmer },+ { 1839, PT_SCX, ucp_Khojki },+ { 1844, PT_SCX, ucp_Khojki },+ { 1851, PT_SCX, ucp_Khudawadi },+ { 1861, PT_SC, ucp_Kirat_Rai },+ { 1870, PT_SC, ucp_Khitan_Small_Script },+ { 1875, PT_SCX, ucp_Kannada },+ { 1880, PT_SC, ucp_Kirat_Rai },+ { 1885, PT_SCX, ucp_Kaithi },+ { 1890, PT_GC, ucp_L },+ { 1892, PT_LAMP, 0 },+ { 1895, PT_SC, ucp_Tai_Tham },+ { 1900, PT_SC, ucp_Lao },+ { 1904, PT_SC, ucp_Lao },+ { 1909, PT_SCX, ucp_Latin },+ { 1915, PT_SCX, ucp_Latin },+ { 1920, PT_LAMP, 0 },+ { 1923, PT_SC, ucp_Lepcha },+ { 1928, PT_SC, ucp_Lepcha },+ { 1935, PT_SCX, ucp_Limbu },+ { 1940, PT_SCX, ucp_Limbu },+ { 1946, PT_SCX, ucp_Linear_A },+ { 1951, PT_SCX, ucp_Linear_B },+ { 1956, PT_SCX, ucp_Linear_A },+ { 1964, PT_SCX, ucp_Linear_B },+ { 1972, PT_SCX, ucp_Lisu },+ { 1977, PT_PC, ucp_Ll },+ { 1980, PT_PC, ucp_Lm },+ { 1983, PT_PC, ucp_Lo },+ { 1986, PT_BOOL, ucp_Logical_Order_Exception },+ { 1990, PT_BOOL, ucp_Logical_Order_Exception },+ { 2012, PT_BOOL, ucp_Lowercase },+ { 2018, PT_BOOL, ucp_Lowercase },+ { 2028, PT_PC, ucp_Lt },+ { 2031, PT_PC, ucp_Lu },+ { 2034, PT_SCX, ucp_Lycian },+ { 2039, PT_SCX, ucp_Lycian },+ { 2046, PT_SCX, ucp_Lydian },+ { 2051, PT_SCX, ucp_Lydian },+ { 2058, PT_GC, ucp_M },+ { 2060, PT_SCX, ucp_Mahajani },+ { 2069, PT_SCX, ucp_Mahajani },+ { 2074, PT_SC, ucp_Makasar },+ { 2079, PT_SC, ucp_Makasar },+ { 2087, PT_SCX, ucp_Malayalam },+ { 2097, PT_SCX, ucp_Mandaic },+ { 2102, PT_SCX, ucp_Mandaic },+ { 2110, PT_SCX, ucp_Manichaean },+ { 2115, PT_SCX, ucp_Manichaean },+ { 2126, PT_SC, ucp_Marchen },+ { 2131, PT_SC, ucp_Marchen },+ { 2139, PT_SCX, ucp_Masaram_Gondi },+ { 2152, PT_BOOL, ucp_Math },+ { 2157, PT_PC, ucp_Mc },+ { 2160, PT_BOOL, ucp_Modifier_Combining_Mark },+ { 2164, PT_PC, ucp_Me },+ { 2167, PT_SC, ucp_Medefaidrin },+ { 2179, PT_SC, ucp_Medefaidrin },+ { 2184, PT_SC, ucp_Meetei_Mayek },+ { 2196, PT_SC, ucp_Mende_Kikakui },+ { 2201, PT_SC, ucp_Mende_Kikakui },+ { 2214, PT_SC, ucp_Meroitic_Cursive },+ { 2219, PT_SCX, ucp_Meroitic_Hieroglyphs },+ { 2224, PT_SC, ucp_Meroitic_Cursive },+ { 2240, PT_SCX, ucp_Meroitic_Hieroglyphs },+ { 2260, PT_SC, ucp_Miao },+ { 2265, PT_SCX, ucp_Malayalam },+ { 2270, PT_PC, ucp_Mn },+ { 2273, PT_SCX, ucp_Modi },+ { 2278, PT_BOOL, ucp_Modifier_Combining_Mark },+ { 2300, PT_SCX, ucp_Mongolian },+ { 2305, PT_SCX, ucp_Mongolian },+ { 2315, PT_SC, ucp_Mro },+ { 2319, PT_SC, ucp_Mro },+ { 2324, PT_SC, ucp_Meetei_Mayek },+ { 2329, PT_SCX, ucp_Multani },+ { 2334, PT_SCX, ucp_Multani },+ { 2342, PT_SCX, ucp_Myanmar },+ { 2350, PT_SCX, ucp_Myanmar },+ { 2355, PT_GC, ucp_N },+ { 2357, PT_SC, ucp_Nabataean },+ { 2367, PT_SC, ucp_Nag_Mundari },+ { 2372, PT_SC, ucp_Nag_Mundari },+ { 2383, PT_SCX, ucp_Nandinagari },+ { 2388, PT_SCX, ucp_Nandinagari },+ { 2400, PT_SC, ucp_Old_North_Arabian },+ { 2405, PT_SC, ucp_Nabataean },+ { 2410, PT_BOOL, ucp_Noncharacter_Code_Point },+ { 2416, PT_PC, ucp_Nd },+ { 2419, PT_SC, ucp_Newa },+ { 2424, PT_SC, ucp_New_Tai_Lue },+ { 2434, PT_SCX, ucp_Nko },+ { 2438, PT_SCX, ucp_Nko },+ { 2443, PT_PC, ucp_Nl },+ { 2446, PT_PC, ucp_No },+ { 2449, PT_BOOL, ucp_Noncharacter_Code_Point },+ { 2471, PT_SC, ucp_Nushu },+ { 2476, PT_SC, ucp_Nushu },+ { 2482, PT_SC, ucp_Nyiakeng_Puachue_Hmong },+ { 2503, PT_SC, ucp_Ogham },+ { 2508, PT_SC, ucp_Ogham },+ { 2514, PT_SC, ucp_Ol_Chiki },+ { 2522, PT_SC, ucp_Ol_Chiki },+ { 2527, PT_SCX, ucp_Old_Hungarian },+ { 2540, PT_SC, ucp_Old_Italic },+ { 2550, PT_SC, ucp_Old_North_Arabian },+ { 2566, PT_SCX, ucp_Old_Permic },+ { 2576, PT_SC, ucp_Old_Persian },+ { 2587, PT_SC, ucp_Old_Sogdian },+ { 2598, PT_SC, ucp_Old_South_Arabian },+ { 2614, PT_SCX, ucp_Old_Turkic },+ { 2624, PT_SCX, ucp_Old_Uyghur },+ { 2634, PT_SCX, ucp_Ol_Onal },+ { 2641, PT_SCX, ucp_Ol_Onal },+ { 2646, PT_SCX, ucp_Oriya },+ { 2652, PT_SCX, ucp_Old_Turkic },+ { 2657, PT_SCX, ucp_Oriya },+ { 2662, PT_SCX, ucp_Osage },+ { 2668, PT_SCX, ucp_Osage },+ { 2673, PT_SC, ucp_Osmanya },+ { 2678, PT_SC, ucp_Osmanya },+ { 2686, PT_SCX, ucp_Old_Uyghur },+ { 2691, PT_GC, ucp_P },+ { 2693, PT_SC, ucp_Pahawh_Hmong },+ { 2705, PT_SC, ucp_Palmyrene },+ { 2710, PT_SC, ucp_Palmyrene },+ { 2720, PT_BOOL, ucp_Pattern_Syntax },+ { 2727, PT_BOOL, ucp_Pattern_Syntax },+ { 2741, PT_BOOL, ucp_Pattern_White_Space },+ { 2759, PT_BOOL, ucp_Pattern_White_Space },+ { 2765, PT_SC, ucp_Pau_Cin_Hau },+ { 2770, PT_SC, ucp_Pau_Cin_Hau },+ { 2780, PT_PC, ucp_Pc },+ { 2783, PT_BOOL, ucp_Prepended_Concatenation_Mark },+ { 2787, PT_PC, ucp_Pd },+ { 2790, PT_PC, ucp_Pe },+ { 2793, PT_SCX, ucp_Old_Permic },+ { 2798, PT_PC, ucp_Pf },+ { 2801, PT_SCX, ucp_Phags_Pa },+ { 2806, PT_SCX, ucp_Phags_Pa },+ { 2814, PT_SC, ucp_Inscriptional_Pahlavi },+ { 2819, PT_SCX, ucp_Psalter_Pahlavi },+ { 2824, PT_SC, ucp_Phoenician },+ { 2829, PT_SC, ucp_Phoenician },+ { 2840, PT_PC, ucp_Pi },+ { 2843, PT_SC, ucp_Miao },+ { 2848, PT_PC, ucp_Po },+ { 2851, PT_BOOL, ucp_Prepended_Concatenation_Mark },+ { 2878, PT_SC, ucp_Inscriptional_Parthian },+ { 2883, PT_PC, ucp_Ps },+ { 2886, PT_SCX, ucp_Psalter_Pahlavi },+ { 2901, PT_SCX, ucp_Coptic },+ { 2906, PT_SC, ucp_Inherited },+ { 2911, PT_BOOL, ucp_Quotation_Mark },+ { 2917, PT_BOOL, ucp_Quotation_Mark },+ { 2931, PT_BOOL, ucp_Radical },+ { 2939, PT_BOOL, ucp_Regional_Indicator },+ { 2957, PT_SC, ucp_Rejang },+ { 2964, PT_BOOL, ucp_Regional_Indicator },+ { 2967, PT_SC, ucp_Rejang },+ { 2972, PT_SCX, ucp_Hanifi_Rohingya },+ { 2977, PT_SCX, ucp_Runic },+ { 2983, PT_SCX, ucp_Runic },+ { 2988, PT_GC, ucp_S },+ { 2990, PT_SCX, ucp_Samaritan },+ { 3000, PT_SCX, ucp_Samaritan },+ { 3005, PT_SC, ucp_Old_South_Arabian },+ { 3010, PT_SC, ucp_Saurashtra },+ { 3015, PT_SC, ucp_Saurashtra },+ { 3026, PT_PC, ucp_Sc },+ { 3029, PT_BOOL, ucp_Soft_Dotted },+ { 3032, PT_BOOL, ucp_Sentence_Terminal },+ { 3049, PT_SC, ucp_SignWriting },+ { 3054, PT_SCX, ucp_Sharada },+ { 3062, PT_SCX, ucp_Shavian },+ { 3070, PT_SCX, ucp_Shavian },+ { 3075, PT_SCX, ucp_Sharada },+ { 3080, PT_SC, ucp_Siddham },+ { 3085, PT_SC, ucp_Siddham },+ { 3093, PT_SC, ucp_SignWriting },+ { 3105, PT_SCX, ucp_Khudawadi },+ { 3110, PT_SCX, ucp_Sinhala },+ { 3115, PT_SCX, ucp_Sinhala },+ { 3123, PT_PC, ucp_Sk },+ { 3126, PT_PC, ucp_Sm },+ { 3129, PT_PC, ucp_So },+ { 3132, PT_BOOL, ucp_Soft_Dotted },+ { 3143, PT_SCX, ucp_Sogdian },+ { 3148, PT_SCX, ucp_Sogdian },+ { 3156, PT_SC, ucp_Old_Sogdian },+ { 3161, PT_SC, ucp_Sora_Sompeng },+ { 3166, PT_SC, ucp_Sora_Sompeng },+ { 3178, PT_SC, ucp_Soyombo },+ { 3183, PT_SC, ucp_Soyombo },+ { 3191, PT_BOOL, ucp_White_Space },+ { 3197, PT_BOOL, ucp_Sentence_Terminal },+ { 3203, PT_SC, ucp_Sundanese },+ { 3208, PT_SC, ucp_Sundanese },+ { 3218, PT_SCX, ucp_Sunuwar },+ { 3223, PT_SCX, ucp_Sunuwar },+ { 3231, PT_SCX, ucp_Syloti_Nagri },+ { 3236, PT_SCX, ucp_Syloti_Nagri },+ { 3248, PT_SCX, ucp_Syriac },+ { 3253, PT_SCX, ucp_Syriac },+ { 3260, PT_SCX, ucp_Tagalog },+ { 3268, PT_SCX, ucp_Tagbanwa },+ { 3273, PT_SCX, ucp_Tagbanwa },+ { 3282, PT_SCX, ucp_Tai_Le },+ { 3288, PT_SC, ucp_Tai_Tham },+ { 3296, PT_SC, ucp_Tai_Viet },+ { 3304, PT_SCX, ucp_Takri },+ { 3309, PT_SCX, ucp_Takri },+ { 3315, PT_SCX, ucp_Tai_Le },+ { 3320, PT_SC, ucp_New_Tai_Lue },+ { 3325, PT_SCX, ucp_Tamil },+ { 3331, PT_SCX, ucp_Tamil },+ { 3336, PT_SCX, ucp_Tangut },+ { 3341, PT_SC, ucp_Tangsa },+ { 3348, PT_SCX, ucp_Tangut },+ { 3355, PT_SC, ucp_Tai_Viet },+ { 3360, PT_SCX, ucp_Telugu },+ { 3365, PT_SCX, ucp_Telugu },+ { 3372, PT_BOOL, ucp_Terminal_Punctuation },+ { 3377, PT_BOOL, ucp_Terminal_Punctuation },+ { 3397, PT_SCX, ucp_Tifinagh },+ { 3402, PT_SCX, ucp_Tagalog },+ { 3407, PT_SCX, ucp_Thaana },+ { 3412, PT_SCX, ucp_Thaana },+ { 3419, PT_SCX, ucp_Thai },+ { 3424, PT_SCX, ucp_Tibetan },+ { 3432, PT_SCX, ucp_Tibetan },+ { 3437, PT_SCX, ucp_Tifinagh },+ { 3446, PT_SCX, ucp_Tirhuta },+ { 3451, PT_SCX, ucp_Tirhuta },+ { 3459, PT_SC, ucp_Tangsa },+ { 3464, PT_SCX, ucp_Todhri },+ { 3471, PT_SCX, ucp_Todhri },+ { 3476, PT_SCX, ucp_Toto },+ { 3481, PT_SCX, ucp_Tulu_Tigalari },+ { 3494, PT_SCX, ucp_Tulu_Tigalari },+ { 3499, PT_SC, ucp_Ugaritic },+ { 3504, PT_SC, ucp_Ugaritic },+ { 3513, PT_BOOL, ucp_Unified_Ideograph },+ { 3519, PT_BOOL, ucp_Unified_Ideograph },+ { 3536, PT_SC, ucp_Unknown },+ { 3544, PT_BOOL, ucp_Uppercase },+ { 3550, PT_BOOL, ucp_Uppercase },+ { 3560, PT_SC, ucp_Vai },+ { 3564, PT_SC, ucp_Vai },+ { 3569, PT_BOOL, ucp_Variation_Selector },+ { 3587, PT_SC, ucp_Vithkuqi },+ { 3592, PT_SC, ucp_Vithkuqi },+ { 3601, PT_BOOL, ucp_Variation_Selector },+ { 3604, PT_SC, ucp_Wancho },+ { 3611, PT_SC, ucp_Warang_Citi },+ { 3616, PT_SC, ucp_Warang_Citi },+ { 3627, PT_SC, ucp_Wancho },+ { 3632, PT_BOOL, ucp_White_Space },+ { 3643, PT_BOOL, ucp_White_Space },+ { 3650, PT_ALNUM, 0 },+ { 3654, PT_BOOL, ucp_XID_Continue },+ { 3659, PT_BOOL, ucp_XID_Continue },+ { 3671, PT_BOOL, ucp_XID_Start },+ { 3676, PT_BOOL, ucp_XID_Start },+ { 3685, PT_SC, ucp_Old_Persian },+ { 3690, PT_PXSPACE, 0 },+ { 3694, PT_SPACE, 0 },+ { 3698, PT_SC, ucp_Cuneiform },+ { 3703, PT_UCNC, 0 },+ { 3707, PT_WORD, 0 },+ { 3711, PT_SCX, ucp_Yezidi },+ { 3716, PT_SCX, ucp_Yezidi },+ { 3723, PT_SCX, ucp_Yi },+ { 3726, PT_SCX, ucp_Yi },+ { 3731, PT_GC, ucp_Z },+ { 3733, PT_SC, ucp_Zanabazar_Square },+ { 3749, PT_SC, ucp_Zanabazar_Square },+ { 3754, PT_SC, ucp_Inherited },+ { 3759, PT_PC, ucp_Zl },+ { 3762, PT_PC, ucp_Zp },+ { 3765, PT_PC, ucp_Zs },+ { 3768, PT_SC, ucp_Common },+ { 3773, PT_SC, ucp_Unknown }+};++const size_t PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table);++#endif /* SUPPORT_UNICODE */++/* End of pcre2_ucptables_inc.h */
+ src/c/pcre2/src/pcre2_util.h view
@@ -0,0 +1,179 @@+/*************************************************+* Perl-Compatible Regular Expressions *+*************************************************/++/* PCRE2 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+ Original API code Copyright (c) 1997-2012 University of Cambridge+ 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.+-----------------------------------------------------------------------------+*/++#ifndef PCRE2_UTIL_H_IDEMPOTENT_GUARD+#define PCRE2_UTIL_H_IDEMPOTENT_GUARD++/* Assertion macros */++#ifdef PCRE2_DEBUG++#if defined(HAVE_ASSERT_H) && !defined(NDEBUG)+#include <assert.h>+#endif++/* PCRE2_ASSERT(x) can be used to inject an assert() for conditions+that the code below doesn't support. It is a NOP for non debug builds+but in debug builds will print information about the location of the+code where it triggered and crash.++It is meant to work like assert(), and therefore the expression used+should indicate what the expected state is, and shouldn't have any+side-effects. */++#if defined(HAVE_ASSERT_H) && !defined(NDEBUG)+#define PCRE2_ASSERT(x) assert(x)+#else+#define PCRE2_ASSERT(x) do \+{ \+ if (!(x)) \+ { \+ fprintf(stderr, "Assertion failed at " __FILE__ ":%d\n", __LINE__); \+ abort(); \+ } \+} while(0)+#endif++/* LCOV_EXCL_START */++/* PCRE2_UNREACHABLE() can be used to mark locations on the code that+shouldn't be reached. In non debug builds is defined as a hint for+the compiler to eliminate any code after it, so it is useful also for+performance reasons, but should be used with care because if it is+ever reached will trigger Undefined Behaviour and if you are lucky a+crash. In debug builds it will report the location where it was triggered+and crash. One important point to consider when using this macro, is+that it is only implemented for a few compilers, and therefore can't+be relied on to always be active either, so if it is followed by some+code it is important to make sure that the whole thing is safe to+use even if the macro is not there (ex: make sure there is a `break`+after it if used at the end of a `case`) and to test your code also+with a configuration where the macro will be a NOP. */++#if defined(HAVE_ASSERT_H) && !defined(NDEBUG)+#define PCRE2_UNREACHABLE() \+assert(((void)"Execution reached unexpected point", 0))+#else+#define PCRE2_UNREACHABLE() do \+{ \+fprintf(stderr, "Execution reached unexpected point at " __FILE__ \+ ":%d\n", __LINE__); \+abort(); \+} while(0)+#endif++/* PCRE2_DEBUG_UNREACHABLE() is a debug only version of the previous+macro. It is meant to be used in places where the code is handling+an error situation in code that shouldn't be reached, but that has+some sort of fallback code to normally handle the error. When in+doubt you should use this instead of the previous macro. Like in+the previous case, it is a good idea to document as much as possible+the reason and the actions that should be taken if it ever triggers. */++#define PCRE2_DEBUG_UNREACHABLE() PCRE2_UNREACHABLE()++/* LCOV_EXCL_STOP */++#endif /* PCRE2_DEBUG */++#ifndef PCRE2_ASSERT+#define PCRE2_ASSERT(x) do {} while(0)+#endif++/* LCOV_EXCL_START */++#ifndef PCRE2_DEBUG_UNREACHABLE+#define PCRE2_DEBUG_UNREACHABLE() do {} while(0)+#endif++#ifndef PCRE2_UNREACHABLE+#ifdef HAVE_BUILTIN_UNREACHABLE+#define PCRE2_UNREACHABLE() __builtin_unreachable()+#elif defined(HAVE_BUILTIN_ASSUME)+#define PCRE2_UNREACHABLE() __assume(0)+#else+#define PCRE2_UNREACHABLE() do {} while(0)+#endif+#endif /* !PCRE2_UNREACHABLE */++/* LCOV_EXCL_STOP */++/* We define this fallthrough macro for suppressing -Wimplicit-fallthrough warnings.+Clang only allows this via an attribute, whereas other compilers (eg. GCC) match attributes+and also specially-formatted comments.++This macro should be used with no following semicolon, and ideally with a comment: */++// PCRE2_FALLTHROUGH /* Fall through */++#ifndef PCRE2_FALLTHROUGH++#if defined(__cplusplus) && __cplusplus >= 202002L && \+ defined(__has_cpp_attribute)+/* Standards-compatible C++ variant. */+#if __has_cpp_attribute(fallthrough)+#define PCRE2_FALLTHROUGH [[fallthrough]];+#endif+#elif !defined(__cplusplus) && \+ defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L && \+ defined(__has_c_attribute)+/* Standards-compatible C variant. */+#if __has_c_attribute(fallthrough)+#define PCRE2_FALLTHROUGH [[fallthrough]];+#endif+#elif ((defined(__clang__) && __clang_major__ >= 10) || \+ (defined(__GNUC__) && __GNUC__ >= 7)) && \+ defined(__has_attribute)+/* Clang and GCC syntax. Rule out old versions because apparently Clang at+ least has a broken implementation of __has_attribute. */+#if __has_attribute(fallthrough)+#define PCRE2_FALLTHROUGH __attribute__((fallthrough));+#endif+#endif++#endif /* !PCRE2_FALLTHROUGH */++#ifndef PCRE2_FALLTHROUGH+#define PCRE2_FALLTHROUGH+#endif++#endif /* PCRE2_UTIL_H_IDEMPOTENT_GUARD */++/* End of pcre2_util.h */
src/c/pcre2/src/pcre2_valid_utf.c view
@@ -44,12 +44,11 @@ macros to change names from _pcre2_xxx to xxxx, thereby avoiding name clashes with the library. In this case, PCRE2_PCRE2TEST is defined. */ + #ifndef PCRE2_PCRE2TEST /* We're compiling the library */-#ifdef HAVE_CONFIG_H-#include "config.h"-#endif #include "pcre2_internal.h" #endif /* PCRE2_PCRE2TEST */+ #ifndef SUPPORT_UNICODE
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-2023 University of Cambridge+ New API code Copyright (c) 2016-2024 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -38,18 +38,16 @@ ----------------------------------------------------------------------------- */ -/* This module contains an internal function that is used to match an extended-class. It is used by pcre2_auto_possessify() and by both pcre2_match() and-pcre2_def_match(). */ --#ifdef HAVE_CONFIG_H-#include "config.h"-#endif+/* This module contains two internal functions that are used to match+OP_XCLASS and OP_ECLASS. It is used by pcre2_auto_possessify() and by both+pcre2_match() and pcre2_dfa_match(). */ #include "pcre2_internal.h" ++ /************************************************* * Match character against an XCLASS * *************************************************/@@ -66,114 +64,75 @@ */ BOOL-PRIV(xclass)(uint32_t c, PCRE2_SPTR data, BOOL utf)+PRIV(xclass)(uint32_t c, PCRE2_SPTR data, const uint8_t *char_lists_end, BOOL utf) {+/* Update PRIV(update_classbits) when this function is changed. */ PCRE2_UCHAR t;-BOOL negated = (*data & XCL_NOT) != 0;+BOOL not_negated = (*data & XCL_NOT) == 0;+uint32_t type, max_index, min_index, value;+const uint8_t *next_char; #if PCRE2_CODE_UNIT_WIDTH == 8 /* In 8 bit mode, this must always be TRUE. Help the compiler to know that. */ utf = TRUE; #endif -/* Code points < 256 are matched against a bitmap, if one is present. If not,-we still carry on, because there may be ranges that start below 256 in the-additional data. */+/* Code points < 256 are matched against a bitmap, if one is present. */ -if (c < 256)+if ((*data++ & XCL_MAP) != 0) {- if ((*data & XCL_HASPROP) == 0)- {- if ((*data & XCL_MAP) == 0) return negated;- return (((uint8_t *)(data + 1))[c/8] & (1u << (c&7))) != 0;- }- if ((*data & XCL_MAP) != 0 &&- (((uint8_t *)(data + 1))[c/8] & (1u << (c&7))) != 0)- return !negated; /* char found */+ if (c < 256)+ return (((const uint8_t *)data)[c/8] & (1u << (c&7))) != 0;+ /* Skip bitmap. */+ data += 32 / sizeof(PCRE2_UCHAR); } -/* First skip the bit map if present. Then match against the list of Unicode-properties or large chars or ranges that end with a large char. We won't ever+/* Match against the list of Unicode properties. We won't ever encounter XCL_PROP or XCL_NOTPROP when UTF support is not compiled. */--if ((*data++ & XCL_MAP) != 0) data += 32 / sizeof(PCRE2_UCHAR);--while ((t = *data++) != XCL_END)- {- uint32_t x, y;- if (t == XCL_SINGLE)- { #ifdef SUPPORT_UNICODE- if (utf)- {- GETCHARINC(x, data); /* macro generates multiple statements */- }- else-#endif- x = *data++;- if (c == x) return !negated;- }- else if (t == XCL_RANGE)- {-#ifdef SUPPORT_UNICODE- if (utf)- {- GETCHARINC(x, data); /* macro generates multiple statements */- GETCHARINC(y, data); /* macro generates multiple statements */- }- else-#endif- {- x = *data++;- y = *data++;- }- if (c >= x && c <= y) return !negated;- }+if (*data == XCL_PROP || *data == XCL_NOTPROP)+ {+ /* The UCD record is the same for all properties. */+ const ucd_record *prop = GET_UCD(c); -#ifdef SUPPORT_UNICODE- else /* XCL_PROP & XCL_NOTPROP */+ do { int chartype;- const ucd_record *prop = GET_UCD(c);- BOOL isprop = t == XCL_PROP;+ BOOL isprop = (*data++) == XCL_PROP; BOOL ok; switch(*data) {- case PT_ANY:- if (isprop) return !negated;- break;- case PT_LAMP: chartype = prop->chartype; if ((chartype == ucp_Lu || chartype == ucp_Ll ||- chartype == ucp_Lt) == isprop) return !negated;+ chartype == ucp_Lt) == isprop) return not_negated; break; case PT_GC: if ((data[1] == PRIV(ucp_gentype)[prop->chartype]) == isprop)- return !negated;+ return not_negated; break; case PT_PC:- if ((data[1] == prop->chartype) == isprop) return !negated;+ if ((data[1] == prop->chartype) == isprop) return not_negated; break; case PT_SC:- if ((data[1] == prop->script) == isprop) return !negated;+ if ((data[1] == prop->script) == isprop) return not_negated; break; case PT_SCX: ok = (data[1] == prop->script || MAPBIT(PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(prop), data[1]) != 0);- if (ok == isprop) return !negated;+ if (ok == isprop) return not_negated; break; case PT_ALNUM: chartype = prop->chartype; if ((PRIV(ucp_gentype)[chartype] == ucp_L || PRIV(ucp_gentype)[chartype] == ucp_N) == isprop)- return !negated;+ return not_negated; break; /* Perl space used to exclude VT, but from Perl 5.18 it is included,@@ -186,12 +145,12 @@ { HSPACE_CASES: VSPACE_CASES:- if (isprop) return !negated;+ if (isprop) return not_negated; break; default: if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == isprop)- return !negated;+ return not_negated; break; } break;@@ -201,7 +160,7 @@ if ((PRIV(ucp_gentype)[chartype] == ucp_L || PRIV(ucp_gentype)[chartype] == ucp_N || chartype == ucp_Mn || chartype == ucp_Pc) == isprop)- return !negated;+ return not_negated; break; case PT_UCNC:@@ -209,24 +168,24 @@ { if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT || c == CHAR_GRAVE_ACCENT) == isprop)- return !negated;+ return not_negated; } else { if ((c < 0xd800 || c > 0xdfff) == isprop)- return !negated;+ return not_negated; } break; case PT_BIDICL: if ((UCD_BIDICLASS_PROP(prop) == data[1]) == isprop)- return !negated;+ return not_negated; break; case PT_BOOL: ok = MAPBIT(PRIV(ucd_boolprop_sets) + UCD_BPROPS_PROP(prop), data[1]) != 0;- if (ok == isprop) return !negated;+ if (ok == isprop) return not_negated; break; /* The following three properties can occur only in an XCLASS, as there@@ -248,7 +207,7 @@ (chartype == ucp_Cf && c != 0x061c && c != 0x180e && (c < 0x2066 || c > 0x2069)) )) == isprop)- return !negated;+ return not_negated; break; /* Printable character: same as graphic, with the addition of Zs, i.e.@@ -262,7 +221,7 @@ (chartype == ucp_Cf && c != 0x061c && (c < 0x2066 || c > 0x2069)) )) == isprop)- return !negated;+ return not_negated; break; /* Punctuation: all Unicode punctuation, plus ASCII characters that@@ -273,7 +232,7 @@ chartype = prop->chartype; if ((PRIV(ucp_gentype)[chartype] == ucp_P || (c < 128 && PRIV(ucp_gentype)[chartype] == ucp_S)) == isprop)- return !negated;+ return not_negated; break; /* Perl has two sets of hex digits */@@ -285,24 +244,304 @@ (c >= 0xff10 && c <= 0xff19) || /* Fullwidth digits */ (c >= 0xff21 && c <= 0xff26) || /* Fullwidth letters */ (c >= 0xff41 && c <= 0xff46)) == isprop)- return !negated;+ return not_negated; break; /* This should never occur, but compilers may mutter if there is no default. */ + /* LCOV_EXCL_START */ default:+ PCRE2_DEBUG_UNREACHABLE(); return FALSE;+ /* LCOV_EXCL_STOP */ } data += 2; }+ while (*data == XCL_PROP || *data == XCL_NOTPROP);+ } #else (void)utf; /* Avoid compiler warning */ #endif /* SUPPORT_UNICODE */++/* Match against large chars or ranges that end with a large char. */+if (*data < XCL_LIST)+ {+ while ((t = *data++) != XCL_END)+ {+ uint32_t x, y;++#ifdef SUPPORT_UNICODE+ if (utf)+ {+ GETCHARINC(x, data); /* macro generates multiple statements */+ }+ else+#endif+ x = *data++;++ if (t == XCL_SINGLE)+ {+ /* Since character ranges follow the properties, and they are+ sorted, early return is possible for all characters <= x. */+ if (c <= x) return (c == x) ? not_negated : !not_negated;+ continue;+ }++ PCRE2_ASSERT(t == XCL_RANGE);+#ifdef SUPPORT_UNICODE+ if (utf)+ {+ GETCHARINC(y, data); /* macro generates multiple statements */+ }+ else+#endif+ y = *data++;++ /* Since character ranges follow the properties, and they are+ sorted, early return is possible for all characters <= y. */+ if (c <= y) return (c >= x) ? not_negated : !not_negated;+ }++ return !not_negated; /* char did not match */ } -return negated; /* char did not match */+#if PCRE2_CODE_UNIT_WIDTH == 8+type = (uint32_t)(data[0] << 8) | data[1];+data += 2;+#else+type = data[0];+data++;+#endif /* CODE_UNIT_WIDTH */++/* Align characters. */+next_char = char_lists_end - (GET(data, 0) << 1);+type &= XCL_TYPE_MASK;++/* Alignment check. */+PCRE2_ASSERT(((uintptr_t)next_char & 0x1) == 0);++if (c >= XCL_CHAR_LIST_HIGH_16_START)+ {+ max_index = type & XCL_ITEM_COUNT_MASK;+ if (max_index == XCL_ITEM_COUNT_MASK)+ {+ max_index = *(const uint16_t*)next_char;+ PCRE2_ASSERT(max_index >= XCL_ITEM_COUNT_MASK);+ next_char += 2;+ }++ next_char += max_index << 1;+ type >>= XCL_TYPE_BIT_LEN;+ }++if (c < XCL_CHAR_LIST_LOW_32_START)+ {+ max_index = type & XCL_ITEM_COUNT_MASK;++ c = (uint16_t)((c << XCL_CHAR_SHIFT) | XCL_CHAR_END);++ if (max_index == XCL_ITEM_COUNT_MASK)+ {+ max_index = *(const uint16_t*)next_char;+ PCRE2_ASSERT(max_index >= XCL_ITEM_COUNT_MASK);+ next_char += 2;+ }++ if (max_index == 0 || c < *(const uint16_t*)next_char)+ return ((type & XCL_BEGIN_WITH_RANGE) != 0) == not_negated;++ min_index = 0;+ value = ((const uint16_t*)next_char)[--max_index];+ if (c >= value)+ return (value == c || (value & XCL_CHAR_END) == 0) == not_negated;++ max_index--;++ /* Binary search of a range. */+ while (TRUE)+ {+ uint32_t mid_index = (min_index + max_index) >> 1;+ value = ((const uint16_t*)next_char)[mid_index];++ if (c < value)+ max_index = mid_index - 1;+ else if (((const uint16_t*)next_char)[mid_index + 1] <= c)+ min_index = mid_index + 1;+ else+ return (value == c || (value & XCL_CHAR_END) == 0) == not_negated;+ }+ }++/* Skip the 16 bit ranges. */+max_index = type & XCL_ITEM_COUNT_MASK;+if (max_index == XCL_ITEM_COUNT_MASK)+ {+ max_index = *(const uint16_t*)next_char;+ PCRE2_ASSERT(max_index >= XCL_ITEM_COUNT_MASK);+ next_char += 2;+ }++next_char += (max_index << 1);+type >>= XCL_TYPE_BIT_LEN;++/* Alignment check. */+PCRE2_ASSERT(((uintptr_t)next_char & 0x3) == 0);++max_index = type & XCL_ITEM_COUNT_MASK;++#if PCRE2_CODE_UNIT_WIDTH == 32+if (c >= XCL_CHAR_LIST_HIGH_32_START)+ {+ if (max_index == XCL_ITEM_COUNT_MASK)+ {+ max_index = *(const uint32_t*)next_char;+ PCRE2_ASSERT(max_index >= XCL_ITEM_COUNT_MASK);+ next_char += 4;+ }++ next_char += max_index << 2;+ type >>= XCL_TYPE_BIT_LEN;+ max_index = type & XCL_ITEM_COUNT_MASK;+ }+#endif++c = (uint32_t)((c << XCL_CHAR_SHIFT) | XCL_CHAR_END);++if (max_index == XCL_ITEM_COUNT_MASK)+ {+ max_index = *(const uint32_t*)next_char;+ next_char += 4;+ }++if (max_index == 0 || c < *(const uint32_t*)next_char)+ return ((type & XCL_BEGIN_WITH_RANGE) != 0) == not_negated;++min_index = 0;+value = ((const uint32_t*)next_char)[--max_index];+if (c >= value)+ return (value == c || (value & XCL_CHAR_END) == 0) == not_negated;++max_index--;++/* Binary search of a range. */+while (TRUE)+ {+ uint32_t mid_index = (min_index + max_index) >> 1;+ value = ((const uint32_t*)next_char)[mid_index];++ if (c < value)+ max_index = mid_index - 1;+ else if (((const uint32_t*)next_char)[mid_index + 1] <= c)+ min_index = mid_index + 1;+ else+ return (value == c || (value & XCL_CHAR_END) == 0) == not_negated;+ }+}++++/*************************************************+* Match character against an ECLASS *+*************************************************/++/* This function is called to match a character against an extended class+used for describing characters using boolean operations on sets.++Arguments:+ c the character+ data_start points to the start of the ECLASS data+ data_end points one-past-the-last of the ECLASS data+ utf TRUE if in UTF mode++Returns: TRUE if character matches, else FALSE+*/++BOOL+PRIV(eclass)(uint32_t c, PCRE2_SPTR data_start, PCRE2_SPTR data_end,+ const uint8_t *char_lists_end, BOOL utf)+{+PCRE2_SPTR ptr = data_start;+PCRE2_UCHAR flags;+uint32_t stack = 0;+int stack_depth = 0;++PCRE2_ASSERT(data_start < data_end);+flags = *ptr++;+PCRE2_ASSERT((flags & ECL_MAP) == 0 ||+ (data_end - ptr) >= 32 / (int)sizeof(PCRE2_UCHAR));++/* Code points < 256 are matched against a bitmap, if one is present.+Otherwise all codepoints are checked later. */++if ((flags & ECL_MAP) != 0)+ {+ if (c < 256)+ return (((const uint8_t *)ptr)[c/8] & (1u << (c&7))) != 0;++ /* Skip the bitmap. */+ ptr += 32 / sizeof(PCRE2_UCHAR);+ }++/* Do a little loop, until we reach the end of the ECLASS. */+while (ptr < data_end)+ {+ switch (*ptr)+ {+ case ECL_AND:+ ++ptr;+ stack = (stack >> 1) & (stack | ~(uint32_t)1u);+ PCRE2_ASSERT(stack_depth >= 2);+ --stack_depth;+ break;++ case ECL_OR:+ ++ptr;+ stack = (stack >> 1) | (stack & (uint32_t)1u);+ PCRE2_ASSERT(stack_depth >= 2);+ --stack_depth;+ break;++ case ECL_XOR:+ ++ptr;+ stack = (stack >> 1) ^ (stack & (uint32_t)1u);+ PCRE2_ASSERT(stack_depth >= 2);+ --stack_depth;+ break;++ case ECL_NOT:+ ++ptr;+ stack ^= (uint32_t)1u;+ PCRE2_ASSERT(stack_depth >= 1);+ break;++ case ECL_XCLASS:+ {+ uint32_t matched = PRIV(xclass)(c, ptr + 1 + LINK_SIZE, char_lists_end, utf);++ ptr += GET(ptr, 1);+ stack = (stack << 1) | matched;+ ++stack_depth;+ break;+ }++ /* This should never occur, but compilers may mutter if there is no+ default. */++ /* LCOV_EXCL_START */+ default:+ PCRE2_DEBUG_UNREACHABLE();+ return FALSE;+ /* LCOV_EXCL_STOP */+ }+ }++PCRE2_ASSERT(stack_depth == 1);+(void)stack_depth; /* Ignore unused variable, if assertions are disabled. */++/* The final bit left on the stack now holds the match result. */+return (stack & 1u) != 0; } /* End of pcre2_xclass.c */
src/c/pcre2/src/pcre2demo.c view
@@ -73,36 +73,38 @@ PCRE2_SPTR subject; /* the appropriate width (in this case, 8 bits). */ PCRE2_SPTR name_table; -int crlf_is_newline; int errornumber;-int find_all;+int find_all, caseless_match; int i; int rc;-int utf8; -uint32_t option_bits; uint32_t namecount; uint32_t name_entry_size;-uint32_t newline; PCRE2_SIZE erroroffset; PCRE2_SIZE *ovector;+PCRE2_SIZE ovector_last[2]; PCRE2_SIZE subject_length; pcre2_match_data *match_data; /**************************************************************************-* First, sort out the command line. There is only one possible option at *-* the moment, "-g" to request repeated matching to find all occurrences, *-* like Perl's /g option. We set the variable find_all to a non-zero value *-* if the -g option is present. *+* First, sort out the command line. Options: *+* - "-g" to request repeated matching to find all occurrences, *+* like Perl's /g option. We set the variable find_all to a non-zero *+* value if the -g option is present. *+* - "-i" to request caseless matching, like Perl's /i option. We set the *+* variable caseless_match to PCRE2_CASELESS if the -i option is *+* present. * **************************************************************************/ find_all = 0;+caseless_match = 0; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-g") == 0) find_all = 1;+ else if (strcmp(argv[i], "-i") == 0) caseless_match = PCRE2_CASELESS; else if (argv[i][0] == '-') { printf("Unrecognised option %s\n", argv[i]);@@ -138,7 +140,7 @@ re = pcre2_compile( pattern, /* the pattern */ PCRE2_ZERO_TERMINATED, /* indicates pattern is zero-terminated */- 0, /* default options */+ caseless_match, /* possibly enable caseless */ &errornumber, /* for error number */ &erroroffset, /* for error offset */ NULL); /* use default compile context */@@ -218,11 +220,12 @@ printf("ovector was not big enough for all the captured substrings\n"); /* Since release 10.38 PCRE2 has locked out the use of \K in lookaround-assertions. However, there is an option to re-enable the old behaviour. If that-is set, it is possible to run patterns such as /(?=.\K)/ that use \K in an-assertion to set the start of a match later than its end. In this demonstration-program, we show how to detect this case, but it shouldn't arise because the-option is never set. */+assertions. This is the recommended behaviour. However, the option+PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK allows applications to re-enable the old+behaviour. If that is set, it is possible to run patterns such as /(?=.\K)/ that+use \K in an assertion to set the start of a match later than its end. In this+demonstration program, we show how to detect this case, although it cannot arise+because the option is never set. */ if (ovector[0] > ovector[1]) {@@ -261,7 +264,9 @@ PCRE2_INFO_NAMECOUNT, /* get the number of named substrings */ &namecount); /* where to put the answer */ -if (namecount == 0) printf("No named substrings\n"); else+if (namecount == 0)+ printf("No named substrings\n");+else { PCRE2_SPTR tabptr; printf("Named substrings\n");@@ -299,28 +304,8 @@ * to search for additional matches in the subject string, in a similar * * way to the /g option in Perl. This turns out to be trickier than you * * might think because of the possibility of matching an empty string. *-* What happens is as follows: * * *-* If the previous match was NOT for an empty string, we can just start *-* the next match at the end of the previous one. *-* *-* If the previous match WAS for an empty string, we can't do that, as it *-* would lead to an infinite loop. Instead, a call of pcre2_match() is *-* made with the PCRE2_NOTEMPTY_ATSTART and PCRE2_ANCHORED flags set. The *-* first of these tells PCRE2 that an empty string at the start of the *-* subject is not a valid match; other possibilities must be tried. The *-* second flag restricts PCRE2 to one match attempt at the initial string *-* position. If this match succeeds, an alternative to the empty string *-* match has been found, and we can print it and proceed round the loop, *-* advancing by the length of whatever was found. If this match does not *-* succeed, we still stay in the loop, advancing by just one character. *-* In UTF-8 mode, which can be set by (*UTF) in the pattern, this may be *-* more than one byte. *-* *-* However, there is a complication concerned with newlines. When the *-* newline convention is such that CRLF is a valid newline, we must *-* advance by two characters rather than one. The newline convention can *-* be set in the regex by (*CR), etc.; if not, we must find the default. *+* To help with this task, PCRE2 provides the pcre2_next_match() helper. * *************************************************************************/ if (!find_all) /* Check for -g */@@ -330,60 +315,21 @@ return 0; /* Exit the program. */ } -/* Before running the loop, check for UTF-8 and whether CRLF is a valid newline-sequence. First, find the options with which the regex was compiled and extract-the UTF state. */--(void)pcre2_pattern_info(re, PCRE2_INFO_ALLOPTIONS, &option_bits);-utf8 = (option_bits & PCRE2_UTF) != 0;--/* Now find the newline convention and see whether CRLF is a valid newline-sequence. */--(void)pcre2_pattern_info(re, PCRE2_INFO_NEWLINE, &newline);-crlf_is_newline = newline == PCRE2_NEWLINE_ANY ||- newline == PCRE2_NEWLINE_CRLF ||- newline == PCRE2_NEWLINE_ANYCRLF;- /* Loop for second and subsequent matches */ +ovector_last[0] = ovector[0];+ovector_last[1] = ovector[1];+ for (;;) {- uint32_t options = 0; /* Normally no options */- PCRE2_SIZE start_offset = ovector[1]; /* Start at end of previous match */-- /* If the previous match was for an empty string, we are finished if we are- at the end of the subject. Otherwise, arrange to run another match at the- same point to see if a non-empty match can be found. */-- if (ovector[0] == ovector[1])- {- if (ovector[0] == subject_length) break;- options = PCRE2_NOTEMPTY_ATSTART | PCRE2_ANCHORED;- }+ PCRE2_SIZE start_offset;+ uint32_t options; - /* If the previous match was not an empty string, there is one tricky case to- consider. If a pattern contains \K within a lookbehind assertion at the- start, the end of the matched string can be at the offset where the match- started. Without special action, this leads to a loop that keeps on matching- the same substring. We must detect this case and arrange to move the start on- by one character. The pcre2_get_startchar() function returns the starting- offset that was passed to pcre2_match(). */+ /* After each successful match, we use pcre2_next_match() to obtain the match+ parameters for subsequent match attempts. */ - else- {- PCRE2_SIZE startchar = pcre2_get_startchar(match_data);- if (start_offset <= startchar)- {- if (startchar >= subject_length) break; /* Reached end of subject. */- start_offset = startchar + 1; /* Advance by one character. */- if (utf8) /* If UTF-8, it may be more */- { /* than one code unit. */- for (; start_offset < subject_length; start_offset++)- if ((subject[start_offset] & 0xc0) != 0x80) break;- }- }- }+ if (!pcre2_next_match(match_data, &start_offset, &options))+ break; /* Run the next matching operation */ @@ -396,38 +342,10 @@ match_data, /* block for storing the result */ NULL); /* use default match context */ - /* This time, a result of NOMATCH isn't an error. If the value in "options"- is zero, it just means we have found all possible matches, so the loop ends.- Otherwise, it means we have failed to find a non-empty-string match at a- point where there was a previous empty-string match. In this case, we do what- Perl does: advance the matching position by one character, and continue. We- do this by setting the "end of previous match" offset, because that is picked- up at the top of the loop as the point at which to start again.-- There are two complications: (a) When CRLF is a valid newline sequence, and- the current position is just before it, advance by an extra byte. (b)- Otherwise we must ensure that we skip an entire UTF character if we are in- UTF mode. */+ /* If this match attempt fails, exit the loop for subsequent matches. */ if (rc == PCRE2_ERROR_NOMATCH)- {- if (options == 0) break; /* All matches found */- ovector[1] = start_offset + 1; /* Advance one code unit */- if (crlf_is_newline && /* If CRLF is a newline & */- start_offset < subject_length - 1 && /* we are at CRLF, */- subject[start_offset] == '\r' &&- subject[start_offset + 1] == '\n')- ovector[1] += 1; /* Advance by one more. */- else if (utf8) /* Otherwise, ensure we */- { /* advance a whole UTF-8 */- while (ovector[1] < subject_length) /* character. */- {- if ((subject[ovector[1]] & 0xc0) != 0x80) break;- ovector[1] += 1;- }- }- continue; /* Go round the loop again */- }+ break; /* Other matching errors are not recoverable. */ @@ -439,8 +357,34 @@ return 1; } - /* Match succeeded */+ /* This demonstration program depends on pcre2_next_match() to ensure that the+ loop for second and subsequent matches does not run forever. However, it would+ be robust practice for a production application to verify this. The following+ block of code shows how to do this. This error case is not reachable unless+ there is a bug in PCRE2. + Because this program does not set the PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK option,+ the logic is simple. We verify that either ovector[1] has advanced, or that we+ have an empty match touching the end of a previous non-empty match. See the+ API documentation for guidance if your application uses+ PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK and searches for multiple matches. */++ if (!(ovector[1] > ovector_last[1] ||+ (ovector[1] == ovector[0] && ovector_last[1] > ovector_last[0] &&+ ovector[1] == ovector_last[1])))+ {+ printf("\\K was used in an assertion to yield non-advancing matches.\n");+ printf("Run abandoned\n");+ pcre2_match_data_free(match_data);+ pcre2_code_free(re);+ return 1;+ }++ ovector_last[0] = ovector[0];+ ovector_last[1] = ovector[1];++ /* Match succeeded. */+ printf("\nMatch succeeded again at offset %d\n", (int)ovector[0]); /* The match succeeded, but the output vector wasn't big enough. This@@ -449,9 +393,11 @@ if (rc == 0) printf("ovector was not big enough for all the captured substrings\n"); - /* We must guard against patterns such as /(?=.\K)/ that use \K in an- assertion to set the start of a match later than its end. In this- demonstration program, we just detect this case and give up. */+ /* We guard against patterns such as /(?=.\K)/ that use \K in an assertion to+ set the start of a match later than its end. As explained above, this case+ should not occur because this demonstration program does not set the+ PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK option, however, we do include code showing+ how to detect it. */ if (ovector[0] > ovector[1]) {@@ -474,7 +420,9 @@ printf("%2d: %.*s\n", i, (int)substring_length, (char *)substring_start); } - if (namecount == 0) printf("No named substrings\n"); else+ if (namecount == 0)+ printf("No named substrings\n");+ else { PCRE2_SPTR tabptr = name_table; printf("Named substrings\n");@@ -489,6 +437,7 @@ } /* End of loop to find second and subsequent matches */ printf("\n");+ pcre2_match_data_free(match_data); pcre2_code_free(re); return 0;
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-2023 University of Cambridge+ Copyright (c) 1997-2024 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -48,8 +48,12 @@ #include "config.h" #endif +#include "pcre2_util.h"+ #include <ctype.h>+#include <limits.h> #include <locale.h>+#include <stddef.h> #include <stdio.h> #include <string.h> #include <stdlib.h>@@ -87,6 +91,10 @@ #endif #endif +#ifdef SUPPORT_VALGRIND+#include <valgrind/memcheck.h>+#endif+ #ifdef HAVE_UNISTD_H #include <unistd.h> #endif@@ -256,7 +264,7 @@ static uint32_t pcre2_options = 0; static uint32_t extra_options = 0;-static PCRE2_SIZE heap_limit = PCRE2_UNSET;+static uint32_t heap_limit = ~(uint32_t)0; static uint32_t match_limit = 0; static uint32_t depth_limit = 0; @@ -290,6 +298,7 @@ static BOOL silent = FALSE; static BOOL utf = FALSE; static BOOL posix_digit = FALSE;+static BOOL posix_pattern_file = FALSE; static uint8_t utf8_buffer[8]; @@ -428,6 +437,7 @@ #define N_POSIX_DIGIT (-26) #define N_GROUP_SEPARATOR (-27) #define N_NO_GROUP_SEPARATOR (-28)+#define N_POSIX_PATFILE (-29) static option_item optionlist[] = { { OP_NODATA, N_NULL, NULL, "", "terminate options" },@@ -449,6 +459,7 @@ { 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_NODATA, N_POSIX_PATFILE, NULL, "posix-pattern-file", "use POSIX semantics for pattern files" }, { 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" },@@ -462,7 +473,7 @@ { OP_NODATA, N_LBUFFER, NULL, "line-buffered", "use line buffering" }, { OP_NODATA, N_LOFFSETS, NULL, "line-offsets", "output line numbers and offsets, not text" }, { OP_STRING, N_LOCALE, &locale, "locale=locale", "use the named locale" },- { OP_SIZE, N_H_LIMIT, &heap_limit, "heap-limit=number", "set PCRE2 heap limit option (kibibytes)" },+ { OP_U32NUMBER, N_H_LIMIT, &heap_limit, "heap-limit=number", "set PCRE2 heap limit option (kibibytes)" }, { OP_U32NUMBER, N_M_LIMIT, &match_limit, "match-limit=number", "set PCRE2 match limit option" }, { OP_U32NUMBER, N_M_LIMIT_DEP, &depth_limit, "depth-limit=number", "set PCRE2 depth limit option" }, { OP_U32NUMBER, N_M_LIMIT_DEP, &depth_limit, "recursion-limit=number", "obsolete synonym for depth-limit" },@@ -524,45 +535,7 @@ 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 }; -#if !defined(VPCOMPAT) && !defined(HAVE_MEMMOVE)-/*************************************************-* Emulated memmove() for systems without it *-*************************************************/ -/* This function can make use of bcopy() if it is available. Otherwise do it by-steam, as there are some non-Unix environments that lack both memmove() and-bcopy(). */--static void *-emulated_memmove(void *d, const void *s, size_t n)-{-#ifdef HAVE_BCOPY-bcopy(s, d, n);-return d;-#else-size_t i;-unsigned char *dest = (unsigned char *)d;-const unsigned char *src = (const unsigned char *)s;-if (dest > src)- {- dest += n;- src += n;- for (i = 0; i < n; ++i) *(--dest) = *(--src);- return (void *)dest;- }-else- {- for (i = 0; i < n; ++i) *dest++ = *src++;- return (void *)(dest - n);- }-#endif /* not HAVE_BCOPY */-}-#undef memmove-#define memmove(d,s,n) emulated_memmove(d,s,n)-#endif /* not VPCOMPAT && not HAVE_MEMMOVE */--- /************************************************* * Convert code point to UTF-8 * *************************************************/@@ -824,7 +797,7 @@ static void-init_colour_output()+init_colour_output(void) { if (do_colour) {@@ -853,7 +826,9 @@ /************* Directory scanning Unix-style and z/OS ***********/ -#if (defined HAVE_SYS_STAT_H && defined HAVE_DIRENT_H && defined HAVE_SYS_TYPES_H) || defined NATIVE_ZOS+#if !defined WIN32 && \+ (defined HAVE_SYS_STAT_H && defined HAVE_DIRENT_H && defined HAVE_SYS_TYPES_H) || \+ defined NATIVE_ZOS #include <sys/types.h> #include <sys/stat.h> #include <dirent.h>@@ -893,11 +868,12 @@ for (;;) { struct dirent *dent = readdir(dir);- if (dent == NULL) return NULL;+ if (dent == NULL) break; if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0) return dent->d_name; }-/* Control never reaches here */++return NULL; } static void@@ -956,7 +932,7 @@ /************* Print optionally coloured match Unix-style and z/OS **********/ static void-print_match(const void *buf, int length)+print_match(const void *buf, size_t length) { if (length == 0) return; if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);@@ -1092,7 +1068,7 @@ /************* Print optionally coloured match in Windows **********/ static void-print_match(const void *buf, int length)+print_match(const void *buf, size_t length) { if (length == 0) return; if (do_colour)@@ -1151,7 +1127,7 @@ /************* Print optionally coloured match when we can't do it **********/ static void-print_match(const void *buf, int length)+print_match(const void *buf, size_t length) { if (length == 0) return; FWRITE_IGNORE(buf, 1, length, stdout);@@ -1161,29 +1137,7 @@ -#ifndef HAVE_STRERROR /*************************************************-* Provide strerror() for non-ANSI libraries *-*************************************************/--/* Some old-fashioned systems still around (e.g. SunOS4) don't have strerror()-in their libraries, but can provide the same facility by this simple-alternative function. */--extern int sys_nerr;-extern char *sys_errlist[];--char *-strerror(int n)-{-if (n < 0 || n >= sys_nerr) return "unknown error number";-return sys_errlist[n];-}-#endif /* HAVE_STRERROR */----/************************************************* * Usage function * *************************************************/ @@ -1255,8 +1209,8 @@ n = 31 - printf(" -%c", op->one_char); else {- if (op->one_char > 0) sprintf(s, "-%c,", op->one_char);- else strcpy(s, " ");+ if (op->one_char > 0) snprintf(s, sizeof(s), "-%c,", op->one_char);+ else snprintf(s, sizeof(s), " "); n = 31 - printf(" %s --%s", s, op->long_name); } @@ -1295,7 +1249,7 @@ static BOOL test_incexc(char *path, patstr *ip, patstr *ep) {-int plen = strlen((const char *)path);+size_t plen = strlen((const char *)path); for (; ep != NULL; ep = ep->next) {@@ -1448,8 +1402,35 @@ return yield; } +/*************************************************+* Read one pattern from file *+*************************************************/ +/* Wrap around read_one_line() to make sure any terminating '\n' is not+included in the pattern and empty patterns are correctly identified. +Arguments:+ buffer the buffer to read into+ length maximum number of characters to read and report how many were+ f the file++Returns: TRUE if a pattern was read into buffer+*/++static BOOL+read_pattern(char *buffer, PCRE2_SIZE *length, FILE *f)+{+*buffer = '\0';+*length = read_one_line(buffer, *length, f);+if (*length > 0 && buffer[*length-1] == '\n') *length = *length - 1;+if (posix_pattern_file && *length > 0 && buffer[*length-1] == '\r')+ {+ *length = *length - 1;+ if (*length == 0) return TRUE;+ }+return (*length > 0 || *buffer == '\n');+}+ /************************************************* * Find end of line * *************************************************/@@ -1506,12 +1487,13 @@ for (;;) { while (p < endptr && *p != '\r') p++;- if (++p >= endptr)+ if (p == endptr) { *lenptr = 0; return endptr; }- if (*p == '\n')+ p++;+ if (p < endptr && *p == '\n') { *lenptr = 2; return p + 1;@@ -1522,42 +1504,25 @@ case PCRE2_NEWLINE_ANYCRLF: while (p < endptr) {- int extra = 0;- int c = *((unsigned char *)p);-- if (utf && c >= 0xc0)+ if (*p == '\n') {- int gcii, gcss;- extra = utf8_table4[c & 0x3f]; /* Number of additional bytes */- gcss = 6*extra;- c = (c & utf8_table3[extra]) << gcss;- for (gcii = 1; gcii <= extra; gcii++)- {- gcss -= 6;- c |= (p[gcii] & 0x3f) << gcss;- }+ *lenptr = 1;+ return p + 1; } - p += 1 + extra;-- switch (c)+ if (*p == '\r') {- case '\n':- *lenptr = 1;- return p;-- case '\r':- if (p < endptr && *p == '\n')+ if (p + 1 < endptr && p[1] == '\n') { *lenptr = 2;- p++;+ return p + 2; }- else *lenptr = 1;- return p; - default:- break;+ *lenptr = 1;+ return p + 1; }++ p++; } /* End of loop for ANYCRLF case */ *lenptr = 0; /* Must have hit the end */@@ -1573,6 +1538,11 @@ { int gcii, gcss; extra = utf8_table4[c & 0x3f]; /* Number of additional bytes */+ if (endptr - p < 1 + extra)+ {+ *lenptr = 0; /* Hit the end, halfway through a character */+ return endptr;+ } gcss = 6*extra; c = (c & utf8_table3[extra]) << gcss; for (gcii = 1; gcii <= extra; gcii++)@@ -1589,26 +1559,26 @@ case '\n': /* LF */ case '\v': /* VT */ case '\f': /* FF */- *lenptr = 1;+ *lenptr = 1 + extra; return p; case '\r': /* CR */- if (p < endptr && *p == '\n')+ if (extra == 0 && p < endptr && *p == '\n') { *lenptr = 2; p++; }- else *lenptr = 1;+ else *lenptr = 1 + extra; return p; #ifndef EBCDIC case 0x85: /* Unicode NEL */- *lenptr = utf? 2 : 1;+ *lenptr = 1 + extra; return p; case 0x2028: /* Unicode LS */ case 0x2029: /* Unicode PS */- *lenptr = 3;+ *lenptr = 1 + extra; return p; #endif /* Not EBCDIC */ @@ -1659,33 +1629,53 @@ return p; case PCRE2_NEWLINE_CRLF:+ p -= 2; for (;;) {- p -= 2; while (p > startptr && p[-1] != '\n') p--;- if (p <= startptr + 1 || p[-2] == '\r') return p;+ if (p == startptr) break;+ if (p - startptr >= 2 && p[-2] == '\r') break;+ p--; }- /* Control can never get here */+ return p; - case PCRE2_NEWLINE_ANY: case PCRE2_NEWLINE_ANYCRLF:- if (*(--p) == '\n' && p > startptr && p[-1] == '\r') p--;- if (utf) while ((*p & 0xc0) == 0x80) p--;+ if (p - startptr >= 2 && p[-2] == '\r' && p[-1] == '\n') p -= 2;+ else p--;+ while (p > startptr)+ {+ if (p[-1] == '\n' || p[-1] == '\r') break;+ p--;+ }+ return p; + case PCRE2_NEWLINE_ANY:+ if (p - startptr >= 2 && p[-2] == '\r' && p[-1] == '\n') p -= 2;+ else+ {+ if (utf) while (p > startptr && (p[-1] & 0xc0) == 0x80) p--;+ if (p > startptr) p--;+ }+ while (p > startptr) {- unsigned int c;+ int c; char *pp = p - 1; if (utf) { int extra = 0;- while ((*pp & 0xc0) == 0x80) pp--;+ while (pp > startptr && (*pp & 0xc0) == 0x80) pp--; c = *((unsigned char *)pp); if (c >= 0xc0) { int gcii, gcss; extra = utf8_table4[c & 0x3f]; /* Number of additional bytes */+ if (p - pp < 1 + extra)+ {+ p = pp; /* Rewind over the broken character */+ continue;+ } gcss = 6*extra; c = (c & utf8_table3[extra]) << gcss; for (gcii = 1; gcii <= extra; gcii++)@@ -1697,17 +1687,7 @@ } else c = *((unsigned char *)pp); - if (endlinetype == PCRE2_NEWLINE_ANYCRLF) switch (c)- {- case '\n': /* LF */- case '\r': /* CR */- return p;-- default:- break;- }-- else switch (c)+ switch (c) { case '\n': /* LF */ case '\v': /* VT */@@ -1727,7 +1707,7 @@ p = pp; /* Back one character */ } /* End of loop for ANY case */ - return startptr; /* Hit start of data */+ return p; } /* End of overall switch */ } @@ -1991,11 +1971,23 @@ *last = string; return DDE_ERROR; + case '&':+ /* In a callout, no capture is available. Return the character '0' for+ consistency with $0. */++ if (callout) *value = '0';+ else+ {+ *value = 0;+ rc = DDE_CAPTURE;+ }+ break;+ case '{': brace = TRUE; string++;- if (!isdigit((unsigned char)(*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", (int)(string - begin), "decimal number expected");@@ -2003,7 +1995,7 @@ break; } - /* Fall through */+ PCRE2_FALLTHROUGH /* Fall through */ /* The maximum capture number is 65535, so any number greater than that will always be an unknown capture number. We just stop incrementing, in order to@@ -2072,9 +2064,9 @@ { if (!isxdigit(*string)) break; if (*string >= '0' && *string <= '9')- c = c *16 + *string++ - '0';+ c = c *16 + (*string++ - '0'); else- c = c * 16 + (*string++ | 0x20) - 'a' + 10;+ c = c * 16 + ((*string++ | 0x20) - 'a') + 10; } *value = c; string--; /* Point to last digit */@@ -2454,10 +2446,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. */+ default:+ /* Even though this should not occur, the string having been checked above,+ * we need to include the free() calls so that source checkers do not complain. */+ case DDE_ERROR:+ free(args); free(argsvector);+ abort(); return 0; /* LCOV_EXCL_STOP */ }@@ -2480,7 +2475,8 @@ necessary, otherwise assume fork(). */ #ifdef WIN32-result = _spawnvp(_P_WAIT, argsvector[0], (const char * const *)argsvector);+(void)fflush(stdout);+result = _spawnvp(_P_WAIT, argsvector[0], (const char * const *)argsvector) != 0; #elif defined __VMS {@@ -2503,6 +2499,7 @@ } #else /* Neither Windows nor VMS */+(void)fflush(stdout); pid = fork(); if (pid == 0) {@@ -2512,9 +2509,7 @@ } else if (pid > 0) {- (void)fflush(stdout); (void)waitpid(pid, &result, 0);- (void)fflush(stdout); } #endif /* End Windows/VMS/other handling */ @@ -2535,27 +2530,37 @@ * Read a portion of the file into buffer * *************************************************/ -static PCRE2_SIZE+static ptrdiff_t fill_buffer(void *handle, int frtype, char *buffer, PCRE2_SIZE length, BOOL input_line_buffered) {+PCRE2_SIZE nread; (void)frtype; /* Avoid warning when not used */ #ifdef SUPPORT_LIBZ if (frtype == FR_LIBZ)- return gzread((gzFile)handle, buffer, length);+ return gzread((gzFile)handle, buffer,+ (length > UINT_MAX)? UINT_MAX : (unsigned)length); else #endif #ifdef SUPPORT_LIBBZ2 if (frtype == FR_LIBBZ2)- return (PCRE2_SIZE)BZ2_bzread((BZFILE *)handle, buffer, length);+ return BZ2_bzread((BZFILE *)handle, buffer,+ (length > UINT_MAX)? UINT_MAX : (unsigned)length); else #endif -return (input_line_buffered ?+nread = (input_line_buffered ? read_one_line(buffer, length, (FILE *)handle) : fread(buffer, 1, length, (FILE *)handle));++#ifdef SUPPORT_VALGRIND+if (nread > 0) VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(buffer, nread);+if (nread < length) VALGRIND_MAKE_MEM_UNDEFINED(buffer + nread, length - nread);+#endif++return (ptrdiff_t)nread; } @@ -2600,6 +2605,7 @@ char *ptr = main_buffer; char *endptr; PCRE2_SIZE bufflength;+ptrdiff_t buffrc; BOOL binary = FALSE; BOOL endhyphenpending = FALSE; BOOL lines_printed = FALSE;@@ -2625,13 +2631,17 @@ } else input_line_buffered = FALSE; -bufflength = fill_buffer(handle, frtype, main_buffer, bufsize,+buffrc = fill_buffer(handle, frtype, main_buffer, bufsize, input_line_buffered); +#if defined SUPPORT_LIBZ+if (frtype == FR_LIBZ && buffrc < 0) return 3;+#endif #ifdef SUPPORT_LIBBZ2-if (frtype == FR_LIBBZ2 && (int)bufflength < 0) return 3; /* Gotcha: bufflength is PCRE2_SIZE */+if (frtype == FR_LIBBZ2 && buffrc < 0) return 3; #endif +bufflength = (PCRE2_SIZE)buffrc; endptr = main_buffer + bufflength; /* Unless binary-files=text, see if we have a binary file. This uses the same@@ -2729,8 +2739,17 @@ /* Read more data into the buffer and then try to find the line ending again. */ - bufflength += fill_buffer(handle, frtype, main_buffer + bufflength,+ buffrc = fill_buffer(handle, frtype, main_buffer + bufflength, bufsize - bufflength, input_line_buffered);++#if defined SUPPORT_LIBZ+ if (frtype == FR_LIBZ && buffrc < 0) return 3;+#endif+#ifdef SUPPORT_LIBBZ2+ if (frtype == FR_LIBBZ2 && buffrc < 0) return 3;+#endif++ bufflength += (PCRE2_SIZE)buffrc; endptr = main_buffer + bufflength; continue; }@@ -2862,7 +2881,7 @@ int n = om->groupnum; if (n == 0 || n < mrc) {- int plen = offsets[2*n + 1] - offsets[2*n];+ size_t plen = offsets[2*n + 1] - offsets[2*n]; if (plen > 0) { if (printed && om_separator != NULL)@@ -2952,12 +2971,15 @@ FWRITE_IGNORE(lastmatchrestart, 1, pp - lastmatchrestart, stdout); lastmatchrestart = pp; }+ if (lastmatchrestart != ptr) hyphenpending = TRUE; } - /* If there were non-contiguous lines printed above, insert hyphens. */+ /* If hyphenpending is TRUE when there is no "after" context, it means we+ are at the start of a new file, having output something from the previous+ file. Output a separator if enabled.*/ - if (hyphenpending)+ else if (hyphenpending) { if (group_separator != NULL) fprintf(stdout, "%s%s", group_separator, STDOUT_NL);@@ -2984,6 +3006,7 @@ if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted && group_separator != NULL) fprintf(stdout, "%s%s", group_separator, STDOUT_NL);+ hyphenpending = FALSE; while (p < ptr) {@@ -2998,12 +3021,23 @@ } } + /* If hyphenpending is TRUE here, it was set after outputting some+ "after" lines (and there are no "before" lines). */++ else if (hyphenpending)+ {+ if (group_separator != NULL)+ fprintf(stdout, "%s%s", group_separator, STDOUT_NL);+ hyphenpending = FALSE;+ }+ /* Now print the matching line(s); ensure we set hyphenpending at the end of the file if any context lines are being output. */ if (after_context > 0 || before_context > 0) endhyphenpending = TRUE; + if (printname != NULL) fprintf(stdout, "%s%c", printname, printname_colon); if (number) fprintf(stdout, "%lu:", linenumber);@@ -3186,8 +3220,17 @@ (void)memmove(main_buffer, main_buffer + bufthird, 2*bufthird); ptr -= bufthird; - bufflength = 2*bufthird + fill_buffer(handle, frtype,- main_buffer + 2*bufthird, bufthird, input_line_buffered);+ buffrc = fill_buffer(handle, frtype, main_buffer + 2*bufthird, bufthird,+ input_line_buffered);++#if defined SUPPORT_LIBZ+ if (frtype == FR_LIBZ && buffrc < 0) return 3;+#endif+#ifdef SUPPORT_LIBBZ2+ if (frtype == FR_LIBBZ2 && buffrc < 0) return 3;+#endif++ bufflength = 2*bufthird + (PCRE2_SIZE)buffrc; endptr = main_buffer + bufflength; /* Adjust any last match point */@@ -3366,8 +3409,11 @@ while ((nextfile = readdirectory(dir)) != NULL) { int frc;- int fnlength = strlen(pathname) + strlen(nextfile) + 2;- if (fnlength > FNBUFSIZ)+ int prc;+ if (strlen(pathname) + strlen(nextfile) + 2 > sizeof(childpath) ||+ (prc = snprintf(childpath, sizeof(childpath), "%s%c%s", pathname,+ FILESEP, nextfile)) < 0 ||+ prc >= (int)sizeof(childpath)) { /* LCOV_EXCL_START - this is a "never" event */ fprintf(stderr, "pcre2grep: recursive filename is too long\n");@@ -3375,7 +3421,6 @@ break; /* LCOV_EXCL_STOP */ }- sprintf(childpath, "%s%c%s", pathname, FILESEP, nextfile); /* If the realpath() function is available, we can try to prevent endless recursion caused by a symlink pointing to a parent directory (GitHub@@ -3435,7 +3480,19 @@ while ((nextfile = readdirectory(dir)) != NULL) { int frc;- sprintf(buffer, "%.512s%.128s", pathname, nextfile);+ int prc;+ if (strlen(pathname) + strlen(nextfile) + 1 > sizeof(buffer) ||+ (prc = snprintf(buffer, sizeof(buffer), "%s%s", pathname,+ nextfile)) < 0 ||+ prc >= (int)sizeof(buffer))+ {+ /* LCOV_EXCL_START - this is a "never" event */+ fprintf(stderr, "pcre2grep: wildcard filename is too long\n");+ rc = 2;+ break;+ /* LCOV_EXCL_STOP */+ }+ frc = grep_or_recurse(buffer, dir_recurse, FALSE); if (frc > 1) rc = frc; else if (frc == 0 && rc == 1) rc = 0;@@ -3537,7 +3594,18 @@ #ifdef SUPPORT_LIBZ if (frtype == FR_LIBZ)+ {+ if (rc == 3)+ {+ int errnum;+ const char *err = gzerror(ingz, &errnum);+ if (!silent)+ fprintf(stderr, "pcre2grep: Failed to read %s using zlib: %s\n",+ pathname, err);+ rc = 2; /* The normal "something went wrong" code */+ } gzclose(ingz);+ } else #endif @@ -3598,6 +3666,7 @@ 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 N_POSIX_PATFILE: posix_pattern_file = TRUE; break; case 'a': binary_files = BIN_TEXT; break; case 'c': count_only = TRUE; break; case N_POSIX_DIGIT: posix_digit = TRUE; break;@@ -3663,16 +3732,16 @@ { static char buffer[14]; char *p = buffer;-sprintf(p, "%d", n);+snprintf(p, sizeof(buffer), "%d", n); while (*p != 0) p++; n %= 100; if (n >= 11 && n <= 13) n = 0; switch (n%10) {- case 1: strcpy(p, "st"); break;- case 2: strcpy(p, "nd"); break;- case 3: strcpy(p, "rd"); break;- default: strcpy(p, "th"); break;+ case 1: snprintf(p, (buffer + sizeof(buffer)) - p, "st"); break;+ case 2: snprintf(p, (buffer + sizeof(buffer)) - p, "nd"); break;+ case 3: snprintf(p, (buffer + sizeof(buffer)) - p, "rd"); break;+ default: snprintf(p, (buffer + sizeof(buffer)) - p, "th"); break; } return buffer; }@@ -3808,11 +3877,19 @@ filename = name; } -while ((patlen = read_one_line(buffer, sizeof(buffer), f)) > 0)+while (TRUE) {- while (patlen > 0 && isspace((unsigned char)(buffer[patlen-1]))) patlen--;+ patlen = sizeof(buffer);+ if (!read_pattern(buffer, &patlen, f))+ break;++ if (!posix_pattern_file)+ {+ while (patlen > 0 && isspace((unsigned char)(buffer[patlen-1]))) patlen--;+ }+ linenumber++;- if (patlen == 0) continue; /* Skip blank lines */+ if (!posix_pattern_file && patlen == 0) continue; /* Skip blank lines */ /* Note: this call to add_pattern() puts a pointer to the local variable "buffer" into the pattern chain. However, that pointer is used only when@@ -3973,10 +4050,10 @@ (int)strlen(arg) : (int)(argequals - arg); if ((ret = snprintf(buff1, sizeof(buff1), "%.*s", baselen, op->long_name),- ret < 0 || ret > (int)sizeof(buff1)) ||+ ret < 0 || ret >= (int)sizeof(buff1)) || (ret = snprintf(buff2, sizeof(buff2), "%s%.*s", buff1, fulllen - baselen - 2, opbra + 1),- ret < 0 || ret > (int)sizeof(buff2)))+ ret < 0 || ret >= (int)sizeof(buff2))) { /* LCOV_EXCL_START - this is a "never" event */ fprintf(stderr, "pcre2grep: Buffer overflow when parsing %s option\n",@@ -4178,9 +4255,9 @@ else { unsigned long int n = decode_number(option_data, op, longop);- if (op->type == OP_U32NUMBER) *((uint32_t *)op->dataptr) = n;+ if (op->type == OP_U32NUMBER) *((uint32_t *)op->dataptr) = (uint32_t)n; else if (op->type == OP_SIZE) *((PCRE2_SIZE *)op->dataptr) = n;- else *((int *)op->dataptr) = n;+ else *((int *)op->dataptr) = (int)n; } } @@ -4244,11 +4321,13 @@ #ifdef SUPPORT_PCRE2GREP_CALLOUT pcre2_set_callout(match_context, pcre2grep_callout, NULL);+#else+extra_options |= PCRE2_EXTRA_NEVER_CALLOUT; #endif /* Put limits into the match context. */ -if (heap_limit != PCRE2_UNSET) pcre2_set_heap_limit(match_context, heap_limit);+if (heap_limit != ~(uint32_t)0) pcre2_set_heap_limit(match_context, heap_limit); if (match_limit > 0) pcre2_set_match_limit(match_context, match_limit); if (depth_limit > 0) pcre2_set_depth_limit(match_context, depth_limit); @@ -4381,6 +4460,8 @@ if (case_restrict) extra_options |= PCRE2_EXTRA_CASELESS_RESTRICT; if (posix_digit) extra_options |= (PCRE2_EXTRA_ASCII_BSD | PCRE2_EXTRA_ASCII_DIGIT);+if ((pcre2_options & PCRE2_LITERAL) != 0)+ extra_options &= ~PCRE2_EXTRA_NEVER_CALLOUT; /* Set the extra options in the compile context. */
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-2022 University of Cambridge+ New API code Copyright (c) 2016-2024 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without@@ -41,18 +41,21 @@ /* This module is a wrapper that provides a POSIX API to the underlying PCRE2 functions. The functions are called pcre2_regcomp(), pcre2_regexec(), etc.-pcre2posix.h defines the POSIX names as macros for the corresonding pcre2_xxx+pcre2posix.h defines the POSIX names as macros for the corresponding pcre2_xxx functions, so any program that includes it and uses the POSIX names will call the PCRE2 implementations instead. */ -#ifdef HAVE_CONFIG_H+/* This module doesn't use pcre2_internal.h, because the pcre2posix dynamic+library has an "internal" view of some macros, but is an "external" client of+the pcre2-8 dynamic library. This is unusual, and justifies a (rare) direct+inclusion of config.h. */++#if defined HAVE_CONFIG_H && !defined PCRE2_CONFIG_H_IDEMPOTENT_GUARD+#define PCRE2_CONFIG_H_IDEMPOTENT_GUARD #include "config.h" #endif -#ifdef PCRE2POSIX_SHARED-#undef PCRE2_STATIC-#endif /* Ensure that the PCRE2POSIX_EXP_xxx macros are set appropriately for@@ -60,18 +63,32 @@ they are set for an application (using these functions) if they have not previously been set. */ -#if defined(_WIN32) && (defined(PCRE2POSIX_SHARED) || !defined(PCRE2_STATIC))-# define PCRE2POSIX_EXP_DECL extern __declspec(dllexport)-# define PCRE2POSIX_EXP_DEFN __declspec(dllexport)+#if defined __cplusplus+#error This project uses C99. C++ is not supported. #endif +#ifndef PCRE2POSIX_EXP_DECL+# if defined(_WIN32) && defined(PCRE2POSIX_SHARED)+# define PCRE2POSIX_EXP_DECL extern __declspec(dllexport)+# else+# define PCRE2POSIX_EXP_DECL extern PCRE2_EXPORT+# endif+#endif++#ifndef PCRE2POSIX_EXP_DEFN+# if defined(_WIN32) && defined(PCRE2POSIX_SHARED)+# define PCRE2POSIX_EXP_DEFN extern __declspec(dllexport)+# else+# define PCRE2POSIX_EXP_DEFN extern PCRE2_EXPORT+# endif+#endif+ /* Older versions of MSVC lack snprintf(). This define allows for warning/error-free compilation and testing with MSVC compilers back to at least MSVC 10/2010. Except for VC6 (which is missing some fundamentals and fails). */ #if defined(_MSC_VER) && (_MSC_VER < 1900) #define snprintf _snprintf-#define BROKEN_SNPRINTF #endif @@ -94,11 +111,20 @@ #include "pcre2.h" #include "pcre2posix.h"+#include "pcre2_util.h" +/* For pcre2_tables.c */+#define PCRE2_PCRE2POSIX+/* For pcre2_tables.c */+#define PRIV(name) name++#include "pcre2_tables.c"+ /* 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-don't. */+don't, even though some of them cannot currently be provoked from within the+POSIX wrapper. */ static const int eint1[] = { 0, /* No error */@@ -137,7 +163,9 @@ 37, REG_EESCAPE, /* PCRE2 does not support \L, \l, \N{name}, \U, or \u */ 56, REG_INVARG, /* internal error: unknown newline setting */ 92, REG_INVARG, /* invalid option bits with PCRE2_LITERAL */- 99, REG_EESCAPE /* \K in lookaround */+ 98, REG_EESCAPE, /* missing digit after \0 in NO_BS0 mode */+ 99, REG_EESCAPE, /* \K in lookaround */+ 102, REG_EESCAPE /* \ddd octal > \377 in PYTHON_OCTAL mode */ }; /* Table of texts corresponding to POSIX error codes */@@ -163,14 +191,6 @@ "match failed" /* NOMATCH */ }; -static int message_len(const char *message, int offset)-{-char buf[12];--/* 11 magic number comes from the format below */-return (int)strlen(message) + 11 + snprintf(buf, sizeof(buf), "%d", offset);-}- /************************************************* * Translate error code to string * *************************************************/@@ -179,64 +199,50 @@ pcre2_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) {-int ret; const char *message;-size_t len = 0; /* keeps 0 if snprintf is used */+char offset_buf[11+12]; /* big enough for " at offset -2147483648" */+int snprintf_rc, have_offset = 0;+PCRE2_SIZE i; message = (errcode <= 0 || errcode >= (int)(sizeof(pstring)/sizeof(char *)))? "unknown error code" : pstring[errcode]; -if (preg != NULL && (int)preg->re_erroffset != -1)+if (preg != NULL && preg->re_erroffset != (size_t)(-1)+ /* LCOV_EXCL_START - snprintf failures here are essentially unreachable */+ && (snprintf_rc = snprintf(offset_buf, sizeof(offset_buf), " at offset %d",+ (int)preg->re_erroffset)) > 0+ && snprintf_rc < (int)sizeof(offset_buf))+ /* LCOV_EXCL_STOP */ {- /* 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);+ have_offset = 1;+ offset_buf[sizeof(offset_buf) - 1] = 0; /* Paranoia for very old snprintf */ }-else++for (i = 0; *message != 0; i++, message++)+ if (i + 1 < errbuf_size) errbuf[i] = *message;++if (have_offset) {- len = strlen(message);- if (errbuf_size != 0)- {- strncpy(errbuf, message, errbuf_size);- if (errbuf_size <= len) errbuf[errbuf_size - 1] = '\0';- }- ret = (int)len;+ for (message = offset_buf; *message != 0; i++, message++)+ if (i + 1 < errbuf_size) errbuf[i] = *message; } -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;- }+#if defined EBCDIC && 'a' != 0x81+/* If compiling for EBCDIC, but the compiler's string literals are not EBCDIC,+then we are in the "force EBCDIC 1047" mode. I have chosen to add a few lines+here to translate the error strings on the fly, rather than require the string+literals above to be written out arduously using the "STR_XYZ" macros. */+for (PCRE2_SIZE j = 0; j < i && j < errbuf_size; ++j)+ errbuf[j] = PRIV(ascii_to_ebcdic_1047)[(uint8_t)errbuf[j]]; #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);+/* Terminate message, even if truncated. */ -return ret + 1;+if (errbuf_size > 0)+ errbuf[(i < errbuf_size)? i : errbuf_size - 1] = 0;+i++;++return (int)i; } @@ -277,6 +283,9 @@ int options = 0; int re_nsub = 0; +preg->re_match_data = NULL;+preg->re_pcre2_code = NULL;+ patlen = ((cflags & REG_PEND) != 0)? (PCRE2_SIZE)(preg->re_endp - pattern) : PCRE2_ZERO_TERMINATED; @@ -318,10 +327,14 @@ if (preg->re_match_data == NULL) {- /* LCOV_EXCL_START */+ /* There is no facility for passing a custom allocator to the POSIX API, so+ our test code cannot force a malloc failure here. If there were an API to+ customize the default (global) PCRE2 allocator, we could test it. Since the+ code is nonetheless reachable, I prefer not to exclude it from coverage+ reporting. */ pcre2_code_free(preg->re_pcre2_code);+ preg->re_pcre2_code = NULL; return REG_ESPACE;- /* LCOV_EXCL_STOP */ } return 0;
src/c/pcre2/src/pcre2posix.h view
@@ -118,39 +118,36 @@ 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. */+file. So, we don't change existing definitions of PCRE2POSIX_EXP_DECL. -/* By default, we use the standard "extern" declarations. */+By default, we use the standard "extern" declarations. */ #ifndef PCRE2POSIX_EXP_DECL-# if defined(_WIN32) && defined(PCRE2POSIX_SHARED) && !defined(PCRE2_STATIC)-# define PCRE2POSIX_EXP_DECL extern __declspec(dllimport)-# define PCRE2POSIX_EXP_DEFN __declspec(dllimport)+# if defined(_WIN32) && defined(PCRE2POSIX_SHARED)+# define PCRE2POSIX_EXP_DECL extern __declspec(dllimport)+# elif defined __cplusplus+# define PCRE2POSIX_EXP_DECL extern "C" # else-# define PCRE2POSIX_EXP_DECL extern PCRE2_EXPORT-# define PCRE2POSIX_EXP_DEFN+# define PCRE2POSIX_EXP_DECL extern # endif+#endif++/* When compiling with the MSVC compiler, it is sometimes necessary to include+a "calling convention" before exported function names. For example:++ void __cdecl function(....)++might be needed. In order to make this easy, all the exported functions have+PCRE2_CALL_CONVENTION just before their names.++PCRE2 normally uses the platform's standard calling convention, so this should+not be set unless you know you need it. */++#ifndef PCRE2_CALL_CONVENTION+#define PCRE2_CALL_CONVENTION #endif /* The functions. The actual code is in functions with pcre2_xxx names for
src/c/pcre2/src/pcre2posix_test.c view
@@ -1,13 +1,45 @@ /*************************************************-* PCRE2 POSIX interface test program *+* Perl-Compatible Regular Expressions * *************************************************/ -/*-Written by Philip Hazel, December 2022-Copyright (c) 2022-File last edited: December 2022+/* 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. -This program tests the POSIX wrapper to the PCRE2 regular expression library.+ Written by Philip Hazel+ Original API code Copyright (c) 1997-2012 University of Cambridge+ New API code Copyright (c) 2016-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 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.@@ -22,6 +54,7 @@ For testing purposes, the "-v" option causes verification output to be written to stdout. */ + #include <stdio.h> #include <string.h> #include <pcre2posix.h>@@ -144,12 +177,9 @@ if (rc != 0) {- if (v)- {- char buffer[256];- (void)regerror(rc, &re, buffer, sizeof(buffer));- PRINTF("Compile error %d: %s (expected)\n", rc, buffer);- }+ char buffer[256];+ (void)regerror(rc, &re, buffer, sizeof(buffer));+ PRINTF("Compile error %d: %s (expected)\n", rc, buffer); continue; } @@ -189,7 +219,7 @@ } } - else if (v)+ else { char buffer[256]; (void)regerror(rc, &re, buffer, sizeof(buffer));
src/c/pcre2/src/pcre2test.c view
@@ -54,9649 +54,4164 @@ use of SUPPORT_PCRE2_8, SUPPORT_PCRE2_16, and SUPPORT_PCRE2_32, to ensure that it references only the enabled library functions. */ -#ifdef HAVE_CONFIG_H-#include "config.h"-#endif--#include <ctype.h>-#include <stdio.h>-#include <string.h>-#include <stdlib.h>-#include <time.h>-#include <locale.h>-#include <errno.h>--#if defined NATIVE_ZOS-#include "pcrzoscs.h"-/* That header is not included in the main PCRE2 distribution because other-apparatus is needed to compile pcre2test for z/OS. The header can be found in-the special z/OS distribution, which is available from www.zaconsultants.net or-from www.cbttape.org. */-#endif--#ifdef HAVE_UNISTD_H-#include <unistd.h>-#endif--/* Debugging code enabler */--/* #define DEBUG_SHOW_MALLOC_ADDRESSES */--/* Both libreadline and libedit are optionally supported */-#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)-#if defined(SUPPORT_LIBREADLINE)-#include <readline/readline.h>-#include <readline/history.h>-#else-#if defined(HAVE_EDITLINE_READLINE_H)-#include <editline/readline.h>-#elif defined(HAVE_EDIT_READLINE_READLINE_H)-#include <edit/readline/readline.h>-#else-#include <readline.h>-/* GNU readline defines this macro but libedit doesn't, if that ever changes-this needs to be updated or the build could break */-#ifdef RL_VERSION_MAJOR-#include <history.h>-#endif-#endif-#endif-#endif--/* Put the test for interactive input into a macro so that it can be changed if-required for different environments. */--#define INTERACTIVE(f) isatty(fileno(f))---/* ---------------------- System-specific definitions ---------------------- */--/* A number of things vary for Windows builds. Originally, pcretest opened its-input and output without "b"; then I was told that "b" was needed in some-environments, so it was added for release 5.0 to both the input and output. (It-makes no difference on Unix-like systems.) Later I was told that it is wrong-for the input on Windows. I've now abstracted the modes into macros that are-set here, to make it easier to fiddle with them, and removed "b" from the input-mode under Windows. The BINARY versions are used when saving/restoring compiled-patterns. */--#if defined(_WIN32) || defined(WIN32)-#include <io.h> /* For _setmode() */-#include <fcntl.h> /* For _O_BINARY */-#define INPUT_MODE "r"-#define OUTPUT_MODE "wb"-#define BINARY_INPUT_MODE "rb"-#define BINARY_OUTPUT_MODE "wb"--#ifndef isatty-#define isatty _isatty /* This is what Windows calls them, I'm told, */-#endif /* though in some environments they seem to */- /* be already defined, hence the #ifndefs. */-#ifndef fileno-#define fileno _fileno-#endif--/* A user sent this fix for Borland Builder 5 under Windows. */--#ifdef __BORLANDC__-#define _setmode(handle, mode) setmode(handle, mode)-#endif--/* Not Windows */--#else-#include <sys/time.h> /* These two includes are needed */-#include <sys/resource.h> /* for setrlimit(). */-#if defined NATIVE_ZOS /* z/OS uses non-binary I/O */-#define INPUT_MODE "r"-#define OUTPUT_MODE "w"-#define BINARY_INPUT_MODE "rb"-#define BINARY_OUTPUT_MODE "wb"-#else-#define INPUT_MODE "rb"-#define OUTPUT_MODE "wb"-#define BINARY_INPUT_MODE "rb"-#define BINARY_OUTPUT_MODE "wb"-#endif-#endif--/* VMS-specific code was included as suggested by a VMS user [1]. Another VMS-user [2] provided alternative code which worked better for him. I have-commented out the original, but kept it around just in case. */--#ifdef __VMS-#include <ssdef.h>-/* These two includes came from [2]. */-#include descrip-#include lib$routines-/* void vms_setsymbol( char *, char *, int ); Original code from [1]. */-#endif--/* old VC and older compilers don't support %td or %zu, and even some that-claim to be C99 don't support it (hence DISABLE_PERCENT_ZT). */--#if defined(DISABLE_PERCENT_ZT) || (defined(_MSC_VER) && (_MSC_VER < 1800)) || \- (!defined(_MSC_VER) && (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)))-#ifdef _WIN64-#define PTR_FORM "lld"-#define SIZ_FORM "llu"-#else-#define PTR_FORM "ld"-#define SIZ_FORM "lu"-#endif-#else-#define PTR_FORM "td"-#define SIZ_FORM "zu"-#endif--/* ------------------End of system-specific definitions -------------------- */--/* Glueing macros that are used in several places below. */--#define glue(a,b) a##b-#define G(a,b) glue(a,b)--/* Miscellaneous parameters and manifests */--#ifndef CLOCKS_PER_SEC-#ifdef CLK_TCK-#define CLOCKS_PER_SEC CLK_TCK-#else-#define CLOCKS_PER_SEC 100-#endif-#endif--#define CFORE_UNSET UINT32_MAX /* Unset value for startend/cfail/cerror fields */-#define CONVERT_UNSET UINT32_MAX /* Unset value for convert_type field */-#define DFA_WS_DIMENSION 1000 /* Size of DFA workspace */-#define DEFAULT_OVECCOUNT 15 /* Default ovector count */-#define JUNK_OFFSET 0xdeadbeef /* For initializing ovector */-#define LOCALESIZE 32 /* Size of locale name */-#define LOOPREPEAT 500000 /* Default loop count for timing */-#define MALLOCLISTSIZE 20 /* For remembering mallocs */-#define PARENS_NEST_DEFAULT 220 /* Default parentheses nest limit */-#define PATSTACKSIZE 20 /* Pattern stack for save/restore testing */-#define REPLACE_MODSIZE 100 /* Field for reading 8-bit replacement */-#define VERSION_SIZE 64 /* Size of buffer for the version strings */--/* Default JIT compile options */--#define JIT_DEFAULT (PCRE2_JIT_COMPLETE|\- PCRE2_JIT_PARTIAL_SOFT|\- PCRE2_JIT_PARTIAL_HARD)--/* Make sure the buffer into which replacement strings are copied is big enough-to hold them as 32-bit code units. */--#define REPLACE_BUFFSIZE 1024 /* This is a byte value */--/* Execution modes */--#define PCRE8_MODE 8-#define PCRE16_MODE 16-#define PCRE32_MODE 32--/* Processing returns */--enum { PR_OK, PR_SKIP, PR_ABEND };--/* The macro PRINTABLE determines whether to print an output character as-is or-as a hex value when showing compiled patterns. is We use it in cases when the-locale has not been explicitly changed, so as to get consistent output from-systems that differ in their output from isprint() even in the "C" locale. */--#ifdef EBCDIC-#define PRINTABLE(c) ((c) >= 64 && (c) < 255)-#else-#define PRINTABLE(c) ((c) >= 32 && (c) < 127)-#endif--#define PRINTOK(c) ((use_tables != NULL && c < 256)? isprint(c) : PRINTABLE(c))--/* We have to include some of the library source files because we need-to use some of the macros, internal structure definitions, and other internal-values - pcre2test has "inside information" compared to an application program-that strictly follows the PCRE2 API.--Before including pcre2_internal.h we define PRIV so that it does not get-defined therein. This ensures that PRIV names in the included files do not-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.--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_PCRE2TEST makes some minor changes in the files. The previous definition-of PRIV avoids name clashes. */--#define PCRE2_PCRE2TEST-#include "pcre2_tables.c"-#include "pcre2_ucd.c"--/* 32-bit integer values in the input are read by strtoul() or strtol(). The-check needed for overflow depends on whether long ints are in fact longer than-ints. They are defined not to be shorter. */--#if ULONG_MAX > UINT32_MAX-#define U32OVERFLOW(x) (x > UINT32_MAX)-#else-#define U32OVERFLOW(x) (x == UINT32_MAX)-#endif--#if LONG_MAX > INT32_MAX-#define S32OVERFLOW(x) (x > INT32_MAX || x < INT32_MIN)-#else-#define S32OVERFLOW(x) (x == INT32_MAX || x == INT32_MIN)-#endif--/* When PCRE2_CODE_UNIT_WIDTH is zero, pcre2_internal.h does not include-pcre2_intmodedep.h, which is where mode-dependent macros and structures are-defined. We can now include it for each supported code unit width. Because-PCRE2_CODE_UNIT_WIDTH was defined as zero before including pcre2.h, it will-have left PCRE2_SUFFIX defined as a no-op. We must re-define it appropriately-while including these files, and then restore it to a no-op. Because LINK_SIZE-may be changed in 16-bit mode and forced to 1 in 32-bit mode, the order of-these inclusions should not be changed. */--#undef PCRE2_SUFFIX-#undef PCRE2_CODE_UNIT_WIDTH--#ifdef SUPPORT_PCRE2_8-#define PCRE2_CODE_UNIT_WIDTH 8-#define PCRE2_SUFFIX(a) G(a,8)-#include "pcre2_intmodedep.h"-#include "pcre2_printint.c"-#undef PCRE2_CODE_UNIT_WIDTH-#undef PCRE2_SUFFIX-#endif /* SUPPORT_PCRE2_8 */--#ifdef SUPPORT_PCRE2_16-#define PCRE2_CODE_UNIT_WIDTH 16-#define PCRE2_SUFFIX(a) G(a,16)-#include "pcre2_intmodedep.h"-#include "pcre2_printint.c"-#undef PCRE2_CODE_UNIT_WIDTH-#undef PCRE2_SUFFIX-#endif /* SUPPORT_PCRE2_16 */--#ifdef SUPPORT_PCRE2_32-#define PCRE2_CODE_UNIT_WIDTH 32-#define PCRE2_SUFFIX(a) G(a,32)-#include "pcre2_intmodedep.h"-#include "pcre2_printint.c"-#undef PCRE2_CODE_UNIT_WIDTH-#undef PCRE2_SUFFIX-#endif /* SUPPORT_PCRE2_32 */--#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-code units. */--extern int valid_utf(PCRE2_SPTR8, PCRE2_SIZE, PCRE2_SIZE *);--#define PCRE2_CODE_UNIT_WIDTH 8-#undef PCRE2_SPTR-#define PCRE2_SPTR PCRE2_SPTR8-#include "pcre2_valid_utf.c"-#undef PCRE2_CODE_UNIT_WIDTH-#undef PCRE2_SPTR--/* If we have 8-bit support, default to it; if there is also 16-or 32-bit-support, it can be selected by a command-line option. If there is no 8-bit-support, there must be 16-bit or 32-bit support, so default to one of them. The-config function, JIT stack, contexts, and version string are the same in all-modes, so use the form of the first that is available. */--#if defined SUPPORT_PCRE2_8-#define DEFAULT_TEST_MODE PCRE8_MODE-#define VERSION_TYPE PCRE2_UCHAR8-#define PCRE2_CONFIG pcre2_config_8-#define PCRE2_JIT_STACK pcre2_jit_stack_8-#define PCRE2_REAL_GENERAL_CONTEXT pcre2_real_general_context_8-#define PCRE2_REAL_COMPILE_CONTEXT pcre2_real_compile_context_8-#define PCRE2_REAL_CONVERT_CONTEXT pcre2_real_convert_context_8-#define PCRE2_REAL_MATCH_CONTEXT pcre2_real_match_context_8--#elif defined SUPPORT_PCRE2_16-#define DEFAULT_TEST_MODE PCRE16_MODE-#define VERSION_TYPE PCRE2_UCHAR16-#define PCRE2_CONFIG pcre2_config_16-#define PCRE2_JIT_STACK pcre2_jit_stack_16-#define PCRE2_REAL_GENERAL_CONTEXT pcre2_real_general_context_16-#define PCRE2_REAL_COMPILE_CONTEXT pcre2_real_compile_context_16-#define PCRE2_REAL_CONVERT_CONTEXT pcre2_real_convert_context_16-#define PCRE2_REAL_MATCH_CONTEXT pcre2_real_match_context_16--#elif defined SUPPORT_PCRE2_32-#define DEFAULT_TEST_MODE PCRE32_MODE-#define VERSION_TYPE PCRE2_UCHAR32-#define PCRE2_CONFIG pcre2_config_32-#define PCRE2_JIT_STACK pcre2_jit_stack_32-#define PCRE2_REAL_GENERAL_CONTEXT pcre2_real_general_context_32-#define PCRE2_REAL_COMPILE_CONTEXT pcre2_real_compile_context_32-#define PCRE2_REAL_CONVERT_CONTEXT pcre2_real_convert_context_32-#define PCRE2_REAL_MATCH_CONTEXT pcre2_real_match_context_32-#endif--/* ------------- Structure and table for handling #-commands ------------- */--typedef struct cmdstruct {- const char *name;- int value;-} cmdstruct;--enum { CMD_FORBID_UTF, CMD_LOAD, CMD_LOADTABLES, CMD_NEWLINE_DEFAULT,- CMD_PATTERN, CMD_PERLTEST, CMD_POP, CMD_POPCOPY, CMD_SAVE, CMD_SUBJECT,- CMD_UNKNOWN };--static cmdstruct cmdlist[] = {- { "forbid_utf", CMD_FORBID_UTF },- { "load", CMD_LOAD },- { "loadtables", CMD_LOADTABLES },- { "newline_default", CMD_NEWLINE_DEFAULT },- { "pattern", CMD_PATTERN },- { "perltest", CMD_PERLTEST },- { "pop", CMD_POP },- { "popcopy", CMD_POPCOPY },- { "save", CMD_SAVE },- { "subject", CMD_SUBJECT }};--#define cmdlistcount (sizeof(cmdlist)/sizeof(cmdstruct))--/* ------------- Structures and tables for handling modifiers -------------- */--/* Table of names for newline types. Must be kept in step with the definitions-of PCRE2_NEWLINE_xx in pcre2.h. */--static const char *newlines[] = {- "DEFAULT", "CR", "LF", "CRLF", "ANY", "ANYCRLF", "NUL" };--/* Structure and table for handling pattern conversion types. */--typedef struct convertstruct {- const char *name;- uint32_t option;-} convertstruct;--static convertstruct convertlist[] = {- { "glob", PCRE2_CONVERT_GLOB },- { "glob_no_starstar", PCRE2_CONVERT_GLOB_NO_STARSTAR },- { "glob_no_wild_separator", PCRE2_CONVERT_GLOB_NO_WILD_SEPARATOR },- { "posix_basic", PCRE2_CONVERT_POSIX_BASIC },- { "posix_extended", PCRE2_CONVERT_POSIX_EXTENDED },- { "unset", CONVERT_UNSET }};--#define convertlistcount (sizeof(convertlist)/sizeof(convertstruct))--/* Modifier types and applicability */--enum { MOD_CTC, /* Applies to a compile context */- MOD_CTM, /* Applies to a match context */- MOD_PAT, /* Applies to a pattern */- MOD_PATP, /* Ditto, OK for Perl test */- MOD_DAT, /* Applies to a data line */- MOD_DATP, /* Ditto, OK for Perl test */- MOD_PD, /* Applies to a pattern or a data line */- MOD_PDP, /* As MOD_PD, OK for Perl test */- MOD_PND, /* As MOD_PD, but not for a default pattern */- MOD_PNDP, /* As MOD_PND, OK for Perl test */- MOD_CHR, /* Is a single character */- MOD_CON, /* Is a "convert" type/options list */- MOD_CTL, /* Is a control bit */- MOD_BSR, /* Is a BSR value */- MOD_IN2, /* Is one or two unsigned integers */- MOD_INS, /* Is a signed integer */- MOD_INT, /* Is an unsigned integer */- MOD_IND, /* Is an unsigned integer, but no value => default */- MOD_NL, /* Is a newline value */- MOD_NN, /* Is a number or a name; more than one may occur */- MOD_OPT, /* Is an option bit */- MOD_SIZ, /* Is a PCRE2_SIZE value */- MOD_STR }; /* Is a string */--/* Control bits. Some apply to compiling, some to matching, but some can be set-either on a pattern or a data line, so they must all be distinct. There are now-so many of them that they are split into two fields. */--#define CTL_AFTERTEXT 0x00000001u-#define CTL_ALLAFTERTEXT 0x00000002u-#define CTL_ALLCAPTURES 0x00000004u-#define CTL_ALLUSEDTEXT 0x00000008u-#define CTL_ALTGLOBAL 0x00000010u-#define CTL_BINCODE 0x00000020u-#define CTL_CALLOUT_CAPTURE 0x00000040u-#define CTL_CALLOUT_INFO 0x00000080u-#define CTL_CALLOUT_NONE 0x00000100u-#define CTL_DFA 0x00000200u-#define CTL_EXPAND 0x00000400u-#define CTL_FINDLIMITS 0x00000800u-#define CTL_FINDLIMITS_NOHEAP 0x00001000u-#define CTL_FULLBINCODE 0x00002000u-#define CTL_GETALL 0x00004000u-#define CTL_GLOBAL 0x00008000u-#define CTL_HEXPAT 0x00010000u /* Same word as USE_LENGTH */-#define CTL_INFO 0x00020000u-#define CTL_JITFAST 0x00040000u-#define CTL_JITVERIFY 0x00080000u-#define CTL_MARK 0x00100000u-#define CTL_MEMORY 0x00200000u-#define CTL_NULLCONTEXT 0x00400000u-#define CTL_POSIX 0x00800000u-#define CTL_POSIX_NOSUB 0x01000000u-#define CTL_PUSH 0x02000000u /* These three must be */-#define CTL_PUSHCOPY 0x04000000u /* all in the same */-#define CTL_PUSHTABLESCOPY 0x08000000u /* word. */-#define CTL_STARTCHAR 0x10000000u-#define CTL_USE_LENGTH 0x20000000u /* Same word as HEXPAT */-#define CTL_UTF8_INPUT 0x40000000u-#define CTL_ZERO_TERMINATE 0x80000000u--/* Combinations */--#define CTL_DEBUG (CTL_FULLBINCODE|CTL_INFO) /* For setting */-#define CTL_ANYINFO (CTL_DEBUG|CTL_BINCODE|CTL_CALLOUT_INFO)-#define CTL_ANYGLOB (CTL_ALTGLOBAL|CTL_GLOBAL)--/* Second control word */--#define CTL2_SUBSTITUTE_CALLOUT 0x00000001u-#define CTL2_SUBSTITUTE_EXTENDED 0x00000002u-#define CTL2_SUBSTITUTE_LITERAL 0x00000004u-#define CTL2_SUBSTITUTE_MATCHED 0x00000008u-#define CTL2_SUBSTITUTE_OVERFLOW_LENGTH 0x00000010u-#define CTL2_SUBSTITUTE_REPLACEMENT_ONLY 0x00000020u-#define CTL2_SUBSTITUTE_UNKNOWN_UNSET 0x00000040u-#define CTL2_SUBSTITUTE_UNSET_EMPTY 0x00000080u-#define CTL2_SUBJECT_LITERAL 0x00000100u-#define CTL2_CALLOUT_NO_WHERE 0x00000200u-#define CTL2_CALLOUT_EXTRA 0x00000400u-#define CTL2_ALLVECTOR 0x00000800u-#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 */--/* These are the matching controls that may be set either on a pattern or on a-data line. They are copied from the pattern controls as initial settings for-data line controls. Note that CTL_MEMORY is not included here, because it does-different things in the two cases. */--#define CTL_ALLPD (CTL_AFTERTEXT|\- CTL_ALLAFTERTEXT|\- CTL_ALLCAPTURES|\- CTL_ALLUSEDTEXT|\- CTL_ALTGLOBAL|\- CTL_GLOBAL|\- CTL_MARK|\- CTL_STARTCHAR|\- CTL_UTF8_INPUT)--#define CTL2_ALLPD (CTL2_SUBSTITUTE_CALLOUT|\- CTL2_SUBSTITUTE_EXTENDED|\- CTL2_SUBSTITUTE_LITERAL|\- CTL2_SUBSTITUTE_MATCHED|\- CTL2_SUBSTITUTE_OVERFLOW_LENGTH|\- CTL2_SUBSTITUTE_REPLACEMENT_ONLY|\- CTL2_SUBSTITUTE_UNKNOWN_UNSET|\- CTL2_SUBSTITUTE_UNSET_EMPTY|\- 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-subject must be at the start and in the same order in both cases so that the-same offset in the big table below works for both. */--typedef struct patctl { /* Structure for pattern modifiers. */- uint32_t options; /* Must be in same position as datctl */- uint32_t control; /* Must be in same position as datctl */- uint32_t control2; /* Must be in same position as datctl */- uint32_t jitstack; /* Must be in same position as datctl */- uint8_t replacement[REPLACE_MODSIZE]; /* So must this */- uint32_t substitute_skip; /* Must be in same position as patctl */- uint32_t substitute_stop; /* Must be in same position as patctl */- uint32_t jit;- uint32_t stackguard_test;- uint32_t tables_id;- uint32_t convert_type;- uint32_t convert_length;- uint32_t convert_glob_escape;- uint32_t convert_glob_separator;- uint32_t regerror_buffsize;- uint8_t locale[LOCALESIZE];-} patctl;--#define MAXCPYGET 10-#define LENCPYGET 64--typedef struct datctl { /* Structure for data line modifiers. */- uint32_t options; /* Must be in same position as patctl */- uint32_t control; /* Must be in same position as patctl */- uint32_t control2; /* Must be in same position as patctl */- uint32_t jitstack; /* Must be in same position as patctl */- uint8_t replacement[REPLACE_MODSIZE]; /* So must this */- uint32_t substitute_skip; /* Must be in same position as patctl */- uint32_t substitute_stop; /* Must be in same position as patctl */- uint32_t startend[2];- uint32_t cerror[2];- uint32_t cfail[2];- int32_t callout_data;- int32_t copy_numbers[MAXCPYGET];- int32_t get_numbers[MAXCPYGET];- uint32_t oveccount;- uint32_t offset;- uint8_t copy_names[LENCPYGET];- uint8_t get_names[LENCPYGET];-} datctl;--/* Ids for which context to modify. */--enum { CTX_PAT, /* Active pattern context */- CTX_POPPAT, /* Ditto, for a popped pattern */- CTX_DEFPAT, /* Default pattern context */- CTX_DAT, /* Active data (match) context */- CTX_DEFDAT }; /* Default data (match) context */--/* Macros to simplify the big table below. */--#define CO(name) offsetof(PCRE2_REAL_COMPILE_CONTEXT, name)-#define MO(name) offsetof(PCRE2_REAL_MATCH_CONTEXT, name)-#define PO(name) offsetof(patctl, name)-#define PD(name) PO(name)-#define DO(name) offsetof(datctl, name)--/* Table of all long-form modifiers. Must be in collating sequence of modifier-name because it is searched by binary chop. */--typedef struct modstruct {- const char *name;- uint16_t which;- uint16_t type;- uint32_t value;- 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) },- { "allcaptures", MOD_PND, MOD_CTL, CTL_ALLCAPTURES, PO(control) },- { "allow_empty_class", MOD_PAT, MOD_OPT, PCRE2_ALLOW_EMPTY_CLASS, PO(options) },- { "allow_lookaround_bsk", MOD_CTC, MOD_OPT, PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK, CO(extra_options) },- { "allow_surrogate_escapes", MOD_CTC, MOD_OPT, PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES, CO(extra_options) },- { "allusedtext", MOD_PNDP, MOD_CTL, CTL_ALLUSEDTEXT, PO(control) },- { "allvector", MOD_PND, MOD_CTL, CTL2_ALLVECTOR, PO(control2) },- { "alt_bsux", MOD_PAT, MOD_OPT, PCRE2_ALT_BSUX, PO(options) },- { "alt_circumflex", MOD_PAT, MOD_OPT, PCRE2_ALT_CIRCUMFLEX, PO(options) },- { "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) },- { "bsr", MOD_CTC, MOD_BSR, 0, CO(bsr_convention) },- { "callout_capture", MOD_DAT, MOD_CTL, CTL_CALLOUT_CAPTURE, DO(control) },- { "callout_data", MOD_DAT, MOD_INS, 0, DO(callout_data) },- { "callout_error", MOD_DAT, MOD_IN2, 0, DO(cerror) },- { "callout_extra", MOD_DAT, MOD_CTL, CTL2_CALLOUT_EXTRA, DO(control2) },- { "callout_fail", MOD_DAT, MOD_IN2, 0, DO(cfail) },- { "callout_info", MOD_PAT, MOD_CTL, CTL_CALLOUT_INFO, PO(control) },- { "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) },- { "convert_length", MOD_PAT, MOD_INT, 0, PO(convert_length) },- { "copy", MOD_DAT, MOD_NN, DO(copy_numbers), DO(copy_names) },- { "copy_matched_subject", MOD_DAT, MOD_OPT, PCRE2_COPY_MATCHED_SUBJECT, DO(options) },- { "debug", MOD_PAT, MOD_CTL, CTL_DEBUG, PO(control) },- { "depth_limit", MOD_CTM, MOD_INT, 0, MO(depth_limit) },- { "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) },- { "endanchored", MOD_PD, MOD_OPT, PCRE2_ENDANCHORED, PD(options) },- { "escaped_cr_is_lf", MOD_CTC, MOD_OPT, PCRE2_EXTRA_ESCAPED_CR_IS_LF, CO(extra_options) },- { "expand", MOD_PAT, MOD_CTL, CTL_EXPAND, PO(control) },- { "extended", MOD_PATP, MOD_OPT, PCRE2_EXTENDED, PO(options) },- { "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, 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) },- { "jitfast", MOD_PAT, MOD_CTL, CTL_JITFAST, PO(control) },- { "jitstack", MOD_PNDP, MOD_INT, 0, PO(jitstack) },- { "jitverify", MOD_PAT, MOD_CTL, CTL_JITVERIFY, PO(control) },- { "literal", MOD_PAT, MOD_OPT, PCRE2_LITERAL, PO(options) },- { "locale", MOD_PAT, MOD_STR, LOCALESIZE, PO(locale) },- { "mark", MOD_PNDP, MOD_CTL, CTL_MARK, PO(control) },- { "match_invalid_utf", MOD_PAT, MOD_OPT, PCRE2_MATCH_INVALID_UTF, PO(options) },- { "match_limit", MOD_CTM, MOD_INT, 0, MO(match_limit) },- { "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) },- { "never_ucp", MOD_PAT, MOD_OPT, PCRE2_NEVER_UCP, PO(options) },- { "never_utf", MOD_PAT, MOD_OPT, PCRE2_NEVER_UTF, PO(options) },- { "newline", MOD_CTC, MOD_NL, 0, CO(newline_convention) },- { "no_auto_capture", MOD_PAT, MOD_OPT, PCRE2_NO_AUTO_CAPTURE, PO(options) },- { "no_auto_possess", MOD_PATP, MOD_OPT, PCRE2_NO_AUTO_POSSESS, PO(options) },- { "no_dotstar_anchor", MOD_PAT, MOD_OPT, PCRE2_NO_DOTSTAR_ANCHOR, PO(options) },- { "no_jit", MOD_DATP, MOD_OPT, PCRE2_NO_JIT, DO(options) },- { "no_start_optimize", MOD_PATP, MOD_OPT, PCRE2_NO_START_OPTIMIZE, PO(options) },- { "no_utf_check", MOD_PD, MOD_OPT, PCRE2_NO_UTF_CHECK, PD(options) },- { "notbol", MOD_DAT, MOD_OPT, PCRE2_NOTBOL, DO(options) },- { "notempty", MOD_DAT, MOD_OPT, PCRE2_NOTEMPTY, DO(options) },- { "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) },- { "offset_limit", MOD_CTM, MOD_SIZ, 0, MO(offset_limit)},- { "ovector", MOD_DAT, MOD_INT, 0, DO(oveccount) },- { "parens_nest_limit", MOD_CTC, MOD_INT, 0, CO(parens_nest_limit) },- { "partial_hard", MOD_DAT, MOD_OPT, PCRE2_PARTIAL_HARD, DO(options) },- { "partial_soft", MOD_DAT, MOD_OPT, PCRE2_PARTIAL_SOFT, DO(options) },- { "ph", MOD_DAT, MOD_OPT, PCRE2_PARTIAL_HARD, DO(options) },- { "posix", MOD_PAT, MOD_CTL, CTL_POSIX, PO(control) },- { "posix_nosub", MOD_PAT, MOD_CTL, CTL_POSIX|CTL_POSIX_NOSUB, PO(control) },- { "posix_startend", MOD_DAT, MOD_IN2, 0, DO(startend) },- { "ps", MOD_DAT, MOD_OPT, PCRE2_PARTIAL_SOFT, DO(options) },- { "push", MOD_PAT, MOD_CTL, CTL_PUSH, PO(control) },- { "pushcopy", MOD_PAT, MOD_CTL, CTL_PUSHCOPY, PO(control) },- { "pushtablescopy", MOD_PAT, MOD_CTL, CTL_PUSHTABLESCOPY, PO(control) },- { "recursion_limit", MOD_CTM, MOD_INT, 0, MO(depth_limit) }, /* Obsolete synonym */- { "regerror_buffsize", MOD_PAT, MOD_INT, 0, PO(regerror_buffsize) },- { "replace", MOD_PND, MOD_STR, REPLACE_MODSIZE, PO(replacement) },- { "stackguard", MOD_PAT, MOD_INT, 0, PO(stackguard_test) },- { "startchar", MOD_PND, MOD_CTL, CTL_STARTCHAR, PO(control) },- { "startoffset", MOD_DAT, MOD_INT, 0, DO(offset) },- { "subject_literal", MOD_PATP, MOD_CTL, CTL2_SUBJECT_LITERAL, PO(control2) },- { "substitute_callout", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_CALLOUT, PO(control2) },- { "substitute_extended", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_EXTENDED, PO(control2) },- { "substitute_literal", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_LITERAL, PO(control2) },- { "substitute_matched", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_MATCHED, PO(control2) },- { "substitute_overflow_length", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_OVERFLOW_LENGTH, PO(control2) },- { "substitute_replacement_only", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_REPLACEMENT_ONLY, PO(control2) },- { "substitute_skip", MOD_PND, MOD_INT, 0, PO(substitute_skip) },- { "substitute_stop", MOD_PND, MOD_INT, 0, PO(substitute_stop) },- { "substitute_unknown_unset", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_UNKNOWN_UNSET, PO(control2) },- { "substitute_unset_empty", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_UNSET_EMPTY, PO(control2) },- { "tables", MOD_PAT, MOD_INT, 0, PO(tables_id) },- { "ucp", MOD_PATP, MOD_OPT, PCRE2_UCP, PO(options) },- { "ungreedy", MOD_PAT, MOD_OPT, PCRE2_UNGREEDY, PO(options) },- { "use_length", MOD_PAT, MOD_CTL, CTL_USE_LENGTH, PO(control) },- { "use_offset_limit", MOD_PAT, MOD_OPT, PCRE2_USE_OFFSET_LIMIT, PO(options) },- { "utf", MOD_PATP, MOD_OPT, PCRE2_UTF, PO(options) },- { "utf8_input", MOD_PAT, MOD_CTL, CTL_UTF8_INPUT, PO(control) },- { "zero_terminate", MOD_DAT, MOD_CTL, CTL_ZERO_TERMINATE, DO(control) }-};--#define MODLISTCOUNT sizeof(modlist)/sizeof(modstruct)--/* Controls and options that are supported for use with the POSIX interface. */--#define POSIX_SUPPORTED_COMPILE_OPTIONS ( \- PCRE2_CASELESS|PCRE2_DOTALL|PCRE2_LITERAL|PCRE2_MULTILINE|PCRE2_UCP| \- PCRE2_UTF|PCRE2_UNGREEDY)--#define POSIX_SUPPORTED_COMPILE_EXTRA_OPTIONS (0)--#define POSIX_SUPPORTED_COMPILE_CONTROLS ( \- CTL_AFTERTEXT|CTL_ALLAFTERTEXT|CTL_EXPAND|CTL_HEXPAT|CTL_POSIX| \- CTL_POSIX_NOSUB|CTL_USE_LENGTH)--#define POSIX_SUPPORTED_COMPILE_CONTROLS2 (0)--#define POSIX_SUPPORTED_MATCH_OPTIONS ( \- PCRE2_NOTBOL|PCRE2_NOTEMPTY|PCRE2_NOTEOL)--#define POSIX_SUPPORTED_MATCH_CONTROLS (CTL_AFTERTEXT|CTL_ALLAFTERTEXT)-#define POSIX_SUPPORTED_MATCH_CONTROLS2 (CTL2_NULL_SUBJECT)--/* Control bits that are not ignored with 'push'. */--#define PUSH_SUPPORTED_COMPILE_CONTROLS ( \- CTL_BINCODE|CTL_CALLOUT_INFO|CTL_FULLBINCODE|CTL_HEXPAT|CTL_INFO| \- CTL_JITVERIFY|CTL_MEMORY|CTL_PUSH|CTL_PUSHCOPY| \- CTL_PUSHTABLESCOPY|CTL_USE_LENGTH)--#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'. */--#define PUSH_COMPILE_ONLY_CONTROLS CTL_JITVERIFY-#define PUSH_COMPILE_ONLY_CONTROLS2 (0)--/* Controls that are forbidden with #pop or #popcopy. */--#define NOTPOP_CONTROLS (CTL_HEXPAT|CTL_POSIX|CTL_POSIX_NOSUB|CTL_PUSH| \- CTL_PUSHCOPY|CTL_PUSHTABLESCOPY|CTL_USE_LENGTH)--/* Pattern controls that are mutually exclusive. At present these are all in-the first control word. Note that CTL_POSIX_NOSUB is always accompanied by-CTL_POSIX, so it doesn't need its own entries. */--static uint32_t exclusive_pat_controls[] = {- CTL_POSIX | CTL_PUSH,- CTL_POSIX | CTL_PUSHCOPY,- CTL_POSIX | CTL_PUSHTABLESCOPY,- CTL_PUSH | CTL_PUSHCOPY,- CTL_PUSH | CTL_PUSHTABLESCOPY,- CTL_PUSHCOPY | CTL_PUSHTABLESCOPY,- CTL_EXPAND | CTL_HEXPAT };--/* Data controls that are mutually exclusive. At present these are all in the-first control word. */--static uint32_t exclusive_dat_controls[] = {- 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-in with the index of the full entry in modlist, to save repeated searching when-processing multiple test items. This short list is searched serially, so its-order does not matter. */--typedef struct c1modstruct {- const char *fullname;- uint32_t onechar;- int index;-} c1modstruct;--static c1modstruct c1modlist[] = {- { "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)--/* Table of arguments for the -C command line option. Use macros to make the-table itself easier to read. */--#if defined SUPPORT_PCRE2_8-#define SUPPORT_8 1-#endif-#if defined SUPPORT_PCRE2_16-#define SUPPORT_16 1-#endif-#if defined SUPPORT_PCRE2_32-#define SUPPORT_32 1-#endif--#ifndef SUPPORT_8-#define SUPPORT_8 0-#endif-#ifndef SUPPORT_16-#define SUPPORT_16 0-#endif-#ifndef SUPPORT_32-#define SUPPORT_32 0-#endif--#ifdef EBCDIC-#define SUPPORT_EBCDIC 1-#define EBCDIC_NL CHAR_LF-#else-#define SUPPORT_EBCDIC 0-#define EBCDIC_NL 0-#endif--#ifdef NEVER_BACKSLASH_C-#define BACKSLASH_C 0-#else-#define BACKSLASH_C 1-#endif--typedef struct coptstruct {- const char *name;- uint32_t type;- uint32_t value;-} coptstruct;--enum { CONF_BSR,- CONF_FIX,- CONF_FIZ,- CONF_INT,- CONF_NL-};--static coptstruct coptlist[] = {- { "backslash-C", CONF_FIX, BACKSLASH_C },- { "bsr", CONF_BSR, PCRE2_CONFIG_BSR },- { "ebcdic", CONF_FIX, SUPPORT_EBCDIC },- { "ebcdic-nl", CONF_FIZ, EBCDIC_NL },- { "jit", CONF_INT, PCRE2_CONFIG_JIT },- { "linksize", CONF_INT, PCRE2_CONFIG_LINKSIZE },- { "newline", CONF_NL, PCRE2_CONFIG_NEWLINE },- { "pcre2-16", CONF_FIX, SUPPORT_16 },- { "pcre2-32", CONF_FIX, SUPPORT_32 },- { "pcre2-8", CONF_FIX, SUPPORT_8 },- { "unicode", CONF_INT, PCRE2_CONFIG_UNICODE }-};--#define COPTLISTCOUNT sizeof(coptlist)/sizeof(coptstruct)--#undef SUPPORT_8-#undef SUPPORT_16-#undef SUPPORT_32-#undef SUPPORT_EBCDIC---/* ----------------------- Static variables ------------------------ */--static FILE *infile;-static FILE *outfile;--static const void *last_callout_mark;-static PCRE2_JIT_STACK *jit_stack = NULL;-static size_t jit_stack_size = 0;--static BOOL first_callout;-static BOOL jit_was_used;-static BOOL restrict_for_perl_test = FALSE;-static BOOL show_memory = FALSE;--static int jitrc; /* Return from JIT compile */-static int test_mode = DEFAULT_TEST_MODE;-static int timeit = 0;-static int timeitm = 0;--clock_t total_compile_time = 0;-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;-static uint32_t max_oveccount;-static uint32_t callout_count;-static uint32_t maxcapcount;--static uint16_t local_newline_default = 0;--static VERSION_TYPE jittarget[VERSION_SIZE];-static VERSION_TYPE version[VERSION_SIZE];-static VERSION_TYPE uversion[VERSION_SIZE];--static patctl def_patctl;-static patctl pat_patctl;-static datctl def_datctl;-static datctl dat_datctl;--static void *patstack[PATSTACKSIZE];-static int patstacknext = 0;--static void *malloclist[MALLOCLISTSIZE];-static PCRE2_SIZE malloclistlength[MALLOCLISTSIZE];-static uint32_t malloclistptr = 0;--#ifdef SUPPORT_PCRE2_8-static regex_t preg = { NULL, NULL, 0, 0, 0, 0 };-#endif--static int *dfa_workspace = NULL;-static const uint8_t *locale_tables = NULL;-static const uint8_t *use_tables = NULL;-static uint8_t locale_name[32];-static uint8_t *tables3 = NULL; /* For binary-loaded tables */-static uint32_t loadtables_length = 0;--/* We need buffers for building 16/32-bit strings; 8-bit strings don't need-rebuilding, but set up the same naming scheme for use in macros. The "buffer"-buffer is where all input lines are read. Its size is the same as pbuffer8.-Pattern lines are always copied to pbuffer8 for use in callouts, even if they-are actually compiled from pbuffer16 or pbuffer32. */--static size_t pbuffer8_size = 50000; /* Initial size, bytes */-static uint8_t *pbuffer8 = NULL;-static uint8_t *buffer = NULL;--/* The dbuffer is where all processed data lines are put. In non-8-bit modes it-is cast as needed. For long data lines it grows as necessary. */--static size_t dbuffer_size = 1u << 14; /* Initial size, bytes */-static uint8_t *dbuffer = NULL;---/* ---------------- Mode-dependent variables -------------------*/--#ifdef SUPPORT_PCRE2_8-static pcre2_code_8 *compiled_code8;-static pcre2_general_context_8 *general_context8, *general_context_copy8;-static pcre2_compile_context_8 *pat_context8, *default_pat_context8;-static pcre2_convert_context_8 *con_context8, *default_con_context8;-static pcre2_match_context_8 *dat_context8, *default_dat_context8;-static pcre2_match_data_8 *match_data8;-#endif--#ifdef SUPPORT_PCRE2_16-static pcre2_code_16 *compiled_code16;-static pcre2_general_context_16 *general_context16, *general_context_copy16;-static pcre2_compile_context_16 *pat_context16, *default_pat_context16;-static pcre2_convert_context_16 *con_context16, *default_con_context16;-static pcre2_match_context_16 *dat_context16, *default_dat_context16;-static pcre2_match_data_16 *match_data16;-static PCRE2_SIZE pbuffer16_size = 0; /* Set only when needed */-static uint16_t *pbuffer16 = NULL;-#endif--#ifdef SUPPORT_PCRE2_32-static pcre2_code_32 *compiled_code32;-static pcre2_general_context_32 *general_context32, *general_context_copy32;-static pcre2_compile_context_32 *pat_context32, *default_pat_context32;-static pcre2_convert_context_32 *con_context32, *default_con_context32;-static pcre2_match_context_32 *dat_context32, *default_dat_context32;-static pcre2_match_data_32 *match_data32;-static PCRE2_SIZE pbuffer32_size = 0; /* Set only when needed */-static uint32_t *pbuffer32 = NULL;-#endif---/* ---------------- Macros that work in all modes ----------------- */--#define CAST8VAR(x) CASTVAR(uint8_t *, x)-#define SET(x,y) SETOP(x,y,=)-#define SETPLUS(x,y) SETOP(x,y,+=)-#define strlen8(x) strlen((char *)x)---/* ---------------- Mode-dependent, runtime-testing macros ------------------*/--/* Define macros for variables and functions that must be selected dynamically-depending on the mode setting (8, 16, 32). These are dependent on which modes-are supported. */--#if (defined (SUPPORT_PCRE2_8) + defined (SUPPORT_PCRE2_16) + \- defined (SUPPORT_PCRE2_32)) >= 2--/* ----- All three modes supported ----- */--#if defined(SUPPORT_PCRE2_8) && defined(SUPPORT_PCRE2_16) && defined(SUPPORT_PCRE2_32)--#define CASTFLD(t,a,b) ((test_mode == PCRE8_MODE)? (t)(G(a,8)->b) : \- (test_mode == PCRE16_MODE)? (t)(G(a,16)->b) : (t)(G(a,32)->b))--#define CASTVAR(t,x) ( \- (test_mode == PCRE8_MODE)? (t)G(x,8) : \- (test_mode == PCRE16_MODE)? (t)G(x,16) : (t)G(x,32))--#define CODE_UNIT(a,b) ( \- (test_mode == PCRE8_MODE)? (uint32_t)(((PCRE2_SPTR8)(a))[b]) : \- (test_mode == PCRE16_MODE)? (uint32_t)(((PCRE2_SPTR16)(a))[b]) : \- (uint32_t)(((PCRE2_SPTR32)(a))[b]))--#define CONCTXCPY(a,b) \- if (test_mode == PCRE8_MODE) \- memcpy(G(a,8),G(b,8),sizeof(pcre2_convert_context_8)); \- else if (test_mode == PCRE16_MODE) \- memcpy(G(a,16),G(b,16),sizeof(pcre2_convert_context_16)); \- else memcpy(G(a,32),G(b,32),sizeof(pcre2_convert_context_32))--#define CONVERT_COPY(a,b,c) \- if (test_mode == PCRE8_MODE) \- memcpy(G(a,8),(char *)b,c); \- else if (test_mode == PCRE16_MODE) \- memcpy(G(a,16),(char *)b,(c)*2); \- else if (test_mode == PCRE32_MODE) \- memcpy(G(a,32),(char *)b,(c)*4)--#define DATCTXCPY(a,b) \- if (test_mode == PCRE8_MODE) \- memcpy(G(a,8),G(b,8),sizeof(pcre2_match_context_8)); \- else if (test_mode == PCRE16_MODE) \- memcpy(G(a,16),G(b,16),sizeof(pcre2_match_context_16)); \- else memcpy(G(a,32),G(b,32),sizeof(pcre2_match_context_32))--#define FLD(a,b) ((test_mode == PCRE8_MODE)? G(a,8)->b : \- (test_mode == PCRE16_MODE)? G(a,16)->b : G(a,32)->b)--#define PATCTXCPY(a,b) \- if (test_mode == PCRE8_MODE) \- memcpy(G(a,8),G(b,8),sizeof(pcre2_compile_context_8)); \- else if (test_mode == PCRE16_MODE) \- memcpy(G(a,16),G(b,16),sizeof(pcre2_compile_context_16)); \- else memcpy(G(a,32),G(b,32),sizeof(pcre2_compile_context_32))--#define PCHARS(lv, p, offset, len, utf, f) \- if (test_mode == PCRE32_MODE) \- lv = pchars32((PCRE2_SPTR32)(p)+offset, len, utf, f); \- else if (test_mode == PCRE16_MODE) \- lv = pchars16((PCRE2_SPTR16)(p)+offset, len, utf, f); \- else \- lv = pchars8((PCRE2_SPTR8)(p)+offset, len, utf, f)--#define PCHARSV(p, offset, len, utf, f) \- if (test_mode == PCRE32_MODE) \- (void)pchars32((PCRE2_SPTR32)(p)+offset, len, utf, f); \- else if (test_mode == PCRE16_MODE) \- (void)pchars16((PCRE2_SPTR16)(p)+offset, len, utf, f); \- else \- (void)pchars8((PCRE2_SPTR8)(p)+offset, len, utf, f)--#define PCRE2_CALLOUT_ENUMERATE(a,b,c) \- if (test_mode == PCRE8_MODE) \- a = pcre2_callout_enumerate_8(compiled_code8, \- (int (*)(struct pcre2_callout_enumerate_block_8 *, void *))b,c); \- else if (test_mode == PCRE16_MODE) \- a = pcre2_callout_enumerate_16(compiled_code16, \- (int(*)(struct pcre2_callout_enumerate_block_16 *, void *))b,c); \- else \- a = pcre2_callout_enumerate_32(compiled_code32, \- (int (*)(struct pcre2_callout_enumerate_block_32 *, void *))b,c)--#define PCRE2_CODE_COPY_FROM_VOID(a,b) \- if (test_mode == PCRE8_MODE) \- G(a,8) = pcre2_code_copy_8(b); \- else if (test_mode == PCRE16_MODE) \- G(a,16) = pcre2_code_copy_16(b); \- else \- G(a,32) = pcre2_code_copy_32(b)--#define PCRE2_CODE_COPY_TO_VOID(a,b) \- if (test_mode == PCRE8_MODE) \- a = (void *)pcre2_code_copy_8(G(b,8)); \- else if (test_mode == PCRE16_MODE) \- a = (void *)pcre2_code_copy_16(G(b,16)); \- else \- a = (void *)pcre2_code_copy_32(G(b,32))--#define PCRE2_CODE_COPY_WITH_TABLES_TO_VOID(a,b) \- if (test_mode == PCRE8_MODE) \- a = (void *)pcre2_code_copy_with_tables_8(G(b,8)); \- else if (test_mode == PCRE16_MODE) \- a = (void *)pcre2_code_copy_with_tables_16(G(b,16)); \- else \- a = (void *)pcre2_code_copy_with_tables_32(G(b,32))--#define PCRE2_COMPILE(a,b,c,d,e,f,g) \- if (test_mode == PCRE8_MODE) \- G(a,8) = pcre2_compile_8(b,c,d,e,f,g); \- else if (test_mode == PCRE16_MODE) \- G(a,16) = pcre2_compile_16(b,c,d,e,f,g); \- else \- 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); \- else if (test_mode == PCRE16_MODE) pcre2_converted_pattern_free_16((PCRE2_UCHAR16 *)a); \- else pcre2_converted_pattern_free_32((PCRE2_UCHAR32 *)a)--#define PCRE2_DFA_MATCH(a,b,c,d,e,f,g,h,i,j) \- if (test_mode == PCRE8_MODE) \- a = pcre2_dfa_match_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),h,i,j); \- else if (test_mode == PCRE16_MODE) \- a = pcre2_dfa_match_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),h,i,j); \- else \- a = pcre2_dfa_match_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),h,i,j)--#define PCRE2_GET_ERROR_MESSAGE(r,a,b) \- if (test_mode == PCRE8_MODE) \- r = pcre2_get_error_message_8(a,G(b,8),G(G(b,8),_size)); \- else if (test_mode == PCRE16_MODE) \- r = pcre2_get_error_message_16(a,G(b,16),G(G(b,16),_size/2)); \- 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)); \- else if (test_mode == PCRE16_MODE) \- a = pcre2_get_ovector_count_16(G(b,16)); \- else \- a = pcre2_get_ovector_count_32(G(b,32))--#define PCRE2_GET_STARTCHAR(a,b) \- if (test_mode == PCRE8_MODE) \- a = pcre2_get_startchar_8(G(b,8)); \- else if (test_mode == PCRE16_MODE) \- a = pcre2_get_startchar_16(G(b,16)); \- else \- a = pcre2_get_startchar_32(G(b,32))--#define PCRE2_JIT_COMPILE(r,a,b) \- if (test_mode == PCRE8_MODE) r = pcre2_jit_compile_8(G(a,8),b); \- else if (test_mode == PCRE16_MODE) r = pcre2_jit_compile_16(G(a,16),b); \- else r = pcre2_jit_compile_32(G(a,32),b)--#define PCRE2_JIT_FREE_UNUSED_MEMORY(a) \- if (test_mode == PCRE8_MODE) pcre2_jit_free_unused_memory_8(G(a,8)); \- else if (test_mode == PCRE16_MODE) pcre2_jit_free_unused_memory_16(G(a,16)); \- else pcre2_jit_free_unused_memory_32(G(a,32))--#define PCRE2_JIT_MATCH(a,b,c,d,e,f,g,h) \- if (test_mode == PCRE8_MODE) \- a = pcre2_jit_match_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),h); \- else if (test_mode == PCRE16_MODE) \- a = pcre2_jit_match_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),h); \- else \- a = pcre2_jit_match_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),h)--#define PCRE2_JIT_STACK_CREATE(a,b,c,d) \- if (test_mode == PCRE8_MODE) \- a = (PCRE2_JIT_STACK *)pcre2_jit_stack_create_8(b,c,d); \- else if (test_mode == PCRE16_MODE) \- a = (PCRE2_JIT_STACK *)pcre2_jit_stack_create_16(b,c,d); \- else \- a = (PCRE2_JIT_STACK *)pcre2_jit_stack_create_32(b,c,d);--#define PCRE2_JIT_STACK_ASSIGN(a,b,c) \- if (test_mode == PCRE8_MODE) \- pcre2_jit_stack_assign_8(G(a,8),(pcre2_jit_callback_8)b,c); \- else if (test_mode == PCRE16_MODE) \- pcre2_jit_stack_assign_16(G(a,16),(pcre2_jit_callback_16)b,c); \- else \- pcre2_jit_stack_assign_32(G(a,32),(pcre2_jit_callback_32)b,c);--#define PCRE2_JIT_STACK_FREE(a) \- if (test_mode == PCRE8_MODE) \- pcre2_jit_stack_free_8((pcre2_jit_stack_8 *)a); \- else if (test_mode == PCRE16_MODE) \- pcre2_jit_stack_free_16((pcre2_jit_stack_16 *)a); \- else \- pcre2_jit_stack_free_32((pcre2_jit_stack_32 *)a);--#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); \- else if (test_mode == PCRE16_MODE) \- a = pcre2_match_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),h); \- else \- 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) \- if (test_mode == PCRE8_MODE) \- 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,G(c,16)); \- else \- 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),G(c,8)); \- else if (test_mode == PCRE16_MODE) \- 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),G(c,32))--#define PCRE2_MATCH_DATA_FREE(a) \- if (test_mode == PCRE8_MODE) \- pcre2_match_data_free_8(G(a,8)); \- else if (test_mode == PCRE16_MODE) \- pcre2_match_data_free_16(G(a,16)); \- else \- pcre2_match_data_free_32(G(a,32))--#define PCRE2_PATTERN_CONVERT(a,b,c,d,e,f,g) \- if (test_mode == PCRE8_MODE) \- a = pcre2_pattern_convert_8(G(b,8),c,d,(PCRE2_UCHAR8 **)e,f,G(g,8)); \- else if (test_mode == PCRE16_MODE) \- a = pcre2_pattern_convert_16(G(b,16),c,d,(PCRE2_UCHAR16 **)e,f,G(g,16)); \- else \- 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) \- if (test_mode == PCRE8_MODE) \- a = pcre2_pattern_info_8(G(b,8),c,d); \- else if (test_mode == PCRE16_MODE) \- a = pcre2_pattern_info_16(G(b,16),c,d); \- else \- a = pcre2_pattern_info_32(G(b,32),c,d)--#define PCRE2_PRINTINT(a) \- if (test_mode == PCRE8_MODE) \- pcre2_printint_8(compiled_code8,outfile,a); \- else if (test_mode == PCRE16_MODE) \- pcre2_printint_16(compiled_code16,outfile,a); \- else \- pcre2_printint_32(compiled_code32,outfile,a)--#define PCRE2_SERIALIZE_DECODE(r,a,b,c,d) \- if (test_mode == PCRE8_MODE) \- r = pcre2_serialize_decode_8((pcre2_code_8 **)a,b,c,G(d,8)); \- else if (test_mode == PCRE16_MODE) \- r = pcre2_serialize_decode_16((pcre2_code_16 **)a,b,c,G(d,16)); \- else \- r = pcre2_serialize_decode_32((pcre2_code_32 **)a,b,c,G(d,32))--#define PCRE2_SERIALIZE_ENCODE(r,a,b,c,d,e) \- if (test_mode == PCRE8_MODE) \- r = pcre2_serialize_encode_8((const pcre2_code_8 **)a,b,c,d,G(e,8)); \- else if (test_mode == PCRE16_MODE) \- r = pcre2_serialize_encode_16((const pcre2_code_16 **)a,b,c,d,G(e,16)); \- else \- r = pcre2_serialize_encode_32((const pcre2_code_32 **)a,b,c,d,G(e,32))--#define PCRE2_SERIALIZE_FREE(a) \- if (test_mode == PCRE8_MODE) \- pcre2_serialize_free_8(a); \- else if (test_mode == PCRE16_MODE) \- pcre2_serialize_free_16(a); \- else \- pcre2_serialize_free_32(a)--#define PCRE2_SERIALIZE_GET_NUMBER_OF_CODES(r,a) \- if (test_mode == PCRE8_MODE) \- r = pcre2_serialize_get_number_of_codes_8(a); \- else if (test_mode == PCRE16_MODE) \- r = pcre2_serialize_get_number_of_codes_16(a); \- else \- r = pcre2_serialize_get_number_of_codes_32(a); \--#define PCRE2_SET_CALLOUT(a,b,c) \- if (test_mode == PCRE8_MODE) \- pcre2_set_callout_8(G(a,8),(int (*)(pcre2_callout_block_8 *, void *))b,c); \- else if (test_mode == PCRE16_MODE) \- pcre2_set_callout_16(G(a,16),(int (*)(pcre2_callout_block_16 *, void *))b,c); \- else \- pcre2_set_callout_32(G(a,32),(int (*)(pcre2_callout_block_32 *, void *))b,c);--#define PCRE2_SET_CHARACTER_TABLES(a,b) \- if (test_mode == PCRE8_MODE) \- pcre2_set_character_tables_8(G(a,8),b); \- else if (test_mode == PCRE16_MODE) \- pcre2_set_character_tables_16(G(a,16),b); \- else \- pcre2_set_character_tables_32(G(a,32),b)--#define PCRE2_SET_COMPILE_RECURSION_GUARD(a,b,c) \- if (test_mode == PCRE8_MODE) \- pcre2_set_compile_recursion_guard_8(G(a,8),b,c); \- else if (test_mode == PCRE16_MODE) \- pcre2_set_compile_recursion_guard_16(G(a,16),b,c); \- else \- pcre2_set_compile_recursion_guard_32(G(a,32),b,c)--#define PCRE2_SET_DEPTH_LIMIT(a,b) \- if (test_mode == PCRE8_MODE) \- pcre2_set_depth_limit_8(G(a,8),b); \- else if (test_mode == PCRE16_MODE) \- pcre2_set_depth_limit_16(G(a,16),b); \- else \- pcre2_set_depth_limit_32(G(a,32),b)--#define PCRE2_SET_GLOB_SEPARATOR(r,a,b) \- if (test_mode == PCRE8_MODE) \- r = pcre2_set_glob_separator_8(G(a,8),b); \- else if (test_mode == PCRE16_MODE) \- r = pcre2_set_glob_separator_16(G(a,16),b); \- else \- r = pcre2_set_glob_separator_32(G(a,32),b)--#define PCRE2_SET_GLOB_ESCAPE(r,a,b) \- if (test_mode == PCRE8_MODE) \- r = pcre2_set_glob_escape_8(G(a,8),b); \- else if (test_mode == PCRE16_MODE) \- r = pcre2_set_glob_escape_16(G(a,16),b); \- else \- r = pcre2_set_glob_escape_32(G(a,32),b)--#define PCRE2_SET_HEAP_LIMIT(a,b) \- if (test_mode == PCRE8_MODE) \- pcre2_set_heap_limit_8(G(a,8),b); \- else if (test_mode == PCRE16_MODE) \- pcre2_set_heap_limit_16(G(a,16),b); \- else \- pcre2_set_heap_limit_32(G(a,32),b)--#define PCRE2_SET_MATCH_LIMIT(a,b) \- if (test_mode == PCRE8_MODE) \- pcre2_set_match_limit_8(G(a,8),b); \- else if (test_mode == PCRE16_MODE) \- pcre2_set_match_limit_16(G(a,16),b); \- 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); \- else if (test_mode == PCRE16_MODE) \- pcre2_set_max_pattern_length_16(G(a,16),b); \- 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); \- else if (test_mode == PCRE16_MODE) \- pcre2_set_offset_limit_16(G(a,16),b); \- else \- pcre2_set_offset_limit_32(G(a,32),b)--#define PCRE2_SET_PARENS_NEST_LIMIT(a,b) \- if (test_mode == PCRE8_MODE) \- pcre2_set_parens_nest_limit_8(G(a,8),b); \- else if (test_mode == PCRE16_MODE) \- pcre2_set_parens_nest_limit_16(G(a,16),b); \- else \- pcre2_set_parens_nest_limit_32(G(a,32),b)--#define PCRE2_SET_SUBSTITUTE_CALLOUT(a,b,c) \- if (test_mode == PCRE8_MODE) \- pcre2_set_substitute_callout_8(G(a,8), \- (int (*)(pcre2_substitute_callout_block_8 *, void *))b,c); \- else if (test_mode == PCRE16_MODE) \- pcre2_set_substitute_callout_16(G(a,16), \- (int (*)(pcre2_substitute_callout_block_16 *, void *))b,c); \- else \- pcre2_set_substitute_callout_32(G(a,32), \- (int (*)(pcre2_substitute_callout_block_32 *, void *))b,c)--#define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \- if (test_mode == PCRE8_MODE) \- a = pcre2_substitute_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),h, \- (PCRE2_SPTR8)i,j,(PCRE2_UCHAR8 *)k,l); \- else if (test_mode == PCRE16_MODE) \- a = pcre2_substitute_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),h, \- (PCRE2_SPTR16)i,j,(PCRE2_UCHAR16 *)k,l); \- else \- a = pcre2_substitute_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),h, \- (PCRE2_SPTR32)i,j,(PCRE2_UCHAR32 *)k,l)--#define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \- if (test_mode == PCRE8_MODE) \- a = pcre2_substring_copy_byname_8(G(b,8),G(c,8),(PCRE2_UCHAR8 *)d,e); \- else if (test_mode == PCRE16_MODE) \- a = pcre2_substring_copy_byname_16(G(b,16),G(c,16),(PCRE2_UCHAR16 *)d,e); \- else \- a = pcre2_substring_copy_byname_32(G(b,32),G(c,32),(PCRE2_UCHAR32 *)d,e)--#define PCRE2_SUBSTRING_COPY_BYNUMBER(a,b,c,d,e) \- if (test_mode == PCRE8_MODE) \- a = pcre2_substring_copy_bynumber_8(G(b,8),c,(PCRE2_UCHAR8 *)d,e); \- else if (test_mode == PCRE16_MODE) \- a = pcre2_substring_copy_bynumber_16(G(b,16),c,(PCRE2_UCHAR16 *)d,e); \- else \- a = pcre2_substring_copy_bynumber_32(G(b,32),c,(PCRE2_UCHAR32 *)d,e)--#define PCRE2_SUBSTRING_FREE(a) \- if (test_mode == PCRE8_MODE) pcre2_substring_free_8((PCRE2_UCHAR8 *)a); \- else if (test_mode == PCRE16_MODE) \- pcre2_substring_free_16((PCRE2_UCHAR16 *)a); \- else pcre2_substring_free_32((PCRE2_UCHAR32 *)a)--#define PCRE2_SUBSTRING_GET_BYNAME(a,b,c,d,e) \- if (test_mode == PCRE8_MODE) \- a = pcre2_substring_get_byname_8(G(b,8),G(c,8),(PCRE2_UCHAR8 **)d,e); \- else if (test_mode == PCRE16_MODE) \- a = pcre2_substring_get_byname_16(G(b,16),G(c,16),(PCRE2_UCHAR16 **)d,e); \- else \- a = pcre2_substring_get_byname_32(G(b,32),G(c,32),(PCRE2_UCHAR32 **)d,e)--#define PCRE2_SUBSTRING_GET_BYNUMBER(a,b,c,d,e) \- if (test_mode == PCRE8_MODE) \- a = pcre2_substring_get_bynumber_8(G(b,8),c,(PCRE2_UCHAR8 **)d,e); \- else if (test_mode == PCRE16_MODE) \- a = pcre2_substring_get_bynumber_16(G(b,16),c,(PCRE2_UCHAR16 **)d,e); \- else \- a = pcre2_substring_get_bynumber_32(G(b,32),c,(PCRE2_UCHAR32 **)d,e)--#define PCRE2_SUBSTRING_LENGTH_BYNAME(a,b,c,d) \- if (test_mode == PCRE8_MODE) \- a = pcre2_substring_length_byname_8(G(b,8),G(c,8),d); \- else if (test_mode == PCRE16_MODE) \- a = pcre2_substring_length_byname_16(G(b,16),G(c,16),d); \- else \- a = pcre2_substring_length_byname_32(G(b,32),G(c,32),d)--#define PCRE2_SUBSTRING_LENGTH_BYNUMBER(a,b,c,d) \- if (test_mode == PCRE8_MODE) \- a = pcre2_substring_length_bynumber_8(G(b,8),c,d); \- else if (test_mode == PCRE16_MODE) \- a = pcre2_substring_length_bynumber_16(G(b,16),c,d); \- else \- a = pcre2_substring_length_bynumber_32(G(b,32),c,d)--#define PCRE2_SUBSTRING_LIST_GET(a,b,c,d) \- if (test_mode == PCRE8_MODE) \- a = pcre2_substring_list_get_8(G(b,8),(PCRE2_UCHAR8 ***)c,d); \- else if (test_mode == PCRE16_MODE) \- a = pcre2_substring_list_get_16(G(b,16),(PCRE2_UCHAR16 ***)c,d); \- else \- a = pcre2_substring_list_get_32(G(b,32),(PCRE2_UCHAR32 ***)c,d)--#define PCRE2_SUBSTRING_LIST_FREE(a) \- if (test_mode == PCRE8_MODE) \- pcre2_substring_list_free_8((PCRE2_UCHAR8 **)a); \- else if (test_mode == PCRE16_MODE) \- pcre2_substring_list_free_16((PCRE2_UCHAR16 **)a); \- else \- pcre2_substring_list_free_32((PCRE2_UCHAR32 **)a)--#define PCRE2_SUBSTRING_NUMBER_FROM_NAME(a,b,c) \- if (test_mode == PCRE8_MODE) \- a = pcre2_substring_number_from_name_8(G(b,8),G(c,8)); \- else if (test_mode == PCRE16_MODE) \- a = pcre2_substring_number_from_name_16(G(b,16),G(c,16)); \- else \- a = pcre2_substring_number_from_name_32(G(b,32),G(c,32))--#define PTR(x) ( \- (test_mode == PCRE8_MODE)? (void *)G(x,8) : \- (test_mode == PCRE16_MODE)? (void *)G(x,16) : \- (void *)G(x,32))--#define SETFLD(x,y,z) \- if (test_mode == PCRE8_MODE) G(x,8)->y = z; \- else if (test_mode == PCRE16_MODE) G(x,16)->y = z; \- else G(x,32)->y = z--#define SETFLDVEC(x,y,v,z) \- if (test_mode == PCRE8_MODE) G(x,8)->y[v] = z; \- else if (test_mode == PCRE16_MODE) G(x,16)->y[v] = z; \- else G(x,32)->y[v] = z--#define SETOP(x,y,z) \- if (test_mode == PCRE8_MODE) G(x,8) z y; \- else if (test_mode == PCRE16_MODE) G(x,16) z y; \- else G(x,32) z y--#define SETCASTPTR(x,y) \- if (test_mode == PCRE8_MODE) \- G(x,8) = (uint8_t *)(y); \- else if (test_mode == PCRE16_MODE) \- G(x,16) = (uint16_t *)(y); \- else \- G(x,32) = (uint32_t *)(y)--#define STRLEN(p) ((test_mode == PCRE8_MODE)? ((int)strlen((char *)p)) : \- (test_mode == PCRE16_MODE)? ((int)strlen16((PCRE2_SPTR16)p)) : \- ((int)strlen32((PCRE2_SPTR32)p)))--#define SUB1(a,b) \- if (test_mode == PCRE8_MODE) G(a,8)(G(b,8)); \- else if (test_mode == PCRE16_MODE) G(a,16)(G(b,16)); \- else G(a,32)(G(b,32))--#define SUB2(a,b,c) \- if (test_mode == PCRE8_MODE) G(a,8)(G(b,8),G(c,8)); \- else if (test_mode == PCRE16_MODE) G(a,16)(G(b,16),G(c,16)); \- else G(a,32)(G(b,32),G(c,32))--#define TEST(x,r,y) ( \- (test_mode == PCRE8_MODE && G(x,8) r (y)) || \- (test_mode == PCRE16_MODE && G(x,16) r (y)) || \- (test_mode == PCRE32_MODE && G(x,32) r (y)))--#define TESTFLD(x,f,r,y) ( \- (test_mode == PCRE8_MODE && G(x,8)->f r (y)) || \- (test_mode == PCRE16_MODE && G(x,16)->f r (y)) || \- (test_mode == PCRE32_MODE && G(x,32)->f r (y)))---/* ----- Two out of three modes are supported ----- */--#else--/* We can use some macro trickery to make a single set of definitions work in-the three different cases. */--/* ----- 32-bit and 16-bit but not 8-bit supported ----- */--#if defined(SUPPORT_PCRE2_32) && defined(SUPPORT_PCRE2_16)-#define BITONE 32-#define BITTWO 16--/* ----- 32-bit and 8-bit but not 16-bit supported ----- */--#elif defined(SUPPORT_PCRE2_32) && defined(SUPPORT_PCRE2_8)-#define BITONE 32-#define BITTWO 8--/* ----- 16-bit and 8-bit but not 32-bit supported ----- */--#else-#define BITONE 16-#define BITTWO 8-#endif---/* ----- Common macros for two-mode cases ----- */--#define BYTEONE (BITONE/8)-#define BYTETWO (BITTWO/8)--#define CASTFLD(t,a,b) \- ((test_mode == G(G(PCRE,BITONE),_MODE))? (t)(G(a,BITONE)->b) : \- (t)(G(a,BITTWO)->b))--#define CASTVAR(t,x) ( \- (test_mode == G(G(PCRE,BITONE),_MODE))? \- (t)G(x,BITONE) : (t)G(x,BITTWO))--#define CODE_UNIT(a,b) ( \- (test_mode == G(G(PCRE,BITONE),_MODE))? \- (uint32_t)(((G(PCRE2_SPTR,BITONE))(a))[b]) : \- (uint32_t)(((G(PCRE2_SPTR,BITTWO))(a))[b]))--#define CONCTXCPY(a,b) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- memcpy(G(a,BITONE),G(b,BITONE),sizeof(G(pcre2_convert_context_,BITONE))); \- else \- memcpy(G(a,BITTWO),G(b,BITTWO),sizeof(G(pcre2_convert_context_,BITTWO)))--#define CONVERT_COPY(a,b,c) \- (test_mode == G(G(PCRE,BITONE),_MODE))? \- memcpy(G(a,BITONE),(char *)b,(c)*BYTEONE) : \- memcpy(G(a,BITTWO),(char *)b,(c)*BYTETWO)--#define DATCTXCPY(a,b) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- memcpy(G(a,BITONE),G(b,BITONE),sizeof(G(pcre2_match_context_,BITONE))); \- else \- memcpy(G(a,BITTWO),G(b,BITTWO),sizeof(G(pcre2_match_context_,BITTWO)))--#define FLD(a,b) \- ((test_mode == G(G(PCRE,BITONE),_MODE))? G(a,BITONE)->b : G(a,BITTWO)->b)--#define PATCTXCPY(a,b) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- memcpy(G(a,BITONE),G(b,BITONE),sizeof(G(pcre2_compile_context_,BITONE))); \- else \- memcpy(G(a,BITTWO),G(b,BITTWO),sizeof(G(pcre2_compile_context_,BITTWO)))--#define PCHARS(lv, p, offset, len, utf, f) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- lv = G(pchars,BITONE)((G(PCRE2_SPTR,BITONE))(p)+offset, len, utf, f); \- else \- lv = G(pchars,BITTWO)((G(PCRE2_SPTR,BITTWO))(p)+offset, len, utf, f)--#define PCHARSV(p, offset, len, utf, f) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- (void)G(pchars,BITONE)((G(PCRE2_SPTR,BITONE))(p)+offset, len, utf, f); \- else \- (void)G(pchars,BITTWO)((G(PCRE2_SPTR,BITTWO))(p)+offset, len, utf, f)--#define PCRE2_CALLOUT_ENUMERATE(a,b,c) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- a = G(pcre2_callout_enumerate,BITONE)(G(compiled_code,BITONE), \- (int (*)(struct G(pcre2_callout_enumerate_block_,BITONE) *, void *))b,c); \- else \- a = G(pcre2_callout_enumerate,BITTWO)(G(compiled_code,BITTWO), \- (int (*)(struct G(pcre2_callout_enumerate_block_,BITTWO) *, void *))b,c)--#define PCRE2_CODE_COPY_FROM_VOID(a,b) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(a,BITONE) = G(pcre2_code_copy_,BITONE)(b); \- else \- G(a,BITTWO) = G(pcre2_code_copy_,BITTWO)(b)--#define PCRE2_CODE_COPY_TO_VOID(a,b) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- a = (void *)G(pcre2_code_copy_,BITONE)(G(b,BITONE)); \- else \- a = (void *)G(pcre2_code_copy_,BITTWO)(G(b,BITTWO))--#define PCRE2_CODE_COPY_WITH_TABLES_TO_VOID(a,b) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- a = (void *)G(pcre2_code_copy_with_tables_,BITONE)(G(b,BITONE)); \- else \- a = (void *)G(pcre2_code_copy_with_tables_,BITTWO)(G(b,BITTWO))--#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)(b,c,d,e,f,g); \- else \- 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)) \- G(pcre2_converted_pattern_free_,BITONE)((G(PCRE2_UCHAR,BITONE) *)a); \- else \- G(pcre2_converted_pattern_free_,BITTWO)((G(PCRE2_UCHAR,BITTWO) *)a)--#define PCRE2_DFA_MATCH(a,b,c,d,e,f,g,h,i,j) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- a = G(pcre2_dfa_match_,BITONE)(G(b,BITONE),(G(PCRE2_SPTR,BITONE))c,d,e,f, \- G(g,BITONE),h,i,j); \- else \- a = G(pcre2_dfa_match_,BITTWO)(G(b,BITTWO),(G(PCRE2_SPTR,BITTWO))c,d,e,f, \- G(g,BITTWO),h,i,j)--#define PCRE2_GET_ERROR_MESSAGE(r,a,b) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- r = G(pcre2_get_error_message_,BITONE)(a,G(b,BITONE),G(G(b,BITONE),_size/BYTEONE)); \- 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)); \- else \- a = G(pcre2_get_ovector_count_,BITTWO)(G(b,BITTWO))--#define PCRE2_GET_STARTCHAR(a,b) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- a = G(pcre2_get_startchar_,BITONE)(G(b,BITONE)); \- else \- a = G(pcre2_get_startchar_,BITTWO)(G(b,BITTWO))--#define PCRE2_JIT_COMPILE(r,a,b) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- r = G(pcre2_jit_compile_,BITONE)(G(a,BITONE),b); \- else \- r = G(pcre2_jit_compile_,BITTWO)(G(a,BITTWO),b)--#define PCRE2_JIT_FREE_UNUSED_MEMORY(a) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(pcre2_jit_free_unused_memory_,BITONE)(G(a,BITONE)); \- else \- G(pcre2_jit_free_unused_memory_,BITTWO)(G(a,BITTWO))--#define PCRE2_JIT_MATCH(a,b,c,d,e,f,g,h) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- a = G(pcre2_jit_match_,BITONE)(G(b,BITONE),(G(PCRE2_SPTR,BITONE))c,d,e,f, \- G(g,BITONE),h); \- else \- a = G(pcre2_jit_match_,BITTWO)(G(b,BITTWO),(G(PCRE2_SPTR,BITTWO))c,d,e,f, \- G(g,BITTWO),h)--#define PCRE2_JIT_STACK_CREATE(a,b,c,d) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- a = (PCRE2_JIT_STACK *)G(pcre2_jit_stack_create_,BITONE)(b,c,d); \- else \- a = (PCRE2_JIT_STACK *)G(pcre2_jit_stack_create_,BITTWO)(b,c,d); \--#define PCRE2_JIT_STACK_ASSIGN(a,b,c) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(pcre2_jit_stack_assign_,BITONE)(G(a,BITONE),(G(pcre2_jit_callback_,BITONE))b,c); \- else \- G(pcre2_jit_stack_assign_,BITTWO)(G(a,BITTWO),(G(pcre2_jit_callback_,BITTWO))b,c);--#define PCRE2_JIT_STACK_FREE(a) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(pcre2_jit_stack_free_,BITONE)((G(pcre2_jit_stack_,BITONE) *)a); \- else \- G(pcre2_jit_stack_free_,BITTWO)((G(pcre2_jit_stack_,BITTWO) *)a);--#define PCRE2_MAKETABLES(a,c) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- a = G(pcre2_maketables_,BITONE)(G(c,BITONE)); \- else \- 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, \- G(g,BITONE),h); \- else \- a = G(pcre2_match_,BITTWO)(G(b,BITTWO),(G(PCRE2_SPTR,BITTWO))c,d,e,f, \- G(g,BITTWO),h)--#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,G(c,BITONE)); \- else \- 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),G(c,BITONE)); \- else \- 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)) \- G(pcre2_match_data_free_,BITONE)(G(a,BITONE)); \- else \- G(pcre2_match_data_free_,BITTWO)(G(a,BITTWO))--#define PCRE2_PATTERN_CONVERT(a,b,c,d,e,f,g) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- a = G(pcre2_pattern_convert_,BITONE)(G(b,BITONE),c,d,(G(PCRE2_UCHAR,BITONE) **)e,f,G(g,BITONE)); \- else \- a = G(pcre2_pattern_convert_,BITTWO)(G(b,BITTWO),c,d,(G(PCRE2_UCHAR,BITTWO) **)e,f,G(g,BITTWO))--#define PCRE2_PATTERN_INFO(a,b,c,d) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- a = G(pcre2_pattern_info_,BITONE)(G(b,BITONE),c,d); \- else \- a = G(pcre2_pattern_info_,BITTWO)(G(b,BITTWO),c,d)--#define PCRE2_PRINTINT(a) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(pcre2_printint_,BITONE)(G(compiled_code,BITONE),outfile,a); \- else \- G(pcre2_printint_,BITTWO)(G(compiled_code,BITTWO),outfile,a)--#define PCRE2_SERIALIZE_DECODE(r,a,b,c,d) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- r = G(pcre2_serialize_decode_,BITONE)((G(pcre2_code_,BITONE) **)a,b,c,G(d,BITONE)); \- else \- r = G(pcre2_serialize_decode_,BITTWO)((G(pcre2_code_,BITTWO) **)a,b,c,G(d,BITTWO))--#define PCRE2_SERIALIZE_ENCODE(r,a,b,c,d,e) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- r = G(pcre2_serialize_encode_,BITONE)((G(const pcre2_code_,BITONE) **)a,b,c,d,G(e,BITONE)); \- else \- r = G(pcre2_serialize_encode_,BITTWO)((G(const pcre2_code_,BITTWO) **)a,b,c,d,G(e,BITTWO))--#define PCRE2_SERIALIZE_FREE(a) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(pcre2_serialize_free_,BITONE)(a); \- else \- G(pcre2_serialize_free_,BITTWO)(a)--#define PCRE2_SERIALIZE_GET_NUMBER_OF_CODES(r,a) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- r = G(pcre2_serialize_get_number_of_codes_,BITONE)(a); \- else \- r = G(pcre2_serialize_get_number_of_codes_,BITTWO)(a)--#define PCRE2_SET_CALLOUT(a,b,c) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(pcre2_set_callout_,BITONE)(G(a,BITONE), \- (int (*)(G(pcre2_callout_block_,BITONE) *, void *))b,c); \- else \- G(pcre2_set_callout_,BITTWO)(G(a,BITTWO), \- (int (*)(G(pcre2_callout_block_,BITTWO) *, void *))b,c);--#define PCRE2_SET_CHARACTER_TABLES(a,b) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(pcre2_set_character_tables_,BITONE)(G(a,BITONE),b); \- else \- G(pcre2_set_character_tables_,BITTWO)(G(a,BITTWO),b)--#define PCRE2_SET_COMPILE_RECURSION_GUARD(a,b,c) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(pcre2_set_compile_recursion_guard_,BITONE)(G(a,BITONE),b,c); \- else \- G(pcre2_set_compile_recursion_guard_,BITTWO)(G(a,BITTWO),b,c)--#define PCRE2_SET_DEPTH_LIMIT(a,b) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(pcre2_set_depth_limit_,BITONE)(G(a,BITONE),b); \- else \- G(pcre2_set_depth_limit_,BITTWO)(G(a,BITTWO),b)--#define PCRE2_SET_GLOB_ESCAPE(r,a,b) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- r = G(pcre2_set_glob_escape_,BITONE)(G(a,BITONE),b); \- else \- r = G(pcre2_set_glob_escape_,BITTWO)(G(a,BITTWO),b)--#define PCRE2_SET_GLOB_SEPARATOR(r,a,b) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- r = G(pcre2_set_glob_separator_,BITONE)(G(a,BITONE),b); \- else \- r = G(pcre2_set_glob_separator_,BITTWO)(G(a,BITTWO),b)--#define PCRE2_SET_HEAP_LIMIT(a,b) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(pcre2_set_heap_limit_,BITONE)(G(a,BITONE),b); \- else \- G(pcre2_set_heap_limit_,BITTWO)(G(a,BITTWO),b)--#define PCRE2_SET_MATCH_LIMIT(a,b) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(pcre2_set_match_limit_,BITONE)(G(a,BITONE),b); \- 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); \- else \- G(pcre2_set_offset_limit_,BITTWO)(G(a,BITTWO),b)--#define PCRE2_SET_PARENS_NEST_LIMIT(a,b) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(pcre2_set_parens_nest_limit_,BITONE)(G(a,BITONE),b); \- else \- G(pcre2_set_parens_nest_limit_,BITTWO)(G(a,BITTWO),b)--#define PCRE2_SET_SUBSTITUTE_CALLOUT(a,b,c) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(pcre2_set_substitute_callout_,BITONE)(G(a,BITONE), \- (int (*)(G(pcre2_substitute_callout_block_,BITONE) *, void *))b,c); \- else \- G(pcre2_set_substitute_callout_,BITTWO)(G(a,BITTWO), \- (int (*)(G(pcre2_substitute_callout_block_,BITTWO) *, void *))b,c)--#define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- a = G(pcre2_substitute_,BITONE)(G(b,BITONE),(G(PCRE2_SPTR,BITONE))c,d,e,f, \- G(g,BITONE),h,(G(PCRE2_SPTR,BITONE))i,j, \- (G(PCRE2_UCHAR,BITONE) *)k,l); \- else \- a = G(pcre2_substitute_,BITTWO)(G(b,BITTWO),(G(PCRE2_SPTR,BITTWO))c,d,e,f, \- G(g,BITTWO),h,(G(PCRE2_SPTR,BITTWO))i,j, \- (G(PCRE2_UCHAR,BITTWO) *)k,l)--#define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- a = G(pcre2_substring_copy_byname_,BITONE)(G(b,BITONE),G(c,BITONE),\- (G(PCRE2_UCHAR,BITONE) *)d,e); \- else \- a = G(pcre2_substring_copy_byname_,BITTWO)(G(b,BITTWO),G(c,BITTWO),\- (G(PCRE2_UCHAR,BITTWO) *)d,e)--#define PCRE2_SUBSTRING_COPY_BYNUMBER(a,b,c,d,e) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- a = G(pcre2_substring_copy_bynumber_,BITONE)(G(b,BITONE),c,\- (G(PCRE2_UCHAR,BITONE) *)d,e); \- else \- a = G(pcre2_substring_copy_bynumber_,BITTWO)(G(b,BITTWO),c,\- (G(PCRE2_UCHAR,BITTWO) *)d,e)--#define PCRE2_SUBSTRING_FREE(a) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(pcre2_substring_free_,BITONE)((G(PCRE2_UCHAR,BITONE) *)a); \- else G(pcre2_substring_free_,BITTWO)((G(PCRE2_UCHAR,BITTWO) *)a)--#define PCRE2_SUBSTRING_GET_BYNAME(a,b,c,d,e) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- a = G(pcre2_substring_get_byname_,BITONE)(G(b,BITONE),G(c,BITONE),\- (G(PCRE2_UCHAR,BITONE) **)d,e); \- else \- a = G(pcre2_substring_get_byname_,BITTWO)(G(b,BITTWO),G(c,BITTWO),\- (G(PCRE2_UCHAR,BITTWO) **)d,e)--#define PCRE2_SUBSTRING_GET_BYNUMBER(a,b,c,d,e) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- a = G(pcre2_substring_get_bynumber_,BITONE)(G(b,BITONE),c,\- (G(PCRE2_UCHAR,BITONE) **)d,e); \- else \- a = G(pcre2_substring_get_bynumber_,BITTWO)(G(b,BITTWO),c,\- (G(PCRE2_UCHAR,BITTWO) **)d,e)--#define PCRE2_SUBSTRING_LENGTH_BYNAME(a,b,c,d) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- a = G(pcre2_substring_length_byname_,BITONE)(G(b,BITONE),G(c,BITONE),d); \- else \- a = G(pcre2_substring_length_byname_,BITTWO)(G(b,BITTWO),G(c,BITTWO),d)--#define PCRE2_SUBSTRING_LENGTH_BYNUMBER(a,b,c,d) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- a = G(pcre2_substring_length_bynumber_,BITONE)(G(b,BITONE),c,d); \- else \- a = G(pcre2_substring_length_bynumber_,BITTWO)(G(b,BITTWO),c,d)--#define PCRE2_SUBSTRING_LIST_GET(a,b,c,d) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- a = G(pcre2_substring_list_get_,BITONE)(G(b,BITONE), \- (G(PCRE2_UCHAR,BITONE) ***)c,d); \- else \- a = G(pcre2_substring_list_get_,BITTWO)(G(b,BITTWO), \- (G(PCRE2_UCHAR,BITTWO) ***)c,d)--#define PCRE2_SUBSTRING_LIST_FREE(a) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(pcre2_substring_list_free_,BITONE)((G(PCRE2_UCHAR,BITONE) **)a); \- else \- 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)) \- a = G(pcre2_substring_number_from_name_,BITONE)(G(b,BITONE),G(c,BITONE)); \- else \- a = G(pcre2_substring_number_from_name_,BITTWO)(G(b,BITTWO),G(c,BITTWO))--#define PTR(x) ( \- (test_mode == G(G(PCRE,BITONE),_MODE))? (void *)G(x,BITONE) : \- (void *)G(x,BITTWO))--#define SETFLD(x,y,z) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) G(x,BITONE)->y = z; \- else G(x,BITTWO)->y = z--#define SETFLDVEC(x,y,v,z) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) G(x,BITONE)->y[v] = z; \- else G(x,BITTWO)->y[v] = z--#define SETOP(x,y,z) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) G(x,BITONE) z y; \- else G(x,BITTWO) z y--#define SETCASTPTR(x,y) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(x,BITONE) = (G(G(uint,BITONE),_t) *)(y); \- else \- G(x,BITTWO) = (G(G(uint,BITTWO),_t) *)(y)--#define STRLEN(p) ((test_mode == G(G(PCRE,BITONE),_MODE))? \- G(strlen,BITONE)((G(PCRE2_SPTR,BITONE))p) : \- G(strlen,BITTWO)((G(PCRE2_SPTR,BITTWO))p))--#define SUB1(a,b) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(a,BITONE)(G(b,BITONE)); \- else \- G(a,BITTWO)(G(b,BITTWO))--#define SUB2(a,b,c) \- if (test_mode == G(G(PCRE,BITONE),_MODE)) \- G(a,BITONE))(G(b,BITONE),G(c,BITONE)); \- else \- G(a,BITTWO))(G(b,BITTWO),G(c,BITTWO))--#define TEST(x,r,y) ( \- (test_mode == G(G(PCRE,BITONE),_MODE) && G(x,BITONE) r (y)) || \- (test_mode == G(G(PCRE,BITTWO),_MODE) && G(x,BITTWO) r (y)))--#define TESTFLD(x,f,r,y) ( \- (test_mode == G(G(PCRE,BITONE),_MODE) && G(x,BITONE)->f r (y)) || \- (test_mode == G(G(PCRE,BITTWO),_MODE) && G(x,BITTWO)->f r (y)))---#endif /* Two out of three modes */--/* ----- End of cases where more than one mode is supported ----- */---/* ----- Only 8-bit mode is supported ----- */--#elif defined SUPPORT_PCRE2_8-#define CASTFLD(t,a,b) (t)(G(a,8)->b)-#define CASTVAR(t,x) (t)G(x,8)-#define CODE_UNIT(a,b) (uint32_t)(((PCRE2_SPTR8)(a))[b])-#define CONCTXCPY(a,b) memcpy(G(a,8),G(b,8),sizeof(pcre2_convert_context_8))-#define CONVERT_COPY(a,b,c) memcpy(G(a,8),(char *)b, c)-#define DATCTXCPY(a,b) memcpy(G(a,8),G(b,8),sizeof(pcre2_match_context_8))-#define FLD(a,b) G(a,8)->b-#define PATCTXCPY(a,b) memcpy(G(a,8),G(b,8),sizeof(pcre2_compile_context_8))-#define PCHARS(lv, p, offset, len, utf, f) \- lv = pchars8((PCRE2_SPTR8)(p)+offset, len, utf, f)-#define PCHARSV(p, offset, len, utf, f) \- (void)pchars8((PCRE2_SPTR8)(p)+offset, len, utf, f)-#define PCRE2_CALLOUT_ENUMERATE(a,b,c) \- a = pcre2_callout_enumerate_8(compiled_code8, \- (int (*)(struct pcre2_callout_enumerate_block_8 *, void *))b,c)-#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(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)-#define PCRE2_JIT_FREE_UNUSED_MEMORY(a) pcre2_jit_free_unused_memory_8(G(a,8))-#define PCRE2_JIT_MATCH(a,b,c,d,e,f,g,h) \- a = pcre2_jit_match_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),h)-#define PCRE2_JIT_STACK_CREATE(a,b,c,d) \- a = (PCRE2_JIT_STACK *)pcre2_jit_stack_create_8(b,c,d);-#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,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,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),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)-#define PCRE2_PRINTINT(a) pcre2_printint_8(compiled_code8,outfile,a)-#define PCRE2_SERIALIZE_DECODE(r,a,b,c,d) \- r = pcre2_serialize_decode_8((pcre2_code_8 **)a,b,c,G(d,8))-#define PCRE2_SERIALIZE_ENCODE(r,a,b,c,d,e) \- r = pcre2_serialize_encode_8((const pcre2_code_8 **)a,b,c,d,G(e,8))-#define PCRE2_SERIALIZE_FREE(a) pcre2_serialize_free_8(a)-#define PCRE2_SERIALIZE_GET_NUMBER_OF_CODES(r,a) \- r = pcre2_serialize_get_number_of_codes_8(a)-#define PCRE2_SET_CALLOUT(a,b,c) \- pcre2_set_callout_8(G(a,8),(int (*)(pcre2_callout_block_8 *, void *))b,c)-#define PCRE2_SET_CHARACTER_TABLES(a,b) pcre2_set_character_tables_8(G(a,8),b)-#define PCRE2_SET_COMPILE_RECURSION_GUARD(a,b,c) \- pcre2_set_compile_recursion_guard_8(G(a,8),b,c)-#define PCRE2_SET_DEPTH_LIMIT(a,b) pcre2_set_depth_limit_8(G(a,8),b)-#define PCRE2_SET_GLOB_ESCAPE(r,a,b) r = pcre2_set_glob_escape_8(G(a,8),b)-#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) \- pcre2_set_substitute_callout_8(G(a,8), \- (int (*)(pcre2_substitute_callout_block_8 *, void *))b,c)-#define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \- a = pcre2_substitute_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),h, \- (PCRE2_SPTR8)i,j,(PCRE2_UCHAR8 *)k,l)-#define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \- a = pcre2_substring_copy_byname_8(G(b,8),G(c,8),(PCRE2_UCHAR8 *)d,e)-#define PCRE2_SUBSTRING_COPY_BYNUMBER(a,b,c,d,e) \- a = pcre2_substring_copy_bynumber_8(G(b,8),c,(PCRE2_UCHAR8 *)d,e)-#define PCRE2_SUBSTRING_FREE(a) pcre2_substring_free_8((PCRE2_UCHAR8 *)a)-#define PCRE2_SUBSTRING_GET_BYNAME(a,b,c,d,e) \- a = pcre2_substring_get_byname_8(G(b,8),G(c,8),(PCRE2_UCHAR8 **)d,e)-#define PCRE2_SUBSTRING_GET_BYNUMBER(a,b,c,d,e) \- a = pcre2_substring_get_bynumber_8(G(b,8),c,(PCRE2_UCHAR8 **)d,e)-#define PCRE2_SUBSTRING_LENGTH_BYNAME(a,b,c,d) \- a = pcre2_substring_length_byname_8(G(b,8),G(c,8),d)-#define PCRE2_SUBSTRING_LENGTH_BYNUMBER(a,b,c,d) \- a = pcre2_substring_length_bynumber_8(G(b,8),c,d)-#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_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)-#define SETFLD(x,y,z) G(x,8)->y = z-#define SETFLDVEC(x,y,v,z) G(x,8)->y[v] = z-#define SETOP(x,y,z) G(x,8) z y-#define SETCASTPTR(x,y) G(x,8) = (uint8_t *)(y)-#define STRLEN(p) (int)strlen((char *)p)-#define SUB1(a,b) G(a,8)(G(b,8))-#define SUB2(a,b,c) G(a,8)(G(b,8),G(c,8))-#define TEST(x,r,y) (G(x,8) r (y))-#define TESTFLD(x,f,r,y) (G(x,8)->f r (y))---/* ----- Only 16-bit mode is supported ----- */--#elif defined SUPPORT_PCRE2_16-#define CASTFLD(t,a,b) (t)(G(a,16)->b)-#define CASTVAR(t,x) (t)G(x,16)-#define CODE_UNIT(a,b) (uint32_t)(((PCRE2_SPTR16)(a))[b])-#define CONCTXCPY(a,b) memcpy(G(a,16),G(b,16),sizeof(pcre2_convert_context_16))-#define CONVERT_COPY(a,b,c) memcpy(G(a,16),(char *)b, (c)*2)-#define DATCTXCPY(a,b) memcpy(G(a,16),G(b,16),sizeof(pcre2_match_context_16))-#define FLD(a,b) G(a,16)->b-#define PATCTXCPY(a,b) memcpy(G(a,16),G(b,16),sizeof(pcre2_compile_context_16))-#define PCHARS(lv, p, offset, len, utf, f) \- lv = pchars16((PCRE2_SPTR16)(p)+offset, len, utf, f)-#define PCHARSV(p, offset, len, utf, f) \- (void)pchars16((PCRE2_SPTR16)(p)+offset, len, utf, f)-#define PCRE2_CALLOUT_ENUMERATE(a,b,c) \- a = pcre2_callout_enumerate_16(compiled_code16, \- (int (*)(struct pcre2_callout_enumerate_block_16 *, void *))b,c)-#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(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) \- a = pcre2_dfa_match_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),h,i,j)-#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))-#define PCRE2_JIT_MATCH(a,b,c,d,e,f,g,h) \- a = pcre2_jit_match_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),h)-#define PCRE2_JIT_STACK_CREATE(a,b,c,d) \- a = (PCRE2_JIT_STACK *)pcre2_jit_stack_create_16(b,c,d);-#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,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,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),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)-#define PCRE2_PRINTINT(a) pcre2_printint_16(compiled_code16,outfile,a)-#define PCRE2_SERIALIZE_DECODE(r,a,b,c,d) \- r = pcre2_serialize_decode_16((pcre2_code_16 **)a,b,c,G(d,16))-#define PCRE2_SERIALIZE_ENCODE(r,a,b,c,d,e) \- r = pcre2_serialize_encode_16((const pcre2_code_16 **)a,b,c,d,G(e,16))-#define PCRE2_SERIALIZE_FREE(a) pcre2_serialize_free_16(a)-#define PCRE2_SERIALIZE_GET_NUMBER_OF_CODES(r,a) \- r = pcre2_serialize_get_number_of_codes_16(a)-#define PCRE2_SET_CALLOUT(a,b,c) \- pcre2_set_callout_16(G(a,16),(int (*)(pcre2_callout_block_16 *, void *))b,c);-#define PCRE2_SET_CHARACTER_TABLES(a,b) pcre2_set_character_tables_16(G(a,16),b)-#define PCRE2_SET_COMPILE_RECURSION_GUARD(a,b,c) \- pcre2_set_compile_recursion_guard_16(G(a,16),b,c)-#define PCRE2_SET_DEPTH_LIMIT(a,b) pcre2_set_depth_limit_16(G(a,16),b)-#define PCRE2_SET_GLOB_ESCAPE(r,a,b) r = pcre2_set_glob_escape_16(G(a,16),b)-#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_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) \- pcre2_set_substitute_callout_16(G(a,16), \- (int (*)(pcre2_substitute_callout_block_16 *, void *))b,c)-#define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \- a = pcre2_substitute_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),h, \- (PCRE2_SPTR16)i,j,(PCRE2_UCHAR16 *)k,l)-#define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \- a = pcre2_substring_copy_byname_16(G(b,16),G(c,16),(PCRE2_UCHAR16 *)d,e)-#define PCRE2_SUBSTRING_COPY_BYNUMBER(a,b,c,d,e) \- a = pcre2_substring_copy_bynumber_16(G(b,16),c,(PCRE2_UCHAR16 *)d,e)-#define PCRE2_SUBSTRING_FREE(a) pcre2_substring_free_16((PCRE2_UCHAR16 *)a)-#define PCRE2_SUBSTRING_GET_BYNAME(a,b,c,d,e) \- a = pcre2_substring_get_byname_16(G(b,16),G(c,16),(PCRE2_UCHAR16 **)d,e)-#define PCRE2_SUBSTRING_GET_BYNUMBER(a,b,c,d,e) \- a = pcre2_substring_get_bynumber_16(G(b,16),c,(PCRE2_UCHAR16 **)d,e)-#define PCRE2_SUBSTRING_LENGTH_BYNAME(a,b,c,d) \- a = pcre2_substring_length_byname_16(G(b,16),G(c,16),d)-#define PCRE2_SUBSTRING_LENGTH_BYNUMBER(a,b,c,d) \- a = pcre2_substring_length_bynumber_16(G(b,16),c,d)-#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_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)-#define SETFLD(x,y,z) G(x,16)->y = z-#define SETFLDVEC(x,y,v,z) G(x,16)->y[v] = z-#define SETOP(x,y,z) G(x,16) z y-#define SETCASTPTR(x,y) G(x,16) = (uint16_t *)(y)-#define STRLEN(p) (int)strlen16((PCRE2_SPTR16)p)-#define SUB1(a,b) G(a,16)(G(b,16))-#define SUB2(a,b,c) G(a,16)(G(b,16),G(c,16))-#define TEST(x,r,y) (G(x,16) r (y))-#define TESTFLD(x,f,r,y) (G(x,16)->f r (y))---/* ----- Only 32-bit mode is supported ----- */--#elif defined SUPPORT_PCRE2_32-#define CASTFLD(t,a,b) (t)(G(a,32)->b)-#define CASTVAR(t,x) (t)G(x,32)-#define CODE_UNIT(a,b) (uint32_t)(((PCRE2_SPTR32)(a))[b])-#define CONCTXCPY(a,b) memcpy(G(a,32),G(b,32),sizeof(pcre2_convert_context_32))-#define CONVERT_COPY(a,b,c) memcpy(G(a,32),(char *)b, (c)*4)-#define DATCTXCPY(a,b) memcpy(G(a,32),G(b,32),sizeof(pcre2_match_context_32))-#define FLD(a,b) G(a,32)->b-#define PATCTXCPY(a,b) memcpy(G(a,32),G(b,32),sizeof(pcre2_compile_context_32))-#define PCHARS(lv, p, offset, len, utf, f) \- lv = pchars32((PCRE2_SPTR32)(p)+offset, len, utf, f)-#define PCHARSV(p, offset, len, utf, f) \- (void)pchars32((PCRE2_SPTR32)(p)+offset, len, utf, f)-#define PCRE2_CALLOUT_ENUMERATE(a,b,c) \- a = pcre2_callout_enumerate_32(compiled_code32, \- (int (*)(struct pcre2_callout_enumerate_block_32 *, void *))b,c)-#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(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) \- a = pcre2_dfa_match_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),h,i,j)-#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))-#define PCRE2_JIT_MATCH(a,b,c,d,e,f,g,h) \- a = pcre2_jit_match_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),h)-#define PCRE2_JIT_STACK_CREATE(a,b,c,d) \- a = (PCRE2_JIT_STACK *)pcre2_jit_stack_create_32(b,c,d);-#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,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,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),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)-#define PCRE2_PRINTINT(a) pcre2_printint_32(compiled_code32,outfile,a)-#define PCRE2_SERIALIZE_DECODE(r,a,b,c,d) \- r = pcre2_serialize_decode_32((pcre2_code_32 **)a,b,c,G(d,32))-#define PCRE2_SERIALIZE_ENCODE(r,a,b,c,d,e) \- r = pcre2_serialize_encode_32((const pcre2_code_32 **)a,b,c,d,G(e,32))-#define PCRE2_SERIALIZE_FREE(a) pcre2_serialize_free_32(a)-#define PCRE2_SERIALIZE_GET_NUMBER_OF_CODES(r,a) \- r = pcre2_serialize_get_number_of_codes_32(a)-#define PCRE2_SET_CALLOUT(a,b,c) \- pcre2_set_callout_32(G(a,32),(int (*)(pcre2_callout_block_32 *, void *))b,c)-#define PCRE2_SET_CHARACTER_TABLES(a,b) pcre2_set_character_tables_32(G(a,32),b)-#define PCRE2_SET_COMPILE_RECURSION_GUARD(a,b,c) \- pcre2_set_compile_recursion_guard_32(G(a,32),b,c)-#define PCRE2_SET_DEPTH_LIMIT(a,b) pcre2_set_depth_limit_32(G(a,32),b)-#define PCRE2_SET_GLOB_ESCAPE(r,a,b) r = pcre2_set_glob_escape_32(G(a,32),b)-#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_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) \- pcre2_set_substitute_callout_32(G(a,32), \- (int (*)(pcre2_substitute_callout_block_32 *, void *))b,c)-#define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \- a = pcre2_substitute_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),h, \- (PCRE2_SPTR32)i,j,(PCRE2_UCHAR32 *)k,l)-#define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \- a = pcre2_substring_copy_byname_32(G(b,32),G(c,32),(PCRE2_UCHAR32 *)d,e)-#define PCRE2_SUBSTRING_COPY_BYNUMBER(a,b,c,d,e) \- a = pcre2_substring_copy_bynumber_32(G(b,32),c,(PCRE2_UCHAR32 *)d,e);-#define PCRE2_SUBSTRING_FREE(a) pcre2_substring_free_32((PCRE2_UCHAR32 *)a)-#define PCRE2_SUBSTRING_GET_BYNAME(a,b,c,d,e) \- a = pcre2_substring_get_byname_32(G(b,32),G(c,32),(PCRE2_UCHAR32 **)d,e)-#define PCRE2_SUBSTRING_GET_BYNUMBER(a,b,c,d,e) \- a = pcre2_substring_get_bynumber_32(G(b,32),c,(PCRE2_UCHAR32 **)d,e)-#define PCRE2_SUBSTRING_LENGTH_BYNAME(a,b,c,d) \- a = pcre2_substring_length_byname_32(G(b,32),G(c,32),d)-#define PCRE2_SUBSTRING_LENGTH_BYNUMBER(a,b,c,d) \- a = pcre2_substring_length_bynumber_32(G(b,32),c,d)-#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_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)-#define SETFLD(x,y,z) G(x,32)->y = z-#define SETFLDVEC(x,y,v,z) G(x,32)->y[v] = z-#define SETOP(x,y,z) G(x,32) z y-#define SETCASTPTR(x,y) G(x,32) = (uint32_t *)(y)-#define STRLEN(p) (int)strlen32((PCRE2_SPTR32)p)-#define SUB1(a,b) G(a,32)(G(b,32))-#define SUB2(a,b,c) G(a,32)(G(b,32),G(c,32))-#define TEST(x,r,y) (G(x,32) r (y))-#define TESTFLD(x,f,r,y) (G(x,32)->f r (y))--#endif--/* ----- End of mode-specific function call macros ----- */-----/*************************************************-* Alternate character tables *-*************************************************/--/* By default, the "tables" pointer in the compile context when calling-pcre2_compile() is not set (= NULL), thereby using the default tables of the-library. However, the tables modifier can be used to select alternate sets of-tables, for different kinds of testing. Note that the locale modifier also-adjusts the tables. */--/* This is the set of tables distributed as default with PCRE2. It recognizes-only ASCII characters. */--static const uint8_t tables1[] = {--/* This table is a lower casing table. */-- 0, 1, 2, 3, 4, 5, 6, 7,- 8, 9, 10, 11, 12, 13, 14, 15,- 16, 17, 18, 19, 20, 21, 22, 23,- 24, 25, 26, 27, 28, 29, 30, 31,- 32, 33, 34, 35, 36, 37, 38, 39,- 40, 41, 42, 43, 44, 45, 46, 47,- 48, 49, 50, 51, 52, 53, 54, 55,- 56, 57, 58, 59, 60, 61, 62, 63,- 64, 97, 98, 99,100,101,102,103,- 104,105,106,107,108,109,110,111,- 112,113,114,115,116,117,118,119,- 120,121,122, 91, 92, 93, 94, 95,- 96, 97, 98, 99,100,101,102,103,- 104,105,106,107,108,109,110,111,- 112,113,114,115,116,117,118,119,- 120,121,122,123,124,125,126,127,- 128,129,130,131,132,133,134,135,- 136,137,138,139,140,141,142,143,- 144,145,146,147,148,149,150,151,- 152,153,154,155,156,157,158,159,- 160,161,162,163,164,165,166,167,- 168,169,170,171,172,173,174,175,- 176,177,178,179,180,181,182,183,- 184,185,186,187,188,189,190,191,- 192,193,194,195,196,197,198,199,- 200,201,202,203,204,205,206,207,- 208,209,210,211,212,213,214,215,- 216,217,218,219,220,221,222,223,- 224,225,226,227,228,229,230,231,- 232,233,234,235,236,237,238,239,- 240,241,242,243,244,245,246,247,- 248,249,250,251,252,253,254,255,--/* This table is a case flipping table. */-- 0, 1, 2, 3, 4, 5, 6, 7,- 8, 9, 10, 11, 12, 13, 14, 15,- 16, 17, 18, 19, 20, 21, 22, 23,- 24, 25, 26, 27, 28, 29, 30, 31,- 32, 33, 34, 35, 36, 37, 38, 39,- 40, 41, 42, 43, 44, 45, 46, 47,- 48, 49, 50, 51, 52, 53, 54, 55,- 56, 57, 58, 59, 60, 61, 62, 63,- 64, 97, 98, 99,100,101,102,103,- 104,105,106,107,108,109,110,111,- 112,113,114,115,116,117,118,119,- 120,121,122, 91, 92, 93, 94, 95,- 96, 65, 66, 67, 68, 69, 70, 71,- 72, 73, 74, 75, 76, 77, 78, 79,- 80, 81, 82, 83, 84, 85, 86, 87,- 88, 89, 90,123,124,125,126,127,- 128,129,130,131,132,133,134,135,- 136,137,138,139,140,141,142,143,- 144,145,146,147,148,149,150,151,- 152,153,154,155,156,157,158,159,- 160,161,162,163,164,165,166,167,- 168,169,170,171,172,173,174,175,- 176,177,178,179,180,181,182,183,- 184,185,186,187,188,189,190,191,- 192,193,194,195,196,197,198,199,- 200,201,202,203,204,205,206,207,- 208,209,210,211,212,213,214,215,- 216,217,218,219,220,221,222,223,- 224,225,226,227,228,229,230,231,- 232,233,234,235,236,237,238,239,- 240,241,242,243,244,245,246,247,- 248,249,250,251,252,253,254,255,--/* This table contains bit maps for various character classes. Each map is 32-bytes long and the bits run from the least significant end of each byte. The-classes that have their own maps are: space, xdigit, digit, upper, lower, word,-graph, print, punct, and cntrl. Other classes are built from combinations. */-- 0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,-- 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,- 0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,-- 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,- 0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,- 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,-- 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,- 0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,-- 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,-- 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,-- 0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc,- 0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,-- 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,--/* This table identifies various classes of character by individual bits:- 0x01 white space character- 0x02 letter- 0x04 decimal digit- 0x08 hexadecimal digit- 0x10 alphanumeric or '_'- 0x80 regular expression metacharacter or binary zero-*/-- 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */- 0x00,0x01,0x01,0x01,0x01,0x01,0x00,0x00, /* 8- 15 */- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */- 0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /* - ' */- 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x00, /* ( - / */- 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */- 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x80, /* 8 - ? */- 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* @ - G */- 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* H - O */- 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* P - W */- 0x12,0x12,0x12,0x80,0x80,0x00,0x80,0x10, /* X - _ */- 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* ` - g */- 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* h - o */- 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* p - w */- 0x12,0x12,0x12,0x80,0x80,0x00,0x00,0x00, /* x -127 */- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */--/* This is a set of tables that came originally from a Windows user. It seems-to be at least an approximation of ISO 8859. In particular, there are-characters greater than 128 that are marked as spaces, letters, etc. */--static const uint8_t tables2[] = {-0,1,2,3,4,5,6,7,-8,9,10,11,12,13,14,15,-16,17,18,19,20,21,22,23,-24,25,26,27,28,29,30,31,-32,33,34,35,36,37,38,39,-40,41,42,43,44,45,46,47,-48,49,50,51,52,53,54,55,-56,57,58,59,60,61,62,63,-64,97,98,99,100,101,102,103,-104,105,106,107,108,109,110,111,-112,113,114,115,116,117,118,119,-120,121,122,91,92,93,94,95,-96,97,98,99,100,101,102,103,-104,105,106,107,108,109,110,111,-112,113,114,115,116,117,118,119,-120,121,122,123,124,125,126,127,-128,129,130,131,132,133,134,135,-136,137,138,139,140,141,142,143,-144,145,146,147,148,149,150,151,-152,153,154,155,156,157,158,159,-160,161,162,163,164,165,166,167,-168,169,170,171,172,173,174,175,-176,177,178,179,180,181,182,183,-184,185,186,187,188,189,190,191,-224,225,226,227,228,229,230,231,-232,233,234,235,236,237,238,239,-240,241,242,243,244,245,246,215,-248,249,250,251,252,253,254,223,-224,225,226,227,228,229,230,231,-232,233,234,235,236,237,238,239,-240,241,242,243,244,245,246,247,-248,249,250,251,252,253,254,255,-0,1,2,3,4,5,6,7,-8,9,10,11,12,13,14,15,-16,17,18,19,20,21,22,23,-24,25,26,27,28,29,30,31,-32,33,34,35,36,37,38,39,-40,41,42,43,44,45,46,47,-48,49,50,51,52,53,54,55,-56,57,58,59,60,61,62,63,-64,97,98,99,100,101,102,103,-104,105,106,107,108,109,110,111,-112,113,114,115,116,117,118,119,-120,121,122,91,92,93,94,95,-96,65,66,67,68,69,70,71,-72,73,74,75,76,77,78,79,-80,81,82,83,84,85,86,87,-88,89,90,123,124,125,126,127,-128,129,130,131,132,133,134,135,-136,137,138,139,140,141,142,143,-144,145,146,147,148,149,150,151,-152,153,154,155,156,157,158,159,-160,161,162,163,164,165,166,167,-168,169,170,171,172,173,174,175,-176,177,178,179,180,181,182,183,-184,185,186,187,188,189,190,191,-224,225,226,227,228,229,230,231,-232,233,234,235,236,237,238,239,-240,241,242,243,244,245,246,215,-248,249,250,251,252,253,254,223,-192,193,194,195,196,197,198,199,-200,201,202,203,204,205,206,207,-208,209,210,211,212,213,214,247,-216,217,218,219,220,221,222,255,-0,62,0,0,1,0,0,0,-0,0,0,0,0,0,0,0,-32,0,0,0,1,0,0,0,-0,0,0,0,0,0,0,0,-0,0,0,0,0,0,255,3,-126,0,0,0,126,0,0,0,-0,0,0,0,0,0,0,0,-0,0,0,0,0,0,0,0,-0,0,0,0,0,0,255,3,-0,0,0,0,0,0,0,0,-0,0,0,0,0,0,12,2,-0,0,0,0,0,0,0,0,-0,0,0,0,0,0,0,0,-254,255,255,7,0,0,0,0,-0,0,0,0,0,0,0,0,-255,255,127,127,0,0,0,0,-0,0,0,0,0,0,0,0,-0,0,0,0,254,255,255,7,-0,0,0,0,0,4,32,4,-0,0,0,128,255,255,127,255,-0,0,0,0,0,0,255,3,-254,255,255,135,254,255,255,7,-0,0,0,0,0,4,44,6,-255,255,127,255,255,255,127,255,-0,0,0,0,254,255,255,255,-255,255,255,255,255,255,255,127,-0,0,0,0,254,255,255,255,-255,255,255,255,255,255,255,255,-0,2,0,0,255,255,255,255,-255,255,255,255,255,255,255,127,-0,0,0,0,255,255,255,255,-255,255,255,255,255,255,255,255,-0,0,0,0,254,255,0,252,-1,0,0,248,1,0,0,120,-0,0,0,0,254,255,255,255,-0,0,128,0,0,0,128,0,-255,255,255,255,0,0,0,0,-0,0,0,0,0,0,0,128,-255,255,255,255,0,0,0,0,-0,0,0,0,0,0,0,0,-128,0,0,0,0,0,0,0,-0,1,1,0,1,1,0,0,-0,0,0,0,0,0,0,0,-0,0,0,0,0,0,0,0,-1,0,0,0,128,0,0,0,-128,128,128,128,0,0,128,0,-28,28,28,28,28,28,28,28,-28,28,0,0,0,0,0,128,-0,26,26,26,26,26,26,18,-18,18,18,18,18,18,18,18,-18,18,18,18,18,18,18,18,-18,18,18,128,128,0,128,16,-0,26,26,26,26,26,26,18,-18,18,18,18,18,18,18,18,-18,18,18,18,18,18,18,18,-18,18,18,128,128,0,0,0,-0,0,0,0,0,1,0,0,-0,0,0,0,0,0,0,0,-0,0,0,0,0,0,0,0,-0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,-0,0,18,0,0,0,0,0,-0,0,20,20,0,18,0,0,-0,20,18,0,0,0,0,0,-18,18,18,18,18,18,18,18,-18,18,18,18,18,18,18,18,-18,18,18,18,18,18,18,0,-18,18,18,18,18,18,18,18,-18,18,18,18,18,18,18,18,-18,18,18,18,18,18,18,18,-18,18,18,18,18,18,18,0,-18,18,18,18,18,18,18,18-};----#if !defined(VPCOMPAT) && !defined(HAVE_MEMMOVE)-/*************************************************-* Emulated memmove() for systems without it *-*************************************************/--/* This function can make use of bcopy() if it is available. Otherwise do it by-steam, as there are some non-Unix environments that lack both memmove() and-bcopy(). */--static void *-emulated_memmove(void *d, const void *s, size_t n)-{-#ifdef HAVE_BCOPY-bcopy(s, d, n);-return d;-#else-size_t i;-unsigned char *dest = (unsigned char *)d;-const unsigned char *src = (const unsigned char *)s;-if (dest > src)- {- dest += n;- src += n;- for (i = 0; i < n; ++i) *(--dest) = *(--src);- return (void *)dest;- }-else- {- for (i = 0; i < n; ++i) *dest++ = *src++;- return (void *)(dest - n);- }-#endif /* not HAVE_BCOPY */-}-#undef memmove-#define memmove(d,s,n) emulated_memmove(d,s,n)-#endif /* not VPCOMPAT && not HAVE_MEMMOVE */----#ifndef HAVE_STRERROR-/*************************************************-* Provide strerror() for non-ANSI libraries *-*************************************************/--/* Some old-fashioned systems (e.g. SunOS4) didn't have strerror() in their-libraries. They may no longer be around, but just in case, we can try to-provide the same facility by this simple alternative function. */--extern int sys_nerr;-extern char *sys_errlist[];--char *-strerror(int n)-{-if (n < 0 || n >= sys_nerr) return "unknown error number";-return sys_errlist[n];-}-#endif /* HAVE_STRERROR */----/*************************************************-* Local memory functions *-*************************************************/--/* Alternative memory functions, to test functionality. */--static void *my_malloc(size_t size, void *data)-{-void *block = malloc(size);-(void)data;-if (show_memory)- {- if (block == NULL)- {- fprintf(outfile, "** malloc() failed for %" SIZ_FORM "\n", size);- }- else- {- fprintf(outfile, "malloc %5" SIZ_FORM, size);-#ifdef DEBUG_SHOW_MALLOC_ADDRESSES- fprintf(outfile, " %p", block); /* Not portable */-#endif- if (malloclistptr < MALLOCLISTSIZE)- {- malloclist[malloclistptr] = block;- malloclistlength[malloclistptr++] = size;- }- else- fprintf(outfile, " (not remembered)");- fprintf(outfile, "\n");- }- }-return block;-}--static void my_free(void *block, void *data)-{-(void)data;-if (show_memory && block != NULL)- {- uint32_t i, j;- BOOL found = FALSE;-- fprintf(outfile, "free");- for (i = 0; i < malloclistptr; i++)- {- if (block == malloclist[i])- {- fprintf(outfile, " %5" SIZ_FORM, malloclistlength[i]);- malloclistptr--;- for (j = i; j < malloclistptr; j++)- {- malloclist[j] = malloclist[j+1];- malloclistlength[j] = malloclistlength[j+1];- }- found = TRUE;- break;- }- }- if (!found) fprintf(outfile, " unremembered block");-#ifdef DEBUG_SHOW_MALLOC_ADDRESSES- fprintf(outfile, " %p", block); /* Not portable */-#endif- fprintf(outfile, "\n");- }-free(block);-}----/*************************************************-* Callback function for stack guard *-*************************************************/--/* This is set up to be called from pcre2_compile() when the stackguard=n-modifier sets a value greater than zero. The test we do is whether the-parenthesis nesting depth is greater than the value set by the modifier.--Argument: the current parenthesis nesting depth-Returns: non-zero to kill the compilation-*/--static int-stack_guard(uint32_t depth, void *user_data)-{-(void)user_data;-return depth > pat_patctl.stackguard_test;-}---/*************************************************-* JIT memory callback *-*************************************************/--static PCRE2_JIT_STACK*-jit_callback(void *arg)-{-jit_was_used = TRUE;-return (PCRE2_JIT_STACK *)arg;-}---/*************************************************-* Convert UTF-8 character to code point *-*************************************************/--/* This function reads one or more bytes that represent a UTF-8 character,-and returns the codepoint of that character. Note that the function supports-the original UTF-8 definition of RFC 2279, allowing for values in the range 0-to 0x7fffffff, up to 6 bytes long. This makes it possible to generate-codepoints greater than 0x10ffff which are useful for testing PCRE2's error-checking, and also for generating 32-bit non-UTF data values above the UTF-limit.--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- -6 to 0 => malformed UTF-8 character at offset = (-return)-*/--static int-utf82ord(PCRE2_SPTR8 utf8bytes, PCRE2_SPTR8 end, uint32_t *vptr)-{-uint32_t c = *utf8bytes++;-uint32_t d = c;-int i, j, s;--for (i = -1; i < 6; i++) /* i is number of additional bytes */- {- if ((d & 0x80) == 0) break;- d <<= 1;- }--if (i == -1) { *vptr = c; return 1; } /* ascii character */-if (i == 0 || i == 6) return 0; /* invalid UTF-8 */--/* i now has a value in the range 1-5 */--s = 6*i;-d = (c & utf8_table3[i]) << s;--for (j = 0; j < i; j++)- {- if (utf8bytes >= end) return 0;-- c = *utf8bytes++;- if ((c & 0xc0) != 0x80) return -(j+1);- s -= 6;- d |= (c & 0x3f) << s;- }--/* Check that encoding was the correct unique one */--for (j = 0; j < utf8_table1_size; j++)- if (d <= (uint32_t)utf8_table1[j]) break;-if (j != i) return -(i+1);--/* Valid value */--*vptr = d;-return i+1;-}----/*************************************************-* Print one character *-*************************************************/--/* Print a single character either literally, or as a hex escape, and count how-many printed characters are used.--Arguments:- c the character- utf TRUE in UTF mode- f the FILE to print to, or NULL just to count characters--Returns: number of characters written-*/--static int-pchar(uint32_t c, BOOL utf, FILE *f)-{-int n = 0;-char tempbuffer[16];--if (PRINTOK(c))- {- if (f != NULL) fprintf(f, "%c", c);- return 1;- }--if (c < 0x100)- {- if (utf)- {- if (f != NULL) fprintf(f, "\\x{%02x}", c);- return 6;- }- else- {- if (f != NULL) fprintf(f, "\\x%02x", c);- return 4;- }- }--if (f != NULL) n = fprintf(f, "\\x{%02x}", c);- else n = sprintf(tempbuffer, "\\x{%02x}", c);--return n >= 0 ? n : 0;-}----#ifdef SUPPORT_PCRE2_16-/*************************************************-* Find length of 0-terminated 16-bit string *-*************************************************/--static size_t strlen16(PCRE2_SPTR16 p)-{-PCRE2_SPTR16 pp = p;-while (*pp != 0) pp++;-return (int)(pp - p);-}-#endif /* SUPPORT_PCRE2_16 */----#ifdef SUPPORT_PCRE2_32-/*************************************************-* Find length of 0-terminated 32-bit string *-*************************************************/--static size_t strlen32(PCRE2_SPTR32 p)-{-PCRE2_SPTR32 pp = p;-while (*pp != 0) pp++;-return (int)(pp - p);-}-#endif /* SUPPORT_PCRE2_32 */---#ifdef SUPPORT_PCRE2_8-/*************************************************-* Print 8-bit character string *-*************************************************/--/* Must handle UTF-8 strings in utf8 mode. Yields number of characters printed.-For printing *MARK strings, a negative length is given, indicating that the-length is in the first code unit. If handed a NULL file, this function just-counts chars without printing (because pchar() does that). */--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, end, &c);- if (rc > 0 && rc <= length + 1) /* Mustn't run over the end */- {- length -= rc - 1;- p += rc;- yield += pchar(c, utf, f);- continue;- }- }- c = *p++;- yield += pchar(c, utf, f);- }--return yield;-}-#endif---#ifdef SUPPORT_PCRE2_16-/*************************************************-* Print 16-bit character string *-*************************************************/--/* Must handle UTF-16 strings in utf mode. Yields number of characters printed.-For printing *MARK strings, a negative length is given, indicating that the-length is in the first code unit. If handed a NULL file, just counts chars-without printing. */--static int pchars16(PCRE2_SPTR16 p, int length, BOOL utf, FILE *f)-{-int yield = 0;-if (length < 0) length = *p++;-while (length-- > 0)- {- uint32_t c = *p++ & 0xffff;- if (utf && c >= 0xD800 && c < 0xDC00 && length > 0)- {- int d = *p & 0xffff;- if (d >= 0xDC00 && d <= 0xDFFF)- {- c = ((c & 0x3ff) << 10) + (d & 0x3ff) + 0x10000;- length--;- p++;- }- }- yield += pchar(c, utf, f);- }-return yield;-}-#endif /* SUPPORT_PCRE2_16 */----#ifdef SUPPORT_PCRE2_32-/*************************************************-* Print 32-bit character string *-*************************************************/--/* Must handle UTF-32 strings in utf mode. Yields number of characters printed.-For printing *MARK strings, a negative length is given, indicating that the-length is in the first code unit. If handed a NULL file, just counts chars-without printing. */--static int pchars32(PCRE2_SPTR32 p, int length, BOOL utf, FILE *f)-{-int yield = 0;-(void)(utf); /* Avoid compiler warning */-if (length < 0) length = *p++;-while (length-- > 0)- {- uint32_t c = *p++;- yield += pchar(c, utf, f);- }-return yield;-}-#endif /* SUPPORT_PCRE2_32 */-----/*************************************************-* Convert character value to UTF-8 *-*************************************************/--/* This function takes an integer value in the range 0 - 0x7fffffff-and encodes it as a UTF-8 character in 0 to 6 bytes. It is needed even when the-8-bit library is not supported, to generate UTF-8 output for non-ASCII-characters.--Arguments:- cvalue the character value- utf8bytes pointer to buffer for result - at least 6 bytes long--Returns: number of characters placed in the buffer-*/--static int-ord2utf8(uint32_t cvalue, uint8_t *utf8bytes)-{-int i, j;-if (cvalue > 0x7fffffffu)- return -1;-for (i = 0; i < utf8_table1_size; i++)- if (cvalue <= (uint32_t)utf8_table1[i]) break;-utf8bytes += i;-for (j = i; j > 0; j--)- {- *utf8bytes-- = 0x80 | (cvalue & 0x3f);- cvalue >>= 6;- }-*utf8bytes = utf8_table2[i] | cvalue;-return i + 1;-}----#ifdef SUPPORT_PCRE2_16-/*************************************************-* Convert string to 16-bit *-*************************************************/--/* In UTF mode the input is always interpreted as a string of UTF-8 bytes using-the original UTF-8 definition of RFC 2279, which allows for up to 6 bytes, and-code values from 0 to 0x7fffffff. However, values greater than the later UTF-limit of 0x10ffff cause an error. In non-UTF mode the input is interpreted as-UTF-8 if the utf8_input modifier is set, but an error is generated for values-greater than 0xffff.--If all the input bytes are ASCII, the space needed for a 16-bit string is-exactly double the 8-bit size. Otherwise, the size needed for a 16-bit string-is no more than double, because up to 0xffff uses no more than 3 bytes in UTF-8-but possibly 4 in UTF-16. Higher values use 4 bytes in UTF-8 and up to 4 bytes-in UTF-16. The result is always left in pbuffer16. Impose a minimum size to-save repeated re-sizing.--Note that this function does not object to surrogate values. This is-deliberate; it makes it possible to construct UTF-16 strings that are invalid,-for the purpose of testing that they are correctly faulted.--Arguments:- p points to a byte string- utf true in UTF mode- lenptr points to number of bytes in the string (excluding trailing zero)--Returns: 0 on success, with the length updated to the number of 16-bit- data items used (excluding the trailing zero)- OR -1 if a UTF-8 string is malformed- OR -2 if a value > 0x10ffff is encountered in UTF mode- OR -3 if a value > 0xffff is encountered when not in UTF mode-*/--static int-to16(uint8_t *p, int utf, PCRE2_SIZE *lenptr)-{-uint16_t *pp;-PCRE2_SIZE len = *lenptr;--if (pbuffer16_size < 2*len + 2)- {- if (pbuffer16 != NULL) free(pbuffer16);- pbuffer16_size = 2*len + 2;- if (pbuffer16_size < 4096) pbuffer16_size = 4096;- pbuffer16 = (uint16_t *)malloc(pbuffer16_size);- if (pbuffer16 == NULL)- {- fprintf(stderr, "pcre2test: malloc(%" SIZ_FORM ") failed for pbuffer16\n",- pbuffer16_size);- exit(1);- }- }--pp = pbuffer16;-if (!utf && (pat_patctl.control & CTL_UTF8_INPUT) == 0)- {- for (; len > 0; len--) *pp++ = *p++;- }-else while (len > 0)- {- uint32_t 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;- p += chlen;- len -= chlen;- if (c < 0x10000) *pp++ = c; else- {- c -= 0x10000;- *pp++ = 0xD800 | (c >> 10);- *pp++ = 0xDC00 | (c & 0x3ff);- }- }--*pp = 0;-*lenptr = pp - pbuffer16;-return 0;-}-#endif----#ifdef SUPPORT_PCRE2_32-/*************************************************-* Convert string to 32-bit *-*************************************************/--/* In UTF mode the input is always interpreted as a string of UTF-8 bytes using-the original UTF-8 definition of RFC 2279, which allows for up to 6 bytes, and-code values from 0 to 0x7fffffff. However, values greater than the later UTF-limit of 0x10ffff cause an error.--In non-UTF mode the input is interpreted as UTF-8 if the utf8_input modifier-is set, and no limit is imposed. There is special interpretation of the 0xff-byte (which is illegal in UTF-8) in this case: it causes the top bit of the-next character to be set. This provides a way of generating 32-bit characters-greater than 0x7fffffff.--If all the input bytes are ASCII, the space needed for a 32-bit string is-exactly four times the 8-bit size. Otherwise, the size needed for a 32-bit-string is no more than four times, because the number of characters must be-less than the number of bytes. The result is always left in pbuffer32. Impose a-minimum size to save repeated re-sizing.--Note that this function does not object to surrogate values. This is-deliberate; it makes it possible to construct UTF-32 strings that are invalid,-for the purpose of testing that they are correctly faulted.--Arguments:- p points to a byte string- utf true in UTF mode- lenptr points to number of bytes in the string (excluding trailing zero)--Returns: 0 on success, with the length updated to the number of 32-bit- data items used (excluding the trailing zero)- OR -1 if a UTF-8 string is malformed- OR -2 if a value > 0x10ffff is encountered in UTF mode-*/--static int-to32(uint8_t *p, int utf, PCRE2_SIZE *lenptr)-{-uint32_t *pp;-PCRE2_SIZE len = *lenptr;--if (pbuffer32_size < 4*len + 4)- {- if (pbuffer32 != NULL) free(pbuffer32);- pbuffer32_size = 4*len + 4;- if (pbuffer32_size < 8192) pbuffer32_size = 8192;- pbuffer32 = (uint32_t *)malloc(pbuffer32_size);- if (pbuffer32 == NULL)- {- fprintf(stderr, "pcre2test: malloc(%" SIZ_FORM ") failed for pbuffer32\n",- pbuffer32_size);- exit(1);- }- }--pp = pbuffer32;--if (!utf && (pat_patctl.control & CTL_UTF8_INPUT) == 0)- {- for (; len > 0; len--) *pp++ = *p++;- }--else while (len > 0)- {- 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, end, &c);- if (chlen <= 0) return -1;- if (utf && c > 0x10ffff) return -2;- p += chlen;- len -= chlen;- *pp++ = c | topbit;- }--*pp = 0;-*lenptr = pp - pbuffer32;-return 0;-}-#endif /* SUPPORT_PCRE2_32 */----/* This function is no longer used. Keep it around for a while, just in case it-needs to be re-instated. */--#ifdef NEVERNEVERNEVER--/*************************************************-* Move back by so many characters *-*************************************************/--/* Given a code unit offset in a subject string, move backwards by a number of-characters, and return the resulting offset.--Arguments:- subject pointer to the string- offset start offset- count count to move back by- utf TRUE if in UTF mode--Returns: a possibly changed offset-*/--static PCRE2_SIZE-backchars(uint8_t *subject, PCRE2_SIZE offset, uint32_t count, BOOL utf)-{-if (!utf || test_mode == PCRE32_MODE)- return (count >= offset)? 0 : (offset - count);--else if (test_mode == PCRE8_MODE)- {- PCRE2_SPTR8 pp = (PCRE2_SPTR8)subject + offset;- for (; count > 0 && pp > (PCRE2_SPTR8)subject; count--)- {- pp--;- while ((*pp & 0xc0) == 0x80) pp--;- }- return pp - (PCRE2_SPTR8)subject;- }--else /* 16-bit mode */- {- PCRE2_SPTR16 pp = (PCRE2_SPTR16)subject + offset;- for (; count > 0 && pp > (PCRE2_SPTR16)subject; count--)- {- pp--;- if ((*pp & 0xfc00) == 0xdc00) pp--;- }- return pp - (PCRE2_SPTR16)subject;- }-}-#endif /* NEVERNEVERNEVER */----/*************************************************-* Expand input buffers *-*************************************************/--/* This function doubles the size of the input buffer and the buffer for-keeping an 8-bit copy of patterns (pbuffer8), and copies the current buffers to-the new ones.--Arguments: none-Returns: nothing (aborts if malloc() fails)-*/--static void-expand_input_buffers(void)-{-int new_pbuffer8_size = 2*pbuffer8_size;-uint8_t *new_buffer = (uint8_t *)malloc(new_pbuffer8_size);-uint8_t *new_pbuffer8 = (uint8_t *)malloc(new_pbuffer8_size);--if (new_buffer == NULL || new_pbuffer8 == NULL)- {- fprintf(stderr, "pcre2test: malloc(%d) failed\n", new_pbuffer8_size);- exit(1);- }--memcpy(new_buffer, buffer, pbuffer8_size);-memcpy(new_pbuffer8, pbuffer8, pbuffer8_size);--pbuffer8_size = new_pbuffer8_size;--free(buffer);-free(pbuffer8);--buffer = new_buffer;-pbuffer8 = new_pbuffer8;-}----/*************************************************-* Read or extend an input line *-*************************************************/--/* Input lines are read into buffer, but both patterns and data lines can be-continued over multiple input lines. In addition, if the buffer fills up, we-want to automatically expand it so as to be able to handle extremely large-lines that are needed for certain stress tests, although this is less likely-now that there are repetition features for both patterns and data. When the-input buffer is expanded, the other two buffers must also be expanded likewise,-and the contents of pbuffer, which are a copy of the input for callouts, must-be preserved (for when expansion happens for a data line). This is not the most-optimal way of handling this, but hey, this is just a test program!--Arguments:- f the file to read- start where in buffer to start (this *must* be within buffer)- prompt for stdin or readline()--Returns: pointer to the start of new data- could be a copy of start, or could be moved- NULL if no data read and EOF reached-*/--static uint8_t *-extend_inputline(FILE *f, uint8_t *start, const char *prompt)-{-uint8_t *here = start;--for (;;)- {- size_t rlen = (size_t)(pbuffer8_size - (here - buffer));-- if (rlen > 1000)- {- size_t dlen;-- /* If libreadline or libedit support is required, use readline() to read a- line if the input is a terminal. Note that readline() removes the trailing- newline, so we must put it back again, to be compatible with fgets(). */--#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)- if (INTERACTIVE(f))- {- size_t len;- char *s = readline(prompt);- if (s == NULL) return (here == start)? NULL : start;- len = strlen(s);- if (len > 0) add_history(s);- if (len > rlen - 1) len = rlen - 1;- memcpy(here, s, len);- here[len] = '\n';- here[len+1] = 0;- free(s);- }- else-#endif-- /* Read the next line by normal means, prompting if the file is a tty. */-- {- if (INTERACTIVE(f)) printf("%s", prompt);- if (fgets((char *)here, rlen, f) == NULL)- return (here == start)? NULL : start;- }-- dlen = strlen((char *)here);- here += dlen;-- /* Check for end of line reached. Take care not to read data from before- start (dlen will be zero for a file starting with a binary zero). */-- if (here > start && here[-1] == '\n') return start;-- /* If we have not read a newline when reading a file, we have either filled- the buffer or reached the end of the file. We can detect the former by- checking that the string fills the buffer, and the latter by feof(). If- neither of these is true, it means we read a binary zero which has caused- strlen() to give a short length. This is a hard error because pcre2test- expects to work with C strings. */-- if (!INTERACTIVE(f) && dlen < rlen - 1 && !feof(f))- {- fprintf(outfile, "** Binary zero encountered in input\n");- fprintf(outfile, "** pcre2test run abandoned\n");- exit(1);- }- }-- else- {- size_t start_offset = start - buffer;- size_t here_offset = here - buffer;- expand_input_buffers();- start = buffer + start_offset;- here = buffer + here_offset;- }- }--/* Control never gets here */-}----/*************************************************-* Case-independent strncmp() function *-*************************************************/--/*-Arguments:- s first string- t second string- n number of characters to compare--Returns: < 0, = 0, or > 0, according to the comparison-*/--static int-strncmpic(const uint8_t *s, const uint8_t *t, int n)-{-while (n--)- {- int c = tolower(*s++) - tolower(*t++);- if (c != 0) return c;- }-return 0;-}----/*************************************************-* Scan the main modifier list *-*************************************************/--/* This function searches the modifier list for a long modifier name.--Argument:- p start of the name- lenp length of the name--Returns: an index in the modifier list, or -1 on failure-*/--static int-scan_modifiers(const uint8_t *p, unsigned int len)-{-int bot = 0;-int top = MODLISTCOUNT;--while (top > bot)- {- int mid = (bot + top)/2;- unsigned int mlen = strlen(modlist[mid].name);- int c = strncmp((char *)p, modlist[mid].name, (len < mlen)? len : mlen);- if (c == 0)- {- if (len == mlen) return mid;- c = (int)len - (int)mlen;- }- if (c > 0) bot = mid + 1; else top = mid;- }--return -1;--}----/*************************************************-* Check a modifer and find its field *-*************************************************/--/* This function is called when a modifier has been identified. We check that-it is allowed here and find the field that is to be changed.--Arguments:- m the modifier list entry- ctx CTX_PAT => pattern context- CTX_POPPAT => pattern context for popped pattern- CTX_DEFPAT => default pattern context- CTX_DAT => data context- CTX_DEFDAT => default data context- pctl point to pattern control block- dctl point to data control block- c a single character or 0--Returns: a field pointer or NULL-*/--static void *-check_modifier(modstruct *m, int ctx, patctl *pctl, datctl *dctl, uint32_t c)-{-void *field = NULL;-PCRE2_SIZE offset = m->offset;--if (restrict_for_perl_test) switch(m->which)- {- case MOD_PNDP:- case MOD_PATP:- case MOD_DATP:- case MOD_PDP:- break;-- default:- fprintf(outfile, "** '%s' is not allowed in a Perl-compatible test\n",- m->name);- return NULL;- }--switch (m->which)- {- case MOD_CTC: /* Compile context modifier */- if (ctx == CTX_DEFPAT) field = PTR(default_pat_context);- else if (ctx == CTX_PAT) field = PTR(pat_context);- break;-- case MOD_CTM: /* Match context modifier */- if (ctx == CTX_DEFDAT) field = PTR(default_dat_context);- else if (ctx == CTX_DAT) field = PTR(dat_context);- break;-- case MOD_DAT: /* Data line modifier */- case MOD_DATP: /* Allowed for Perl test */- if (dctl != NULL) field = dctl;- break;-- case MOD_PAT: /* Pattern modifier */- case MOD_PATP: /* Allowed for Perl test */- if (pctl != NULL) field = pctl;- break;-- case MOD_PD: /* Pattern or data line modifier */- case MOD_PDP: /* Ditto, allowed for Perl test */- case MOD_PND: /* Ditto, but not default pattern */- case MOD_PNDP: /* Ditto, allowed for Perl test */- if (dctl != NULL) field = dctl;- else if (pctl != NULL && (m->which == MOD_PD || m->which == MOD_PDP ||- ctx != CTX_DEFPAT))- field = pctl;- break;- }--if (field == NULL)- {- if (c == 0)- fprintf(outfile, "** '%s' is not valid here\n", m->name);- else- fprintf(outfile, "** /%c is not valid here\n", c);- return NULL;- }--return (char *)field + offset;-}----/*************************************************-* Decode a modifier list *-*************************************************/--/* A pointer to a control block is NULL when called in cases when that block is-not relevant. They are never all relevant in one call. At least one of patctl-and datctl is NULL. The second argument specifies which context to use for-modifiers that apply to contexts.--Arguments:- p point to modifier string- ctx CTX_PAT => pattern context- CTX_POPPAT => pattern context for popped pattern- CTX_DEFPAT => default pattern context- CTX_DAT => data context- CTX_DEFDAT => default data context- pctl point to pattern control block- dctl point to data control block--Returns: TRUE if successful decode, FALSE otherwise-*/--static BOOL-decode_modifiers(uint8_t *p, int ctx, patctl *pctl, datctl *dctl)-{-uint8_t *ep, *pp;-long li;-unsigned long uli;-BOOL first = TRUE;--for (;;)- {- void *field;- modstruct *m;- BOOL off = FALSE;- unsigned int i, len;- int index;- char *endptr;-- /* Skip white space and commas. */-- while (isspace(*p) || *p == ',') p++;- if (*p == 0) break;-- /* Find the end of the item; lose trailing whitespace at end of line. */-- for (ep = p; *ep != 0 && *ep != ','; ep++);- if (*ep == 0)- {- while (ep > p && isspace(ep[-1])) ep--;- *ep = 0;- }-- /* Remember if the first character is '-'. */-- if (*p == '-')- {- off = TRUE;- p++;- }-- /* Find the length of a full-length modifier name, and scan for it. */-- pp = p;- while (pp < ep && *pp != '=') pp++;- index = scan_modifiers(p, pp - p);-- /* If the first modifier is unrecognized, try to interpret it as a sequence- of single-character abbreviated modifiers. None of these modifiers have any- associated data. They just set options or control bits. */-- if (index < 0)- {- uint32_t cc;- uint8_t *mp = p;-- if (!first)- {- fprintf(outfile, "** Unrecognized modifier '%.*s'\n", (int)(ep-p), p);- if (ep - p == 1)- fprintf(outfile, "** Single-character modifiers must come first\n");- return FALSE;- }-- for (cc = *p; cc != ',' && cc != '\n' && cc != 0; cc = *(++p))- {- for (i = 0; i < C1MODLISTCOUNT; i++)- if (cc == c1modlist[i].onechar) break;-- if (i >= C1MODLISTCOUNT)- {- fprintf(outfile, "** Unrecognized modifier '%c' in '%.*s'\n",- *p, (int)(ep-mp), mp);- return FALSE;- }-- if (c1modlist[i].index >= 0)- {- index = c1modlist[i].index;- }-- else- {- index = scan_modifiers((uint8_t *)(c1modlist[i].fullname),- strlen(c1modlist[i].fullname));- if (index < 0)- {- fprintf(outfile, "** Internal error: single-character equivalent "- "modifier '%s' not found\n", c1modlist[i].fullname);- return FALSE;- }- c1modlist[i].index = index; /* Cache for next time */- }-- field = check_modifier(modlist + index, ctx, pctl, dctl, *p);- if (field == NULL) return FALSE;-- /* /x is a special case; a second appearance changes PCRE2_EXTENDED to- PCRE2_EXTENDED_MORE. */-- if (cc == 'x' && (*((uint32_t *)field) & PCRE2_EXTENDED) != 0)- {- *((uint32_t *)field) &= ~PCRE2_EXTENDED;- *((uint32_t *)field) |= PCRE2_EXTENDED_MORE;- }- else- *((uint32_t *)field) |= modlist[index].value;- }-- continue; /* With tne next (fullname) modifier */- }-- /* We have a match on a full-name modifier. Check for the existence of data- when needed. */-- m = modlist + index; /* Save typing */- if (m->type != MOD_CTL && m->type != MOD_OPT &&- (m->type != MOD_IND || *pp == '='))- {- if (*pp++ != '=')- {- fprintf(outfile, "** '=' expected after '%s'\n", m->name);- return FALSE;- }- if (off)- {- fprintf(outfile, "** '-' is not valid for '%s'\n", m->name);- return FALSE;- }- }-- /* These on/off types have no data. */-- else if (*pp != ',' && *pp != '\n' && *pp != ' ' && *pp != 0)- {- fprintf(outfile, "** Unrecognized modifier '%.*s'\n", (int)(ep-p), p);- return FALSE;- }-- /* Set the data length for those types that have data. Then find the field- that is to be set. If check_modifier() returns NULL, it has already output an- error message. */-- len = ep - pp;- field = check_modifier(m, ctx, pctl, dctl, 0);- if (field == NULL) return FALSE;-- /* Process according to data type. */-- switch (m->type)- {- case MOD_CTL:- case MOD_OPT:- if (off) *((uint32_t *)field) &= ~m->value;- else *((uint32_t *)field) |= m->value;- break;-- case MOD_BSR:- if (len == 7 && strncmpic(pp, (const uint8_t *)"default", 7) == 0)- {-#ifdef BSR_ANYCRLF- *((uint16_t *)field) = PCRE2_BSR_ANYCRLF;-#else- *((uint16_t *)field) = PCRE2_BSR_UNICODE;-#endif- if (ctx == CTX_PAT || ctx == CTX_DEFPAT) pctl->control2 &= ~CTL2_BSR_SET;- else dctl->control2 &= ~CTL2_BSR_SET;- }- else- {- if (len == 7 && strncmpic(pp, (const uint8_t *)"anycrlf", 7) == 0)- *((uint16_t *)field) = PCRE2_BSR_ANYCRLF;- else if (len == 7 && strncmpic(pp, (const uint8_t *)"unicode", 7) == 0)- *((uint16_t *)field) = PCRE2_BSR_UNICODE;- else goto INVALID_VALUE;- if (ctx == CTX_PAT || ctx == CTX_DEFPAT) pctl->control2 |= CTL2_BSR_SET;- else dctl->control2 |= CTL2_BSR_SET;- }- pp = ep;- break;-- case MOD_CHR: /* A single character */- *((uint32_t *)field) = *pp++;- break;-- case MOD_CON: /* A convert type/options list */- for (;; pp++)- {- uint8_t *colon = (uint8_t *)strchr((const char *)pp, ':');- len = ((colon != NULL && colon < ep)? colon:ep) - pp;- for (i = 0; i < convertlistcount; i++)- {- if (strncmpic(pp, (const uint8_t *)convertlist[i].name, len) == 0)- {- if (*((uint32_t *)field) == CONVERT_UNSET)- *((uint32_t *)field) = convertlist[i].option;- else- *((uint32_t *)field) |= convertlist[i].option;- break;- }- }- if (i >= convertlistcount) goto INVALID_VALUE;- pp += len;- if (*pp != ':') break;- }- break;-- case MOD_IN2: /* One or two unsigned integers */- if (!isdigit(*pp)) goto INVALID_VALUE;- uli = strtoul((const char *)pp, &endptr, 10);- if (U32OVERFLOW(uli)) goto INVALID_VALUE;- ((uint32_t *)field)[0] = (uint32_t)uli;- if (*endptr == ':')- {- uli = strtoul((const char *)endptr+1, &endptr, 10);- if (U32OVERFLOW(uli)) goto INVALID_VALUE;- ((uint32_t *)field)[1] = (uint32_t)uli;- }- else ((uint32_t *)field)[1] = 0;- pp = (uint8_t *)endptr;- break;-- /* PCRE2_SIZE_MAX is usually SIZE_MAX, which may be greater, equal to, or- less than ULONG_MAX. So first test for overflowing the long int, and then- test for overflowing PCRE2_SIZE_MAX if it is smaller than ULONG_MAX. */-- case MOD_SIZ: /* PCRE2_SIZE value */- if (!isdigit(*pp)) goto INVALID_VALUE;- uli = strtoul((const char *)pp, &endptr, 10);- if (uli == ULONG_MAX) goto INVALID_VALUE;-#if ULONG_MAX > PCRE2_SIZE_MAX- if (uli > PCRE2_SIZE_MAX) goto INVALID_VALUE;-#endif- *((PCRE2_SIZE *)field) = (PCRE2_SIZE)uli;- pp = (uint8_t *)endptr;- break;-- case MOD_IND: /* Unsigned integer with default */- if (len == 0)- {- *((uint32_t *)field) = (uint32_t)(m->value);- break;- }- /* Fall through */-- case MOD_INT: /* Unsigned integer */- if (!isdigit(*pp)) goto INVALID_VALUE;- uli = strtoul((const char *)pp, &endptr, 10);- if (U32OVERFLOW(uli)) goto INVALID_VALUE;- *((uint32_t *)field) = (uint32_t)uli;- pp = (uint8_t *)endptr;- break;-- case MOD_INS: /* Signed integer */- if (!isdigit(*pp) && *pp != '-') goto INVALID_VALUE;- li = strtol((const char *)pp, &endptr, 10);- if (S32OVERFLOW(li)) goto INVALID_VALUE;- *((int32_t *)field) = (int32_t)li;- pp = (uint8_t *)endptr;- break;-- case MOD_NL:- for (i = 0; i < sizeof(newlines)/sizeof(char *); i++)- if (len == strlen(newlines[i]) &&- strncmpic(pp, (const uint8_t *)newlines[i], len) == 0) break;- if (i >= sizeof(newlines)/sizeof(char *)) goto INVALID_VALUE;- if (i == 0)- {- *((uint16_t *)field) = NEWLINE_DEFAULT;- if (ctx == CTX_PAT || ctx == CTX_DEFPAT) pctl->control2 &= ~CTL2_NL_SET;- else dctl->control2 &= ~CTL2_NL_SET;- }- else- {- *((uint16_t *)field) = i;- if (ctx == CTX_PAT || ctx == CTX_DEFPAT) pctl->control2 |= CTL2_NL_SET;- else dctl->control2 |= CTL2_NL_SET;- }- pp = ep;- break;-- case MOD_NN: /* Name or (signed) number; may be several */- if (isdigit(*pp) || *pp == '-')- {- int ct = MAXCPYGET - 1;- int32_t value;- li = strtol((const char *)pp, &endptr, 10);- if (S32OVERFLOW(li)) goto INVALID_VALUE;- value = (int32_t)li;- field = (char *)field - m->offset + m->value; /* Adjust field ptr */- if (value >= 0) /* Add new number */- {- while (*((int32_t *)field) >= 0 && ct-- > 0) /* Skip previous */- field = (char *)field + sizeof(int32_t);- if (ct <= 0)- {- fprintf(outfile, "** Too many numeric '%s' modifiers\n", m->name);- return FALSE;- }- }- *((int32_t *)field) = value;- if (ct > 0) ((int32_t *)field)[1] = -1;- pp = (uint8_t *)endptr;- }-- /* Multiple strings are put end to end. */-- else- {- char *nn = (char *)field;- if (len > 0) /* Add new name */- {- if (len > MAX_NAME_SIZE)- {- fprintf(outfile, "** Group name in '%s' is too long\n", m->name);- return FALSE;- }- while (*nn != 0) nn += strlen(nn) + 1;- if (nn + len + 2 - (char *)field > LENCPYGET)- {- fprintf(outfile, "** Too many characters in named '%s' modifiers\n",- m->name);- return FALSE;- }- memcpy(nn, pp, len);- }- nn[len] = 0 ;- nn[len+1] = 0;- pp = ep;- }- break;-- case MOD_STR:- if (len + 1 > m->value)- {- fprintf(outfile, "** Overlong value for '%s' (max %d code units)\n",- m->name, m->value - 1);- return FALSE;- }- memcpy(field, pp, len);- ((uint8_t *)field)[len] = 0;- pp = ep;- break;- }-- if (*pp != ',' && *pp != '\n' && *pp != ' ' && *pp != 0)- {- fprintf(outfile, "** Comma expected after modifier item '%s'\n", m->name);- return FALSE;- }-- p = pp;- first = FALSE;-- if (ctx == CTX_POPPAT &&- (pctl->options != 0 ||- pctl->tables_id != 0 ||- pctl->locale[0] != 0 ||- (pctl->control & NOTPOP_CONTROLS) != 0))- {- fprintf(outfile, "** '%s' is not valid here\n", m->name);- return FALSE;- }- }--return TRUE;--INVALID_VALUE:-fprintf(outfile, "** Invalid value in '%.*s'\n", (int)(ep-p), p);-return FALSE;-}---/*************************************************-* Get info from a pattern *-*************************************************/--/* A wrapped call to pcre2_pattern_info(), applied to the current compiled-pattern.--Arguments:- what code for the required information- where where to put the answer- unsetok PCRE2_ERROR_UNSET is an "expected" result--Returns: the return from pcre2_pattern_info()-*/--static int-pattern_info(int what, void *where, BOOL unsetok)-{-int rc;-PCRE2_PATTERN_INFO(rc, compiled_code, what, NULL); /* Exercise the code */-PCRE2_PATTERN_INFO(rc, compiled_code, what, where);-if (rc >= 0) return 0;-if (rc != PCRE2_ERROR_UNSET || !unsetok)- {- fprintf(outfile, "Error %d from pcre2_pattern_info_%d(%d)\n", rc, test_mode,- what);- if (rc == PCRE2_ERROR_BADMODE)- fprintf(outfile, "Running in %d-bit mode but pattern was compiled in "- "%d-bit mode\n", test_mode,- 8 * (FLD(compiled_code, flags) & PCRE2_MODE_MASK));- }-return rc;-}----#ifdef SUPPORT_PCRE2_8-/*************************************************-* Show something in a list *-*************************************************/--/* This function just helps to keep the code that uses it tidier. It's used for-various lists of things where there needs to be introductory text before the-first item. As these calls are all in the POSIX-support code, they happen only-when 8-bit mode is supported. */--static void-prmsg(const char **msg, const char *s)-{-fprintf(outfile, "%s %s", *msg, s);-*msg = "";-}-#endif /* SUPPORT_PCRE2_8 */----/*************************************************-* Show control bits *-*************************************************/--/* Called for mutually exclusive controls and for unsupported POSIX controls.-Because the bits are unique, this can be used for both pattern and data control-words.--Arguments:- controls control bits- controls2 more control bits- before text to print before--Returns: nothing-*/--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%s%s",- before,- ((controls & CTL_AFTERTEXT) != 0)? " aftertext" : "",- ((controls & CTL_ALLAFTERTEXT) != 0)? " allaftertext" : "",- ((controls & CTL_ALLCAPTURES) != 0)? " allcaptures" : "",- ((controls & CTL_ALLUSEDTEXT) != 0)? " allusedtext" : "",- ((controls2 & CTL2_ALLVECTOR) != 0)? " allvector" : "",- ((controls & CTL_ALTGLOBAL) != 0)? " altglobal" : "",- ((controls & CTL_BINCODE) != 0)? " bincode" : "",- ((controls2 & CTL2_BSR_SET) != 0)? " bsr" : "",- ((controls & CTL_CALLOUT_CAPTURE) != 0)? " callout_capture" : "",- ((controls2 & CTL2_CALLOUT_EXTRA) != 0)? " callout_extra" : "",- ((controls & CTL_CALLOUT_INFO) != 0)? " callout_info" : "",- ((controls & CTL_CALLOUT_NONE) != 0)? " callout_none" : "",- ((controls2 & CTL2_CALLOUT_NO_WHERE) != 0)? " callout_no_where" : "",- ((controls & CTL_DFA) != 0)? " dfa" : "",- ((controls & CTL_EXPAND) != 0)? " expand" : "",- ((controls & CTL_FINDLIMITS) != 0)? " find_limits" : "",- ((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" : "",- ((controls & CTL_JITVERIFY) != 0)? " jitverify" : "",- ((controls & CTL_MARK) != 0)? " mark" : "",- ((controls & CTL_MEMORY) != 0)? " memory" : "",- ((controls2 & CTL2_NL_SET) != 0)? " newline" : "",- ((controls & CTL_NULLCONTEXT) != 0)? " null_context" : "",- ((controls2 & CTL2_NULL_REPLACEMENT) != 0)? " null_replacement" : "",- ((controls2 & CTL2_NULL_SUBJECT) != 0)? " null_subject" : "",- ((controls & CTL_POSIX) != 0)? " posix" : "",- ((controls & CTL_POSIX_NOSUB) != 0)? " posix_nosub" : "",- ((controls & CTL_PUSH) != 0)? " push" : "",- ((controls & CTL_PUSHCOPY) != 0)? " pushcopy" : "",- ((controls & CTL_PUSHTABLESCOPY) != 0)? " pushtablescopy" : "",- ((controls & CTL_STARTCHAR) != 0)? " startchar" : "",- ((controls2 & CTL2_SUBSTITUTE_CALLOUT) != 0)? " substitute_callout" : "",- ((controls2 & CTL2_SUBSTITUTE_EXTENDED) != 0)? " substitute_extended" : "",- ((controls2 & CTL2_SUBSTITUTE_LITERAL) != 0)? " substitute_literal" : "",- ((controls2 & CTL2_SUBSTITUTE_MATCHED) != 0)? " substitute_matched" : "",- ((controls2 & CTL2_SUBSTITUTE_OVERFLOW_LENGTH) != 0)? " substitute_overflow_length" : "",- ((controls2 & CTL2_SUBSTITUTE_REPLACEMENT_ONLY) != 0)? " substitute_replacement_only" : "",- ((controls2 & CTL2_SUBSTITUTE_UNKNOWN_UNSET) != 0)? " substitute_unknown_unset" : "",- ((controls2 & CTL2_SUBSTITUTE_UNSET_EMPTY) != 0)? " substitute_unset_empty" : "",- ((controls & CTL_USE_LENGTH) != 0)? " use_length" : "",- ((controls & CTL_UTF8_INPUT) != 0)? " utf8_input" : "",- ((controls & CTL_ZERO_TERMINATE) != 0)? " zero_terminate" : "");-}----/*************************************************-* Show compile options *-*************************************************/--/* Called from show_pattern_info() and for unsupported POSIX options.--Arguments:- options an options word- before text to print before- after text to print after--Returns: nothing-*/--static void-show_compile_options(uint32_t options, const char *before, const char *after)-{-if (options == 0) fprintf(outfile, "%s <none>%s", before, after);-else 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",- before,- ((options & PCRE2_ALT_BSUX) != 0)? " alt_bsux" : "",- ((options & PCRE2_ALT_CIRCUMFLEX) != 0)? " alt_circumflex" : "",- ((options & PCRE2_ALT_VERBNAMES) != 0)? " alt_verbnames" : "",- ((options & PCRE2_ALLOW_EMPTY_CLASS) != 0)? " allow_empty_class" : "",- ((options & PCRE2_ANCHORED) != 0)? " anchored" : "",- ((options & PCRE2_AUTO_CALLOUT) != 0)? " auto_callout" : "",- ((options & PCRE2_CASELESS) != 0)? " caseless" : "",- ((options & PCRE2_DOLLAR_ENDONLY) != 0)? " dollar_endonly" : "",- ((options & PCRE2_DOTALL) != 0)? " dotall" : "",- ((options & PCRE2_DUPNAMES) != 0)? " dupnames" : "",- ((options & PCRE2_ENDANCHORED) != 0)? " endanchored" : "",- ((options & PCRE2_EXTENDED) != 0)? " extended" : "",- ((options & PCRE2_EXTENDED_MORE) != 0)? " extended_more" : "",- ((options & PCRE2_FIRSTLINE) != 0)? " firstline" : "",- ((options & PCRE2_LITERAL) != 0)? " literal" : "",- ((options & PCRE2_MATCH_INVALID_UTF) != 0)? " match_invalid_utf" : "",- ((options & PCRE2_MATCH_UNSET_BACKREF) != 0)? " match_unset_backref" : "",- ((options & PCRE2_MULTILINE) != 0)? " multiline" : "",- ((options & PCRE2_NEVER_BACKSLASH_C) != 0)? " never_backslash_c" : "",- ((options & PCRE2_NEVER_UCP) != 0)? " never_ucp" : "",- ((options & PCRE2_NEVER_UTF) != 0)? " never_utf" : "",- ((options & PCRE2_NO_AUTO_CAPTURE) != 0)? " no_auto_capture" : "",- ((options & PCRE2_NO_AUTO_POSSESS) != 0)? " no_auto_possess" : "",- ((options & PCRE2_NO_DOTSTAR_ANCHOR) != 0)? " no_dotstar_anchor" : "",- ((options & PCRE2_NO_UTF_CHECK) != 0)? " no_utf_check" : "",- ((options & PCRE2_NO_START_OPTIMIZE) != 0)? " no_start_optimize" : "",- ((options & PCRE2_UCP) != 0)? " ucp" : "",- ((options & PCRE2_UNGREEDY) != 0)? " ungreedy" : "",- ((options & PCRE2_USE_OFFSET_LIMIT) != 0)? " use_offset_limit" : "",- ((options & PCRE2_UTF) != 0)? " utf" : "",- after);-}---/*************************************************-* Show compile extra options *-*************************************************/--/* Called from show_pattern_info() and for unsupported POSIX options.--Arguments:- options an options word- before text to print before- after text to print after--Returns: nothing-*/--static void-show_compile_extra_options(uint32_t options, const char *before,- const char *after)-{-if (options == 0) fprintf(outfile, "%s <none>%s", before, after);-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_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" : "",- after);-}----#ifdef SUPPORT_PCRE2_8-/*************************************************-* Show match options *-*************************************************/--/* Called for unsupported POSIX options. */--static void-show_match_options(uint32_t options)-{-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" : "",- ((options & PCRE2_NOTBOL) != 0)? " notbol" : "",- ((options & PCRE2_NOTEMPTY) != 0)? " notempty" : "",- ((options & PCRE2_NOTEMPTY_ATSTART) != 0)? " notempty_atstart" : "",- ((options & PCRE2_NOTEOL) != 0)? " noteol" : "",- ((options & PCRE2_PARTIAL_HARD) != 0)? " partial_hard" : "",- ((options & PCRE2_PARTIAL_SOFT) != 0)? " partial_soft" : "");-}-#endif /* SUPPORT_PCRE2_8 */----/*************************************************-* Show memory usage info for a pattern *-*************************************************/--static void-show_memory_info(void)-{-uint32_t name_count, name_entry_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. */--cblock_size = 0;-#ifdef SUPPORT_PCRE2_8-if (test_mode == PCRE8_MODE) cblock_size = sizeof(pcre2_real_code_8);-#endif-#ifdef SUPPORT_PCRE2_16-if (test_mode == PCRE16_MODE) cblock_size = sizeof(pcre2_real_code_16);-#endif-#ifdef SUPPORT_PCRE2_32-if (test_mode == PCRE32_MODE) cblock_size = sizeof(pcre2_real_code_32);-#endif--(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);--/* 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 : %" SIZ_FORM "\n", size);- }-}----/*************************************************-* Show frame size info for a pattern *-*************************************************/--static void-show_framesize(void)-{-PCRE2_SIZE frame_size;-(void)pattern_info(PCRE2_INFO_FRAMESIZE, &frame_size, FALSE);-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 *-*************************************************/--static BOOL-print_error_message(int errorcode, const char *before, const char *after)-{-int len;-PCRE2_GET_ERROR_MESSAGE(len, errorcode, pbuffer);-if (len < 0)- {- fprintf(outfile, "\n** pcre2test internal error: cannot interpret error "- "number\n** Unexpected return (%d) from pcre2_get_error_message()\n", len);- }-else- {- fprintf(outfile, "%s", before);- PCHARSV(CASTVAR(void *, pbuffer), 0, len, FALSE, outfile);- fprintf(outfile, "%s", after);- }-return len >= 0;-}---/*************************************************-* Callback function for callout enumeration *-*************************************************/--/* The only differences in the callout emumeration block for different code-unit widths are that the pointers to the subject, the most recent MARK, and a-callout argument string point to strings of the appropriate width. Casts can be-used to deal with this.--Argument:- cb pointer to enumerate block- callout_data user data--Returns: 0-*/--static int callout_callback(pcre2_callout_enumerate_block_8 *cb,- void *callout_data)-{-uint32_t i;-BOOL utf = (FLD(compiled_code, overall_options) & PCRE2_UTF) != 0;--(void)callout_data; /* Not currently displayed */--fprintf(outfile, "Callout ");-if (cb->callout_string != NULL)- {- uint32_t delimiter = CODE_UNIT(cb->callout_string, -1);- fprintf(outfile, "%c", delimiter);- PCHARSV(cb->callout_string, 0,- cb->callout_string_length, utf, outfile);- for (i = 0; callout_start_delims[i] != 0; i++)- if (delimiter == callout_start_delims[i])- {- delimiter = callout_end_delims[i];- break;- }- fprintf(outfile, "%c ", delimiter);- }-else fprintf(outfile, "%d ", cb->callout_number);--fprintf(outfile, "%.*s\n",- (int)((cb->next_item_length == 0)? 1 : cb->next_item_length),- pbuffer8 + cb->pattern_position);--return 0;-}----/*************************************************-* Show information about a pattern *-*************************************************/--/* This function is called after a pattern has been compiled if any of the-information-requesting controls have been set.--Arguments: none--Returns: PR_OK continue processing next line- PR_SKIP skip to a blank line- PR_ABEND abort the pcre2test run-*/--static int-show_pattern_info(void)-{-uint32_t compile_options, overall_options, extra_options;-BOOL utf = (FLD(compiled_code, overall_options) & PCRE2_UTF) != 0;--if ((pat_patctl.control & (CTL_BINCODE|CTL_FULLBINCODE)) != 0)- {- fprintf(outfile, "------------------------------------------------------------------\n");- PCRE2_PRINTINT((pat_patctl.control & CTL_FULLBINCODE) != 0);- }--if ((pat_patctl.control & CTL_INFO) != 0)- {- int rc;- void *nametable;- uint8_t *start_bits;- BOOL heap_limit_set, match_limit_set, depth_limit_set;- uint32_t backrefmax, bsr_convention, capture_count, first_ctype, first_cunit,- hasbackslashc, hascrorlf, jchanged, last_ctype, last_cunit, match_empty,- depth_limit, heap_limit, match_limit, minlength, nameentrysize, namecount,- newline_convention;-- /* Exercise the error route. */-- PCRE2_PATTERN_INFO(rc, compiled_code, 999, NULL);- (void)rc;-- /* These info requests may return PCRE2_ERROR_UNSET. */-- switch(pattern_info(PCRE2_INFO_HEAPLIMIT, &heap_limit, TRUE))- {- case 0:- heap_limit_set = TRUE;- break;-- case PCRE2_ERROR_UNSET:- heap_limit_set = FALSE;- break;-- default:- return PR_ABEND;- }-- switch(pattern_info(PCRE2_INFO_MATCHLIMIT, &match_limit, TRUE))- {- case 0:- match_limit_set = TRUE;- break;-- case PCRE2_ERROR_UNSET:- match_limit_set = FALSE;- break;-- default:- return PR_ABEND;- }-- switch(pattern_info(PCRE2_INFO_DEPTHLIMIT, &depth_limit, TRUE))- {- case 0:- depth_limit_set = TRUE;- break;-- case PCRE2_ERROR_UNSET:- depth_limit_set = FALSE;- break;-- default:- return PR_ABEND;- }-- /* These info requests should always succeed. */-- if (pattern_info(PCRE2_INFO_BACKREFMAX, &backrefmax, FALSE) +- pattern_info(PCRE2_INFO_BSR, &bsr_convention, FALSE) +- pattern_info(PCRE2_INFO_CAPTURECOUNT, &capture_count, FALSE) +- pattern_info(PCRE2_INFO_FIRSTBITMAP, &start_bits, FALSE) +- pattern_info(PCRE2_INFO_FIRSTCODEUNIT, &first_cunit, FALSE) +- pattern_info(PCRE2_INFO_FIRSTCODETYPE, &first_ctype, FALSE) +- pattern_info(PCRE2_INFO_HASBACKSLASHC, &hasbackslashc, FALSE) +- pattern_info(PCRE2_INFO_HASCRORLF, &hascrorlf, FALSE) +- pattern_info(PCRE2_INFO_JCHANGED, &jchanged, FALSE) +- pattern_info(PCRE2_INFO_LASTCODEUNIT, &last_cunit, FALSE) +- pattern_info(PCRE2_INFO_LASTCODETYPE, &last_ctype, FALSE) +- pattern_info(PCRE2_INFO_MATCHEMPTY, &match_empty, FALSE) +- pattern_info(PCRE2_INFO_MINLENGTH, &minlength, FALSE) +- pattern_info(PCRE2_INFO_NAMECOUNT, &namecount, FALSE) +- pattern_info(PCRE2_INFO_NAMEENTRYSIZE, &nameentrysize, FALSE) +- pattern_info(PCRE2_INFO_NAMETABLE, &nametable, FALSE) +- pattern_info(PCRE2_INFO_NEWLINE, &newline_convention, FALSE)- != 0)- return PR_ABEND;-- fprintf(outfile, "Capture group count = %d\n", capture_count);-- if (backrefmax > 0)- fprintf(outfile, "Max back reference = %d\n", backrefmax);-- if (maxlookbehind > 0)- fprintf(outfile, "Max lookbehind = %d\n", maxlookbehind);-- if (heap_limit_set)- fprintf(outfile, "Heap limit = %u\n", heap_limit);-- if (match_limit_set)- fprintf(outfile, "Match limit = %u\n", match_limit);-- if (depth_limit_set)- fprintf(outfile, "Depth limit = %u\n", depth_limit);-- if (namecount > 0)- {- fprintf(outfile, "Named capture groups:\n");- for (; namecount > 0; namecount--)- {- int imm2_size = test_mode == PCRE8_MODE ? 2 : 1;- uint32_t length = (uint32_t)STRLEN(nametable + imm2_size);- fprintf(outfile, " ");-- /* In UTF mode the name may be a UTF string containing non-ASCII- letters and digits. We must output it as a UTF-8 string. In non-UTF mode,- use the normal string printing functions, which use escapes for all- non-ASCII characters. */-- if (utf)- {-#ifdef SUPPORT_PCRE2_32- if (test_mode == PCRE32_MODE)- {- PCRE2_SPTR32 nameptr = (PCRE2_SPTR32)nametable + imm2_size;- while (*nameptr != 0)- {- uint8_t u8buff[6];- int len = ord2utf8(*nameptr++, u8buff);- fprintf(outfile, "%.*s", len, u8buff);- }- }-#endif-#ifdef SUPPORT_PCRE2_16- if (test_mode == PCRE16_MODE)- {- PCRE2_SPTR16 nameptr = (PCRE2_SPTR16)nametable + imm2_size;- while (*nameptr != 0)- {- int len;- uint8_t u8buff[6];- uint32_t c = *nameptr++ & 0xffff;- if (c >= 0xD800 && c < 0xDC00)- c = ((c & 0x3ff) << 10) + (*nameptr++ & 0x3ff) + 0x10000;- len = ord2utf8(c, u8buff);- fprintf(outfile, "%.*s", len, u8buff);- }- }-#endif-#ifdef SUPPORT_PCRE2_8- if (test_mode == PCRE8_MODE)- fprintf(outfile, "%s", (PCRE2_SPTR8)nametable + imm2_size);-#endif- }- else /* Not UTF mode */- {- PCHARSV(nametable, imm2_size, length, FALSE, outfile);- }-- while (length++ < nameentrysize - imm2_size) putc(' ', outfile);--#ifdef SUPPORT_PCRE2_32- if (test_mode == PCRE32_MODE)- fprintf(outfile, "%3d\n", (int)(((PCRE2_SPTR32)nametable)[0]));-#endif-#ifdef SUPPORT_PCRE2_16- if (test_mode == PCRE16_MODE)- fprintf(outfile, "%3d\n", (int)(((PCRE2_SPTR16)nametable)[0]));-#endif-#ifdef SUPPORT_PCRE2_8- if (test_mode == PCRE8_MODE)- fprintf(outfile, "%3d\n", (int)(- ((((PCRE2_SPTR8)nametable)[0]) << 8) | ((PCRE2_SPTR8)nametable)[1]));-#endif-- nametable = (void*)((PCRE2_SPTR8)nametable + nameentrysize * code_unit_size);- }- }-- if (hascrorlf) fprintf(outfile, "Contains explicit CR or LF match\n");- if (hasbackslashc) fprintf(outfile, "Contains \\C\n");- if (match_empty) fprintf(outfile, "May match empty string\n");-- pattern_info(PCRE2_INFO_ARGOPTIONS, &compile_options, FALSE);- pattern_info(PCRE2_INFO_ALLOPTIONS, &overall_options, FALSE);- pattern_info(PCRE2_INFO_EXTRAOPTIONS, &extra_options, FALSE);-- /* Remove UTF/UCP if they were there only because of forbid_utf. This saves- cluttering up the verification output of non-UTF test files. */-- if ((pat_patctl.options & PCRE2_NEVER_UTF) == 0)- {- compile_options &= ~PCRE2_NEVER_UTF;- overall_options &= ~PCRE2_NEVER_UTF;- }-- if ((pat_patctl.options & PCRE2_NEVER_UCP) == 0)- {- compile_options &= ~PCRE2_NEVER_UCP;- overall_options &= ~PCRE2_NEVER_UCP;- }-- if ((compile_options|overall_options) != 0)- {- if (compile_options == overall_options)- show_compile_options(compile_options, "Options:", "\n");- else- {- show_compile_options(compile_options, "Compile options:", "\n");- show_compile_options(overall_options, "Overall options:", "\n");- }- }-- if (extra_options != 0)- show_compile_extra_options(extra_options, "Extra options:", "\n");-- if (jchanged) fprintf(outfile, "Duplicate name status changes\n");-- if ((pat_patctl.control2 & CTL2_BSR_SET) != 0 ||- (FLD(compiled_code, flags) & PCRE2_BSR_SET) != 0)- fprintf(outfile, "\\R matches %s\n", (bsr_convention == PCRE2_BSR_UNICODE)?- "any Unicode newline" : "CR, LF, or CRLF");-- if ((FLD(compiled_code, flags) & PCRE2_NL_SET) != 0)- {- switch (newline_convention)- {- case PCRE2_NEWLINE_CR:- fprintf(outfile, "Forced newline is CR\n");- break;-- case PCRE2_NEWLINE_LF:- fprintf(outfile, "Forced newline is LF\n");- break;-- case PCRE2_NEWLINE_CRLF:- fprintf(outfile, "Forced newline is CRLF\n");- break;-- case PCRE2_NEWLINE_ANYCRLF:- fprintf(outfile, "Forced newline is CR, LF, or CRLF\n");- break;-- case PCRE2_NEWLINE_ANY:- fprintf(outfile, "Forced newline is any Unicode newline\n");- break;-- case PCRE2_NEWLINE_NUL:- fprintf(outfile, "Forced newline is NUL\n");- break;-- default:- break;- }- }-- if (first_ctype == 2)- {- fprintf(outfile, "First code unit at start or follows newline\n");- }- else if (first_ctype == 1)- {- const char *caseless =- ((FLD(compiled_code, flags) & PCRE2_FIRSTCASELESS) == 0)?- "" : " (caseless)";- if (PRINTOK(first_cunit))- fprintf(outfile, "First code unit = \'%c\'%s\n", first_cunit, caseless);- else- {- fprintf(outfile, "First code unit = ");- pchar(first_cunit, FALSE, outfile);- fprintf(outfile, "%s\n", caseless);- }- }- else if (start_bits != NULL)- {- int i;- int c = 24;- fprintf(outfile, "Starting code units: ");- for (i = 0; i < 256; i++)- {- if ((start_bits[i/8] & (1u << (i&7))) != 0)- {- if (c > 75)- {- fprintf(outfile, "\n ");- c = 2;- }- if (PRINTOK(i) && i != ' ')- {- fprintf(outfile, "%c ", i);- c += 2;- }- else- {- fprintf(outfile, "\\x%02x ", i);- c += 5;- }- }- }- fprintf(outfile, "\n");- }-- if (last_ctype != 0)- {- const char *caseless =- ((FLD(compiled_code, flags) & PCRE2_LASTCASELESS) == 0)?- "" : " (caseless)";- if (PRINTOK(last_cunit))- fprintf(outfile, "Last code unit = \'%c\'%s\n", last_cunit, caseless);- else- {- fprintf(outfile, "Last code unit = ");- pchar(last_cunit, FALSE, outfile);- fprintf(outfile, "%s\n", caseless);- }- }-- if ((FLD(compiled_code, overall_options) & PCRE2_NO_START_OPTIMIZE) == 0)- fprintf(outfile, "Subject length lower bound = %d\n", minlength);-- 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- {- 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- }- }--if ((pat_patctl.control & CTL_CALLOUT_INFO) != 0)- {- int errorcode;- PCRE2_CALLOUT_ENUMERATE(errorcode, callout_callback, 0);- if (errorcode != 0)- {- fprintf(outfile, "Callout enumerate failed: error %d: ", errorcode);- if (errorcode < 0 && !print_error_message(errorcode, "", "\n"))- return PR_ABEND;- return PR_SKIP;- }- }--return PR_OK;-}----/*************************************************-* Handle serialization error *-*************************************************/--/* Print an error message after a serialization failure.--Arguments:- rc the error code- msg an initial message for what failed--Returns: FALSE if print_error_message() fails-*/--static BOOL-serial_error(int rc, const char *msg)-{-fprintf(outfile, "%s failed: error %d: ", msg, rc);-return print_error_message(rc, "", "\n");-}----/*************************************************-* Open file for save/load commands *-*************************************************/--/* This function decodes the file name and opens the file.--Arguments:- buffptr point after the #command- mode open mode- fptr points to the FILE variable- name name of # command--Returns: PR_OK or PR_ABEND-*/--static int-open_file(uint8_t *buffptr, const char *mode, FILE **fptr, const char *name)-{-char *endf;-char *filename = (char *)buffptr;-while (isspace(*filename)) filename++;-endf = filename + strlen8(filename);-while (endf > filename && isspace(endf[-1])) endf--;--if (endf == filename)- {- fprintf(outfile, "** File name expected after %s\n", name);- return PR_ABEND;- }--*endf = 0;-*fptr = fopen((const char *)filename, mode);-if (*fptr == NULL)- {- fprintf(outfile, "** Failed to open '%s': %s\n", filename, strerror(errno));- return PR_ABEND;- }--return PR_OK;-}----/*************************************************-* Process command line *-*************************************************/--/* This function is called for lines beginning with # and a character that is-not ! or whitespace, when encountered between tests, which means that there is-no compiled pattern (compiled_code is NULL). The line is in buffer.--Arguments: none--Returns: PR_OK continue processing next line- PR_SKIP skip to a blank line- PR_ABEND abort the pcre2test run-*/--static int-process_command(void)-{-FILE *f;-PCRE2_SIZE serial_size;-size_t i;-int rc, cmd, cmdlen, yield;-uint16_t first_listed_newline;-const char *cmdname;-uint8_t *argptr, *serial;--yield = PR_OK;-cmd = CMD_UNKNOWN;-cmdlen = 0;--for (i = 0; i < cmdlistcount; i++)- {- cmdname = cmdlist[i].name;- cmdlen = strlen(cmdname);- if (strncmp((char *)(buffer+1), cmdname, cmdlen) == 0 &&- isspace(buffer[cmdlen+1]))- {- cmd = cmdlist[i].value;- break;- }- }--argptr = buffer + cmdlen + 1;--if (restrict_for_perl_test && cmd != CMD_PATTERN && cmd != CMD_SUBJECT)- {- fprintf(outfile, "** #%s is not allowed after #perltest\n", cmdname);- return PR_ABEND;- }--switch(cmd)- {- case CMD_UNKNOWN:- fprintf(outfile, "** Unknown command: %s", buffer);- break;-- case CMD_FORBID_UTF:- forbid_utf = PCRE2_NEVER_UTF|PCRE2_NEVER_UCP;- break;-- case CMD_PERLTEST:- restrict_for_perl_test = TRUE;- break;-- /* Set default pattern modifiers */-- case CMD_PATTERN:- (void)decode_modifiers(argptr, CTX_DEFPAT, &def_patctl, NULL);- if (def_patctl.jit == 0 && (def_patctl.control & CTL_JITVERIFY) != 0)- def_patctl.jit = JIT_DEFAULT;- break;-- /* Set default subject modifiers */-- case CMD_SUBJECT:- (void)decode_modifiers(argptr, CTX_DEFDAT, NULL, &def_datctl);- break;-- /* Check the default newline, and if not one of those listed, set up the- first one to be forced. An empty list unsets. */-- case CMD_NEWLINE_DEFAULT:- local_newline_default = 0; /* Unset */- first_listed_newline = 0;- for (;;)- {- while (isspace(*argptr)) argptr++;- if (*argptr == 0) break;- for (i = 1; i < sizeof(newlines)/sizeof(char *); i++)- {- size_t nlen = strlen(newlines[i]);- if (strncmpic(argptr, (const uint8_t *)newlines[i], nlen) == 0 &&- isspace(argptr[nlen]))- {- if (i == NEWLINE_DEFAULT) return PR_OK; /* Default is valid */- if (first_listed_newline == 0) first_listed_newline = i;- }- }- while (*argptr != 0 && !isspace(*argptr)) argptr++;- }- local_newline_default = first_listed_newline;- break;-- /* Pop or copy a compiled pattern off the stack. Modifiers that do not affect- the compiled pattern (e.g. to give information) are permitted. The default- pattern modifiers are ignored. */-- case CMD_POP:- case CMD_POPCOPY:- if (patstacknext <= 0)- {- fprintf(outfile, "** Can't pop off an empty stack\n");- return PR_SKIP;- }- memset(&pat_patctl, 0, sizeof(patctl)); /* Completely unset */- if (!decode_modifiers(argptr, CTX_POPPAT, &pat_patctl, NULL))- return PR_SKIP;-- if (cmd == CMD_POP)- {- SET(compiled_code, patstack[--patstacknext]);- }- else- {- PCRE2_CODE_COPY_FROM_VOID(compiled_code, patstack[patstacknext - 1]);- }-- if (pat_patctl.jit != 0)- {- PCRE2_JIT_COMPILE(jitrc, compiled_code, pat_patctl.jit);- }- if ((pat_patctl.control & CTL_MEMORY) != 0) show_memory_info();- if ((pat_patctl.control2 & CTL2_FRAMESIZE) != 0) show_framesize();- if ((pat_patctl.control & CTL_ANYINFO) != 0)- {- rc = show_pattern_info();- if (rc != PR_OK) return rc;- }- break;-- /* Save the stack of compiled patterns to a file, then empty the stack. */-- case CMD_SAVE:- if (patstacknext <= 0)- {- fprintf(outfile, "** No stacked patterns to save\n");- return PR_OK;- }-- rc = open_file(argptr+1, BINARY_OUTPUT_MODE, &f, "#save");- if (rc != PR_OK) return rc;-- PCRE2_SERIALIZE_ENCODE(rc, patstack, patstacknext, &serial, &serial_size,- general_context);- if (rc < 0)- {- fclose(f);- if (!serial_error(rc, "Serialization")) return PR_ABEND;- break;- }-- /* Write the length at the start of the file to make it straightforward to- get the right memory when re-loading. This saves having to read the file size- in different operating systems. To allow for different endianness (even- though reloading with the opposite endianness does not work), write the- length byte-by-byte. */-- for (i = 0; i < 4; i++) fputc((serial_size >> (i*8)) & 255, f);- if (fwrite(serial, 1, serial_size, f) != serial_size)- {- fprintf(outfile, "** Wrong return from fwrite()\n");- fclose(f);- return PR_ABEND;- }-- fclose(f);- PCRE2_SERIALIZE_FREE(serial);- while(patstacknext > 0)- {- SET(compiled_code, patstack[--patstacknext]);- SUB1(pcre2_code_free, compiled_code);- }- SET(compiled_code, NULL);- break;-- /* Load a set of compiled patterns from a file onto the stack */-- case CMD_LOAD:- rc = open_file(argptr+1, BINARY_INPUT_MODE, &f, "#load");- if (rc != PR_OK) return rc;-- serial_size = 0;- for (i = 0; i < 4; i++) serial_size |= fgetc(f) << (i*8);-- serial = malloc(serial_size);- if (serial == NULL)- {- fprintf(outfile, "** Failed to get memory (size %" SIZ_FORM ") for #load\n",- serial_size);- fclose(f);- return PR_ABEND;- }-- i = fread(serial, 1, serial_size, f);- fclose(f);-- if (i != serial_size)- {- fprintf(outfile, "** Wrong return from fread()\n");- yield = PR_ABEND;- }- else- {- PCRE2_SERIALIZE_GET_NUMBER_OF_CODES(rc, serial);- if (rc < 0)- {- if (!serial_error(rc, "Get number of codes")) yield = PR_ABEND;- }- else- {- if (rc + patstacknext > PATSTACKSIZE)- {- fprintf(outfile, "** Not enough space on pattern stack for %d pattern%s\n",- rc, (rc == 1)? "" : "s");- rc = PATSTACKSIZE - patstacknext;- fprintf(outfile, "** Decoding %d pattern%s\n", rc,- (rc == 1)? "" : "s");- }- PCRE2_SERIALIZE_DECODE(rc, patstack + patstacknext, rc, serial,- general_context);- if (rc < 0)- {- if (!serial_error(rc, "Deserialization")) yield = PR_ABEND;- }- else patstacknext += rc;- }- }-- free(serial);- break;-- /* Load a set of binary tables into tables3. */-- case CMD_LOADTABLES:- rc = open_file(argptr+1, BINARY_INPUT_MODE, &f, "#loadtables");- if (rc != PR_OK) return rc;-- if (tables3 == NULL)- {- (void)PCRE2_CONFIG(PCRE2_CONFIG_TABLES_LENGTH, &loadtables_length);- tables3 = malloc(loadtables_length);- }-- if (tables3 == NULL)- {- fprintf(outfile, "** Failed: malloc failed for #loadtables\n");- yield = PR_ABEND;- }- else if (fread(tables3, 1, loadtables_length, f) != loadtables_length)- {- fprintf(outfile, "** Wrong return from fread()\n");- yield = PR_ABEND;- }-- fclose(f);- break;- }--return yield;-}----/*************************************************-* Process pattern line *-*************************************************/--/* This function is called when the input buffer contains the start of a-pattern. The first character is known to be a valid delimiter. The pattern is-read, modifiers are interpreted, and a suitable local context is set up for-this test. The pattern is then compiled.--Arguments: none--Returns: PR_OK continue processing next line- PR_SKIP skip to a blank line- PR_ABEND abort the pcre2test run-*/--static int-process_pattern(void)-{-BOOL utf;-uint32_t k;-uint8_t *p = buffer;-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;-PCRE2_SIZE erroroffset;--/* The perltest.sh script supports only / as a delimiter. */--if (restrict_for_perl_test && delimiter != '/')- {- fprintf(outfile, "** The only allowed delimiter after #perltest is '/'\n");- return PR_ABEND;- }--/* Initialize the context and pattern/data controls for this test from the-defaults. */--PATCTXCPY(pat_context, default_pat_context);-memcpy(&pat_patctl, &def_patctl, sizeof(patctl));--/* Find the end of the pattern, reading more lines if necessary. */--for(;;)- {- while (*p != 0)- {- if (*p == '\\' && p[1] != 0) p++;- else if (*p == delimiter) break;- p++;- }- if (*p != 0) break;- if ((p = extend_inputline(infile, p, " > ")) == NULL)- {- fprintf(outfile, "** Unexpected EOF\n");- return PR_ABEND;- }- if (!INTERACTIVE(infile)) fprintf(outfile, "%s", (char *)p);- }--/* If the first character after the delimiter is backslash, make the pattern-end with backslash. This is purely to provide a way of testing for the error-message when a pattern ends with backslash. */--if (p[1] == '\\') *p++ = '\\';--/* Terminate the pattern at the delimiter, and compute the length. */--*p++ = 0;-patlen = p - buffer - 2;--/* Look for modifiers and options after the final delimiter. */--if (!decode_modifiers(p, CTX_PAT, &pat_patctl, NULL)) return PR_SKIP;--/* Note that the match_invalid_utf option also sets utf when passed to-pcre2_compile(). */--utf = (pat_patctl.options & (PCRE2_UTF|PCRE2_MATCH_INVALID_UTF)) != 0;--/* The utf8_input modifier is not allowed in 8-bit mode, and is mutually-exclusive with the utf modifier. */--if ((pat_patctl.control & CTL_UTF8_INPUT) != 0)- {- if (test_mode == PCRE8_MODE)- {- fprintf(outfile, "** The utf8_input modifier is not allowed in 8-bit mode\n");- return PR_SKIP;- }- if (utf)- {- fprintf(outfile, "** The utf and utf8_input modifiers are mutually exclusive\n");- return PR_SKIP;- }- }--/* The convert and posix modifiers are mutually exclusive. */--if (pat_patctl.convert_type != CONVERT_UNSET &&- (pat_patctl.control & CTL_POSIX) != 0)- {- fprintf(outfile, "** The convert and posix modifiers are mutually exclusive\n");- return PR_SKIP;- }--/* Check for mutually exclusive control modifiers. At present, these are all in-the first control word. */--for (k = 0; k < sizeof(exclusive_pat_controls)/sizeof(uint32_t); k++)- {- uint32_t c = pat_patctl.control & exclusive_pat_controls[k];- if (c != 0 && c != (c & (~c+1)))- {- show_controls(c, 0, "** Not allowed together:");- fprintf(outfile, "\n");- return PR_SKIP;- }- }--/* Assume full JIT compile for jitverify and/or jitfast if nothing else was-specified. */--if (pat_patctl.jit == 0 &&- (pat_patctl.control & (CTL_JITVERIFY|CTL_JITFAST)) != 0)- pat_patctl.jit = JIT_DEFAULT;--/* Now copy the pattern to pbuffer8 for use in 8-bit testing and for reflecting-in callouts. Convert from hex if requested (literal strings in quotes may be-present within the hexadecimal pairs). The result must necessarily be fewer-characters so will always fit in pbuffer8. */--if ((pat_patctl.control & CTL_HEXPAT) != 0)- {- uint8_t *pp, *pt;- uint32_t c, d;-- pt = pbuffer8;- for (pp = buffer + 1; *pp != 0; pp++)- {- if (isspace(*pp)) continue;- c = *pp++;-- /* Handle a literal substring */-- if (c == '\'' || c == '"')- {- uint8_t *pq = pp;- for (;; pp++)- {- d = *pp;- if (d == 0)- {- fprintf(outfile, "** Missing closing quote in hex pattern: "- "opening quote is at offset %" PTR_FORM ".\n", pq - buffer - 2);- return PR_SKIP;- }- if (d == c) break;- *pt++ = d;- }- }-- /* Expect a hex pair */-- else- {- if (!isxdigit(c))- {- fprintf(outfile, "** Unexpected non-hex-digit '%c' at offset %"- PTR_FORM " in hex pattern: quote missing?\n", c, pp - buffer - 2);- return PR_SKIP;- }- if (*pp == 0)- {- fprintf(outfile, "** Odd number of digits in hex pattern\n");- return PR_SKIP;- }- d = *pp;- if (!isxdigit(d))- {- fprintf(outfile, "** Unexpected non-hex-digit '%c' at offset %"- PTR_FORM " in hex pattern: quote missing?\n", d, pp - buffer - 1);- return PR_SKIP;- }- c = toupper(c);- d = toupper(d);- *pt++ = ((isdigit(c)? (c - '0') : (c - 'A' + 10)) << 4) +- (isdigit(d)? (d - '0') : (d - 'A' + 10));- }- }- *pt = 0;- patlen = pt - pbuffer8;- }--/* If not a hex string, process for repetition expansion if requested. */--else if ((pat_patctl.control & CTL_EXPAND) != 0)- {- uint8_t *pp, *pt;-- pt = pbuffer8;- for (pp = buffer + 1; *pp != 0; pp++)- {- uint8_t *pc = pp;- uint32_t count = 1;- size_t length = 1;-- /* Check for replication syntax; if not found, the defaults just set will- prevail and one character will be copied. */-- if (pp[0] == '\\' && pp[1] == '[')- {- uint8_t *pe;- for (pe = pp + 2; *pe != 0; pe++)- {- if (pe[0] == ']' && pe[1] == '{')- {- uint32_t clen = pe - pc - 2;- uint32_t i = 0;- unsigned long uli;- char *endptr;-- pe += 2;- uli = strtoul((const char *)pe, &endptr, 10);- if (U32OVERFLOW(uli))- {- fprintf(outfile, "** Pattern repeat count too large\n");- return PR_SKIP;- }-- i = (uint32_t)uli;- pe = (uint8_t *)endptr;- if (*pe == '}')- {- if (i == 0)- {- fprintf(outfile, "** Zero repeat not allowed\n");- return PR_SKIP;- }- pc += 2;- count = i;- length = clen;- pp = pe;- break;- }- }- }- }-- /* Add to output. If the buffer is too small expand it. The function for- expanding buffers always keeps buffer and pbuffer8 in step as far as their- size goes. */-- while (pt + count * length > pbuffer8 + pbuffer8_size)- {- size_t pc_offset = pc - buffer;- size_t pp_offset = pp - buffer;- size_t pt_offset = pt - pbuffer8;- expand_input_buffers();- pc = buffer + pc_offset;- pp = buffer + pp_offset;- pt = pbuffer8 + pt_offset;- }-- for (; count > 0; count--)- {- memcpy(pt, pc, length);- pt += length;- }- }-- *pt = 0;- patlen = pt - pbuffer8;-- if ((pat_patctl.control & CTL_INFO) != 0)- fprintf(outfile, "Expanded: %s\n", pbuffer8);- }--/* Neither hex nor expanded, just copy the input verbatim. */--else- {- strncpy((char *)pbuffer8, (char *)(buffer+1), patlen + 1);- }--/* Sort out character tables */--if (pat_patctl.locale[0] != 0)- {- if (pat_patctl.tables_id != 0)- {- fprintf(outfile, "** 'Locale' and 'tables' must not both be set\n");- return PR_SKIP;- }- if (setlocale(LC_CTYPE, (const char *)pat_patctl.locale) == NULL)- {- fprintf(outfile, "** Failed to set locale '%s'\n", pat_patctl.locale);- return PR_SKIP;- }- if (strcmp((const char *)pat_patctl.locale, (const char *)locale_name) != 0)- {- strcpy((char *)locale_name, (char *)pat_patctl.locale);- if (locale_tables != NULL)- {- PCRE2_MAKETABLES_FREE(general_context, (void *)locale_tables);- }- PCRE2_MAKETABLES(locale_tables, general_context);- }- use_tables = locale_tables;- }--else switch (pat_patctl.tables_id)- {- case 0: use_tables = NULL; break;- case 1: use_tables = tables1; break;- case 2: use_tables = tables2; break;-- case 3:- if (tables3 == NULL)- {- fprintf(outfile, "** 'Tables = 3' is invalid: binary tables have not "- "been loaded\n");- return PR_SKIP;- }- use_tables = tables3;- break;-- default:- fprintf(outfile, "** 'Tables' must specify 0, 1, 2, or 3.\n");- return PR_SKIP;- }--PCRE2_SET_CHARACTER_TABLES(pat_context, use_tables);--/* Set up for the stackguard test. */--if (pat_patctl.stackguard_test != 0)- {- PCRE2_SET_COMPILE_RECURSION_GUARD(pat_context, stack_guard, NULL);- }--/* Handle compiling via the POSIX interface, which doesn't support the-timing, showing, or debugging options, nor the ability to pass over-local character tables. Neither does it have 16-bit or 32-bit support. */--if ((pat_patctl.control & CTL_POSIX) != 0)- {-#ifdef SUPPORT_PCRE2_8- int rc;- int cflags = 0;- const char *msg = "** Ignored with POSIX interface:";-#endif-- if (test_mode != PCRE8_MODE)- {- fprintf(outfile, "** The POSIX interface is available only in 8-bit mode\n");- return PR_SKIP;- }--#ifdef SUPPORT_PCRE2_8- /* Check for features that the POSIX interface does not support. */-- if (pat_patctl.locale[0] != 0) prmsg(&msg, "locale");- if (pat_patctl.replacement[0] != 0) prmsg(&msg, "replace");- if (pat_patctl.tables_id != 0) prmsg(&msg, "tables");- if (pat_patctl.stackguard_test != 0) prmsg(&msg, "stackguard");- if (timeit > 0) prmsg(&msg, "timing");- if (pat_patctl.jit != 0) prmsg(&msg, "JIT");-- if ((pat_patctl.options & ~POSIX_SUPPORTED_COMPILE_OPTIONS) != 0)- {- show_compile_options(- pat_patctl.options & (uint32_t)(~POSIX_SUPPORTED_COMPILE_OPTIONS),- msg, "");- msg = "";- }-- if ((FLD(pat_context, extra_options) &- (uint32_t)(~POSIX_SUPPORTED_COMPILE_EXTRA_OPTIONS)) != 0)- {- show_compile_extra_options(- FLD(pat_context, extra_options) &- (uint32_t)(~POSIX_SUPPORTED_COMPILE_EXTRA_OPTIONS), msg, "");- msg = "";- }-- if ((pat_patctl.control & (uint32_t)(~POSIX_SUPPORTED_COMPILE_CONTROLS)) != 0 ||- (pat_patctl.control2 & (uint32_t)(~POSIX_SUPPORTED_COMPILE_CONTROLS2)) != 0)- {- show_controls(- pat_patctl.control & (uint32_t)(~POSIX_SUPPORTED_COMPILE_CONTROLS),- 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");-- if (msg[0] == 0) fprintf(outfile, "\n");-- /* Translate PCRE2 options to POSIX options and then compile. */-- if (utf) cflags |= REG_UTF;- if ((pat_patctl.control & CTL_POSIX_NOSUB) != 0) cflags |= REG_NOSUB;- if ((pat_patctl.options & PCRE2_UCP) != 0) cflags |= REG_UCP;- if ((pat_patctl.options & PCRE2_CASELESS) != 0) cflags |= REG_ICASE;- if ((pat_patctl.options & PCRE2_LITERAL) != 0) cflags |= REG_NOSPEC;- if ((pat_patctl.options & PCRE2_MULTILINE) != 0) cflags |= REG_NEWLINE;- if ((pat_patctl.options & PCRE2_DOTALL) != 0) cflags |= REG_DOTALL;- if ((pat_patctl.options & PCRE2_UNGREEDY) != 0) cflags |= REG_UNGREEDY;-- if ((pat_patctl.control & (CTL_HEXPAT|CTL_USE_LENGTH)) != 0)- {- preg.re_endp = (char *)pbuffer8 + patlen;- cflags |= REG_PEND;- }-- rc = regcomp(&preg, (char *)pbuffer8, cflags);-- /* Compiling failed */-- if (rc != 0)- {- size_t bsize, usize;- int psize;-- preg.re_pcre2_code = NULL; /* In case something was left in there */- preg.re_match_data = NULL;-- bsize = (pat_patctl.regerror_buffsize != 0)?- pat_patctl.regerror_buffsize : pbuffer8_size;- if (bsize + 8 < pbuffer8_size)- memcpy(pbuffer8 + bsize, "DEADBEEF", 8);- usize = regerror(rc, &preg, (char *)pbuffer8, bsize);-- /* Inside regerror(), snprintf() is used. If the buffer is too small, some- versions of snprintf() put a zero byte at the end, but others do not.- Therefore, we print a maximum of one less than the size of the buffer. */-- psize = (int)bsize - 1;- fprintf(outfile, "Failed: POSIX code %d: %.*s\n", rc, psize, pbuffer8);- if (usize > bsize)- {- fprintf(outfile, "** regerror() message truncated\n");- if (memcmp(pbuffer8 + bsize, "DEADBEEF", 8) != 0)- fprintf(outfile, "** regerror() buffer overflow\n");- }- return PR_SKIP;- }-- /* Compiling succeeded. Check that the values in the preg block are sensible.- It can happen that pcre2test is accidentally linked with a different POSIX- library which succeeds, but of course puts different things into preg. In- this situation, calling regfree() may cause a segfault (or invalid free() in- valgrind), so ensure that preg.re_pcre2_code is NULL, which suppresses the- calling of regfree() on exit. */-- if (preg.re_pcre2_code == NULL ||- ((pcre2_real_code_8 *)preg.re_pcre2_code)->magic_number != MAGIC_NUMBER ||- ((pcre2_real_code_8 *)preg.re_pcre2_code)->top_bracket != preg.re_nsub ||- preg.re_match_data == NULL ||- preg.re_cflags != cflags)- {- fprintf(outfile,- "** The regcomp() function returned zero (success), but the values set\n"- "** in the preg block are not valid for PCRE2. Check that pcre2test is\n"- "** linked with PCRE2's pcre2posix module (-lpcre2-posix) and not with\n"- "** some other POSIX regex library.\n**\n");- preg.re_pcre2_code = NULL;- return PR_ABEND;- }-- return PR_OK;-#endif /* SUPPORT_PCRE2_8 */- }--/* Handle compiling via the native interface. Controls that act later are-ignored with "push". Replacements are locked out. */--if ((pat_patctl.control & (CTL_PUSH|CTL_PUSHCOPY|CTL_PUSHTABLESCOPY)) != 0)- {- if (pat_patctl.replacement[0] != 0)- {- fprintf(outfile, "** Replacement text is not supported with 'push'.\n");- return PR_OK;- }- if ((pat_patctl.control & ~PUSH_SUPPORTED_COMPILE_CONTROLS) != 0 ||- (pat_patctl.control2 & ~PUSH_SUPPORTED_COMPILE_CONTROLS2) != 0)- {- show_controls(pat_patctl.control & ~PUSH_SUPPORTED_COMPILE_CONTROLS,- pat_patctl.control2 & ~PUSH_SUPPORTED_COMPILE_CONTROLS2,- "** Ignored when compiled pattern is stacked with 'push':");- fprintf(outfile, "\n");- }- if ((pat_patctl.control & PUSH_COMPILE_ONLY_CONTROLS) != 0 ||- (pat_patctl.control2 & PUSH_COMPILE_ONLY_CONTROLS2) != 0)- {- show_controls(pat_patctl.control & PUSH_COMPILE_ONLY_CONTROLS,- pat_patctl.control2 & PUSH_COMPILE_ONLY_CONTROLS2,- "** Applies only to compile when pattern is stacked with 'push':");- fprintf(outfile, "\n");- }- }--/* Convert the input in non-8-bit modes. */--errorcode = 0;--#ifdef SUPPORT_PCRE2_16-if (test_mode == PCRE16_MODE) errorcode = to16(pbuffer8, utf, &patlen);-#endif--#ifdef SUPPORT_PCRE2_32-if (test_mode == PCRE32_MODE) errorcode = to32(pbuffer8, utf, &patlen);-#endif--switch(errorcode)- {- case -1:- fprintf(outfile, "** Failed: invalid UTF-8 string cannot be "- "converted to %d-bit string\n", (test_mode == PCRE16_MODE)? 16:32);- return PR_SKIP;-- case -2:- fprintf(outfile, "** Failed: character value greater than 0x10ffff "- "cannot be converted to UTF\n");- return PR_SKIP;-- case -3:- fprintf(outfile, "** Failed: character value greater than 0xffff "- "cannot be converted to 16-bit in non-UTF mode\n");- return PR_SKIP;-- default:- break;- }--/* The pattern is now in pbuffer[8|16|32], with the length in code units in-patlen. If it is to be converted, copy the result back afterwards so that it-ends up back in the usual place. */--if (pat_patctl.convert_type != CONVERT_UNSET)- {- int rc;- int convert_return = PR_OK;- uint32_t convert_options = pat_patctl.convert_type;- void *converted_pattern;- PCRE2_SIZE converted_length;-- if (pat_patctl.convert_length != 0)- {- converted_length = pat_patctl.convert_length;- converted_pattern = malloc(converted_length * code_unit_size);- if (converted_pattern == NULL)- {- fprintf(outfile, "** Failed: malloc failed for converted pattern\n");- return PR_SKIP;- }- }- else converted_pattern = NULL; /* Let the library allocate */-- if (utf) convert_options |= PCRE2_CONVERT_UTF;- if ((pat_patctl.options & PCRE2_NO_UTF_CHECK) != 0)- convert_options |= PCRE2_CONVERT_NO_UTF_CHECK;-- CONCTXCPY(con_context, default_con_context);-- if (pat_patctl.convert_glob_escape != 0)- {- uint32_t escape = (pat_patctl.convert_glob_escape == '0')? 0 :- pat_patctl.convert_glob_escape;- PCRE2_SET_GLOB_ESCAPE(rc, con_context, escape);- if (rc != 0)- {- fprintf(outfile, "** Invalid glob escape '%c'\n",- pat_patctl.convert_glob_escape);- convert_return = PR_SKIP;- goto CONVERT_FINISH;- }- }-- if (pat_patctl.convert_glob_separator != 0)- {- PCRE2_SET_GLOB_SEPARATOR(rc, con_context, pat_patctl.convert_glob_separator);- if (rc != 0)- {- fprintf(outfile, "** Invalid glob separator '%c'\n",- pat_patctl.convert_glob_separator);- convert_return = PR_SKIP;- goto CONVERT_FINISH;- }- }-- PCRE2_PATTERN_CONVERT(rc, pbuffer, patlen, convert_options,- &converted_pattern, &converted_length, con_context);-- if (rc != 0)- {- fprintf(outfile, "** Pattern conversion error at offset %" SIZ_FORM ": ",- converted_length);- convert_return = print_error_message(rc, "", "\n")? PR_SKIP:PR_ABEND;- }-- /* Output the converted pattern, then copy it. */-- else- {- BOOL toolong;- PCHARSV(converted_pattern, 0, converted_length, utf, outfile);- fprintf(outfile, "\n");-- 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. */-- CONVERT_FINISH:- if (pat_patctl.convert_length != 0)- free(converted_pattern);- else- PCRE2_CONVERTED_PATTERN_FREE(converted_pattern);-- /* Return if conversion was unsuccessful. */-- if (convert_return != PR_OK) return convert_return;- }--/* By default we pass a zero-terminated pattern, but a length is passed if-"use_length" was specified or this is a hex pattern (which might contain binary-zeros). When valgrind is supported, arrange for the unused part of the buffer-to be marked as no access. */--valgrind_access_length = patlen;-if ((pat_patctl.control & (CTL_HEXPAT|CTL_USE_LENGTH)) == 0)- {- patlen = PCRE2_ZERO_TERMINATED;- valgrind_access_length += 1; /* For the terminating zero */- }--#ifdef SUPPORT_VALGRIND-#ifdef SUPPORT_PCRE2_8-if (test_mode == PCRE8_MODE && pbuffer8 != NULL)- {- VALGRIND_MAKE_MEM_NOACCESS(pbuffer8 + valgrind_access_length,- pbuffer8_size - valgrind_access_length);- }-#endif-#ifdef SUPPORT_PCRE2_16-if (test_mode == PCRE16_MODE && pbuffer16 != NULL)- {- VALGRIND_MAKE_MEM_NOACCESS(pbuffer16 + valgrind_access_length,- pbuffer16_size - valgrind_access_length*sizeof(uint16_t));- }-#endif-#ifdef SUPPORT_PCRE2_32-if (test_mode == PCRE32_MODE && pbuffer32 != NULL)- {- VALGRIND_MAKE_MEM_NOACCESS(pbuffer32 + valgrind_access_length,- pbuffer32_size - valgrind_access_length*sizeof(uint32_t));- }-#endif-#else /* Valgrind not supported */-(void)valgrind_access_length; /* Avoid compiler warning */-#endif--/* If #newline_default has been used and the library was not compiled with an-appropriate default newline setting, local_newline_default will be non-zero. We-use this if there is no explicit newline modifier. */--if ((pat_patctl.control2 & CTL2_NL_SET) == 0 && local_newline_default != 0)- {- SETFLD(pat_context, newline_convention, local_newline_default);- }--/* The null_context modifier is used to test calling pcre2_compile() with a-NULL context. */--use_pat_context = ((pat_patctl.control & CTL_NULLCONTEXT) != 0)?- NULL : PTR(pat_context);--/* If PCRE2_LITERAL is set, set use_forbid_utf zero because PCRE2_NEVER_UTF-and PCRE2_NEVER_UCP are invalid with it. */--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)- {- int i;- clock_t time_taken = 0;- for (i = 0; i < timeit; i++)- {- clock_t start_time = clock();- PCRE2_COMPILE(compiled_code, use_pbuffer, patlen,- pat_patctl.options|use_forbid_utf, &errorcode, &erroroffset,- use_pat_context);- time_taken += clock() - start_time;- if (TEST(compiled_code, !=, NULL))- { SUB1(pcre2_code_free, compiled_code); }- }- total_compile_time += time_taken;- 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, 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. */--if (TEST(compiled_code, !=, NULL) && pat_patctl.jit != 0)- {- if (timeit > 0)- {- int i;- clock_t time_taken = 0;-- for (i = 0; i < timeit; i++)- {- clock_t start_time;- SUB1(pcre2_code_free, compiled_code);- 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;- 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;- }- }- }--/* Compilation failed; go back for another re, skipping to blank line-if non-interactive. */--if (TEST(compiled_code, ==, NULL))- {- fprintf(outfile, "Failed: error %d at offset %d: ", errorcode,- (int)erroroffset);- if (!print_error_message(errorcode, "", "\n")) return PR_ABEND;- return PR_SKIP;- }--/* If forbid_utf is non-zero, we are running a non-UTF test. UTF and UCP are-locked out at compile time, but we must also check for occurrences of \P, \p,-and \X, which are only supported when Unicode is supported. */--if (forbid_utf != 0)- {- if ((FLD(compiled_code, flags) & PCRE2_HASBKPORX) != 0)- {- fprintf(outfile, "** \\P, \\p, and \\X are not allowed after the "- "#forbid_utf command\n");- return PR_SKIP;- }- }--/* Remember the maximum lookbehind, for partial matching. */--if (pattern_info(PCRE2_INFO_MAXLOOKBEHIND, &maxlookbehind, FALSE) != 0)- return PR_ABEND;--/* Remember the number of captures. */--if (pattern_info(PCRE2_INFO_CAPTURECOUNT, &maxcapcount, FALSE) < 0)- return PR_ABEND;--/* If an explicit newline modifier was given, set the information flag in the-pattern so that it is preserved over push/pop. */--if ((pat_patctl.control2 & CTL2_NL_SET) != 0)- {- SETFLD(compiled_code, flags, FLD(compiled_code, flags) | PCRE2_NL_SET);- }--/* Output code size and other information if requested. */--if ((pat_patctl.control & CTL_MEMORY) != 0) show_memory_info();-if ((pat_patctl.control2 & CTL2_FRAMESIZE) != 0) show_framesize();-if ((pat_patctl.control & CTL_ANYINFO) != 0)- {- int rc = show_pattern_info();- if (rc != PR_OK) return rc;- }--/* The "push" control requests that the compiled pattern be remembered on a-stack. This is mainly for testing the serialization functionality. */--if ((pat_patctl.control & CTL_PUSH) != 0)- {- if (patstacknext >= PATSTACKSIZE)- {- fprintf(outfile, "** Too many pushed patterns (max %d)\n", PATSTACKSIZE);- return PR_ABEND;- }- patstack[patstacknext++] = PTR(compiled_code);- SET(compiled_code, NULL);- }--/* The "pushcopy" and "pushtablescopy" controls are similar, but push a-copy of the pattern, the latter with a copy of its character tables. This tests-the pcre2_code_copy() and pcre2_code_copy_with_tables() functions. */--if ((pat_patctl.control & (CTL_PUSHCOPY|CTL_PUSHTABLESCOPY)) != 0)- {- if (patstacknext >= PATSTACKSIZE)- {- fprintf(outfile, "** Too many pushed patterns (max %d)\n", PATSTACKSIZE);- return PR_ABEND;- }- if ((pat_patctl.control & CTL_PUSHCOPY) != 0)- {- PCRE2_CODE_COPY_TO_VOID(patstack[patstacknext++], compiled_code);- }- else- {- PCRE2_CODE_COPY_WITH_TABLES_TO_VOID(patstack[patstacknext++],- compiled_code); }- }--return PR_OK;-}----/*************************************************-* Check heap, match or depth limit *-*************************************************/--/* This is used for DFA, normal, and JIT fast matching. For DFA matching it-should only be called with the third argument set to PCRE2_ERROR_DEPTHLIMIT.--Arguments:- pp the subject string- ulen length of subject or PCRE2_ZERO_TERMINATED- errnumber defines which limit to test- msg string to include in final message--Returns: the return from the final match function call-*/--static int-check_match_limit(uint8_t *pp, PCRE2_SIZE ulen, int errnumber, const char *msg)-{-int capcount;-uint32_t min = 0;-uint32_t mid = 64;-uint32_t max = UINT32_MAX;--PCRE2_SET_MATCH_LIMIT(dat_context, max);-PCRE2_SET_DEPTH_LIMIT(dat_context, max);-PCRE2_SET_HEAP_LIMIT(dat_context, max);--for (;;)- {- 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);- }- else- {- 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;- if (dfa_workspace == NULL)- dfa_workspace = (int *)malloc(DFA_WS_DIMENSION*sizeof(int));- if (dfa_matched++ == 0)- dfa_workspace[0] = -1; /* To catch bad restart */- PCRE2_DFA_MATCH(capcount, compiled_code, pp, ulen, dat_datctl.offset,- dat_datctl.options, match_data,- PTR(dat_context), dfa_workspace, DFA_WS_DIMENSION);- }-- else if ((pat_patctl.control & CTL_JITFAST) != 0)- PCRE2_JIT_MATCH(capcount, compiled_code, pp, ulen, dat_datctl.offset,- dat_datctl.options, match_data, PTR(dat_context));-- else- {- PCRE2_MATCH(capcount, compiled_code, pp, ulen, dat_datctl.offset,- dat_datctl.options, match_data, PTR(dat_context));- }-- if (capcount == errnumber)- {- if ((mid & 0x80000000u) != 0)- {- fprintf(outfile, "Can't find minimum %s limit: check pattern for "- "restriction\n", msg);- break;- }-- min = mid;- mid = (mid == max - 1)? max : (max != UINT32_MAX)? (min + max)/2 : mid*2;- }- else if (capcount >= 0 ||- capcount == PCRE2_ERROR_NOMATCH ||- capcount == PCRE2_ERROR_PARTIAL)- {- /* If we've not hit the error with a heap limit less than the size of the- initial stack frame vector (for pcre2_match()) or the initial stack- workspace vector (for pcre2_dfa_match()), the heap is not being used, so- the minimum limit is zero; there's no need to go on. The other limits are- always greater than zero. */-- if (errnumber == PCRE2_ERROR_HEAPLIMIT && mid < stack_start)- {- fprintf(outfile, "Minimum %s limit = 0\n", msg);- break;- }- if (mid == min + 1)- {- fprintf(outfile, "Minimum %s limit = %d\n", msg, mid);- break;- }- max = mid;- mid = (min + max)/2;- }- else break; /* Some other error */- }--return capcount;-}----/*************************************************-* Substitute callout function *-*************************************************/--/* Called from pcre2_substitute() when the substitute_callout modifier is set.-Print out the data that is passed back. The substitute callout block is-identical for all code unit widths, so we just pick one.--Arguments:- scb pointer to substitute callout block- data_ptr callout data--Returns: nothing-*/--static int-substitute_callout_function(pcre2_substitute_callout_block_8 *scb,- void *data_ptr)-{-int yield = 0;-BOOL utf = (FLD(compiled_code, overall_options) & PCRE2_UTF) != 0;-(void)data_ptr; /* Not used */--fprintf(outfile, "%2d(%d) Old %" SIZ_FORM " %" SIZ_FORM " \"",- scb->subscount, scb->oveccount,- scb->ovector[0], scb->ovector[1]);--PCHARSV(scb->input, scb->ovector[0], scb->ovector[1] - scb->ovector[0],- utf, outfile);--fprintf(outfile, "\" New %" SIZ_FORM " %" SIZ_FORM " \"",- scb->output_offsets[0], scb->output_offsets[1]);--PCHARSV(scb->output, scb->output_offsets[0],- scb->output_offsets[1] - scb->output_offsets[0], utf, outfile);--if (scb->subscount == dat_datctl.substitute_stop)- {- yield = -1;- fprintf(outfile, " STOPPED");- }-else if (scb->subscount == dat_datctl.substitute_skip)- {- yield = +1;- fprintf(outfile, " SKIPPED");- }--fprintf(outfile, "\"\n");-return yield;-}---/*************************************************-* Callout function *-*************************************************/--/* Called from a PCRE2 library as a result of the (?C) item. We print out where-we are in the match (unless suppressed). Yield zero unless more callouts than-the fail count, or the callout data is not zero. The only differences in the-callout block for different code unit widths are that the pointers to the-subject, the most recent MARK, and a callout argument string point to strings-of the appropriate width. Casts can be used to deal with this.--Arguments:- cb a pointer to a callout block- callout_data_ptr the provided callout data--Returns: 0 or 1 or an error, as determined by settings-*/--static int-callout_function(pcre2_callout_block_8 *cb, void *callout_data_ptr)-{-FILE *f, *fdefault;-uint32_t i, pre_start, post_start, subject_length;-PCRE2_SIZE current_position;-BOOL utf = (FLD(compiled_code, overall_options) & PCRE2_UTF) != 0;-BOOL callout_capture = (dat_datctl.control & CTL_CALLOUT_CAPTURE) != 0;-BOOL callout_where = (dat_datctl.control2 & CTL2_CALLOUT_NO_WHERE) == 0;--/* The FILE f is used for echoing the subject string if it is non-NULL. This-happens only once in simple cases, but we want to repeat after any additional-output caused by CALLOUT_EXTRA. */--fdefault = (!first_callout && !callout_capture && cb->callout_string == NULL)?- NULL : outfile;--if ((dat_datctl.control2 & CTL2_CALLOUT_EXTRA) != 0)- {- f = outfile;- switch (cb->callout_flags)- {- case PCRE2_CALLOUT_BACKTRACK:- fprintf(f, "Backtrack\n");- break;-- case PCRE2_CALLOUT_STARTMATCH|PCRE2_CALLOUT_BACKTRACK:- fprintf(f, "Backtrack\nNo other matching paths\n");- /* Fall through */-- case PCRE2_CALLOUT_STARTMATCH:- fprintf(f, "New match attempt\n");- break;-- default:- f = fdefault;- break;- }- }-else f = fdefault;--/* For a callout with a string argument, show the string first because there-isn't a tidy way to fit it in the rest of the data. */--if (cb->callout_string != NULL)- {- uint32_t delimiter = CODE_UNIT(cb->callout_string, -1);- fprintf(outfile, "Callout (%" SIZ_FORM "): %c",- cb->callout_string_offset, delimiter);- PCHARSV(cb->callout_string, 0,- cb->callout_string_length, utf, outfile);- for (i = 0; callout_start_delims[i] != 0; i++)- if (delimiter == callout_start_delims[i])- {- delimiter = callout_end_delims[i];- break;- }- fprintf(outfile, "%c", delimiter);- if (!callout_capture) fprintf(outfile, "\n");- }--/* Show captured strings if required */--if (callout_capture)- {- if (cb->callout_string == NULL)- fprintf(outfile, "Callout %d:", cb->callout_number);- fprintf(outfile, " last capture = %d\n", cb->capture_last);- for (i = 2; i < cb->capture_top * 2; i += 2)- {- fprintf(outfile, "%2d: ", i/2);- if (cb->offset_vector[i] == PCRE2_UNSET)- fprintf(outfile, "<unset>");- else- {- PCHARSV(cb->subject, cb->offset_vector[i],- cb->offset_vector[i+1] - cb->offset_vector[i], utf, f);- }- fprintf(outfile, "\n");- }- }--/* Unless suppressed, re-print the subject in canonical form (with escapes for-non-printing characters), the first time, or if giving full details. On-subsequent calls in the same match, we use PCHARS() just to find the printed-lengths of the substrings. */--if (callout_where)- {- if (f != NULL) fprintf(f, "--->");-- /* The subject before the match start. */-- PCHARS(pre_start, cb->subject, 0, cb->start_match, utf, f);-- /* If a lookbehind is involved, the current position may be earlier than the- match start. If so, use the match start instead. */-- current_position = (cb->current_position >= cb->start_match)?- cb->current_position : cb->start_match;-- /* The subject between the match start and the current position. */-- PCHARS(post_start, cb->subject, cb->start_match,- current_position - cb->start_match, utf, f);-- /* Print from the current position to the end. */-- PCHARSV(cb->subject, current_position, cb->subject_length - current_position,- utf, f);-- /* Calculate the total subject printed length (no print). */-- PCHARS(subject_length, cb->subject, 0, cb->subject_length, utf, NULL);-- if (f != NULL) fprintf(f, "\n");-- /* For automatic callouts, show the pattern offset. Otherwise, for a- numerical callout whose number has not already been shown with captured- strings, show the number here. A callout with a string argument has been- displayed above. */-- if (cb->callout_number == 255)- {- fprintf(outfile, "%+3d ", (int)cb->pattern_position);- if (cb->pattern_position > 99) fprintf(outfile, "\n ");- }- else- {- if (callout_capture || cb->callout_string != NULL) fprintf(outfile, " ");- else fprintf(outfile, "%3d ", cb->callout_number);- }-- /* Now show position indicators */-- for (i = 0; i < pre_start; i++) fprintf(outfile, " ");- fprintf(outfile, "^");-- if (post_start > 0)- {- for (i = 0; i < post_start - 1; i++) fprintf(outfile, " ");- fprintf(outfile, "^");- }-- for (i = 0; i < subject_length - pre_start - post_start + 4; i++)- fprintf(outfile, " ");-- if (cb->next_item_length != 0)- fprintf(outfile, "%.*s", (int)(cb->next_item_length),- pbuffer8 + cb->pattern_position);- else- fprintf(outfile, "End of pattern");-- fprintf(outfile, "\n");- }--first_callout = FALSE;--/* Show any mark info */--if (cb->mark != last_callout_mark)- {- if (cb->mark == NULL)- fprintf(outfile, "Latest Mark: <unset>\n");- else- {- fprintf(outfile, "Latest Mark: ");- PCHARSV(cb->mark, -1, -1, utf, outfile);- putc('\n', outfile);- }- last_callout_mark = cb->mark;- }--/* Show callout data */--if (callout_data_ptr != NULL)- {- int callout_data = *((int32_t *)callout_data_ptr);- if (callout_data != 0)- {- fprintf(outfile, "Callout data = %d\n", callout_data);- return callout_data;- }- }--/* Keep count and give the appropriate return code */--callout_count++;--if (cb->callout_number == dat_datctl.cerror[0] &&- callout_count >= dat_datctl.cerror[1])- return PCRE2_ERROR_CALLOUT;--if (cb->callout_number == dat_datctl.cfail[0] &&- callout_count >= dat_datctl.cfail[1])- return 1;--return 0;-}----/*************************************************-* Handle *MARK and copy/get tests *-*************************************************/--/* This function is called after complete and partial matches. It runs the-tests for substring extraction.--Arguments:- utf TRUE for utf- capcount return from pcre2_match()--Returns: FALSE if print_error_message() fails-*/--static BOOL-copy_and_get(BOOL utf, int capcount)-{-int i;-uint8_t *nptr;--/* Test copy strings by number */--for (i = 0; i < MAXCPYGET && dat_datctl.copy_numbers[i] >= 0; i++)- {- int rc;- PCRE2_SIZE length, length2;- uint32_t copybuffer[256];- uint32_t n = (uint32_t)(dat_datctl.copy_numbers[i]);- length = sizeof(copybuffer)/code_unit_size;- PCRE2_SUBSTRING_COPY_BYNUMBER(rc, match_data, n, copybuffer, &length);- if (rc < 0)- {- fprintf(outfile, "Copy substring %d failed (%d): ", n, rc);- if (!print_error_message(rc, "", "\n")) return FALSE;- }- else- {- PCRE2_SUBSTRING_LENGTH_BYNUMBER(rc, match_data, n, &length2);- if (rc < 0)- {- fprintf(outfile, "Get substring %d length failed (%d): ", n, rc);- if (!print_error_message(rc, "", "\n")) return FALSE;- }- else if (length2 != length)- {- fprintf(outfile, "Mismatched substring lengths: %"- SIZ_FORM " %" SIZ_FORM "\n", length, length2);- }- fprintf(outfile, "%2dC ", n);- PCHARSV(copybuffer, 0, length, utf, outfile);- fprintf(outfile, " (%" SIZ_FORM ")\n", length);- }- }--/* Test copy strings by name */--nptr = dat_datctl.copy_names;-for (;;)- {- int rc;- int groupnumber;- PCRE2_SIZE length, length2;- uint32_t copybuffer[256];- int namelen = strlen((const char *)nptr);-#if defined SUPPORT_PCRE2_16 || defined SUPPORT_PCRE2_32- PCRE2_SIZE cnl = namelen;-#endif- if (namelen == 0) break;--#ifdef SUPPORT_PCRE2_8- if (test_mode == PCRE8_MODE) strcpy((char *)pbuffer8, (char *)nptr);-#endif-#ifdef SUPPORT_PCRE2_16- if (test_mode == PCRE16_MODE)(void)to16(nptr, utf, &cnl);-#endif-#ifdef SUPPORT_PCRE2_32- if (test_mode == PCRE32_MODE)(void)to32(nptr, utf, &cnl);-#endif-- PCRE2_SUBSTRING_NUMBER_FROM_NAME(groupnumber, compiled_code, pbuffer);- if (groupnumber < 0 && groupnumber != PCRE2_ERROR_NOUNIQUESUBSTRING)- fprintf(outfile, "Number not found for group '%s'\n", nptr);-- length = sizeof(copybuffer)/code_unit_size;- PCRE2_SUBSTRING_COPY_BYNAME(rc, match_data, pbuffer, copybuffer, &length);- if (rc < 0)- {- fprintf(outfile, "Copy substring '%s' failed (%d): ", nptr, rc);- if (!print_error_message(rc, "", "\n")) return FALSE;- }- else- {- PCRE2_SUBSTRING_LENGTH_BYNAME(rc, match_data, pbuffer, &length2);- if (rc < 0)- {- fprintf(outfile, "Get substring '%s' length failed (%d): ", nptr, rc);- if (!print_error_message(rc, "", "\n")) return FALSE;- }- else if (length2 != length)- {- fprintf(outfile, "Mismatched substring lengths: %"- SIZ_FORM " %" SIZ_FORM "\n", length, length2);- }- fprintf(outfile, " C ");- PCHARSV(copybuffer, 0, length, utf, outfile);- fprintf(outfile, " (%" SIZ_FORM ") %s", length, nptr);- if (groupnumber >= 0) fprintf(outfile, " (group %d)\n", groupnumber);- else fprintf(outfile, " (non-unique)\n");- }- nptr += namelen + 1;- }--/* Test get strings by number */--for (i = 0; i < MAXCPYGET && dat_datctl.get_numbers[i] >= 0; i++)- {- int rc;- PCRE2_SIZE length;- void *gotbuffer;- uint32_t n = (uint32_t)(dat_datctl.get_numbers[i]);- PCRE2_SUBSTRING_GET_BYNUMBER(rc, match_data, n, &gotbuffer, &length);- if (rc < 0)- {- fprintf(outfile, "Get substring %d failed (%d): ", n, rc);- if (!print_error_message(rc, "", "\n")) return FALSE;- }- else- {- fprintf(outfile, "%2dG ", n);- PCHARSV(gotbuffer, 0, length, utf, outfile);- fprintf(outfile, " (%" SIZ_FORM ")\n", length);- PCRE2_SUBSTRING_FREE(gotbuffer);- }- }--/* Test get strings by name */--nptr = dat_datctl.get_names;-for (;;)- {- PCRE2_SIZE length;- void *gotbuffer;- int rc;- int groupnumber;- int namelen = strlen((const char *)nptr);-#if defined SUPPORT_PCRE2_16 || defined SUPPORT_PCRE2_32- PCRE2_SIZE cnl = namelen;-#endif- if (namelen == 0) break;--#ifdef SUPPORT_PCRE2_8- if (test_mode == PCRE8_MODE) strcpy((char *)pbuffer8, (char *)nptr);-#endif-#ifdef SUPPORT_PCRE2_16- if (test_mode == PCRE16_MODE)(void)to16(nptr, utf, &cnl);-#endif-#ifdef SUPPORT_PCRE2_32- if (test_mode == PCRE32_MODE)(void)to32(nptr, utf, &cnl);-#endif-- PCRE2_SUBSTRING_NUMBER_FROM_NAME(groupnumber, compiled_code, pbuffer);- if (groupnumber < 0 && groupnumber != PCRE2_ERROR_NOUNIQUESUBSTRING)- fprintf(outfile, "Number not found for group '%s'\n", nptr);-- PCRE2_SUBSTRING_GET_BYNAME(rc, match_data, pbuffer, &gotbuffer, &length);- if (rc < 0)- {- fprintf(outfile, "Get substring '%s' failed (%d): ", nptr, rc);- if (!print_error_message(rc, "", "\n")) return FALSE;- }- else- {- fprintf(outfile, " G ");- PCHARSV(gotbuffer, 0, length, utf, outfile);- fprintf(outfile, " (%" SIZ_FORM ") %s", length, nptr);- if (groupnumber >= 0) fprintf(outfile, " (group %d)\n", groupnumber);- else fprintf(outfile, " (non-unique)\n");- PCRE2_SUBSTRING_FREE(gotbuffer);- }- nptr += namelen + 1;- }--/* Test getting the complete list of captured strings. */--if ((dat_datctl.control & CTL_GETALL) != 0)- {- int rc;- void **stringlist;- PCRE2_SIZE *lengths;- PCRE2_SUBSTRING_LIST_GET(rc, match_data, &stringlist, &lengths);- if (rc < 0)- {- fprintf(outfile, "get substring list failed (%d): ", rc);- if (!print_error_message(rc, "", "\n")) return FALSE;- }- else- {- for (i = 0; i < capcount; i++)- {- fprintf(outfile, "%2dL ", i);- PCHARSV(stringlist[i], 0, lengths[i], utf, outfile);- putc('\n', outfile);- }- if (stringlist[i] != NULL)- fprintf(outfile, "string list not terminated by NULL\n");- PCRE2_SUBSTRING_LIST_FREE(stringlist);- }- }--return TRUE;-}----/*************************************************-* Show an entire ovector *-*************************************************/--/* This function is called after partial matching or match failure, when the-"allvector" modifier is set. It is a means of checking the contents of the-entire ovector, to ensure no modification of fields that should be unchanged.--Arguments:- ovector points to the ovector- oveccount number of pairs--Returns: nothing-*/--static void-show_ovector(PCRE2_SIZE *ovector, uint32_t oveccount)-{-uint32_t i;-for (i = 0; i < 2*oveccount; i += 2)- {- PCRE2_SIZE start = ovector[i];- PCRE2_SIZE end = ovector[i+1];-- fprintf(outfile, "%2d: ", i/2);- if (start == PCRE2_UNSET && end == PCRE2_UNSET)- fprintf(outfile, "<unset>\n");- else if (start == JUNK_OFFSET && end == JUNK_OFFSET)- fprintf(outfile, "<unchanged>\n");- else- fprintf(outfile, "%ld %ld\n", (unsigned long int)start,- (unsigned long int)end);- }-}---/*************************************************-* Process a data line *-*************************************************/--/* The line is in buffer; it will not be empty.--Arguments: none--Returns: PR_OK continue processing next line- PR_SKIP skip to a blank line- PR_ABEND abort the pcre2test run-*/--static int-process_data(void)-{-PCRE2_SIZE len, ulen, arg_ulen;-uint32_t gmatched;-uint32_t c, k;-uint32_t g_notempty = 0;-uint8_t *p, *pp, *start_rep;-size_t needlen;-void *use_dat_context;-BOOL utf;-BOOL subject_literal;--PCRE2_SIZE *ovector;-PCRE2_SIZE ovecsave[3];-uint32_t oveccount;--#ifdef SUPPORT_PCRE2_8-uint8_t *q8 = NULL;-#endif-#ifdef SUPPORT_PCRE2_16-uint16_t *q16 = NULL;-#endif-#ifdef SUPPORT_PCRE2_32-uint32_t *q32 = NULL;-#endif--subject_literal = (pat_patctl.control2 & CTL2_SUBJECT_LITERAL) != 0;--/* Copy the default context and data control blocks to the active ones. Then-copy from the pattern the controls that can be set in either the pattern or the-data. This allows them to be overridden in the data line. We do not do this for-options because those that are common apply separately to compiling and-matching. */--DATCTXCPY(dat_context, default_dat_context);-memcpy(&dat_datctl, &def_datctl, sizeof(datctl));-dat_datctl.control |= (pat_patctl.control & CTL_ALLPD);-dat_datctl.control2 |= (pat_patctl.control2 & CTL2_ALLPD);-strcpy((char *)dat_datctl.replacement, (char *)pat_patctl.replacement);-if (dat_datctl.jitstack == 0) dat_datctl.jitstack = pat_patctl.jitstack;--if (dat_datctl.substitute_skip == 0)- dat_datctl.substitute_skip = pat_patctl.substitute_skip;-if (dat_datctl.substitute_stop == 0)- dat_datctl.substitute_stop = pat_patctl.substitute_stop;--/* Initialize for scanning the data line. */--#ifdef SUPPORT_PCRE2_8-utf = ((((pat_patctl.control & CTL_POSIX) != 0)?- ((pcre2_real_code_8 *)preg.re_pcre2_code)->overall_options :- FLD(compiled_code, overall_options)) & PCRE2_UTF) != 0;-#else-utf = (FLD(compiled_code, overall_options) & PCRE2_UTF) != 0;-#endif--start_rep = NULL;-len = strlen((const char *)buffer);-while (len > 0 && isspace(buffer[len-1])) len--;-buffer[len] = 0;-p = buffer;-while (isspace(*p)) p++;--/* Check that the data is well-formed UTF-8 if we're in UTF mode. To create-invalid input to pcre2_match(), you must use \x?? or \x{} sequences. */--if (utf)- {- uint8_t *q;- uint32_t cc;- int n = 1;- 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 "- "in UTF mode\n");- return PR_OK;- }- }--#ifdef SUPPORT_VALGRIND-/* Mark the dbuffer as addressable but undefined again. */-if (dbuffer != NULL)- {- VALGRIND_MAKE_MEM_UNDEFINED(dbuffer, dbuffer_size);- }-#endif--/* Allocate a buffer to hold the data line; len+1 is an upper bound on-the number of code units that will be needed (though the buffer may have to be-extended if replication is involved). */--needlen = (len+1) * code_unit_size;-if (dbuffer == NULL || needlen >= dbuffer_size)- {- 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(%" SIZ_FORM ") failed\n", dbuffer_size);- exit(1);- }- }-SETCASTPTR(q, dbuffer); /* Sets q8, q16, or q32, as appropriate. */--/* Scan the data line, interpreting data escapes, and put the result into a-buffer of the appropriate width. In UTF mode, input is always UTF-8; otherwise,-in 16- and 32-bit modes, it can be forced to UTF-8 by the utf8_input modifier.-*/--while ((c = *p++) != 0)- {- int32_t i = 0;- size_t replen;-- /* ] may mark the end of a replicated sequence */-- if (c == ']' && start_rep != NULL)- {- PCRE2_SIZE d;- long li;- char *endptr;-- if (*p++ != '{')- {- fprintf(outfile, "** Expected '{' after \\[....]\n");- return PR_OK;- }-- li = strtol((const char *)p, &endptr, 10);- if (S32OVERFLOW(li))- {- fprintf(outfile, "** Repeat count too large\n");- return PR_OK;- }-- p = (uint8_t *)endptr;- if (*p++ != '}')- {- fprintf(outfile, "** Expected '}' after \\[...]{...\n");- return PR_OK;- }-- i = (int32_t)li;- if (i-- <= 0)- {- fprintf(outfile, "** Zero or negative repeat not allowed\n");- return PR_OK;- }-- replen = CAST8VAR(q) - start_rep;- if (PRIV(ckd_smul)(&d, replen, i))- {- fprintf(outfile, "** Expanded content too large\n");- return PR_OK;- }- needlen += d;-- if (needlen >= dbuffer_size)- {- 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(%" SIZ_FORM ") failed\n",- dbuffer_size);- exit(1);- }- SETCASTPTR(q, dbuffer + qoffset);- start_rep = dbuffer + rep_offset;- }-- while (i-- > 0)- {- memcpy(CAST8VAR(q), start_rep, replen);- SETPLUS(q, replen/code_unit_size);- }-- start_rep = NULL;- continue;- }-- /* Handle a non-escaped character. In non-UTF 32-bit mode with utf8_input- set, do the fudge for setting the top bit. */-- if (c != '\\' || subject_literal)- {- uint32_t topbit = 0;- if (test_mode == PCRE32_MODE && c == 0xff && *p != 0)- {- topbit = 0x80000000;- c = *p++;- }- if ((utf || (pat_patctl.control & CTL_UTF8_INPUT) != 0) &&- HASUTF8EXTRALEN(c)) { GETUTF8INC(c, p); }- c |= topbit;- }-- /* Handle backslash escapes */-- else switch ((c = *p++))- {- case '\\': break;- case 'a': c = CHAR_BEL; break;- case 'b': c = '\b'; break;- case 'e': c = CHAR_ESC; break;- case 'f': c = '\f'; break;- case 'n': c = '\n'; break;- case 'r': c = '\r'; break;- case 't': c = '\t'; break;- case 'v': c = '\v'; break;-- case '0': case '1': case '2': case '3':- case '4': case '5': case '6': case '7':- c -= '0';- while (i++ < 2 && isdigit(*p) && *p != '8' && *p != '9')- c = c * 8 + *p++ - '0';- break;-- case 'o':- if (*p == '{')- {- uint8_t *pt = p;- c = 0;- for (pt++; isdigit(*pt) && *pt != '8' && *pt != '9'; pt++)- {- if (++i == 12)- fprintf(outfile, "** Too many octal digits in \\o{...} item; "- "using only the first twelve.\n");- else c = c * 8 + *pt - '0';- }- if (*pt == '}') p = pt + 1;- else fprintf(outfile, "** Missing } after \\o{ (assumed)\n");- }- break;-- case 'x':- if (*p == '{')- {- uint8_t *pt = p;- c = 0;-- /* We used to have "while (isxdigit(*(++pt)))" here, but it fails- when isxdigit() is a macro that refers to its argument more than- once. This is banned by the C Standard, but apparently happens in at- least one MacOS environment. */-- for (pt++; isxdigit(*pt); pt++)- {- if (++i == 9)- fprintf(outfile, "** Too many hex digits in \\x{...} item; "- "using only the first eight.\n");- else c = c * 16 + tolower(*pt) - ((isdigit(*pt))? '0' : 'a' - 10);- }- if (*pt == '}')- {- p = pt + 1;- break;- }- /* Not correct form for \x{...}; fall through */- }-- /* \x without {} always defines just one byte in 8-bit mode. This- allows UTF-8 characters to be constructed byte by byte, and also allows- invalid UTF-8 sequences to be made. Just copy the byte in UTF-8 mode.- Otherwise, pass it down as data. */-- c = 0;- while (i++ < 2 && isxdigit(*p))- {- c = c * 16 + tolower(*p) - ((isdigit(*p))? '0' : 'a' - 10);- p++;- }-#if defined SUPPORT_PCRE2_8- if (utf && (test_mode == PCRE8_MODE))- {- *q8++ = c;- continue;- }-#endif- break;-- case 0: /* \ followed by EOF allows for an empty line */- p--;- continue;-- case '=': /* \= terminates the data, starts modifiers */- goto ENDSTRING;-- case '[': /* \[ introduces a replicated character sequence */- if (start_rep != NULL)- {- fprintf(outfile, "** Nested replication is not supported\n");- return PR_OK;- }- start_rep = CAST8VAR(q);- continue;-- default:- if (isalnum(c))- {- fprintf(outfile, "** Unrecognized escape sequence \"\\%c\"\n", c);- return PR_OK;- }- }-- /* We now have a character value in c that may be greater than 255.- In 8-bit mode we convert to UTF-8 if we are in UTF mode. Values greater- than 127 in UTF mode must have come from \x{...} or octal constructs- because values from \x.. get this far only in non-UTF mode. */--#ifdef SUPPORT_PCRE2_8- if (test_mode == PCRE8_MODE)- {- if (utf)- {- if (c > 0x7fffffff)- {- fprintf(outfile, "** Character \\x{%x} is greater than 0x7fffffff "- "and so cannot be converted to UTF-8\n", c);- return PR_OK;- }- q8 += ord2utf8(c, q8);- }- else- {- if (c > 0xffu)- {- fprintf(outfile, "** Character \\x{%x} is greater than 255 "- "and UTF-8 mode is not enabled.\n", c);- fprintf(outfile, "** Truncation will probably give the wrong "- "result.\n");- }- *q8++ = (uint8_t)c;- }- }-#endif-#ifdef SUPPORT_PCRE2_16- if (test_mode == PCRE16_MODE)- {- if (utf)- {- if (c > 0x10ffffu)- {- fprintf(outfile, "** Failed: character \\x{%x} is greater than "- "0x10ffff and so cannot be converted to UTF-16\n", c);- return PR_OK;- }- else if (c >= 0x10000u)- {- c-= 0x10000u;- *q16++ = 0xD800 | (c >> 10);- *q16++ = 0xDC00 | (c & 0x3ff);- }- else- *q16++ = c;- }- else- {- if (c > 0xffffu)- {- fprintf(outfile, "** Character \\x{%x} is greater than 0xffff "- "and UTF-16 mode is not enabled.\n", c);- fprintf(outfile, "** Truncation will probably give the wrong "- "result.\n");- }-- *q16++ = (uint16_t)c;- }- }-#endif-#ifdef SUPPORT_PCRE2_32- if (test_mode == PCRE32_MODE)- {- *q32++ = c;- }-#endif- }--ENDSTRING:-SET(*q, 0);-len = CASTVAR(uint8_t *, q) - dbuffer; /* Length in bytes */-ulen = len/code_unit_size; /* Length in code units */-arg_ulen = ulen; /* Value to use in match arg */--/* If the string was terminated by \= we must now interpret modifiers. */--if (p[-1] != 0 && !decode_modifiers(p, CTX_DAT, NULL, &dat_datctl))- return PR_OK;--/* Setting substitute_{skip,fail} implies a substitute callout. */--if (dat_datctl.substitute_skip != 0 || dat_datctl.substitute_stop != 0)- dat_datctl.control2 |= CTL2_SUBSTITUTE_CALLOUT;--/* Check for mutually exclusive modifiers. At present, these are all in the-first control word. */--for (k = 0; k < sizeof(exclusive_dat_controls)/sizeof(uint32_t); k++)- {- c = dat_datctl.control & exclusive_dat_controls[k];- if (c != 0 && c != (c & (~c+1)))- {- show_controls(c, 0, "** Not allowed together:");- fprintf(outfile, "\n");- return PR_OK;- }- }--if (pat_patctl.replacement[0] != 0)- {- if ((dat_datctl.control2 & CTL2_SUBSTITUTE_CALLOUT) != 0 &&- (dat_datctl.control & CTL_NULLCONTEXT) != 0)- {- fprintf(outfile, "** Replacement callouts are not supported with null_context.\n");- return PR_OK;- }-- if ((dat_datctl.control & CTL_ALLCAPTURES) != 0)- fprintf(outfile, "** Ignored with replacement text: allcaptures\n");- }--/* Warn for modifiers that are ignored for DFA. */--if ((dat_datctl.control & CTL_DFA) != 0)- {- if ((dat_datctl.control & CTL_ALLCAPTURES) != 0)- 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-ulen containing the code unit length, with a copy in arg_ulen for use in match-function arguments (this gets changed to PCRE2_ZERO_TERMINATED when the-zero_terminate modifier is present).--Move the data to the end of the buffer so that a read over the end can be-caught by valgrind or other means. If we have explicit valgrind support, mark-the unused start of the buffer unaddressable. If we are using the POSIX-interface, or testing zero-termination, we must include the terminating zero in-the usable data. */--c = code_unit_size * (((pat_patctl.control & CTL_POSIX) +- (dat_datctl.control & CTL_ZERO_TERMINATE) != 0)? 1:0);-pp = memmove(dbuffer + dbuffer_size - len - c, dbuffer, len + c);-#ifdef SUPPORT_VALGRIND- VALGRIND_MAKE_MEM_NOACCESS(dbuffer, dbuffer_size - (len + c));-#endif--/* Now pp points to the subject string, but if null_subject was specified, set-it to NULL to test PCRE2's behaviour. */--if ((dat_datctl.control2 & CTL2_NULL_SUBJECT) != 0) pp = NULL;--/* POSIX matching is only possible in 8-bit mode, and it does not support-timing or other fancy features. Some were checked at compile time, but we need-to check the match-time settings here. */--#ifdef SUPPORT_PCRE2_8-if ((pat_patctl.control & CTL_POSIX) != 0)- {- int rc;- int eflags = 0;- regmatch_t *pmatch = NULL;- const char *msg = "** Ignored with POSIX interface:";-- if (dat_datctl.cerror[0] != CFORE_UNSET || dat_datctl.cerror[1] != CFORE_UNSET)- prmsg(&msg, "callout_error");- if (dat_datctl.cfail[0] != CFORE_UNSET || dat_datctl.cfail[1] != CFORE_UNSET)- prmsg(&msg, "callout_fail");- if (dat_datctl.copy_numbers[0] >= 0 || dat_datctl.copy_names[0] != 0)- prmsg(&msg, "copy");- if (dat_datctl.get_numbers[0] >= 0 || dat_datctl.get_names[0] != 0)- prmsg(&msg, "get");- if (dat_datctl.jitstack != 0) prmsg(&msg, "jitstack");- if (dat_datctl.offset != 0) prmsg(&msg, "offset");-- if ((dat_datctl.options & ~POSIX_SUPPORTED_MATCH_OPTIONS) != 0)- {- fprintf(outfile, "%s", msg);- 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)- {- show_controls(dat_datctl.control & ~POSIX_SUPPORTED_MATCH_CONTROLS,- dat_datctl.control2 & ~POSIX_SUPPORTED_MATCH_CONTROLS2, msg);- msg = "";- }-- if (msg[0] == 0) fprintf(outfile, "\n");-- if (dat_datctl.oveccount > 0)- {- pmatch = (regmatch_t *)malloc(sizeof(regmatch_t) * dat_datctl.oveccount);- if (pmatch == NULL)- {- fprintf(outfile, "** Failed to get memory for recording matching "- "information (size set = %du)\n", dat_datctl.oveccount);- return PR_OK;- }- }-- if (dat_datctl.startend[0] != CFORE_UNSET)- {- pmatch[0].rm_so = dat_datctl.startend[0];- pmatch[0].rm_eo = (dat_datctl.startend[1] != 0)?- dat_datctl.startend[1] : len;- eflags |= REG_STARTEND;- }-- if ((dat_datctl.options & PCRE2_NOTBOL) != 0) eflags |= REG_NOTBOL;- if ((dat_datctl.options & PCRE2_NOTEOL) != 0) eflags |= REG_NOTEOL;- if ((dat_datctl.options & PCRE2_NOTEMPTY) != 0) eflags |= REG_NOTEMPTY;-- rc = regexec(&preg, (const char *)pp, dat_datctl.oveccount, pmatch, eflags);- if (rc != 0)- {- (void)regerror(rc, &preg, (char *)pbuffer8, pbuffer8_size);- fprintf(outfile, "No match: POSIX code %d: %s\n", rc, pbuffer8);- }- else if ((pat_patctl.control & CTL_POSIX_NOSUB) != 0)- fprintf(outfile, "Matched with REG_NOSUB\n");- else if (dat_datctl.oveccount == 0)- fprintf(outfile, "Matched without capture\n");- else- {- size_t i, j;- size_t last_printed = (size_t)dat_datctl.oveccount;- for (i = 0; i < (size_t)dat_datctl.oveccount; i++)- {- if (pmatch[i].rm_so >= 0)- {- PCRE2_SIZE start = pmatch[i].rm_so;- PCRE2_SIZE end = pmatch[i].rm_eo;- for (j = last_printed + 1; j < i; j++)- fprintf(outfile, "%2d: <unset>\n", (int)j);- last_printed = i;- if (start > end)- {- start = pmatch[i].rm_eo;- end = pmatch[i].rm_so;- fprintf(outfile, "Start of matched string is beyond its end - "- "displaying from end to start.\n");- }- fprintf(outfile, "%2d: ", (int)i);- PCHARSV(pp, start, end - start, utf, outfile);- fprintf(outfile, "\n");-- if ((i == 0 && (dat_datctl.control & CTL_AFTERTEXT) != 0) ||- (dat_datctl.control & CTL_ALLAFTERTEXT) != 0)- {- fprintf(outfile, "%2d+ ", (int)i);- /* Note: don't use the start/end variables here because we want to- show the text from what is reported as the end. */- PCHARSV(pp, pmatch[i].rm_eo, len - pmatch[i].rm_eo, utf, outfile);- fprintf(outfile, "\n"); }- }- }- }- free(pmatch);- return PR_OK;- }-#endif /* SUPPORT_PCRE2_8 */-- /* Handle matching via the native interface. Check for consistency of-modifiers. */--if (dat_datctl.startend[0] != CFORE_UNSET)- fprintf(outfile, "** \\=posix_startend ignored for non-POSIX matching\n");--/* ALLUSEDTEXT is not supported with JIT, but JIT is not used with DFA-matching, even if the JIT compiler was used. */--if ((dat_datctl.control & (CTL_ALLUSEDTEXT|CTL_DFA)) == CTL_ALLUSEDTEXT &&- FLD(compiled_code, executable_jit) != NULL)- {- fprintf(outfile, "** Showing all consulted text is not supported by JIT: ignored\n");- dat_datctl.control &= ~CTL_ALLUSEDTEXT;- }--/* Handle passing the subject as zero-terminated. */--if ((dat_datctl.control & CTL_ZERO_TERMINATE) != 0)- arg_ulen = PCRE2_ZERO_TERMINATED;--/* The nullcontext modifier is used to test calling pcre2_[jit_]match() with a-NULL context. */--use_dat_context = ((dat_datctl.control & CTL_NULLCONTEXT) != 0)?- NULL : PTR(dat_context);--/* Enable display of malloc/free if wanted. We can do this only if either the-pattern or the subject is processed with a context. */--show_memory = (dat_datctl.control & CTL_MEMORY) != 0;--if (show_memory &&- (pat_patctl.control & dat_datctl.control & CTL_NULLCONTEXT) != 0)- fprintf(outfile, "** \\=memory requires either a pattern or a subject "- "context: ignored\n");--/* Create and assign a JIT stack if requested. */--if (dat_datctl.jitstack != 0)- {- if (dat_datctl.jitstack != jit_stack_size)- {- PCRE2_JIT_STACK_FREE(jit_stack);- PCRE2_JIT_STACK_CREATE(jit_stack, 1, dat_datctl.jitstack * 1024, NULL);- jit_stack_size = dat_datctl.jitstack;- }- PCRE2_JIT_STACK_ASSIGN(dat_context, jit_callback, jit_stack);- }--/* Or de-assign */--else if (jit_stack != NULL)- {- PCRE2_JIT_STACK_ASSIGN(dat_context, NULL, NULL);- PCRE2_JIT_STACK_FREE(jit_stack);- jit_stack = NULL;- jit_stack_size = 0;- }--/* When no JIT stack is assigned, we must ensure that there is a JIT callback-if we want to verify that JIT was actually used. */--if ((pat_patctl.control & CTL_JITVERIFY) != 0 && jit_stack == NULL)- {- PCRE2_JIT_STACK_ASSIGN(dat_context, jit_callback, NULL);- }--/* Adjust match_data according to size of offsets required. A size of zero-causes a new match data block to be obtained that exactly fits the pattern. */--if (dat_datctl.oveccount == 0)- {- PCRE2_MATCH_DATA_FREE(match_data);- 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)- {- SETFLD(match_data, oveccount, dat_datctl.oveccount);- }-else- {- max_oveccount = dat_datctl.oveccount;- PCRE2_MATCH_DATA_FREE(match_data);- PCRE2_MATCH_DATA_CREATE(match_data, max_oveccount, general_context);- }--if (CASTVAR(void *, match_data) == NULL)- {- fprintf(outfile, "** Failed to get memory for recording matching "- "information (size requested: %d)\n", dat_datctl.oveccount);- max_oveccount = 0;- return PR_OK;- }--ovector = FLD(match_data, ovector);-PCRE2_GET_OVECTOR_COUNT(oveccount, match_data);--/* Replacement processing is ignored for DFA matching. */--if (dat_datctl.replacement[0] != 0 && (dat_datctl.control & CTL_DFA) != 0)- {- fprintf(outfile, "** Ignored for DFA matching: replace\n");- dat_datctl.replacement[0] = 0;- }--/* 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)- {- int rc;- uint8_t *pr;- uint8_t rbuffer[REPLACE_BUFFSIZE];- uint8_t nbuffer[REPLACE_BUFFSIZE];- uint8_t *rbptr;- uint32_t xoptions;- uint32_t emoption; /* External match option */- PCRE2_SIZE j, rlen, nsize, erroroffset;- BOOL badutf = FALSE;--#ifdef SUPPORT_PCRE2_8- uint8_t *r8 = NULL;-#endif-#ifdef SUPPORT_PCRE2_16- uint16_t *r16 = NULL;-#endif-#ifdef SUPPORT_PCRE2_32- uint32_t *r32 = NULL;-#endif-- /* Fill the ovector with junk to detect elements that do not get set- when they should be (relevant only when "allvector" is specified). */-- for (j = 0; j < 2*oveccount; j++) ovector[j] = JUNK_OFFSET;-- if (timeitm)- fprintf(outfile, "** Timing is not supported with replace: ignored\n");-- if ((dat_datctl.control & CTL_ALTGLOBAL) != 0)- fprintf(outfile, "** Altglobal is not supported with replace: ignored\n");-- /* Check for a test that does substitution after an initial external match.- If this is set, we run the external match, but leave the interpretation of- its output to pcre2_substitute(). */-- emoption = ((dat_datctl.control2 & CTL2_SUBSTITUTE_MATCHED) == 0)? 0 :- PCRE2_SUBSTITUTE_MATCHED;-- if (emoption != 0)- {- 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 |- (((dat_datctl.control & CTL_GLOBAL) == 0)? 0 :- PCRE2_SUBSTITUTE_GLOBAL) |- (((dat_datctl.control2 & CTL2_SUBSTITUTE_EXTENDED) == 0)? 0 :- PCRE2_SUBSTITUTE_EXTENDED) |- (((dat_datctl.control2 & CTL2_SUBSTITUTE_LITERAL) == 0)? 0 :- PCRE2_SUBSTITUTE_LITERAL) |- (((dat_datctl.control2 & CTL2_SUBSTITUTE_OVERFLOW_LENGTH) == 0)? 0 :- PCRE2_SUBSTITUTE_OVERFLOW_LENGTH) |- (((dat_datctl.control2 & CTL2_SUBSTITUTE_REPLACEMENT_ONLY) == 0)? 0 :- PCRE2_SUBSTITUTE_REPLACEMENT_ONLY) |- (((dat_datctl.control2 & CTL2_SUBSTITUTE_UNKNOWN_UNSET) == 0)? 0 :- PCRE2_SUBSTITUTE_UNKNOWN_UNSET) |- (((dat_datctl.control2 & CTL2_SUBSTITUTE_UNSET_EMPTY) == 0)? 0 :- PCRE2_SUBSTITUTE_UNSET_EMPTY);-- SETCASTPTR(r, rbuffer); /* Sets r8, r16, or r32, as appropriate. */- pr = dat_datctl.replacement;-- /* If the replacement starts with '[<number>]' we interpret that as length- value for the replacement buffer. */-- nsize = REPLACE_BUFFSIZE/code_unit_size;- if (*pr == '[')- {- PCRE2_SIZE n = 0;- while ((c = *(++pr)) >= CHAR_0 && c <= CHAR_9) n = n * 10 + c - CHAR_0;- if (*pr++ != ']')- {- fprintf(outfile, "Bad buffer size in replacement string\n");- return PR_OK;- }- if (n > nsize)- {- fprintf(outfile, "Replacement buffer setting (%" SIZ_FORM ") is too "- "large (max %" SIZ_FORM ")\n", n, nsize);- return PR_OK;- }- nsize = n;- }-- /* Now copy the replacement string to a buffer of the appropriate width. No- escape processing is done for replacements. In UTF mode, check for an invalid- UTF-8 input string, and if it is invalid, just copy its code units without- UTF interpretation. This provides a means of checking that an invalid string- is detected. Otherwise, UTF-8 can be used to include wide characters in a- replacement. */-- if (utf) badutf = valid_utf(pr, strlen((const char *)pr), &erroroffset);-- /* Not UTF or invalid UTF-8: just copy the code units. */-- if (!utf || badutf)- {- while ((c = *pr++) != 0)- {-#ifdef SUPPORT_PCRE2_8- if (test_mode == PCRE8_MODE) *r8++ = c;-#endif-#ifdef SUPPORT_PCRE2_16- if (test_mode == PCRE16_MODE) *r16++ = c;-#endif-#ifdef SUPPORT_PCRE2_32- if (test_mode == PCRE32_MODE) *r32++ = c;-#endif- }- }-- /* Valid UTF-8 replacement string */-- else while ((c = *pr++) != 0)- {- if (HASUTF8EXTRALEN(c)) { GETUTF8INC(c, pr); }--#ifdef SUPPORT_PCRE2_8- if (test_mode == PCRE8_MODE) r8 += ord2utf8(c, r8);-#endif--#ifdef SUPPORT_PCRE2_16- if (test_mode == PCRE16_MODE)- {- if (c >= 0x10000u)- {- c-= 0x10000u;- *r16++ = 0xD800 | (c >> 10);- *r16++ = 0xDC00 | (c & 0x3ff);- }- else *r16++ = c;- }-#endif--#ifdef SUPPORT_PCRE2_32- if (test_mode == PCRE32_MODE) *r32++ = c;-#endif- }-- SET(*r, 0);- if ((dat_datctl.control & CTL_ZERO_TERMINATE) != 0)- rlen = PCRE2_ZERO_TERMINATED;- else- rlen = (CASTVAR(uint8_t *, r) - rbuffer)/code_unit_size;-- if ((dat_datctl.control2 & CTL2_SUBSTITUTE_CALLOUT) != 0)- {- PCRE2_SET_SUBSTITUTE_CALLOUT(dat_context, substitute_callout_function, NULL);- }- else- {- PCRE2_SET_SUBSTITUTE_CALLOUT(dat_context, NULL, NULL); /* No callout */- }-- /* There is a special option to set the replacement to NULL in order to test- that case. */-- rbptr = ((dat_datctl.control2 & CTL2_NULL_REPLACEMENT) == 0)? rbuffer : NULL;-- PCRE2_SUBSTITUTE(rc, compiled_code, pp, arg_ulen, dat_datctl.offset,- dat_datctl.options|xoptions, match_data, use_dat_context,- rbptr, rlen, nbuffer, &nsize);-- if (rc < 0)- {- fprintf(outfile, "Failed: error %d", rc);- if (rc != PCRE2_ERROR_NOMEMORY && nsize != PCRE2_UNSET)- fprintf(outfile, " at offset %ld in replacement", (long int)nsize);- fprintf(outfile, ": ");- if (!print_error_message(rc, "", "")) return PR_ABEND;- if (rc == PCRE2_ERROR_NOMEMORY &&- (xoptions & PCRE2_SUBSTITUTE_OVERFLOW_LENGTH) != 0)- fprintf(outfile, ": %ld code units are needed", (long int)nsize);- }- else- {- fprintf(outfile, "%2d: ", rc);- PCHARSV(nbuffer, 0, nsize, utf, outfile);- }-- fprintf(outfile, "\n");- show_memory = FALSE;-- /* 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 */--/* When a replacement string is not provided, run a loop for global matching-with one of the basic matching functions. For altglobal (or first time round-the loop), set an "unset" value for the previous match info. */--ovecsave[0] = ovecsave[1] = ovecsave[2] = PCRE2_UNSET;--for (gmatched = 0;; gmatched++)- {- PCRE2_SIZE j;- int capcount;-- /* Fill the ovector with junk to detect elements that do not get set- when they should be. */-- for (j = 0; j < 2*oveccount; j++) ovector[j] = JUNK_OFFSET;-- /* When matching is via pcre2_match(), we will detect the use of JIT via the- stack callback function. */-- jit_was_used = (pat_patctl.control & CTL_JITFAST) != 0;-- /* Do timing if required. */-- if (timeitm > 0)- {- int i;- clock_t start_time, time_taken;-- if ((dat_datctl.control & CTL_DFA) != 0)- {- if ((dat_datctl.options & PCRE2_DFA_RESTART) != 0)- {- fprintf(outfile, "Timing DFA restarts is not supported\n");- return PR_OK;- }- if (dfa_workspace == NULL)- dfa_workspace = (int *)malloc(DFA_WS_DIMENSION*sizeof(int));- start_time = clock();- for (i = 0; i < timeitm; i++)- {- PCRE2_DFA_MATCH(capcount, compiled_code, pp, arg_ulen,- dat_datctl.offset, dat_datctl.options | g_notempty, match_data,- use_dat_context, dfa_workspace, DFA_WS_DIMENSION);- }- }-- else if ((pat_patctl.control & CTL_JITFAST) != 0)- {- start_time = clock();- for (i = 0; i < timeitm; i++)- {- PCRE2_JIT_MATCH(capcount, compiled_code, pp, arg_ulen,- dat_datctl.offset, dat_datctl.options | g_notempty, match_data,- use_dat_context);- }- }-- else- {- start_time = clock();- for (i = 0; i < timeitm; i++)- {- PCRE2_MATCH(capcount, compiled_code, pp, arg_ulen,- dat_datctl.offset, dat_datctl.options | g_notempty, match_data,- use_dat_context);- }- }- total_match_time += (time_taken = clock() - start_time);- 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|CTL_FINDLIMITS_NOHEAP)) != 0)- {- capcount = 0; /* This stops compiler warnings */-- 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");- }-- capcount = check_match_limit(pp, arg_ulen, PCRE2_ERROR_MATCHLIMIT,- "match");-- if (FLD(compiled_code, executable_jit) == NULL ||- (dat_datctl.options & PCRE2_NO_JIT) != 0 ||- (dat_datctl.control & CTL_DFA) != 0)- {- capcount = check_match_limit(pp, arg_ulen, PCRE2_ERROR_DEPTHLIMIT,- "depth");- }-- if (capcount == 0)- {- fprintf(outfile, "Matched, but offsets vector is too small to show all matches\n");- capcount = dat_datctl.oveccount;- }- }-- /* Otherwise just run a single match, setting up a callout if required (the- default). There is a copy of the pattern in pbuffer8 for use by callouts. */-- else- {- if ((dat_datctl.control & CTL_CALLOUT_NONE) == 0)- {- PCRE2_SET_CALLOUT(dat_context, callout_function,- (void *)(&dat_datctl.callout_data));- first_callout = TRUE;- last_callout_mark = NULL;- callout_count = 0;- }- else- {- PCRE2_SET_CALLOUT(dat_context, NULL, NULL); /* No callout */- }-- /* Run a single DFA or NFA match. */-- if ((dat_datctl.control & CTL_DFA) != 0)- {- if (dfa_workspace == NULL)- dfa_workspace = (int *)malloc(DFA_WS_DIMENSION*sizeof(int));- if (dfa_matched++ == 0)- dfa_workspace[0] = -1; /* To catch bad restart */- PCRE2_DFA_MATCH(capcount, compiled_code, pp, arg_ulen,- dat_datctl.offset, dat_datctl.options | g_notempty, match_data,- use_dat_context, dfa_workspace, DFA_WS_DIMENSION);- if (capcount == 0)- {- fprintf(outfile, "Matched, but offsets vector is too small to show all matches\n");- capcount = dat_datctl.oveccount;- }- }- else- {- if ((pat_patctl.control & CTL_JITFAST) != 0)- PCRE2_JIT_MATCH(capcount, compiled_code, pp, arg_ulen, dat_datctl.offset,- dat_datctl.options | g_notempty, match_data, use_dat_context);- else- PCRE2_MATCH(capcount, compiled_code, pp, arg_ulen, dat_datctl.offset,- dat_datctl.options | g_notempty, match_data, use_dat_context);- if (capcount == 0)- {- fprintf(outfile, "Matched, but too many substrings\n");- capcount = dat_datctl.oveccount;- }- }- }-- /* The result of the match is now in capcount. First handle a successful- match. If pp was forced to be NULL (to test NULL handling) it will have been- treated as an empty string if the length was zero. So re-create that for- outputting. */-- if (capcount >= 0)- {- int i;-- if (pp == NULL) pp = (uint8_t *)"";-- if (capcount > (int)oveccount) /* Check for lunatic return value */- {- fprintf(outfile,- "** PCRE2 error: returned count %d is too big for ovector count %d\n",- capcount, oveccount);- capcount = oveccount;- if ((dat_datctl.control & CTL_ANYGLOB) != 0)- {- fprintf(outfile, "** Global loop abandoned\n");- dat_datctl.control &= ~CTL_ANYGLOB; /* Break g/G loop */- }- }-- /* If PCRE2_COPY_MATCHED_SUBJECT was set, check that things are as they- should be, but not for fast JIT, where it isn't supported. */-- if ((dat_datctl.options & PCRE2_COPY_MATCHED_SUBJECT) != 0 &&- (pat_patctl.control & CTL_JITFAST) == 0)- {- if ((FLD(match_data, flags) & PCRE2_MD_COPIED_SUBJECT) == 0)- fprintf(outfile,- "** PCRE2 error: flag not set after copy_matched_subject\n");-- if (CASTFLD(void *, match_data, subject) == pp)- fprintf(outfile,- "** PCRE2 error: copy_matched_subject has not copied\n");-- if (memcmp(CASTFLD(void *, match_data, subject), pp, ulen) != 0)- fprintf(outfile,- "** PCRE2 error: copy_matched_subject mismatch\n");- }-- /* If this is not the first time round a global loop, check that the- returned string has changed. If it has not, check for an empty string match- at different starting offset from the previous match. This is a failed test- retry for null-matching patterns that don't match at their starting offset,- for example /(?<=\G.)/. A repeated match at the same point is not such a- pattern, and must be discarded, and we then proceed to seek a non-null- match at the current point. For any other repeated match, there is a bug- somewhere and we must break the loop because it will go on for ever. We- know that there are always at least two elements in the ovector. */-- if (gmatched > 0 && ovecsave[0] == ovector[0] && ovecsave[1] == ovector[1])- {- if (ovector[0] == ovector[1] && ovecsave[2] != dat_datctl.offset)- {- g_notempty = PCRE2_NOTEMPTY_ATSTART | PCRE2_ANCHORED;- ovecsave[2] = dat_datctl.offset;- continue; /* Back to the top of the loop */- }- fprintf(outfile,- "** PCRE2 error: global repeat returned the same string as previous\n");- fprintf(outfile, "** Global loop abandoned\n");- dat_datctl.control &= ~CTL_ANYGLOB; /* Break g/G loop */- }-- /* "allcaptures" requests showing of all captures in the pattern, to check- unset ones at the end. It may be set on the pattern or the data. Implement- by setting capcount to the maximum. This is not relevant for DFA matching,- so ignore it (warning given above). */-- if ((dat_datctl.control & (CTL_ALLCAPTURES|CTL_DFA)) == CTL_ALLCAPTURES)- {- capcount = maxcapcount + 1; /* Allow for full match */- if (capcount > (int)oveccount) capcount = oveccount;- }-- /* "allvector" request showing the entire ovector. */-- if ((dat_datctl.control2 & CTL2_ALLVECTOR) != 0) capcount = oveccount;-- /* Output the captured substrings. Note that, for the matched string,- the use of \K in an assertion can make the start later than the end. */-- for (i = 0; i < 2*capcount; i += 2)- {- PCRE2_SIZE lleft, lmiddle, lright;- PCRE2_SIZE start = ovector[i];- PCRE2_SIZE end = ovector[i+1];-- if (start > end)- {- start = ovector[i+1];- end = ovector[i];- fprintf(outfile, "Start of matched string is beyond its end - "- "displaying from end to start.\n");- }-- fprintf(outfile, "%2d: ", i/2);-- /* Check for an unset group */-- if (start == PCRE2_UNSET && end == PCRE2_UNSET)- {- fprintf(outfile, "<unset>\n");- continue;- }-- /* Check for silly offsets, in particular, values that have not been- set when they should have been. However, if we are past the end of the- captures for this pattern ("allvector" causes this), or if we are DFA- matching, it isn't an error if the entry is unchanged. */-- if (start > ulen || end > ulen)- {- if (((dat_datctl.control & CTL_DFA) != 0 ||- i >= (int)(2*maxcapcount + 2)) &&- start == JUNK_OFFSET && end == JUNK_OFFSET)- fprintf(outfile, "<unchanged>\n");- else- fprintf(outfile, "ERROR: bad value(s) for offset(s): 0x%lx 0x%lx\n",- (unsigned long int)start, (unsigned long int)end);- continue;- }-- /* When JIT is not being used, ALLUSEDTEXT may be set. (It if is set with- JIT, it is disabled above, with a comment.) When the match is done by the- interpreter, leftchar and rightchar are available, and if ALLUSEDTEXT is- set, and if the leftmost consulted character is before the start of the- match or the rightmost consulted character is past the end of the match,- we want to show all consulted characters for the main matched string, and- indicate which were lookarounds. */-- if (i == 0)- {- BOOL showallused;- PCRE2_SIZE leftchar, rightchar;-- if ((dat_datctl.control & CTL_ALLUSEDTEXT) != 0)- {- leftchar = FLD(match_data, leftchar);- rightchar = FLD(match_data, rightchar);- showallused = i == 0 && (leftchar < start || rightchar > end);- }- else showallused = FALSE;-- if (showallused)- {- PCHARS(lleft, pp, leftchar, start - leftchar, utf, outfile);- PCHARS(lmiddle, pp, start, end - start, utf, outfile);- PCHARS(lright, pp, end, rightchar - end, utf, outfile);- if ((pat_patctl.control & CTL_JITVERIFY) != 0 && jit_was_used)- fprintf(outfile, " (JIT)");- fprintf(outfile, "\n ");- for (j = 0; j < lleft; j++) fprintf(outfile, "<");- for (j = 0; j < lmiddle; j++) fprintf(outfile, " ");- for (j = 0; j < lright; j++) fprintf(outfile, ">");- }-- /* When a pattern contains \K, the start of match position may be- different to the start of the matched string. When this is the case,- show it when requested. */-- else if ((dat_datctl.control & CTL_STARTCHAR) != 0)- {- PCRE2_SIZE startchar;- PCRE2_GET_STARTCHAR(startchar, match_data);- PCHARS(lleft, pp, startchar, start - startchar, utf, outfile);- PCHARSV(pp, start, end - start, utf, outfile);- if ((pat_patctl.control & CTL_JITVERIFY) != 0 && jit_was_used)- fprintf(outfile, " (JIT)");- if (startchar != start)- {- fprintf(outfile, "\n ");- for (j = 0; j < lleft; j++) fprintf(outfile, "^");- }- }-- /* Otherwise, just show the matched string. */-- else- {- PCHARSV(pp, start, end - start, utf, outfile);- if ((pat_patctl.control & CTL_JITVERIFY) != 0 && jit_was_used)- fprintf(outfile, " (JIT)");- }- }-- /* Not the main matched string. Just show it unadorned. */-- else- {- PCHARSV(pp, start, end - start, utf, outfile);- }-- fprintf(outfile, "\n");-- /* Note: don't use the start/end variables here because we want to- show the text from what is reported as the end. */-- if ((dat_datctl.control & CTL_ALLAFTERTEXT) != 0 ||- (i == 0 && (dat_datctl.control & CTL_AFTERTEXT) != 0))- {- fprintf(outfile, "%2d+ ", i/2);- PCHARSV(pp, ovector[i+1], ulen - ovector[i+1], utf, outfile);- fprintf(outfile, "\n");- }- }-- /* Output (*MARK) data if requested */-- if ((dat_datctl.control & CTL_MARK) != 0 &&- TESTFLD(match_data, mark, !=, NULL))- {- fprintf(outfile, "MK: ");- PCHARSV(CASTFLD(void *, match_data, mark), -1, -1, utf, outfile);- fprintf(outfile, "\n");- }-- /* Process copy/get strings */-- if (!copy_and_get(utf, capcount)) return PR_ABEND;-- } /* End of handling a successful match */-- /* There was a partial match. The value of ovector[0] is the bumpalong point,- that is, startchar, not any \K point that might have been passed. When JIT is- not in use, "allusedtext" may be set, in which case we indicate the leftmost- consulted character. */-- else if (capcount == PCRE2_ERROR_PARTIAL)- {- PCRE2_SIZE leftchar;- int backlength;- int rubriclength = 0;-- if ((dat_datctl.control & CTL_ALLUSEDTEXT) != 0)- {- leftchar = FLD(match_data, leftchar);- }- else leftchar = ovector[0];-- fprintf(outfile, "Partial match");- if ((dat_datctl.control & CTL_MARK) != 0 &&- TESTFLD(match_data, mark, !=, NULL))- {- fprintf(outfile, ", mark=");- PCHARS(rubriclength, CASTFLD(void *, match_data, mark), -1, -1, utf,- outfile);- rubriclength += 7;- }- fprintf(outfile, ": ");- rubriclength += 15;-- PCHARS(backlength, pp, leftchar, ovector[0] - leftchar, 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)");- fprintf(outfile, "\n");-- if (backlength != 0)- {- int i;- for (i = 0; i < rubriclength; i++) fprintf(outfile, " ");- for (i = 0; i < backlength; i++) fprintf(outfile, "<");- fprintf(outfile, "\n");- }-- if (ulen != ovector[1])- fprintf(outfile, "** ovector[1] is not equal to the subject length: "- "%ld != %ld\n", (unsigned long int)ovector[1], (unsigned long int)ulen);-- /* Process copy/get strings */-- if (!copy_and_get(utf, 1)) return PR_ABEND;-- /* "allvector" outputs the entire vector */-- if ((dat_datctl.control2 & CTL2_ALLVECTOR) != 0)- show_ovector(ovector, oveccount);-- break; /* Out of the /g loop */- } /* End of handling partial match */-- /* Failed to match. If this is a /g or /G loop, we might previously have- set g_notempty (to PCRE2_NOTEMPTY_ATSTART|PCRE2_ANCHORED) after a null match.- If that is the case, this is not necessarily the end. We want to advance the- start offset, and continue. We won't be at the end of the string - that was- checked before setting g_notempty. We achieve the effect by pretending that a- single character was matched.-- Complication arises in the case when the newline convention is "any", "crlf",- or "anycrlf". If the previous match was at the end of a line terminated by- CRLF, an advance of one character just passes the CR, whereas we should- prefer the longer newline sequence, as does the code in pcre2_match().-- Otherwise, in the case of UTF-8 or UTF-16 matching, the advance must be one- character, not one byte. */-- else if (g_notempty != 0) /* There was a previous null match */- {- uint16_t nl = FLD(compiled_code, newline_convention);- PCRE2_SIZE start_offset = dat_datctl.offset; /* Where the match was */- PCRE2_SIZE end_offset = start_offset + 1;-- if ((nl == PCRE2_NEWLINE_CRLF || nl == PCRE2_NEWLINE_ANY ||- nl == PCRE2_NEWLINE_ANYCRLF) &&- start_offset < ulen - 1 &&- CODE_UNIT(pp, start_offset) == '\r' &&- CODE_UNIT(pp, end_offset) == '\n')- end_offset++;-- else if (utf && test_mode != PCRE32_MODE)- {- if (test_mode == PCRE8_MODE)- {- for (; end_offset < ulen; end_offset++)- if ((((PCRE2_SPTR8)pp)[end_offset] & 0xc0) != 0x80) break;- }- else /* 16-bit mode */- {- for (; end_offset < ulen; end_offset++)- if ((((PCRE2_SPTR16)pp)[end_offset] & 0xfc00) != 0xdc00) break;- }- }-- SETFLDVEC(match_data, ovector, 0, start_offset);- SETFLDVEC(match_data, ovector, 1, end_offset);- } /* End of handling null match in a global loop */-- /* A "normal" match failure. There will be a negative error number in- capcount. */-- else- {- switch(capcount)- {- case PCRE2_ERROR_NOMATCH:- if (gmatched == 0)- {- fprintf(outfile, "No match");- if ((dat_datctl.control & CTL_MARK) != 0 &&- TESTFLD(match_data, mark, !=, NULL))- {- fprintf(outfile, ", mark = ");- PCHARSV(CASTFLD(void *, match_data, mark), -1, -1, utf, outfile);- }- if ((pat_patctl.control & CTL_JITVERIFY) != 0 && jit_was_used)- fprintf(outfile, " (JIT)");- fprintf(outfile, "\n");-- /* "allvector" outputs the entire vector */-- if ((dat_datctl.control2 & CTL2_ALLVECTOR) != 0)- show_ovector(ovector, oveccount);- }- break;-- case PCRE2_ERROR_BADUTFOFFSET:- fprintf(outfile, "Error %d (bad UTF-%d offset)\n", capcount, test_mode);- break;-- default:- fprintf(outfile, "Failed: error %d: ", capcount);- if (!print_error_message(capcount, "", "")) return PR_ABEND;- if (capcount <= PCRE2_ERROR_UTF8_ERR1 &&- capcount >= PCRE2_ERROR_UTF32_ERR2)- {- PCRE2_SIZE startchar;- PCRE2_GET_STARTCHAR(startchar, match_data);- fprintf(outfile, " at offset %" SIZ_FORM, startchar);- }- fprintf(outfile, "\n");- break;- }-- break; /* Out of the /g loop */- } /* End of failed match handling */-- /* Control reaches here in two circumstances: (a) after a match, and (b)- after a non-match that immediately followed a match on an empty string when- doing a global search. Such a match is done with PCRE2_NOTEMPTY_ATSTART and- PCRE2_ANCHORED set in g_notempty. The code above turns it into a fake match- of one character. So effectively we get here only after a match. If we- are not doing a global search, we are done. */-- if ((dat_datctl.control & CTL_ANYGLOB) == 0) break; else- {- PCRE2_SIZE match_offset = FLD(match_data, ovector)[0];- PCRE2_SIZE end_offset = FLD(match_data, ovector)[1];-- /* We must now set up for the next iteration of a global search. If we have- matched an empty string, first check to see if we are at the end of the- subject. If so, the loop is over. Otherwise, mimic what Perl's /g option- does. Set PCRE2_NOTEMPTY_ATSTART and PCRE2_ANCHORED and try the match again- at the same point. If this fails it will be picked up above, where a fake- match is set up so that at this point we advance to the next character.-- However, in order to cope with patterns that never match at their starting- offset (e.g. /(?<=\G.)/) we don't do this when the match offset is greater- than the starting offset. This means there will be a retry with the- starting offset at the match offset. If this returns the same match again,- it is picked up above and ignored, and the special action is then taken. */-- if (match_offset == end_offset)- {- if (end_offset == ulen) break; /* End of subject */- if (match_offset <= dat_datctl.offset)- g_notempty = PCRE2_NOTEMPTY_ATSTART | PCRE2_ANCHORED;- }-- /* However, even after matching a non-empty string, there is still one- tricky case. If a pattern contains \K within a lookbehind assertion at the- start, the end of the matched string can be at the offset where the match- started. In the case of a normal /g iteration without special action, this- leads to a loop that keeps on returning the same substring. The loop would- be caught above, but we really want to move on to the next match. */-- else- {- g_notempty = 0; /* Set for a "normal" repeat */- if ((dat_datctl.control & CTL_GLOBAL) != 0)- {- PCRE2_SIZE startchar;- PCRE2_GET_STARTCHAR(startchar, match_data);- if (end_offset <= startchar)- {- if (startchar >= ulen) break; /* End of subject */- end_offset = startchar + 1;- if (utf && test_mode != PCRE32_MODE)- {- if (test_mode == PCRE8_MODE)- {- for (; end_offset < ulen; end_offset++)- if ((((PCRE2_SPTR8)pp)[end_offset] & 0xc0) != 0x80) break;- }- else /* 16-bit mode */- {- for (; end_offset < ulen; end_offset++)- if ((((PCRE2_SPTR16)pp)[end_offset] & 0xfc00) != 0xdc00) break;- }- }- }- }- }-- /* For a normal global (/g) iteration, save the current ovector[0,1] and- the starting offset so that we can check that they do change each time.- Otherwise a matching bug that returns the same string causes an infinite- loop. It has happened! Then update the start offset, leaving other- parameters alone. */-- if ((dat_datctl.control & CTL_GLOBAL) != 0)- {- ovecsave[0] = ovector[0];- ovecsave[1] = ovector[1];- ovecsave[2] = dat_datctl.offset;- dat_datctl.offset = end_offset;- }-- /* For altglobal, just update the pointer and length. */-- else- {- pp += end_offset * code_unit_size;- len -= end_offset * code_unit_size;- ulen -= end_offset;- if (arg_ulen != PCRE2_ZERO_TERMINATED) arg_ulen -= end_offset;- }- }- } /* 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;-}-----/*************************************************-* Print PCRE2 version *-*************************************************/--static void-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");-}----/*************************************************-* Print Unicode version *-*************************************************/--static void-print_unicode_version(FILE *f)-{-VERSION_TYPE *vp;-fprintf(f, "Unicode version ");-for (vp = uversion; *vp != 0; vp++) fprintf(f, "%c", *vp);-}----/*************************************************-* Print JIT target *-*************************************************/--static void-print_jit_target(FILE *f)-{-VERSION_TYPE *vp;-for (vp = jittarget; *vp != 0; vp++) fprintf(f, "%c", *vp);-}----/*************************************************-* Print newline configuration *-*************************************************/--/* Output is always to stdout.--Arguments:- rc the return code from PCRE2_CONFIG_NEWLINE- isc TRUE if called from "-C newline"-Returns: nothing-*/--static void-print_newline_config(uint32_t optval, BOOL isc)-{-if (!isc) printf(" Default newline sequence is ");-if (optval < sizeof(newlines)/sizeof(char *))- printf("%s\n", newlines[optval]);-else- printf("a non-standard value: %d\n", optval);-}----/*************************************************-* Usage function *-*************************************************/--static void-usage(void)-{-printf("Usage: pcre2test [options] [<input file> [<output file>]]\n\n");-printf("Input and output default to stdin and stdout.\n");-#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)-printf("If input is a terminal, readline() is used to read from it.\n");-#else-printf("This version of pcre2test is not linked with readline().\n");-#endif-printf("\nOptions:\n");-#ifdef SUPPORT_PCRE2_8-printf(" -8 use the 8-bit library\n");-#endif-#ifdef SUPPORT_PCRE2_16-printf(" -16 use the 16-bit library\n");-#endif-#ifdef SUPPORT_PCRE2_32-printf(" -32 use the 32-bit library\n");-#endif-printf(" -ac set default pattern modifier PCRE2_AUTO_CALLOUT\n");-printf(" -AC as -ac, but also set subject 'callout_extra' modifier\n");-printf(" -b set default pattern modifier 'fullbincode'\n");-printf(" -C show PCRE2 compile-time options and exit\n");-printf(" -C arg show a specific compile-time option and exit with its\n");-printf(" value if numeric (else 0). The arg can be:\n");-printf(" backslash-C use of \\C is enabled [0, 1]\n");-printf(" bsr \\R type [ANYCRLF, ANY]\n");-printf(" ebcdic compiled for EBCDIC character code [0,1]\n");-printf(" ebcdic-nl NL code if compiled for EBCDIC\n");-printf(" jit just-in-time compiler supported [0, 1]\n");-printf(" linksize internal link size [2, 3, 4]\n");-printf(" newline newline type [CR, LF, CRLF, ANYCRLF, ANY, NUL]\n");-printf(" pcre2-8 8 bit library support enabled [0, 1]\n");-printf(" pcre2-16 16 bit library support enabled [0, 1]\n");-printf(" pcre2-32 32 bit library support enabled [0, 1]\n");-printf(" unicode Unicode and UTF support enabled [0, 1]\n");-printf(" -d set default pattern modifier 'debug'\n");-printf(" -dfa set default subject modifier 'dfa'\n");-printf(" -error <n,m,..> show messages for error numbers, then exit\n");-printf(" -help show usage information\n");-printf(" -i set default pattern modifier 'info'\n");-printf(" -jit set default pattern modifier 'jit'\n");-printf(" -jitfast set default pattern modifier 'jitfast'\n");-printf(" -jitverify set default pattern modifier 'jitverify'\n");-printf(" -LM list pattern and subject modifiers, then exit\n");-printf(" -LP list non-script properties, then exit\n");-printf(" -LS list supported scripts, then exit\n");-printf(" -q quiet: do not output PCRE2 version number at start\n");-printf(" -pattern <s> set default pattern modifier fields\n");-printf(" -subject <s> set default subject modifier fields\n");-printf(" -S <n> set stack size to <n> mebibytes\n");-printf(" -t [<n>] time compilation and execution, repeating <n> times\n");-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(" -v|--version show PCRE2 version and exit\n");-}----/*************************************************-* Handle -C option *-*************************************************/--/* This option outputs configuration options and sets an appropriate return-code when asked for a single option. The code is abstracted into a separate-function because of its size. Use whichever pcre2_config() function is-available.--Argument: an option name or NULL-Returns: the return code-*/--static int-c_option(const char *arg)-{-uint32_t optval;-unsigned int i = COPTLISTCOUNT;-int yield = 0;--if (arg != NULL && arg[0] != CHAR_MINUS)- {- for (i = 0; i < COPTLISTCOUNT; i++)- if (strcmp(arg, coptlist[i].name) == 0) break;-- if (i >= COPTLISTCOUNT)- {- fprintf(stderr, "** Unknown -C option '%s'\n", arg);- return 0;- }-- switch (coptlist[i].type)- {- case CONF_BSR:- (void)PCRE2_CONFIG(coptlist[i].value, &optval);- printf("%s\n", (optval == PCRE2_BSR_ANYCRLF)? "ANYCRLF" : "ANY");- break;-- case CONF_FIX:- yield = coptlist[i].value;- printf("%d\n", yield);- break;-- case CONF_FIZ:- optval = coptlist[i].value;- printf("%d\n", optval);- break;-- case CONF_INT:- (void)PCRE2_CONFIG(coptlist[i].value, &yield);- printf("%d\n", yield);- break;-- case CONF_NL:- (void)PCRE2_CONFIG(coptlist[i].value, &optval);- print_newline_config(optval, TRUE);- break;- }--/* For VMS, return the value by setting a symbol, for certain values only. This-is contributed code which the PCRE2 developers have no means of testing. */--#ifdef __VMS--/* This is the original code provided by the first VMS contributor. */-#ifdef NEVER- if (copytlist[i].type == CONF_FIX || coptlist[i].type == CONF_INT)- {- char ucname[16];- strcpy(ucname, coptlist[i].name);- for (i = 0; ucname[i] != 0; i++) ucname[i] = toupper[ucname[i]];- vms_setsymbol(ucname, 0, optval);- }-#endif--/* This is the new code, provided by a second VMS contributor. */-- if (coptlist[i].type == CONF_FIX || coptlist[i].type == CONF_INT)- {- char nam_buf[22], val_buf[4];- $DESCRIPTOR(nam, nam_buf);- $DESCRIPTOR(val, val_buf);-- strcpy(nam_buf, coptlist[i].name);- nam.dsc$w_length = strlen(nam_buf);- sprintf(val_buf, "%d", yield);- val.dsc$w_length = strlen(val_buf);- lib$set_symbol(&nam, &val);- }-#endif /* __VMS */-- return yield;- }--/* No argument for -C: output all configuration information. */--print_version(stdout, FALSE);-printf("Compiled with\n");--#ifdef EBCDIC-printf(" EBCDIC code support: LF is 0x%02x\n", CHAR_LF);-#if defined NATIVE_ZOS-printf(" EBCDIC code page %s or similar\n", pcrz_cpversion());-#endif-#endif--(void)PCRE2_CONFIG(PCRE2_CONFIG_COMPILED_WIDTHS, &optval);-if (optval & 1) printf(" 8-bit support\n");-if (optval & 2) printf(" 16-bit support\n");-if (optval & 4) printf(" 32-bit support\n");--#ifdef SUPPORT_VALGRIND-printf(" Valgrind support\n");-#endif--(void)PCRE2_CONFIG(PCRE2_CONFIG_UNICODE, &optval);-if (optval != 0)- {- printf(" UTF and UCP support (");- print_unicode_version(stdout);- printf(")\n");- }-else printf(" No Unicode support\n");--(void)PCRE2_CONFIG(PCRE2_CONFIG_JIT, &optval);-if (optval != 0)- {- printf(" Just-in-time compiler support: ");- print_jit_target(stdout);- printf("\n");- }-else- {- printf(" No just-in-time compiler support\n");- }--(void)PCRE2_CONFIG(PCRE2_CONFIG_NEWLINE, &optval);-print_newline_config(optval, FALSE);-(void)PCRE2_CONFIG(PCRE2_CONFIG_BSR, &optval);-printf(" \\R matches %s\n",- (optval == PCRE2_BSR_ANYCRLF)? "CR, LF, or CRLF only" :- "all Unicode newlines");-(void)PCRE2_CONFIG(PCRE2_CONFIG_NEVER_BACKSLASH_C, &optval);-printf(" \\C is %ssupported\n", optval? "not ":"");-(void)PCRE2_CONFIG(PCRE2_CONFIG_LINKSIZE, &optval);-printf(" Internal link size = %d\n", optval);-(void)PCRE2_CONFIG(PCRE2_CONFIG_PARENSLIMIT, &optval);-printf(" Parentheses nest limit = %d\n", optval);-(void)PCRE2_CONFIG(PCRE2_CONFIG_HEAPLIMIT, &optval);-printf(" Default heap limit = %d kibibytes\n", optval);-(void)PCRE2_CONFIG(PCRE2_CONFIG_MATCHLIMIT, &optval);-printf(" Default match limit = %d\n", optval);-(void)PCRE2_CONFIG(PCRE2_CONFIG_DEPTHLIMIT, &optval);-printf(" Default depth limit = %d\n", optval);--#if defined SUPPORT_LIBREADLINE-printf(" pcre2test has libreadline support\n");-#elif defined SUPPORT_LIBEDIT-printf(" pcre2test has libedit support\n");-#else-printf(" pcre2test has neither libreadline nor libedit support\n");-#endif--return 0;-}---/*************************************************-* Format one property/script list item *-*************************************************/--#ifdef SUPPORT_UNICODE-static void-format_list_item(int16_t *ff, char *buff, BOOL isscript)-{-int count;-int maxi = 0;-const char *maxs = "";-size_t max = 0;--for (count = 0; ff[count] >= 0; count++) {}--/* Find the name to put first. For scripts, any 3-character name is chosen.-For non-scripts, or if there is no 3-character name, take the longest. */--for (int i = 0; ff[i] >= 0; i++)- {- const char *s = PRIV(utt_names) + ff[i];- size_t len = strlen(s);- if (isscript && len == 3)- {- maxi = i;- max = len;- maxs = s;- break;- }- else if (len > max)- {- max = len;- maxi = i;- maxs = s;- }- }--strcpy(buff, maxs);-buff += max;--if (count > 1)- {- const char *sep = " (";- for (int i = 0; i < count; i++)- {- if (i == maxi) continue;- buff += sprintf(buff, "%s%s", sep, PRIV(utt_names) + ff[i]);- sep = ", ";- }- (void)sprintf(buff, ")");- }-}-#endif /* SUPPORT_UNICODE */----/*************************************************-* Display scripts or properties *-*************************************************/--#define MAX_SYNONYMS 5--static void-display_properties(BOOL wantscripts)-{-#ifndef SUPPORT_UNICODE-(void)wantscripts;-printf("** This version of PCRE2 was compiled without Unicode support.\n");-#else--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 = wantscripts? ucp_Script_Count : ucp_Bprop_Count;--for (size_t i = 0; i < PRIV(utt_size); i++)- {- int k;- int m = 0;- int16_t *fv;- const ucp_type_table *t = PRIV(utt) + i;- unsigned int value = t->value;-- if (wantscripts)- {- if (t->type != PT_SC && t->type != PT_SCX) continue;- }- else- {- if (t->type != PT_BOOL) continue;- }-- for (k = 0; k < seencount; k++)- {- if (t->type == seentypes[k] && t->value == seenvalues[k]) break;- }- if (k < seencount) continue;-- seentypes[seencount] = t->type;- seenvalues[seencount++] = t->value;-- fv = found[fc++];- fv[m++] = t->name_offset;-- for (size_t j = i + 1; j < PRIV(utt_size); j++)- {- const ucp_type_table *tt = PRIV(utt) + j;- if (tt->type != t->type || tt->value != value) continue;- if (m >= MAX_SYNONYMS)- printf("** Too many synonyms: %s ignored\n",- PRIV(utt_names) + tt->name_offset);- else fv[m++] = tt->name_offset;- }-- fv[m] = -1;- }--printf("-------------------------- SUPPORTED %s --------------------------\n\n",- wantscripts? "SCRIPTS" : "PROPERTIES");--if (!wantscripts) printf(-"This release of PCRE2 supports Unicode's general category properties such\n"-"as Lu (upper case letter), bi-directional properties such as Bidi_Class,\n"-"and the following binary (yes/no) properties:\n\n");---for (int k = 0; k < (n+1)/2; k++)- {- int x;- char buff1[128];- char buff2[128];-- format_list_item(found[k], buff1, wantscripts);- x = k + (n+1)/2;- if (x < n) format_list_item(found[x], buff2, wantscripts);- else buff2[0] = 0;-- x = printf("%s", buff1);- while (x++ < colwidth) printf(" ");- printf("%s\n", buff2);- }--#endif /* SUPPORT_UNICODE */-}----/*************************************************-* Display one modifier *-*************************************************/--static void-display_one_modifier(modstruct *m, BOOL for_pattern)-{-uint32_t c = (!for_pattern && (m->which == MOD_PND || m->which == MOD_PNDP))?- '*' : ' ';-printf("%c%s", c, m->name);-for (size_t i = 0; i < C1MODLISTCOUNT; i++)- {- if (strcmp(m->name, c1modlist[i].fullname) == 0)- printf(" (%c)", c1modlist[i].onechar);- }-}----/*************************************************-* Display pattern or subject modifiers *-*************************************************/--/* In order to print in two columns, first scan without printing to get a list-of the modifiers that are required.--Arguments:- for_pattern TRUE for pattern modifiers, FALSE for subject modifiers- title string to be used in title--Returns: nothing-*/--static void-display_selected_modifiers(BOOL for_pattern, const char *title)-{-uint32_t i, j;-uint32_t n = 0;-uint32_t list[MODLISTCOUNT];-uint32_t extra[MODLISTCOUNT];--for (i = 0; i < MODLISTCOUNT; i++)- {- BOOL is_pattern = TRUE;- modstruct *m = modlist + i;-- switch (m->which)- {- case MOD_CTC: /* Compile context */- case MOD_PAT: /* Pattern */- case MOD_PATP: /* Pattern, OK for Perl-compatible test */- break;-- /* The MOD_PND and MOD_PNDP modifiers are precisely those that affect- subjects, but can be given with a pattern. We list them as subject- modifiers, but marked with an asterisk.*/-- case MOD_CTM: /* Match context */- case MOD_DAT: /* Subject line */- case MOD_DATP: /* Subject line, OK for Perl-compatible test */- case MOD_PND: /* As PD, but not default pattern */- case MOD_PNDP: /* As PND, OK for Perl-compatible test */- is_pattern = FALSE;- break;-- default: printf("** Unknown type for modifier '%s'\n", m->name);- /* Fall through */- case MOD_PD: /* Pattern or subject */- case MOD_PDP: /* As PD, OK for Perl-compatible test */- is_pattern = for_pattern;- break;- }-- if (for_pattern == is_pattern)- {- extra[n] = 0;- for (size_t k = 0; k < C1MODLISTCOUNT; k++)- {- if (strcmp(m->name, c1modlist[k].fullname) == 0)- {- extra[n] += 4;- break;- }- }- list[n++] = i;- }- }--/* Now print from the list in two columns. */--printf("-------------- %s MODIFIERS --------------\n", title);--for (i = 0, j = (n+1)/2; i < (n+1)/2; i++, j++)- {- modstruct *m = modlist + list[i];- display_one_modifier(m, for_pattern);- if (j < n)- {- uint32_t k = 27 - strlen(m->name) - extra[i];- while (k-- > 0) printf(" ");- display_one_modifier(modlist + list[j], for_pattern);- }- printf("\n");- }-}----/*************************************************-* Display the list of modifiers *-*************************************************/--static void-display_modifiers(void)-{-printf(- "An asterisk on a subject modifier means that it may be given on a pattern\n"- "line, in order to apply to all subjects matched by that pattern. Modifiers\n"- "that are listed for both patterns and subjects have different effects in\n"- "each case.\n\n");-display_selected_modifiers(TRUE, "PATTERN");-printf("\n");-display_selected_modifiers(FALSE, "SUBJECT");-}----/*************************************************-* Main Program *-*************************************************/--int-main(int argc, char **argv)-{-uint32_t temp;-uint32_t yield = 0;-uint32_t op = 1;-BOOL notdone = TRUE;-BOOL quiet = FALSE;-BOOL showtotaltimes = FALSE;-BOOL skipping = FALSE;-char *arg_subject = NULL;-char *arg_pattern = NULL;-char *arg_error = NULL;--/* The offsets to the options and control bits fields of the pattern and data-control blocks must be the same so that common options and controls such as-"anchored" or "memory" can work for either of them from a single table entry.-We cannot test this till runtime because "offsetof" does not work in the-preprocessor. */--if (PO(options) != DO(options) || PO(control) != DO(control) ||- PO(control2) != DO(control2))- {- fprintf(stderr, "** Coding error: "- "options and control offsets for pattern and data must be the same.\n");- return 1;- }--/* Get the PCRE2 and Unicode version number and JIT target information, at the-same time checking that a request for the length gives the same answer. Also-check lengths for non-string items. */--if (PCRE2_CONFIG(PCRE2_CONFIG_VERSION, NULL) !=- PCRE2_CONFIG(PCRE2_CONFIG_VERSION, version) ||-- PCRE2_CONFIG(PCRE2_CONFIG_UNICODE_VERSION, NULL) !=- PCRE2_CONFIG(PCRE2_CONFIG_UNICODE_VERSION, uversion) ||-- PCRE2_CONFIG(PCRE2_CONFIG_JITTARGET, NULL) !=- PCRE2_CONFIG(PCRE2_CONFIG_JITTARGET, jittarget) ||-- PCRE2_CONFIG(PCRE2_CONFIG_UNICODE, NULL) != sizeof(uint32_t) ||- PCRE2_CONFIG(PCRE2_CONFIG_MATCHLIMIT, NULL) != sizeof(uint32_t))- {- fprintf(stderr, "** Error in pcre2_config(): bad length\n");- return 1;- }--/* Check that bad options are diagnosed. */--if (PCRE2_CONFIG(999, NULL) != PCRE2_ERROR_BADOPTION ||- PCRE2_CONFIG(999, &temp) != PCRE2_ERROR_BADOPTION)- {- fprintf(stderr, "** Error in pcre2_config(): bad option not diagnosed\n");- return 1;- }--/* This configuration option is now obsolete, but running a quick check ensures-that its code is covered. */--(void)PCRE2_CONFIG(PCRE2_CONFIG_STACKRECURSE, &temp);--/* Get buffers from malloc() so that valgrind will check their misuse when-debugging. They grow automatically when very long lines are read. The 16--and 32-bit buffers (pbuffer16, pbuffer32) are obtained only if needed. */--buffer = (uint8_t *)malloc(pbuffer8_size);-pbuffer8 = (uint8_t *)malloc(pbuffer8_size);--/* The following _setmode() stuff is some Windows magic that tells its runtime-library to translate CRLF into a single LF character. At least, that's what-I've been told: never having used Windows I take this all on trust. Originally-it set 0x8000, but then I was advised that _O_BINARY was better. */--#if defined(_WIN32) || defined(WIN32)-_setmode( _fileno( stdout ), _O_BINARY );-#endif--/* Initialization that does not depend on the running mode. */--locale_name[0] = 0;--memset(&def_patctl, 0, sizeof(patctl));-def_patctl.convert_type = CONVERT_UNSET;--memset(&def_datctl, 0, sizeof(datctl));-def_datctl.oveccount = DEFAULT_OVECCOUNT;-def_datctl.copy_numbers[0] = -1;-def_datctl.get_numbers[0] = -1;-def_datctl.startend[0] = def_datctl.startend[1] = CFORE_UNSET;-def_datctl.cerror[0] = def_datctl.cerror[1] = CFORE_UNSET;-def_datctl.cfail[0] = def_datctl.cfail[1] = CFORE_UNSET;--/* Scan command line options. */--while (argc > 1 && argv[op][0] == '-' && argv[op][1] != 0)- {- char *endptr;- char *arg = argv[op];- unsigned long uli;-- /* List modifiers and exit. */-- if (strcmp(arg, "-LM") == 0)- {- display_modifiers();- goto EXIT;- }-- /* List properties and exit */-- if (strcmp(arg, "-LP") == 0)- {- display_properties(FALSE);- goto EXIT;- }-- /* List scripts and exit */-- if (strcmp(arg, "-LS") == 0)- {- display_properties(TRUE);- goto EXIT;- }-- /* Display and/or set return code for configuration options. */-- if (strcmp(arg, "-C") == 0)- {- yield = c_option(argv[op + 1]);- goto EXIT;- }-- /* Select operating mode. Ensure that pcre2_config() is called in 16-bit- and 32-bit modes because that won't happen naturally when 8-bit is also- configured. Also call some other functions that are not otherwise used. This- means that a coverage report won't claim there are uncalled functions. */-- if (strcmp(arg, "-8") == 0)- {-#ifdef SUPPORT_PCRE2_8- test_mode = PCRE8_MODE;- (void)pcre2_set_bsr_8(pat_context8, 999);- (void)pcre2_set_newline_8(pat_context8, 999);-#else- fprintf(stderr,- "** This version of PCRE2 was built without 8-bit support\n");- exit(1);-#endif- }-- else if (strcmp(arg, "-16") == 0)- {-#ifdef SUPPORT_PCRE2_16- test_mode = PCRE16_MODE;- (void)pcre2_config_16(PCRE2_CONFIG_VERSION, NULL);- (void)pcre2_set_bsr_16(pat_context16, 999);- (void)pcre2_set_newline_16(pat_context16, 999);-#else- fprintf(stderr,- "** This version of PCRE2 was built without 16-bit support\n");- exit(1);-#endif- }-- else if (strcmp(arg, "-32") == 0)- {-#ifdef SUPPORT_PCRE2_32- test_mode = PCRE32_MODE;- (void)pcre2_config_32(PCRE2_CONFIG_VERSION, NULL);- (void)pcre2_set_bsr_32(pat_context32, 999);- (void)pcre2_set_newline_32(pat_context32, 999);-#else- fprintf(stderr,- "** This version of PCRE2 was built without 32-bit support\n");- exit(1);-#endif- }-- /* Set quiet (no version verification) */-- else if (strcmp(arg, "-q") == 0) quiet = TRUE;-- /* Set system stack size */-- else if (strcmp(arg, "-S") == 0 && argc > 2 &&- ((uli = strtoul(argv[op+1], &endptr, 10)), *endptr == 0))- {-#if defined(_WIN32) || defined(WIN32) || defined(__HAIKU__) || defined(NATIVE_ZOS) || defined(__VMS)- fprintf(stderr, "pcre2test: -S is not supported on this OS\n");- exit(1);-#else- int rc;- uint32_t stack_size;- struct rlimit rlim;- if (U32OVERFLOW(uli))- {- fprintf(stderr, "** Argument for -S is too big\n");- exit(1);- }- stack_size = (uint32_t)uli;- getrlimit(RLIMIT_STACK, &rlim);- rlim.rlim_cur = stack_size * 1024 * 1024;- if (rlim.rlim_cur > rlim.rlim_max)- {- fprintf(stderr,- "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);- if (rc != 0)- {- fprintf(stderr, "pcre2test: setting stack size %luMiB failed: %s\n",- (unsigned long int)stack_size, strerror(errno));- exit(1);- }- op++;- argc--;-#endif- }-- /* Set some common pattern and subject controls */-- else if (strcmp(arg, "-AC") == 0)- {- def_patctl.options |= PCRE2_AUTO_CALLOUT;- def_datctl.control2 |= CTL2_CALLOUT_EXTRA;- }- else if (strcmp(arg, "-ac") == 0) def_patctl.options |= PCRE2_AUTO_CALLOUT;- else if (strcmp(arg, "-b") == 0) def_patctl.control |= CTL_FULLBINCODE;- else if (strcmp(arg, "-d") == 0) def_patctl.control |= CTL_DEBUG;- else if (strcmp(arg, "-dfa") == 0) def_datctl.control |= CTL_DFA;- else if (strcmp(arg, "-i") == 0) def_patctl.control |= CTL_INFO;- else if (strcmp(arg, "-jit") == 0 || strcmp(arg, "-jitverify") == 0 ||- strcmp(arg, "-jitfast") == 0)- {- if (arg[4] == 'v') def_patctl.control |= CTL_JITVERIFY;- else if (arg[4] == 'f') def_patctl.control |= CTL_JITFAST;- def_patctl.jit = JIT_DEFAULT; /* full & partial */-#ifndef SUPPORT_JIT- fprintf(stderr, "** Warning: JIT support is not available: "- "-jit[fast|verify] calls functions that do nothing.\n");-#endif- }-- /* Set timing parameters */-- else if (strcmp(arg, "-t") == 0 || strcmp(arg, "-tm") == 0 ||- strcmp(arg, "-T") == 0 || strcmp(arg, "-TM") == 0)- {- int both = arg[2] == 0;- showtotaltimes = arg[1] == 'T';- if (argc > 2 && (uli = strtoul(argv[op+1], &endptr, 10), *endptr == 0))- {- if (uli == 0)- {- fprintf(stderr, "** Argument for %s must not be zero\n", arg);- exit(1);- }- if (U32OVERFLOW(uli))- {- fprintf(stderr, "** Argument for %s is too big\n", arg);- exit(1);- }- timeitm = (int)uli;- op++;- argc--;- }- else timeitm = LOOPREPEAT;- if (both) timeit = timeitm;- }-- /* Give help */-- else if (strcmp(arg, "-help") == 0 ||- strcmp(arg, "--help") == 0)- {- usage();- goto EXIT;- }-- /* Show version */-- else if (memcmp(arg, "-v", 2) == 0 ||- strcmp(arg, "--version") == 0)- {- print_version(stdout, FALSE);- goto EXIT;- }-- /* The following options save their data for processing once we know what- the running mode is. */-- else if (strcmp(arg, "-error") == 0)- {- arg_error = argv[op+1];- goto CHECK_VALUE_EXISTS;- }-- else if (strcmp(arg, "-subject") == 0)- {- arg_subject = argv[op+1];- goto CHECK_VALUE_EXISTS;- }-- else if (strcmp(arg, "-pattern") == 0)- {- arg_pattern = argv[op+1];- CHECK_VALUE_EXISTS:- if (argc <= 2)- {- fprintf(stderr, "** Missing value for %s\n", arg);- yield = 1;- goto EXIT;- }- op++;- argc--;- }-- /* Unrecognized option */-- else- {- fprintf(stderr, "** Unknown or malformed option '%s'\n", arg);- usage();- yield = 1;- goto EXIT;- }- op++;- argc--;- }--/* If -error was present, get the error numbers, show the messages, and exit.-We wait to do this until we know which mode we are in. */--if (arg_error != NULL)- {- int len;- int errcode;- char *endptr;--/* Ensure the relevant non-8-bit buffer is available. Ensure that it is at-least 128 code units, because it is used for retrieving error messages. */--#ifdef SUPPORT_PCRE2_16- if (test_mode == PCRE16_MODE)- {- pbuffer16_size = 256;- pbuffer16 = (uint16_t *)malloc(pbuffer16_size);- if (pbuffer16 == NULL)- {- fprintf(stderr, "pcre2test: malloc(%" SIZ_FORM ") failed for pbuffer16\n",- pbuffer16_size);- yield = 1;- goto EXIT;- }- }-#endif--#ifdef SUPPORT_PCRE2_32- if (test_mode == PCRE32_MODE)- {- pbuffer32_size = 512;- pbuffer32 = (uint32_t *)malloc(pbuffer32_size);- if (pbuffer32 == NULL)- {- fprintf(stderr, "pcre2test: malloc(%" SIZ_FORM ") failed for pbuffer32\n",- pbuffer32_size);- yield = 1;- goto EXIT;- }- }-#endif-- /* Loop along a list of error numbers. */-- for (;;)- {- errcode = strtol(arg_error, &endptr, 10);- if (*endptr != 0 && *endptr != CHAR_COMMA)- {- fprintf(stderr, "** '%s' is not a valid error number list\n", arg_error);- yield = 1;- goto EXIT;- }- printf("Error %d: ", errcode);- PCRE2_GET_ERROR_MESSAGE(len, errcode, pbuffer);- if (len < 0)- {- switch (len)- {- case PCRE2_ERROR_BADDATA:- printf("PCRE2_ERROR_BADDATA (unknown error number)");- break;-- case PCRE2_ERROR_NOMEMORY:- printf("PCRE2_ERROR_NOMEMORY (buffer too small)");- break;-- default:- printf("Unexpected return (%d) from pcre2_get_error_message()", len);- break;- }- }- else- {- PCHARSV(CASTVAR(void *, pbuffer), 0, len, FALSE, stdout);- }- printf("\n");- if (*endptr == 0) goto EXIT;- arg_error = endptr + 1;- }- /* Control never reaches here */- } /* End of -error handling */--/* Initialize things that cannot be done until we know which test mode we are-running in. Exercise the general context copying and match data size functions,-which are not otherwise used. */--code_unit_size = test_mode/8;-max_oveccount = DEFAULT_OVECCOUNT;--/* Use macros to save a lot of duplication. */--#define CREATECONTEXTS \- G(general_context,BITS) = G(pcre2_general_context_create_,BITS)(&my_malloc, &my_free, NULL); \- G(general_context_copy,BITS) = G(pcre2_general_context_copy_,BITS)(G(general_context,BITS)); \- G(default_pat_context,BITS) = G(pcre2_compile_context_create_,BITS)(G(general_context,BITS)); \- G(pat_context,BITS) = G(pcre2_compile_context_copy_,BITS)(G(default_pat_context,BITS)); \- G(default_dat_context,BITS) = G(pcre2_match_context_create_,BITS)(G(general_context,BITS)); \- G(dat_context,BITS) = G(pcre2_match_context_copy_,BITS)(G(default_dat_context,BITS)); \- G(default_con_context,BITS) = G(pcre2_convert_context_create_,BITS)(G(general_context,BITS)); \- G(con_context,BITS) = G(pcre2_convert_context_copy_,BITS)(G(default_con_context,BITS)); \- G(match_data,BITS) = G(pcre2_match_data_create_,BITS)(max_oveccount, G(general_context,BITS))--#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_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. */--#ifdef SUPPORT_PCRE2_8-#undef BITS-#define BITS 8-if (test_mode == PCRE8_MODE)- {- CREATECONTEXTS;- CONTEXTTESTS;- }-#endif--#ifdef SUPPORT_PCRE2_16-#undef BITS-#define BITS 16-if (test_mode == PCRE16_MODE)- {- CREATECONTEXTS;- CONTEXTTESTS;- }-#endif--#ifdef SUPPORT_PCRE2_32-#undef BITS-#define BITS 32-if (test_mode == PCRE32_MODE)- {- CREATECONTEXTS;- CONTEXTTESTS;- }-#endif--/* Set a default parentheses nest limit that is large enough to run the-standard tests (this also exercises the function). */--PCRE2_SET_PARENS_NEST_LIMIT(default_pat_context, PARENS_NEST_DEFAULT);--/* Handle command line modifier settings, sending any error messages to-stderr. We need to know the mode before modifying the context, and it is tidier-to do them all in the same way. */--outfile = stderr;-if ((arg_pattern != NULL &&- !decode_modifiers((uint8_t *)arg_pattern, CTX_DEFPAT, &def_patctl, NULL)) ||- (arg_subject != NULL &&- !decode_modifiers((uint8_t *)arg_subject, CTX_DEFDAT, NULL, &def_datctl)))- {- yield = 1;- goto EXIT;- }--/* Sort out the input and output files, defaulting to stdin/stdout. */--infile = stdin;-outfile = stdout;--if (argc > 1 && strcmp(argv[op], "-") != 0)- {- infile = fopen(argv[op], INPUT_MODE);- if (infile == NULL)- {- printf("** Failed to open '%s': %s\n", argv[op], strerror(errno));- yield = 1;- goto EXIT;- }- }--#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)-if (INTERACTIVE(infile)) using_history();-#endif--if (argc > 2)- {- outfile = fopen(argv[op+1], OUTPUT_MODE);- if (outfile == NULL)- {- printf("** Failed to open '%s': %s\n", argv[op+1], strerror(errno));- yield = 1;- goto EXIT;- }- }--/* Output a heading line unless quiet, then process input lines. */--if (!quiet) print_version(outfile, TRUE);--SET(compiled_code, NULL);--#ifdef SUPPORT_PCRE2_8-preg.re_pcre2_code = NULL;-preg.re_match_data = NULL;-#endif--while (notdone)- {- uint8_t *p;- int rc = PR_OK;- BOOL expectdata = TEST(compiled_code, !=, NULL);-#ifdef SUPPORT_PCRE2_8- expectdata |= preg.re_pcre2_code != NULL;-#endif-- if (extend_inputline(infile, buffer, expectdata? "data> " : " re> ") == NULL)- break;- if (!INTERACTIVE(infile)) fprintf(outfile, "%s", (char *)buffer);- fflush(outfile);- p = buffer;-- /* If we have a pattern set up for testing, or we are skipping after a- compile failure, a blank line terminates this test. */-- if (expectdata || skipping)- {- while (isspace(*p)) p++;- if (*p == 0)- {-#ifdef SUPPORT_PCRE2_8- if (preg.re_pcre2_code != NULL)- {- regfree(&preg);- preg.re_pcre2_code = NULL;- preg.re_match_data = NULL;- }-#endif /* SUPPORT_PCRE2_8 */- if (TEST(compiled_code, !=, NULL))- {- SUB1(pcre2_code_free, compiled_code);- SET(compiled_code, NULL);- }- skipping = FALSE;- setlocale(LC_CTYPE, "C");- }-- /* Otherwise, if we are not skipping, and the line is not a data comment- line starting with "\=", process a data line. */-- else if (!skipping && !(p[0] == '\\' && p[1] == '=' && isspace(p[2])))- {- rc = process_data();- }- }-- /* We do not have a pattern set up for testing. Lines starting with # are- either comments or special commands. Blank lines are ignored. Otherwise, the- line must start with a valid delimiter. It is then processed as a pattern- line. A copy of the pattern is left in pbuffer8 for use by callouts. Under- valgrind, make the unused part of the buffer undefined, to catch overruns. */-- else if (*p == '#')- {- if (isspace(p[1]) || p[1] == '!' || p[1] == 0) continue;- rc = process_command();- }-- else if (strchr("/!\"'`%&-=_:;,@~", *p) != NULL)- {- rc = process_pattern();- dfa_matched = 0;- }-- else- {- while (isspace(*p)) p++;- if (*p != 0)- {- fprintf(outfile, "** Invalid pattern delimiter '%c' (x%x).\n", *buffer,- *buffer);- rc = PR_SKIP;- }- }-- if (rc == PR_SKIP && !INTERACTIVE(infile)) skipping = TRUE;- else if (rc == PR_ABEND)- {- fprintf(outfile, "** pcre2test run abandoned\n");- yield = 1;- goto EXIT;- }- }--/* Finish off a normal run. */--if (INTERACTIVE(infile)) fprintf(outfile, "\n");--if (showtotaltimes)- {- const char *pad = "";- fprintf(outfile, "--------------------------------------\n");- if (timeit > 0)- {- 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 %8.2f microseconds\n",- ((1000000 / CLOCKS_PER_SEC) * (double)total_jit_compile_time) / \- timeit);- pad = " ";- }- fprintf(outfile, "Total match time %s%8.2f microseconds\n", pad,- ((1000000 / CLOCKS_PER_SEC) * (double)total_match_time) / timeitm);- }---EXIT:--#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)-if (infile != NULL && INTERACTIVE(infile)) clear_history();-#endif--if (infile != NULL && infile != stdin) fclose(infile);-if (outfile != NULL && outfile != stdout) fclose(outfile);--free(buffer);-free(dbuffer);-free(pbuffer8);-free(dfa_workspace);-free(tables3);-PCRE2_MAKETABLES_FREE(general_context, (void *)locale_tables);-PCRE2_MATCH_DATA_FREE(match_data);-SUB1(pcre2_code_free, compiled_code);--while(patstacknext-- > 0)- {- SET(compiled_code, patstack[patstacknext]);- SUB1(pcre2_code_free, compiled_code);- }--PCRE2_JIT_FREE_UNUSED_MEMORY(general_context);-if (jit_stack != NULL)- {- PCRE2_JIT_STACK_FREE(jit_stack);- }--#define FREECONTEXTS \- G(pcre2_general_context_free_,BITS)(G(general_context,BITS)); \- G(pcre2_general_context_free_,BITS)(G(general_context_copy,BITS)); \- G(pcre2_compile_context_free_,BITS)(G(pat_context,BITS)); \- G(pcre2_compile_context_free_,BITS)(G(default_pat_context,BITS)); \- G(pcre2_match_context_free_,BITS)(G(dat_context,BITS)); \- G(pcre2_match_context_free_,BITS)(G(default_dat_context,BITS)); \- G(pcre2_convert_context_free_,BITS)(G(default_con_context,BITS)); \- G(pcre2_convert_context_free_,BITS)(G(con_context,BITS));--#ifdef SUPPORT_PCRE2_8-#undef BITS-#define BITS 8-if (preg.re_pcre2_code != NULL) regfree(&preg);-FREECONTEXTS;-#endif--#ifdef SUPPORT_PCRE2_16-#undef BITS-#define BITS 16-free(pbuffer16);-FREECONTEXTS;-#endif--#ifdef SUPPORT_PCRE2_32-#undef BITS-#define BITS 32-free(pbuffer32);-FREECONTEXTS;-#endif++#if defined HAVE_CONFIG_H && !defined PCRE2_CONFIG_H_IDEMPOTENT_GUARD+#define PCRE2_CONFIG_H_IDEMPOTENT_GUARD+#include "config.h"+#endif++++#include <ctype.h>+#include <stdio.h>+#include <string.h>+#include <stdarg.h>+#include <stdlib.h>+#include <time.h>+#include <locale.h>+#include <errno.h>++#if defined NATIVE_ZOS+#include "pcrzoscs.h"+/* That header is not included in the main PCRE2 distribution because other+apparatus is needed to compile pcre2test for z/OS. The header can be found in+the special z/OS distribution, which is available from www.zaconsultants.net or+from www.cbttape.org. */+#endif++#ifdef HAVE_UNISTD_H+#include <unistd.h>+#endif++/* Debugging code enabler */++/* #define DEBUG_SHOW_MALLOC_ADDRESSES */++/* Both libreadline and libedit are optionally supported */+#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)+#if defined(SUPPORT_LIBREADLINE)+#include <readline/readline.h>+#include <readline/history.h>+#else+#if defined(HAVE_EDITLINE_READLINE_H)+#include <editline/readline.h>+#elif defined(HAVE_EDIT_READLINE_READLINE_H)+#include <edit/readline/readline.h>+#else+#include <readline.h>+/* GNU readline defines this macro but libedit doesn't, if that ever changes+this needs to be updated or the build could break */+#ifdef RL_VERSION_MAJOR+#include <history.h>+#endif+#endif+#endif+#endif++/* Put the test for interactive input into a macro so that it can be changed if+required for different environments. */++#define INTERACTIVE(f) isatty(fileno(f))+++/* ---------------------- System-specific definitions ---------------------- */++/* A number of things vary for Windows builds. Originally, pcretest opened its+input and output without "b"; then I was told that "b" was needed in some+environments, so it was added for release 5.0 to both the input and output. (It+makes no difference on Unix-like systems.) Later I was told that it is wrong+for the input on Windows. I've now abstracted the modes into macros that are+set here, to make it easier to fiddle with them, and removed "b" from the input+mode under Windows. The BINARY versions are used when saving/restoring compiled+patterns. */++#if defined(_WIN32) || defined(WIN32)+#include <io.h> /* For _setmode() */+#include <fcntl.h> /* For _O_BINARY */+#define INPUT_MODE "r"+#define OUTPUT_MODE "wb"+#define BINARY_INPUT_MODE "rb"+#define BINARY_OUTPUT_MODE "wb"++#ifndef isatty+#define isatty _isatty /* This is what Windows calls them, I'm told, */+#endif /* though in some environments they seem to */+ /* be already defined, hence the #ifndefs. */+#ifndef fileno+#define fileno _fileno+#endif++/* A user sent this fix for Borland Builder 5 under Windows. */++#ifdef __BORLANDC__+#define _setmode(handle, mode) setmode(handle, mode)+#endif++/* Not Windows */++#else+#include <sys/time.h> /* These two includes are needed */+#include <sys/resource.h> /* for setrlimit(). */+#if defined NATIVE_ZOS /* z/OS uses non-binary I/O */+#define INPUT_MODE "r"+#define OUTPUT_MODE "w"+#define BINARY_INPUT_MODE "rb"+#define BINARY_OUTPUT_MODE "wb"+#else+#define INPUT_MODE "rb"+#define OUTPUT_MODE "wb"+#define BINARY_INPUT_MODE "rb"+#define BINARY_OUTPUT_MODE "wb"+#endif+#endif++/* VMS-specific code was included as suggested by a VMS user [1]. Another VMS+user [2] provided alternative code which worked better for him. I have+commented out the original, but kept it around just in case. */++#ifdef __VMS+#include <ssdef.h>+/* These two includes came from [2]. */+#include descrip+#include lib$routines+/* void vms_setsymbol( char *, char *, int ); Original code from [1]. */+#endif++/* old VC and older compilers don't support %td or %zu, and even some that+claim to be C99 don't support it (hence DISABLE_PERCENT_ZT). */++#if defined(DISABLE_PERCENT_ZT) || (defined(_MSC_VER) && (_MSC_VER < 1800)) || \+ (!defined(_MSC_VER) && (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)))+#ifdef _WIN64+#define PTR_FORM "lld"+#define SIZ_FORM "llu"+#else+#define PTR_FORM "ld"+#define SIZ_FORM "lu"+#endif+#else+#define PTR_FORM "td"+#define SIZ_FORM "zu"+#endif++/* ------------------End of system-specific definitions -------------------- */++/* Glueing macros that are used in several places below. */++#define glue(a,b) a##b+#define G(a,b) glue(a,b)++#define stringify(x) #x+#define STR(x) stringify(x)++/* Miscellaneous parameters and manifests */++#ifndef CLOCKS_PER_SEC+#ifdef CLK_TCK+#define CLOCKS_PER_SEC CLK_TCK+#else+#define CLOCKS_PER_SEC 100+#endif+#endif++#define CFORE_UNSET UINT32_MAX /* Unset value for startend/cfail/cerror fields */+#define CONVERT_UNSET UINT32_MAX /* Unset value for convert_type/convert_length fields */+#define MOD_STR_UNSET UINT8_MAX /* Sentinel length for unset string options */+#define DFA_WS_DIMENSION 1000 /* Size of DFA workspace */+#define DEFAULT_OVECCOUNT 15 /* Default ovector count */+#define JUNK_OFFSET 0xdeadbeef /* For initializing ovector */+#define LOCALESIZE 32 /* Size of locale name */+#define LOOPREPEAT 500000 /* Default loop count for timing */+#define MALLOCLISTSIZE 20 /* For remembering mallocs */+#define PARENS_NEST_DEFAULT 220 /* Default parentheses nest limit */+#define PATSTACKSIZE 20 /* Pattern stack for save/restore testing */+#define REPLACE_MODSIZE 100 /* Field for reading 8-bit replacement */+#define SUBSTITUTE_SUBJECT_MODSIZE 100 /* Field for reading 8-bit subject for substitute */+#define VERSION_SIZE 64 /* Size of buffer for the version strings */+#define REPLACE_BUFFSIZE 256 /* Code units for replacement buffer */++/* Default JIT compile options */++#define JIT_DEFAULT (PCRE2_JIT_COMPLETE|\+ PCRE2_JIT_PARTIAL_SOFT|\+ PCRE2_JIT_PARTIAL_HARD)++/* Execution modes */++#define PCRE2TEST_MODE_8 8+#define PCRE2TEST_MODE_16 16+#define PCRE2TEST_MODE_32 32++/* Processing returns */++enum { PR_OK, PR_SKIP, PR_ABEND, PR_ENDIF };++/* The macro EBCDIC_IO describes whether pcre2tests takes ASCII or EBCDIC as+its input files (or terminal input). If the compiler uses ASCII for character+literals, then we make pcre2test take ASCII as its input and output. This is+different to the core PCRE2 library, where we use macros like "CHAR_A" for every+single character and string literal used in pattern parsing and matching. It+would simply be too arduous to do the same for pcre2test, so we make its+input/output format match the compiler's codepage. */+#if defined(EBCDIC) && 'a' == 0x81+#define EBCDIC_IO 1+#else+#define EBCDIC_IO 0+#endif++/* The macro PRINTABLE determines whether to print an output character as-is or+as a hex value when showing compiled patterns. We use it in cases when the+locale has not been explicitly changed, so as to get consistent output from+systems that differ in their output from isprint() even in the "C" locale. */++#if defined(EBCDIC)+#define PRINTABLE(c) printable(c)+#else+#define PRINTABLE(c) ((c) >= 32 && (c) < 127)+#endif++/* The macro CHAR_OUTPUT is used to output characters in pcre2test's output+format. The input character is encoded in PCRE2's native codepage (EBCDIC, if+enabled), but the output may differ in the case where pcre2test uses ASCII input+and output. */+#if defined(EBCDIC) && !EBCDIC_IO+#define CHAR_OUTPUT(c) ebcdic_to_ascii(c)+#define CHAR_OUTPUT_HEX(c) CHAR_OUTPUT(c)+#define CHAR_INPUT(c) ascii_to_ebcdic(c)+#define CHAR_INPUT_HEX(c) CHAR_INPUT(c)+#elif defined(EBCDIC)+#define CHAR_OUTPUT(c) (c)+#define CHAR_OUTPUT_HEX(c) ebcdic_to_ascii(c)+#define CHAR_INPUT(c) (c)+#define CHAR_INPUT_HEX(c) ascii_to_ebcdic(c)+#else+#define CHAR_OUTPUT(c) (c)+#define CHAR_OUTPUT_HEX(c) CHAR_OUTPUT(c)+#define CHAR_INPUT(c) (c)+#define CHAR_INPUT_HEX(c) CHAR_INPUT(c)+#endif++/* We have to include some of the library source files because we need+to use some of the macros, internal structure definitions, and other internal+values - pcre2test has "inside information" compared to an application program+that strictly follows the PCRE2 API.++Before including pcre2_internal.h we define PRIV so that it does not get+defined therein. This ensures that PRIV names in the included files do not+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.++Setting PCRE2_CODE_UNIT_WIDTH to zero cuts out all the width-specific settings+in pcre2.h and pcre2_internal.h. Defining PCRE2_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_PCRE2TEST+#include "pcre2.h"+#include "pcre2posix.h"+#include "pcre2_internal.h"++/* We need access to some of the data tables that PCRE2 uses. The previous+definition of PCRE2_PCRE2TEST makes some minor changes in the files. The+previous definition of PRIV avoids name clashes. */++#include "pcre2_tables.c"+#include "pcre2_ucd.c"++/* Forward-declarations for PRINTABLE(), etc. */++#if defined(EBCDIC)+static BOOL printable(uint32_t c);+#endif+#if defined(EBCDIC) && !EBCDIC_IO+static void ascii_to_ebcdic_str(uint8_t *buf, size_t len);+static void ebcdic_to_ascii_str(uint8_t *buf, size_t len);+#endif+#if defined(EBCDIC)+static uint32_t ascii_to_ebcdic(uint32_t c);+static uint32_t ebcdic_to_ascii(uint32_t c);+#endif++/* 32-bit integer values in the input are read by strtoul() or strtol(). The+check needed for overflow depends on whether long ints are in fact longer than+ints. They are defined not to be shorter. */++#if ULONG_MAX > UINT32_MAX+#define U32OVERFLOW(x) (x > UINT32_MAX)+#else+#define U32OVERFLOW(x) (x == UINT32_MAX)+#endif++#if LONG_MAX > INT32_MAX+#define S32OVERFLOW(x) (x > INT32_MAX || x < INT32_MIN)+#else+#define S32OVERFLOW(x) (x == INT32_MAX || x == INT32_MIN)+#endif++/* When PCRE2_CODE_UNIT_WIDTH is zero, pcre2_internal.h does not include+pcre2_intmodedep.h, which is where mode-dependent macros and structures are+defined. We can now include it for each supported code unit width. Because+PCRE2_CODE_UNIT_WIDTH was defined as zero before including pcre2.h, it will+have left PCRE2_SUFFIX defined as a no-op. We must re-define it appropriately+while including these files, and then restore it to a no-op. Because LINK_SIZE+may be changed in 16-bit mode and forced to 1 in 32-bit mode, the order of+these inclusions should not be changed. */++#undef PCRE2_SUFFIX+#undef PCRE2_CODE_UNIT_WIDTH++#ifdef SUPPORT_PCRE2_8+#define PCRE2_CODE_UNIT_WIDTH 8+#define PCRE2_SUFFIX(a) G(a,8)+#include "pcre2_intmodedep.h"+#include "pcre2_printint_inc.h"+#undef PCRE2_CODE_UNIT_WIDTH+#undef PCRE2_SUFFIX+#endif /* SUPPORT_PCRE2_8 */++#ifdef SUPPORT_PCRE2_16+#define PCRE2_CODE_UNIT_WIDTH 16+#define PCRE2_SUFFIX(a) G(a,16)+#include "pcre2_intmodedep.h"+#include "pcre2_printint_inc.h"+#undef PCRE2_CODE_UNIT_WIDTH+#undef PCRE2_SUFFIX+#endif /* SUPPORT_PCRE2_16 */++#ifdef SUPPORT_PCRE2_32+#define PCRE2_CODE_UNIT_WIDTH 32+#define PCRE2_SUFFIX(a) G(a,32)+#include "pcre2_intmodedep.h"+#include "pcre2_printint_inc.h"+#undef PCRE2_CODE_UNIT_WIDTH+#undef PCRE2_SUFFIX+#endif /* SUPPORT_PCRE2_32 */++#define PCRE2_CODE_UNIT_WIDTH 0+#include "pcre2_intmodedep.h" /* Clear out the stale macros */+#undef PCRE2_CODE_UNIT_WIDTH++#define PCRE2_SUFFIX(a) a++/* 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+code units. */++extern int valid_utf(PCRE2_SPTR8, PCRE2_SIZE, PCRE2_SIZE *);++#define PCRE2_CODE_UNIT_WIDTH 8+#undef PCRE2_SPTR+#define PCRE2_SPTR PCRE2_SPTR8+#include "pcre2_valid_utf.c"+#undef PCRE2_CODE_UNIT_WIDTH+#undef PCRE2_SPTR+#define PCRE2_SPTR PCRE2_SUFFIX(PCRE2_SPTR)++/* If we have 8-bit support, default to it; if there is also 16-or 32-bit+support, it can be selected by a command line option. If there is no 8-bit+support, there must be 16-bit or 32-bit support, so default to one of them.++The contexts just happen to be exactly the same layout on all bit-widths+(although the contents are very much not the same). For example, the 8-bit+and 16-bit match contexts have the same fields, all at the same offsets and+sizes, but the function pointers for the callouts in the 8-bit context are not+of the same type as in the 16-bit context. When we are parsing the modifier+bits, it is convenient to be able to uniformly set flags in any of the contexts,+so for that purpose only we may ignore the differences between the contexts at+different bit-widths. Choose one arbitrarily (does not need to match the+test mode). */++#if defined SUPPORT_PCRE2_8+#define DEFAULT_TEST_MODE PCRE2TEST_MODE_8+#define PCRE2_REAL_COMPILE_CONTEXT pcre2_real_compile_context_8+#define PCRE2_REAL_MATCH_CONTEXT pcre2_real_match_context_8++#elif defined SUPPORT_PCRE2_16+#define DEFAULT_TEST_MODE PCRE2TEST_MODE_16+#define PCRE2_REAL_COMPILE_CONTEXT pcre2_real_compile_context_16+#define PCRE2_REAL_MATCH_CONTEXT pcre2_real_match_context_16++#elif defined SUPPORT_PCRE2_32+#define DEFAULT_TEST_MODE PCRE2TEST_MODE_32+#define PCRE2_REAL_COMPILE_CONTEXT pcre2_real_compile_context_32+#define PCRE2_REAL_MATCH_CONTEXT pcre2_real_match_context_32+#endif++/* ------------- Structure and table for handling #-commands ------------- */++typedef struct cmdstruct {+ const char *name;+ int value;+} cmdstruct;++enum { CMD_ENDIF, CMD_FORBID_UTF, CMD_IF, CMD_LOAD, CMD_LOADTABLES,+ CMD_NEWLINE_DEFAULT, CMD_PATTERN, CMD_PERLTEST, CMD_POP, CMD_POPCOPY,+ CMD_SAVE, CMD_SUBJECT, CMD_UNKNOWN };++static cmdstruct cmdlist[] = {+ { "endif", CMD_ENDIF },+ { "forbid_utf", CMD_FORBID_UTF },+ { "if", CMD_IF },+ { "load", CMD_LOAD },+ { "loadtables", CMD_LOADTABLES },+ { "newline_default", CMD_NEWLINE_DEFAULT },+ { "pattern", CMD_PATTERN },+ { "perltest", CMD_PERLTEST },+ { "pop", CMD_POP },+ { "popcopy", CMD_POPCOPY },+ { "save", CMD_SAVE },+ { "subject", CMD_SUBJECT }};++#define cmdlistcount (sizeof(cmdlist)/sizeof(cmdstruct))++/* ------------- Structures and tables for handling modifiers -------------- */++/* Table of names for newline types. Must be kept in step with the definitions+of PCRE2_NEWLINE_xx in pcre2.h. */++static const char *newlines[] = {+ "DEFAULT", "CR", "LF", "CRLF", "ANY", "ANYCRLF", "NUL" };++/* Structure and table for handling pattern conversion types. */++typedef struct convertstruct {+ const char *name;+ uint32_t option;+} convertstruct;++static convertstruct convertlist[] = {+ { "glob", PCRE2_CONVERT_GLOB },+ { "glob_no_starstar", PCRE2_CONVERT_GLOB_NO_STARSTAR },+ { "glob_no_wild_separator", PCRE2_CONVERT_GLOB_NO_WILD_SEPARATOR },+ { "posix_basic", PCRE2_CONVERT_POSIX_BASIC },+ { "posix_extended", PCRE2_CONVERT_POSIX_EXTENDED },+ { "unset", CONVERT_UNSET }};++#define convertlistcount (sizeof(convertlist)/sizeof(convertstruct))++/* Modifier types and applicability */++enum { MOD_CTC, /* Applies to a compile context */+ MOD_CTM, /* Applies to a match context */+ MOD_PAT, /* Applies to a pattern */+ MOD_PATP, /* Ditto, OK for Perl test */+ MOD_DAT, /* Applies to a data line */+ MOD_DATP, /* Ditto, OK for Perl test */+ MOD_PD, /* Applies to a pattern or a data line */+ MOD_PDP, /* As MOD_PD, OK for Perl test */+ MOD_PND, /* As MOD_PD, but not for a default pattern */+ MOD_PNDP, /* As MOD_PND, OK for Perl test */+ MOD_CHR, /* Is a single character */+ MOD_CON, /* Is a "convert" type/options list */+ MOD_CTL, /* Is a control bit */+ MOD_BSR, /* Is a BSR value */+ MOD_IN2, /* Is one or two unsigned integers */+ MOD_INS, /* Is a signed integer */+ MOD_INT, /* Is an unsigned integer */+ MOD_IND, /* Is an unsigned integer, but no value => default */+ MOD_NL, /* Is a newline value */+ MOD_NN, /* Is a number or a name; more than one may occur */+ MOD_OPT, /* Is an option bit */+ MOD_OPTMZ, /* Is an optimization directive */+ MOD_SIZ, /* Is a PCRE2_SIZE value */+ MOD_STR }; /* Is a string; Pascal-encoded with length in first byte */++/* Control bits. Some apply to compiling, some to matching, but some can be set+either on a pattern or a data line, so they must all be distinct. There are now+so many of them that they are split into two fields. */++#define CTL_AFTERTEXT 0x00000001u+#define CTL_ALLAFTERTEXT 0x00000002u+#define CTL_ALLCAPTURES 0x00000004u+#define CTL_ALLUSEDTEXT 0x00000008u+#define CTL_ALTGLOBAL 0x00000010u+#define CTL_BINCODE 0x00000020u+#define CTL_CALLOUT_CAPTURE 0x00000040u+#define CTL_CALLOUT_INFO 0x00000080u+#define CTL_CALLOUT_NONE 0x00000100u+#define CTL_DFA 0x00000200u+#define CTL_EXPAND 0x00000400u+#define CTL_FINDLIMITS 0x00000800u+#define CTL_FINDLIMITS_NOHEAP 0x00001000u+#define CTL_FULLBINCODE 0x00002000u+#define CTL_GETALL 0x00004000u+#define CTL_GLOBAL 0x00008000u+#define CTL_HEXPAT 0x00010000u /* Same word as USE_LENGTH */+#define CTL_INFO 0x00020000u+#define CTL_JITFAST 0x00040000u+#define CTL_JITVERIFY 0x00080000u+#define CTL_MARK 0x00100000u+#define CTL_MEMORY 0x00200000u+#define CTL_NULLCONTEXT 0x00400000u+#define CTL_POSIX 0x00800000u+#define CTL_POSIX_NOSUB 0x01000000u+#define CTL_PUSH 0x02000000u /* These three must be */+#define CTL_PUSHCOPY 0x04000000u /* all in the same */+#define CTL_PUSHTABLESCOPY 0x08000000u /* word. */+#define CTL_STARTCHAR 0x10000000u+#define CTL_USE_LENGTH 0x20000000u /* Same word as HEXPAT */+#define CTL_UTF8_INPUT 0x40000000u+#define CTL_ZERO_TERMINATE 0x80000000u++/* Combinations */++#define CTL_DEBUG (CTL_FULLBINCODE|CTL_INFO) /* For setting */+#define CTL_ANYGLOB (CTL_ALTGLOBAL|CTL_GLOBAL)++/* Second control word */++#define CTL2_SUBSTITUTE_CALLOUT 0x00000001u+#define CTL2_SUBSTITUTE_EXTENDED 0x00000002u+#define CTL2_SUBSTITUTE_LITERAL 0x00000004u+#define CTL2_SUBSTITUTE_MATCHED 0x00000008u+#define CTL2_SUBSTITUTE_OVERFLOW_LENGTH 0x00000010u+#define CTL2_SUBSTITUTE_REPLACEMENT_ONLY 0x00000020u+#define CTL2_SUBSTITUTE_UNKNOWN_UNSET 0x00000040u+#define CTL2_SUBSTITUTE_UNSET_EMPTY 0x00000080u+#define CTL2_SUBJECT_LITERAL 0x00000100u+#define CTL2_CALLOUT_NO_WHERE 0x00000200u+#define CTL2_CALLOUT_EXTRA 0x00000400u+#define CTL2_ALLVECTOR 0x00000800u+#define CTL2_NULL_PATTERN 0x00001000u+#define CTL2_NULL_SUBJECT 0x00002000u+#define CTL2_NULL_REPLACEMENT 0x00004000u+#define CTL2_FRAMESIZE 0x00008000u+#define CTL2_SUBSTITUTE_CASE_CALLOUT 0x00010000u+#define CTL2_NULL_SUBSTITUTE_MATCH_DATA 0x00020000u++#define CTL2_HEAPFRAMES_SIZE 0x20000000u /* Informational */+#define CTL2_NL_SET 0x40000000u /* Informational */+#define CTL2_BSR_SET 0x80000000u /* Informational */++/* These are the matching controls that may be set either on a pattern or on a+data line. They are copied from the pattern controls as initial settings for+data line controls. Note that CTL_MEMORY is not included here, because it does+different things in the two cases. */++#define CTL_ALLPD (CTL_AFTERTEXT|\+ CTL_ALLAFTERTEXT|\+ CTL_ALLCAPTURES|\+ CTL_ALLUSEDTEXT|\+ CTL_ALTGLOBAL|\+ CTL_GLOBAL|\+ CTL_MARK|\+ CTL_STARTCHAR|\+ CTL_UTF8_INPUT)++#define CTL2_ALLPD (CTL2_SUBSTITUTE_CALLOUT|\+ CTL2_SUBSTITUTE_EXTENDED|\+ CTL2_SUBSTITUTE_LITERAL|\+ CTL2_SUBSTITUTE_MATCHED|\+ CTL2_SUBSTITUTE_OVERFLOW_LENGTH|\+ CTL2_SUBSTITUTE_REPLACEMENT_ONLY|\+ CTL2_SUBSTITUTE_UNKNOWN_UNSET|\+ CTL2_SUBSTITUTE_UNSET_EMPTY|\+ CTL2_ALLVECTOR|\+ CTL2_SUBSTITUTE_CASE_CALLOUT|\+ CTL2_NULL_SUBSTITUTE_MATCH_DATA|\+ 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+subject (MOD_PD[P]/MOD_PND) must be at the start and in the same order in both+structures so that the same offset in the big table below works for both. */++typedef struct patctl { /* Structure for pattern modifiers. */+ uint32_t options; /* Must be in same position as datctl */+ uint32_t control; /* Must be in same position as datctl */+ uint32_t control2; /* Must be in same position as datctl */+ uint32_t jitstack; /* Must be in same position as datctl */+ uint8_t replacement[1+REPLACE_MODSIZE]; /* So must this */+ uint32_t substitute_skip; /* Must be in same position as datctl */+ uint32_t substitute_stop; /* Must be in same position as datctl */+ uint32_t jit;+ uint32_t stackguard_test;+ uint32_t tables_id;+ uint32_t convert_type;+ uint32_t convert_length;+ uint32_t convert_glob_escape;+ uint32_t convert_glob_separator;+ int32_t regerror_buffsize;+ uint8_t locale[1+LOCALESIZE];+} patctl;++#define MAXCPYGET 10+#define LENCPYGET 64++typedef struct datctl { /* Structure for data line modifiers. */+ uint32_t options; /* Must be in same position as patctl */+ uint32_t control; /* Must be in same position as patctl */+ uint32_t control2; /* Must be in same position as patctl */+ uint32_t jitstack; /* Must be in same position as patctl */+ uint8_t replacement[1+REPLACE_MODSIZE]; /* So must this */+ uint32_t substitute_skip; /* Must be in same position as patctl */+ uint32_t substitute_stop; /* Must be in same position as patctl */+ uint8_t substitute_subject[1+SUBSTITUTE_SUBJECT_MODSIZE];+ uint32_t startend[2];+ uint32_t cerror[2];+ uint32_t cfail[2];+ int32_t callout_data;+ int32_t copy_numbers[MAXCPYGET];+ int32_t get_numbers[MAXCPYGET];+ uint32_t oveccount;+ PCRE2_SIZE offset;+ uint8_t copy_names[LENCPYGET];+ uint8_t get_names[LENCPYGET];+} datctl;++/* Helper functions to zero out the structures. */++static void patctl_zero(patctl *p)+{+memset(p, 0, sizeof(patctl));+p->replacement[0] = MOD_STR_UNSET;+p->convert_type = CONVERT_UNSET;+p->convert_length = CONVERT_UNSET;+p->regerror_buffsize = -1;+p->locale[0] = MOD_STR_UNSET;+}++static void datctl_zero(datctl *d)+{+memset(d, 0, sizeof(datctl));+d->replacement[0] = MOD_STR_UNSET;+d->substitute_subject[0] = MOD_STR_UNSET;+d->oveccount = DEFAULT_OVECCOUNT;+d->copy_numbers[0] = -1;+d->get_numbers[0] = -1;+d->startend[0] = d->startend[1] = CFORE_UNSET;+d->cerror[0] = d->cerror[1] = CFORE_UNSET;+d->cfail[0] = d->cfail[1] = CFORE_UNSET;+}++/* Ids for which context to modify. */++enum { CTX_PAT, /* Active pattern context */+ CTX_POPPAT, /* Ditto, for a popped pattern */+ CTX_DEFPAT, /* Default pattern context */+ CTX_DAT, /* Active data (match) context */+ CTX_DEFDAT }; /* Default data (match) context */++/* Macros to simplify the big table below. */++#define CO(name) offsetof(PCRE2_REAL_COMPILE_CONTEXT, name)+#define MO(name) offsetof(PCRE2_REAL_MATCH_CONTEXT, name)+#define PO(name) offsetof(patctl, name)+#define DO(name) offsetof(datctl, name)++/* Validate that the offsets for the shared fields do indeed match. */++STATIC_ASSERT(PO(options) == DO(options), options_mismatch);+STATIC_ASSERT(PO(control) == DO(control), control_mismatch);+STATIC_ASSERT(PO(control2) == DO(control2), control2_mismatch);+STATIC_ASSERT(PO(jitstack) == DO(jitstack), jitstack_mismatch);+STATIC_ASSERT(PO(replacement) == DO(replacement), replacement_mismatch);+STATIC_ASSERT(PO(substitute_skip) == DO(substitute_skip), substitute_skip_mismatch);+STATIC_ASSERT(PO(substitute_stop) == DO(substitute_stop), substitute_stop_mismatch);++/* Table of all long-form modifiers. Must be in collating sequence of modifier+name because it is searched by binary chop. */++typedef struct modstruct {+ const char *name;+ uint16_t which;+ uint16_t type;+ uint32_t value;+ 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) },+ { "allcaptures", MOD_PND, MOD_CTL, CTL_ALLCAPTURES, PO(control) },+ { "allow_empty_class", MOD_PAT, MOD_OPT, PCRE2_ALLOW_EMPTY_CLASS, PO(options) },+ { "allow_lookaround_bsk", MOD_CTC, MOD_OPT, PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK, CO(extra_options) },+ { "allow_surrogate_escapes", MOD_CTC, MOD_OPT, PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES, CO(extra_options) },+ { "allusedtext", MOD_PNDP, MOD_CTL, CTL_ALLUSEDTEXT, PO(control) },+ { "allvector", MOD_PND, MOD_CTL, CTL2_ALLVECTOR, PO(control2) },+ { "alt_bsux", MOD_PAT, MOD_OPT, PCRE2_ALT_BSUX, PO(options) },+ { "alt_circumflex", MOD_PAT, MOD_OPT, PCRE2_ALT_CIRCUMFLEX, PO(options) },+ { "alt_extended_class", MOD_PAT, MOD_OPT, PCRE2_ALT_EXTENDED_CLASS, PO(options) },+ { "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, PO(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) },+ { "auto_possess", MOD_CTC, MOD_OPTMZ, PCRE2_AUTO_POSSESS, 0 },+ { "auto_possess_off", MOD_CTC, MOD_OPTMZ, PCRE2_AUTO_POSSESS_OFF, 0 },+ { "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) },+ { "bsr", MOD_CTC, MOD_BSR, 0, CO(bsr_convention) },+ { "callout_capture", MOD_DAT, MOD_CTL, CTL_CALLOUT_CAPTURE, DO(control) },+ { "callout_data", MOD_DAT, MOD_INS, 0, DO(callout_data) },+ { "callout_error", MOD_DAT, MOD_IN2, 0, DO(cerror) },+ { "callout_extra", MOD_DAT, MOD_CTL, CTL2_CALLOUT_EXTRA, DO(control2) },+ { "callout_fail", MOD_DAT, MOD_IN2, 0, DO(cfail) },+ { "callout_info", MOD_PAT, MOD_CTL, CTL_CALLOUT_INFO, PO(control) },+ { "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) },+ { "convert_length", MOD_PAT, MOD_INT, 0, PO(convert_length) },+ { "copy", MOD_DAT, MOD_NN, DO(copy_numbers), DO(copy_names) },+ { "copy_matched_subject", MOD_DAT, MOD_OPT, PCRE2_COPY_MATCHED_SUBJECT, DO(options) },+ { "debug", MOD_PAT, MOD_CTL, CTL_DEBUG, PO(control) },+ { "depth_limit", MOD_CTM, MOD_INT, 0, MO(depth_limit) },+ { "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) },+ { "dotstar_anchor", MOD_CTC, MOD_OPTMZ, PCRE2_DOTSTAR_ANCHOR, 0 },+ { "dotstar_anchor_off", MOD_CTC, MOD_OPTMZ, PCRE2_DOTSTAR_ANCHOR_OFF, 0 },+ { "dupnames", MOD_PATP, MOD_OPT, PCRE2_DUPNAMES, PO(options) },+ { "endanchored", MOD_PD, MOD_OPT, PCRE2_ENDANCHORED, PO(options) },+ { "escaped_cr_is_lf", MOD_CTC, MOD_OPT, PCRE2_EXTRA_ESCAPED_CR_IS_LF, CO(extra_options) },+ { "expand", MOD_PAT, MOD_CTL, CTL_EXPAND, PO(control) },+ { "extended", MOD_PATP, MOD_OPT, PCRE2_EXTENDED, PO(options) },+ { "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, 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_PATP, MOD_CTL, CTL_HEXPAT, PO(control) },+ { "info", MOD_PAT, MOD_CTL, CTL_INFO, PO(control) },+ { "jit", MOD_PAT, MOD_IND, 7, PO(jit) },+ { "jitfast", MOD_PAT, MOD_CTL, CTL_JITFAST, PO(control) },+ { "jitstack", MOD_PNDP, MOD_INT, 0, PO(jitstack) },+ { "jitverify", MOD_PAT, MOD_CTL, CTL_JITVERIFY, PO(control) },+ { "literal", MOD_PAT, MOD_OPT, PCRE2_LITERAL, PO(options) },+ { "locale", MOD_PATP, MOD_STR, LOCALESIZE, PO(locale) },+ { "mark", MOD_PNDP, MOD_CTL, CTL_MARK, PO(control) },+ { "match_invalid_utf", MOD_PAT, MOD_OPT, PCRE2_MATCH_INVALID_UTF, PO(options) },+ { "match_limit", MOD_CTM, MOD_INT, 0, MO(match_limit) },+ { "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, PO(control) },+ { "multiline", MOD_PATP, MOD_OPT, PCRE2_MULTILINE, PO(options) },+ { "never_backslash_c", MOD_PAT, MOD_OPT, PCRE2_NEVER_BACKSLASH_C, PO(options) },+ { "never_callout", MOD_CTC, MOD_OPT, PCRE2_EXTRA_NEVER_CALLOUT, CO(extra_options) },+ { "never_ucp", MOD_PAT, MOD_OPT, PCRE2_NEVER_UCP, PO(options) },+ { "never_utf", MOD_PAT, MOD_OPT, PCRE2_NEVER_UTF, PO(options) },+ { "newline", MOD_CTC, MOD_NL, 0, 0 },+ { "no_auto_capture", MOD_PAT, MOD_OPT, PCRE2_NO_AUTO_CAPTURE, PO(options) },+ { "no_auto_possess", MOD_PATP, MOD_OPT, PCRE2_NO_AUTO_POSSESS, PO(options) },+ { "no_bs0", MOD_CTC, MOD_OPT, PCRE2_EXTRA_NO_BS0, CO(extra_options) },+ { "no_dotstar_anchor", MOD_PAT, MOD_OPT, PCRE2_NO_DOTSTAR_ANCHOR, PO(options) },+ { "no_jit", MOD_DATP, MOD_OPT, PCRE2_NO_JIT, DO(options) },+ { "no_start_optimize", MOD_PATP, MOD_OPT, PCRE2_NO_START_OPTIMIZE, PO(options) },+ { "no_utf_check", MOD_PD, MOD_OPT, PCRE2_NO_UTF_CHECK, PO(options) },+ { "notbol", MOD_DAT, MOD_OPT, PCRE2_NOTBOL, DO(options) },+ { "notempty", MOD_DAT, MOD_OPT, PCRE2_NOTEMPTY, DO(options) },+ { "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) },+ { "null_substitute_match_data", MOD_PND, MOD_CTL, CTL2_NULL_SUBSTITUTE_MATCH_DATA, PO(control2) },+ { "offset", MOD_DAT, MOD_SIZ, 0, DO(offset) },+ { "offset_limit", MOD_CTM, MOD_SIZ, 0, MO(offset_limit)},+ { "optimization_full", MOD_CTC, MOD_OPTMZ, PCRE2_OPTIMIZATION_FULL, 0 },+ { "optimization_none", MOD_CTC, MOD_OPTMZ, PCRE2_OPTIMIZATION_NONE, 0 },+ { "ovector", MOD_DAT, MOD_INT, 0, DO(oveccount) },+ { "parens_nest_limit", MOD_CTC, MOD_INT, 0, CO(parens_nest_limit) },+ { "partial_hard", MOD_DAT, MOD_OPT, PCRE2_PARTIAL_HARD, DO(options) },+ { "partial_soft", MOD_DAT, MOD_OPT, PCRE2_PARTIAL_SOFT, DO(options) },+ { "ph", MOD_DAT, MOD_OPT, PCRE2_PARTIAL_HARD, DO(options) },+ { "posix", MOD_PAT, MOD_CTL, CTL_POSIX, PO(control) },+ { "posix_nosub", MOD_PAT, MOD_CTL, CTL_POSIX|CTL_POSIX_NOSUB, PO(control) },+ { "posix_startend", MOD_DAT, MOD_IN2, 0, DO(startend) },+ { "ps", MOD_DAT, MOD_OPT, PCRE2_PARTIAL_SOFT, DO(options) },+ { "push", MOD_PAT, MOD_CTL, CTL_PUSH, PO(control) },+ { "pushcopy", MOD_PAT, MOD_CTL, CTL_PUSHCOPY, PO(control) },+ { "pushtablescopy", MOD_PAT, MOD_CTL, CTL_PUSHTABLESCOPY, PO(control) },+ { "python_octal", MOD_CTC, MOD_OPT, PCRE2_EXTRA_PYTHON_OCTAL, CO(extra_options) },+ { "recursion_limit", MOD_CTM, MOD_INT, 0, MO(depth_limit) }, /* Obsolete synonym */+ { "regerror_buffsize", MOD_PAT, MOD_INS, 0, PO(regerror_buffsize) },+ { "replace", MOD_PND, MOD_STR, REPLACE_MODSIZE, PO(replacement) },+ { "stackguard", MOD_PAT, MOD_INT, 0, PO(stackguard_test) },+ { "start_optimize", MOD_CTC, MOD_OPTMZ, PCRE2_START_OPTIMIZE, 0 },+ { "start_optimize_off", MOD_CTC, MOD_OPTMZ, PCRE2_START_OPTIMIZE_OFF, 0 },+ { "startchar", MOD_PND, MOD_CTL, CTL_STARTCHAR, PO(control) },+ { "startoffset", MOD_DAT, MOD_SIZ, 0, DO(offset) },+ { "subject_literal", MOD_PATP, MOD_CTL, CTL2_SUBJECT_LITERAL, PO(control2) },+ { "substitute_callout", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_CALLOUT, PO(control2) },+ { "substitute_case_callout", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_CASE_CALLOUT, PO(control2) },+ { "substitute_extended", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_EXTENDED, PO(control2) },+ { "substitute_literal", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_LITERAL, PO(control2) },+ { "substitute_matched", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_MATCHED, PO(control2) },+ { "substitute_overflow_length", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_OVERFLOW_LENGTH, PO(control2) },+ { "substitute_replacement_only", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_REPLACEMENT_ONLY, PO(control2) },+ { "substitute_skip", MOD_PND, MOD_INT, 0, PO(substitute_skip) },+ { "substitute_stop", MOD_PND, MOD_INT, 0, PO(substitute_stop) },+ { "substitute_subject", MOD_DAT, MOD_STR, SUBSTITUTE_SUBJECT_MODSIZE, DO(substitute_subject) },+ { "substitute_unknown_unset", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_UNKNOWN_UNSET, PO(control2) },+ { "substitute_unset_empty", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_UNSET_EMPTY, PO(control2) },+ { "tables", MOD_PAT, MOD_INT, 0, PO(tables_id) },+ { "turkish_casing", MOD_CTC, MOD_OPT, PCRE2_EXTRA_TURKISH_CASING, CO(extra_options) },+ { "ucp", MOD_PATP, MOD_OPT, PCRE2_UCP, PO(options) },+ { "ungreedy", MOD_PAT, MOD_OPT, PCRE2_UNGREEDY, PO(options) },+ { "use_length", MOD_PAT, MOD_CTL, CTL_USE_LENGTH, PO(control) },+ { "use_offset_limit", MOD_PAT, MOD_OPT, PCRE2_USE_OFFSET_LIMIT, PO(options) },+ { "utf", MOD_PATP, MOD_OPT, PCRE2_UTF, PO(options) },+ { "utf8_input", MOD_PAT, MOD_CTL, CTL_UTF8_INPUT, PO(control) },+ { "zero_terminate", MOD_DAT, MOD_CTL, CTL_ZERO_TERMINATE, DO(control) }+};++#define MODLISTCOUNT sizeof(modlist)/sizeof(modstruct)++/* Controls and options that are supported for use with the POSIX interface. */++#define POSIX_SUPPORTED_COMPILE_OPTIONS ( \+ PCRE2_CASELESS|PCRE2_DOTALL|PCRE2_LITERAL|PCRE2_MULTILINE|PCRE2_UCP| \+ PCRE2_UTF|PCRE2_UNGREEDY)++#define POSIX_SUPPORTED_COMPILE_EXTRA_OPTIONS (0)++#define POSIX_SUPPORTED_COMPILE_CONTROLS ( \+ CTL_AFTERTEXT|CTL_ALLAFTERTEXT|CTL_EXPAND|CTL_HEXPAT|CTL_POSIX| \+ CTL_POSIX_NOSUB|CTL_USE_LENGTH)++#define POSIX_SUPPORTED_COMPILE_CONTROLS2 (0)++#define POSIX_SUPPORTED_MATCH_OPTIONS ( \+ PCRE2_NOTBOL|PCRE2_NOTEMPTY|PCRE2_NOTEOL)++#define POSIX_SUPPORTED_MATCH_CONTROLS (CTL_AFTERTEXT|CTL_ALLAFTERTEXT)+#define POSIX_SUPPORTED_MATCH_CONTROLS2 (CTL2_NULL_SUBJECT)++/* Control bits that are not ignored with 'push'. */++#define PUSH_SUPPORTED_COMPILE_CONTROLS ( \+ CTL_BINCODE|CTL_CALLOUT_INFO|CTL_FULLBINCODE|CTL_HEXPAT|CTL_INFO| \+ CTL_JITVERIFY|CTL_MEMORY|CTL_PUSH|CTL_PUSHCOPY| \+ CTL_PUSHTABLESCOPY|CTL_USE_LENGTH)++#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'. */++#define PUSH_COMPILE_ONLY_CONTROLS CTL_JITVERIFY+#define PUSH_COMPILE_ONLY_CONTROLS2 (0)++/* Controls that are forbidden with #pop or #popcopy. */++#define NOTPOP_CONTROLS (CTL_HEXPAT|CTL_POSIX|CTL_POSIX_NOSUB|CTL_PUSH| \+ CTL_PUSHCOPY|CTL_PUSHTABLESCOPY|CTL_USE_LENGTH)++/* Pattern controls that are mutually exclusive. At present these are all in+the first control word. Note that CTL_POSIX_NOSUB is always accompanied by+CTL_POSIX, so it doesn't need its own entries. */++static uint32_t exclusive_pat_controls[] = {+ CTL_POSIX | CTL_PUSH,+ CTL_POSIX | CTL_PUSHCOPY,+ CTL_POSIX | CTL_PUSHTABLESCOPY,+ CTL_PUSH | CTL_PUSHCOPY,+ CTL_PUSH | CTL_PUSHTABLESCOPY,+ CTL_PUSHCOPY | CTL_PUSHTABLESCOPY,+ CTL_EXPAND | CTL_HEXPAT };++/* Data controls that are mutually exclusive. At present these are all in the+first control word. */++static uint32_t exclusive_dat_controls[] = {+ 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+in with the index of the full entry in modlist, to save repeated searching when+processing multiple test items. This short list is searched serially, so its+order does not matter. */++typedef struct c1modstruct {+ const char *fullname;+ uint32_t onechar;+ int index;+} c1modstruct;++static c1modstruct c1modlist[] = {+ { "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)++/* Table of arguments for the -C command line option. Use macros to make the+table itself easier to read. */++#if defined SUPPORT_PCRE2_8+#define SUPPORT_8 1+#endif+#if defined SUPPORT_PCRE2_16+#define SUPPORT_16 1+#endif+#if defined SUPPORT_PCRE2_32+#define SUPPORT_32 1+#endif++#ifndef SUPPORT_8+#define SUPPORT_8 0+#endif+#ifndef SUPPORT_16+#define SUPPORT_16 0+#endif+#ifndef SUPPORT_32+#define SUPPORT_32 0+#endif++#if defined EBCDIC+#define SUPPORT_EBCDIC 1+#define SUPPORT_EBCDIC_NL25 CHAR_LF == 0x25+#else+#define SUPPORT_EBCDIC 0+#define SUPPORT_EBCDIC_NL25 0+#endif++#ifdef NEVER_BACKSLASH_C+#define BACKSLASH_C 0+#else+#define BACKSLASH_C 1+#endif++typedef struct coptstruct {+ const char *name;+ uint32_t type;+ uint32_t value;+} coptstruct;++enum { CONF_BSR,+ CONF_FIX,+ CONF_INT,+ CONF_NL,+ CONF_JU+};++static coptstruct coptlist[] = {+ { "backslash-C", CONF_FIX, BACKSLASH_C },+ { "bsr", CONF_BSR, PCRE2_CONFIG_BSR },+ { "ebcdic", CONF_FIX, SUPPORT_EBCDIC },+ { "ebcdic-io", CONF_FIX, EBCDIC_IO },+ { "ebcdic-nl25", CONF_FIX, SUPPORT_EBCDIC_NL25 },+ { "jit", CONF_INT, PCRE2_CONFIG_JIT },+ { "jitusable", CONF_JU, 0 },+ { "linksize", CONF_INT, PCRE2_CONFIG_EFFECTIVE_LINKSIZE },+ { "newline", CONF_NL, PCRE2_CONFIG_NEWLINE },+ { "pcre2-16", CONF_FIX, SUPPORT_16 },+ { "pcre2-32", CONF_FIX, SUPPORT_32 },+ { "pcre2-8", CONF_FIX, SUPPORT_8 },+ { "unicode", CONF_INT, PCRE2_CONFIG_UNICODE }+};++#define COPTLISTCOUNT sizeof(coptlist)/sizeof(coptstruct)++#undef SUPPORT_8+#undef SUPPORT_16+#undef SUPPORT_32+#undef SUPPORT_EBCDIC+#undef SUPPORT_EBDCIC_NL25+#undef BACKSLASH_C++/* Types for the parser, to be used in process_data() */++enum force_encoding {+ FORCE_NONE, /* No preference, follow utf modifier */+ FORCE_RAW, /* Encode as a code point or error if too wide */+ FORCE_UTF /* Encode as a character or error if too wide */+};++/* ----------------------- Static variables ------------------------ */++static FILE *infile;+static FILE *outfile;++static const void *last_callout_mark;++static BOOL first_callout;+static BOOL jit_was_used;+static BOOL restrict_for_perl_test = FALSE;+static BOOL show_memory = FALSE;+static BOOL preprocess_only = FALSE;+static BOOL inside_if = FALSE;+static BOOL malloc_testing = FALSE;++static int jitrc; /* Return from JIT compile */+static int timeit = 0;+static int timeitm = 0;+static int mallocs_until_failure = INT_MAX;+static int mallocs_called = 0;++static clock_t total_compile_time = 0;+static clock_t total_jit_compile_time = 0;+static clock_t total_match_time = 0;++static uint32_t dfa_matched;+static uint32_t forbid_utf = 0;+static uint32_t maxlookbehind;+static uint32_t max_oveccount;+static uint32_t callout_count;+static uint32_t maxcapcount;++static uint16_t local_newline_default = 0;++static patctl def_patctl;+static patctl pat_patctl;+static datctl def_datctl;+static datctl dat_datctl;++static void *malloclist[MALLOCLISTSIZE];+static PCRE2_SIZE malloclistlength[MALLOCLISTSIZE];+static uint32_t malloclistptr = 0;++#ifdef SUPPORT_PCRE2_8+static regex_t preg = { NULL, NULL, 0, 0, 0, 0 };+#endif++static int *dfa_workspace = NULL;+static const uint8_t *locale_tables = NULL;+static const uint8_t *use_tables = NULL;+static uint8_t locale_name[LOCALESIZE];+static uint8_t *tables3 = NULL; /* For binary-loaded tables */+static uint32_t loadtables_length = 0;++/* We need buffers for building 16/32-bit strings; 8-bit strings don't need+rebuilding, but set up the same naming scheme for use in macros. The "buffer"+buffer is where all input lines are read. Its size is the same as pbuffer8. */++static size_t pbuffer8_size = 50000; /* Initial size, bytes */+static uint8_t *pbuffer8 = NULL;+#ifdef SUPPORT_PCRE2_16+static size_t pbuffer16_size = 0; /* Size, bytes! Set only when needed */+static uint16_t *pbuffer16 = NULL;+#endif+#ifdef SUPPORT_PCRE2_32+static size_t pbuffer32_size = 0; /* Size, bytes! Set only when needed */+static uint32_t *pbuffer32 = NULL;+#endif+static uint8_t *buffer = NULL;++/* The dbuffer is where all processed data lines are put. In non-8-bit modes it+is cast as needed. For long data lines it grows as necessary. */++static size_t dbuffer_size = 1u << 14; /* Initial size, bytes */+static uint8_t *dbuffer = NULL;++/* ------------------ Colour highlighting definitions -------------------- */++/* Colour of input text that was a comment, when echoing back to the terminal */+static const int clr_comment = 37; /* grey */+/* Colour of other input text that is echoed back to the terminal */+static const int clr_input = 32; /* green */+/* Colour of prompt output */+static const int clr_prompt = 34; /* blue */+/* Colour of output that represents a PCRE2 API error */+static const int clr_api_error = 35; /* magenta */+/* Colour of error messages for the test script itself+(i.e. an error in the testing tool, not an API error) */+static const int clr_test_error = 31; /* red */+/* Colour of profiling information, which doesn't have a "right" answer */+static const int clr_profiling = 36; /* cyan */+/* No colour, for APIs that take a colour value */+static const int clr_none = -1;++enum { COLOUR_NEVER, COLOUR_ALWAYS, COLOUR_AUTO };+static int colour_setting = COLOUR_AUTO;+static int colour_last_fd = -1;+static BOOL colour_fd_interactive = FALSE;++static BOOL+should_print_colour(int clr, FILE* f)+{+if (f == NULL) return FALSE;+if (clr == clr_none) return FALSE;+if (colour_setting == COLOUR_NEVER) return FALSE;+if (colour_setting == COLOUR_AUTO)+ {+ if (fileno(f) != colour_last_fd)+ {+ colour_last_fd = fileno(f);+ colour_fd_interactive = INTERACTIVE(f);+ }+ if (!colour_fd_interactive) return FALSE;+ }+return TRUE;+}++/* Starts a block of colour (but only if colour is enabled). */+static void+colour_begin(int clr, FILE* f)+{+if (should_print_colour(clr, f))+ fprintf(f, "\x1b[%dm", clr);+}++/* Ends a block of colour (but only if colour is enabled). */+static void+colour_end(FILE* f)+{+colour_begin(0, f);+}++/* cfprintf is like fprintf but takes a colour to wrap its output. */+static int+cfprintf(int clr, FILE *file, const char* fmt, ...)+{+va_list args;+int ret;+va_start(args, fmt);+colour_begin(clr, file);+ret = vfprintf(file, fmt, args);+va_end(args);+colour_end(file);+return ret;+}++++/*************************************************+* Alternate character tables *+*************************************************/++/* By default, the "tables" pointer in the compile context when calling+pcre2_compile() is not set (= NULL), thereby using the default tables of the+library. However, the tables modifier can be used to select alternate sets of+tables, for different kinds of testing. Note that the locale modifier also+adjusts the tables. */++/* This is the set of tables distributed as default with PCRE2. It recognizes+only ASCII characters. */++static const uint8_t tables1[] = {++/* This table is a lower casing table. */++ 0, 1, 2, 3, 4, 5, 6, 7,+ 8, 9, 10, 11, 12, 13, 14, 15,+ 16, 17, 18, 19, 20, 21, 22, 23,+ 24, 25, 26, 27, 28, 29, 30, 31,+ 32, 33, 34, 35, 36, 37, 38, 39,+ 40, 41, 42, 43, 44, 45, 46, 47,+ 48, 49, 50, 51, 52, 53, 54, 55,+ 56, 57, 58, 59, 60, 61, 62, 63,+ 64, 97, 98, 99,100,101,102,103,+ 104,105,106,107,108,109,110,111,+ 112,113,114,115,116,117,118,119,+ 120,121,122, 91, 92, 93, 94, 95,+ 96, 97, 98, 99,100,101,102,103,+ 104,105,106,107,108,109,110,111,+ 112,113,114,115,116,117,118,119,+ 120,121,122,123,124,125,126,127,+ 128,129,130,131,132,133,134,135,+ 136,137,138,139,140,141,142,143,+ 144,145,146,147,148,149,150,151,+ 152,153,154,155,156,157,158,159,+ 160,161,162,163,164,165,166,167,+ 168,169,170,171,172,173,174,175,+ 176,177,178,179,180,181,182,183,+ 184,185,186,187,188,189,190,191,+ 192,193,194,195,196,197,198,199,+ 200,201,202,203,204,205,206,207,+ 208,209,210,211,212,213,214,215,+ 216,217,218,219,220,221,222,223,+ 224,225,226,227,228,229,230,231,+ 232,233,234,235,236,237,238,239,+ 240,241,242,243,244,245,246,247,+ 248,249,250,251,252,253,254,255,++/* This table is a case flipping table. */++ 0, 1, 2, 3, 4, 5, 6, 7,+ 8, 9, 10, 11, 12, 13, 14, 15,+ 16, 17, 18, 19, 20, 21, 22, 23,+ 24, 25, 26, 27, 28, 29, 30, 31,+ 32, 33, 34, 35, 36, 37, 38, 39,+ 40, 41, 42, 43, 44, 45, 46, 47,+ 48, 49, 50, 51, 52, 53, 54, 55,+ 56, 57, 58, 59, 60, 61, 62, 63,+ 64, 97, 98, 99,100,101,102,103,+ 104,105,106,107,108,109,110,111,+ 112,113,114,115,116,117,118,119,+ 120,121,122, 91, 92, 93, 94, 95,+ 96, 65, 66, 67, 68, 69, 70, 71,+ 72, 73, 74, 75, 76, 77, 78, 79,+ 80, 81, 82, 83, 84, 85, 86, 87,+ 88, 89, 90,123,124,125,126,127,+ 128,129,130,131,132,133,134,135,+ 136,137,138,139,140,141,142,143,+ 144,145,146,147,148,149,150,151,+ 152,153,154,155,156,157,158,159,+ 160,161,162,163,164,165,166,167,+ 168,169,170,171,172,173,174,175,+ 176,177,178,179,180,181,182,183,+ 184,185,186,187,188,189,190,191,+ 192,193,194,195,196,197,198,199,+ 200,201,202,203,204,205,206,207,+ 208,209,210,211,212,213,214,215,+ 216,217,218,219,220,221,222,223,+ 224,225,226,227,228,229,230,231,+ 232,233,234,235,236,237,238,239,+ 240,241,242,243,244,245,246,247,+ 248,249,250,251,252,253,254,255,++/* This table contains bit maps for various character classes. Each map is 32+bytes long and the bits run from the least significant end of each byte. The+classes that have their own maps are: space, xdigit, digit, upper, lower, word,+graph, print, punct, and cntrl. Other classes are built from combinations. */++ 0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,+ 0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,+ 0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc,+ 0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++ 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,++/* This table identifies various classes of character by individual bits:+ 0x01 white space character+ 0x02 letter+ 0x04 decimal digit+ 0x08 hexadecimal digit+ 0x10 alphanumeric or '_'+ 0x80 regular expression metacharacter or binary zero+*/++ 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */+ 0x00,0x01,0x01,0x01,0x01,0x01,0x00,0x00, /* 8- 15 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */+ 0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /* - ' */+ 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x00, /* ( - / */+ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */+ 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x80, /* 8 - ? */+ 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* @ - G */+ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* H - O */+ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* P - W */+ 0x12,0x12,0x12,0x80,0x80,0x00,0x80,0x10, /* X - _ */+ 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* ` - g */+ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* h - o */+ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* p - w */+ 0x12,0x12,0x12,0x80,0x80,0x00,0x00,0x00, /* x -127 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */++/* This is a set of tables that came originally from a Windows user. It seems+to be at least an approximation of ISO 8859. In particular, there are+characters greater than 128 that are marked as spaces, letters, etc. */++static const uint8_t tables2[] = {+0,1,2,3,4,5,6,7,+8,9,10,11,12,13,14,15,+16,17,18,19,20,21,22,23,+24,25,26,27,28,29,30,31,+32,33,34,35,36,37,38,39,+40,41,42,43,44,45,46,47,+48,49,50,51,52,53,54,55,+56,57,58,59,60,61,62,63,+64,97,98,99,100,101,102,103,+104,105,106,107,108,109,110,111,+112,113,114,115,116,117,118,119,+120,121,122,91,92,93,94,95,+96,97,98,99,100,101,102,103,+104,105,106,107,108,109,110,111,+112,113,114,115,116,117,118,119,+120,121,122,123,124,125,126,127,+128,129,130,131,132,133,134,135,+136,137,138,139,140,141,142,143,+144,145,146,147,148,149,150,151,+152,153,154,155,156,157,158,159,+160,161,162,163,164,165,166,167,+168,169,170,171,172,173,174,175,+176,177,178,179,180,181,182,183,+184,185,186,187,188,189,190,191,+224,225,226,227,228,229,230,231,+232,233,234,235,236,237,238,239,+240,241,242,243,244,245,246,215,+248,249,250,251,252,253,254,223,+224,225,226,227,228,229,230,231,+232,233,234,235,236,237,238,239,+240,241,242,243,244,245,246,247,+248,249,250,251,252,253,254,255,+0,1,2,3,4,5,6,7,+8,9,10,11,12,13,14,15,+16,17,18,19,20,21,22,23,+24,25,26,27,28,29,30,31,+32,33,34,35,36,37,38,39,+40,41,42,43,44,45,46,47,+48,49,50,51,52,53,54,55,+56,57,58,59,60,61,62,63,+64,97,98,99,100,101,102,103,+104,105,106,107,108,109,110,111,+112,113,114,115,116,117,118,119,+120,121,122,91,92,93,94,95,+96,65,66,67,68,69,70,71,+72,73,74,75,76,77,78,79,+80,81,82,83,84,85,86,87,+88,89,90,123,124,125,126,127,+128,129,130,131,132,133,134,135,+136,137,138,139,140,141,142,143,+144,145,146,147,148,149,150,151,+152,153,154,155,156,157,158,159,+160,161,162,163,164,165,166,167,+168,169,170,171,172,173,174,175,+176,177,178,179,180,181,182,183,+184,185,186,187,188,189,190,191,+224,225,226,227,228,229,230,231,+232,233,234,235,236,237,238,239,+240,241,242,243,244,245,246,215,+248,249,250,251,252,253,254,223,+192,193,194,195,196,197,198,199,+200,201,202,203,204,205,206,207,+208,209,210,211,212,213,214,247,+216,217,218,219,220,221,222,255,+0,62,0,0,1,0,0,0,+0,0,0,0,0,0,0,0,+32,0,0,0,1,0,0,0,+0,0,0,0,0,0,0,0,+0,0,0,0,0,0,255,3,+126,0,0,0,126,0,0,0,+0,0,0,0,0,0,0,0,+0,0,0,0,0,0,0,0,+0,0,0,0,0,0,255,3,+0,0,0,0,0,0,0,0,+0,0,0,0,0,0,12,2,+0,0,0,0,0,0,0,0,+0,0,0,0,0,0,0,0,+254,255,255,7,0,0,0,0,+0,0,0,0,0,0,0,0,+255,255,127,127,0,0,0,0,+0,0,0,0,0,0,0,0,+0,0,0,0,254,255,255,7,+0,0,0,0,0,4,32,4,+0,0,0,128,255,255,127,255,+0,0,0,0,0,0,255,3,+254,255,255,135,254,255,255,7,+0,0,0,0,0,4,44,6,+255,255,127,255,255,255,127,255,+0,0,0,0,254,255,255,255,+255,255,255,255,255,255,255,127,+0,0,0,0,254,255,255,255,+255,255,255,255,255,255,255,255,+0,2,0,0,255,255,255,255,+255,255,255,255,255,255,255,127,+0,0,0,0,255,255,255,255,+255,255,255,255,255,255,255,255,+0,0,0,0,254,255,0,252,+1,0,0,248,1,0,0,120,+0,0,0,0,254,255,255,255,+0,0,128,0,0,0,128,0,+255,255,255,255,0,0,0,0,+0,0,0,0,0,0,0,128,+255,255,255,255,0,0,0,0,+0,0,0,0,0,0,0,0,+128,0,0,0,0,0,0,0,+0,1,1,0,1,1,0,0,+0,0,0,0,0,0,0,0,+0,0,0,0,0,0,0,0,+1,0,0,0,128,0,0,0,+128,128,128,128,0,0,128,0,+28,28,28,28,28,28,28,28,+28,28,0,0,0,0,0,128,+0,26,26,26,26,26,26,18,+18,18,18,18,18,18,18,18,+18,18,18,18,18,18,18,18,+18,18,18,128,128,0,128,16,+0,26,26,26,26,26,26,18,+18,18,18,18,18,18,18,18,+18,18,18,18,18,18,18,18,+18,18,18,128,128,0,0,0,+0,0,0,0,0,1,0,0,+0,0,0,0,0,0,0,0,+0,0,0,0,0,0,0,0,+0,0,0,0,0,0,0,0,+1,0,0,0,0,0,0,0,+0,0,18,0,0,0,0,0,+0,0,20,20,0,18,0,0,+0,20,18,0,0,0,0,0,+18,18,18,18,18,18,18,18,+18,18,18,18,18,18,18,18,+18,18,18,18,18,18,18,0,+18,18,18,18,18,18,18,18,+18,18,18,18,18,18,18,18,+18,18,18,18,18,18,18,18,+18,18,18,18,18,18,18,0,+18,18,18,18,18,18,18,18+};++++/*************************************************+* Callout state reset *+*************************************************/++/* Several callout functions use global state to track progress. For convenience+this function resets all relevant state variables, for all the different+callouts. This ensures consistent execution when repeating a match. */++static void+reset_callout_state(void)+{+mallocs_called = 0;+first_callout = TRUE;+last_callout_mark = NULL;+callout_count = 0;+}++++/*************************************************+* Local memory functions *+*************************************************/++/* Alternative memory functions, to test functionality. */++static void *my_malloc(size_t size, void *data)+{+void *block;++(void)data;++mallocs_called++;+if (mallocs_until_failure != INT_MAX && mallocs_until_failure-- <= 0)+ return NULL;++block = malloc(size);+if (show_memory && outfile != NULL)+ {+ if (block == NULL)+ {+ cfprintf(clr_test_error, outfile, "** malloc() failed for %" SIZ_FORM "\n", size);+ }+ else+ {+ cfprintf(clr_profiling, outfile, "malloc %5" SIZ_FORM, size);+#ifdef DEBUG_SHOW_MALLOC_ADDRESSES+ cfprintf(clr_profiling, outfile, " %p", block); /* Not portable */+#endif+ if (malloclistptr < MALLOCLISTSIZE)+ {+ malloclist[malloclistptr] = block;+ malloclistlength[malloclistptr++] = size;+ }+ else+ cfprintf(clr_profiling, outfile, " (not remembered)");+ fprintf(outfile, "\n");+ }+ }+return block;+}++static void my_free(void *block, void *data)+{+(void)data;++if (show_memory && outfile != NULL && block != NULL)+ {+ uint32_t i, j;+ BOOL found = FALSE;++ cfprintf(clr_profiling, outfile, "free");+ for (i = 0; i < malloclistptr; i++)+ {+ if (block == malloclist[i])+ {+ cfprintf(clr_profiling, outfile, " %5" SIZ_FORM, malloclistlength[i]);+ malloclistptr--;+ for (j = i; j < malloclistptr; j++)+ {+ malloclist[j] = malloclist[j+1];+ malloclistlength[j] = malloclistlength[j+1];+ }+ found = TRUE;+ break;+ }+ }+ if (!found) cfprintf(clr_profiling, outfile, " unremembered block");+#ifdef DEBUG_SHOW_MALLOC_ADDRESSES+ cfprintf(clr_profiling, outfile, " %p", block); /* Not portable */+#endif+ fprintf(outfile, "\n");+ }+free(block);+}++++/*************************************************+* Callback function for stack guard *+*************************************************/++/* This is set up to be called from pcre2_compile() when the stackguard=n+modifier sets a value greater than zero. The test we do is whether the+parenthesis nesting depth is greater than the value set by the modifier.++Argument: the current parenthesis nesting depth+Returns: non-zero to kill the compilation+*/++static int+stack_guard(uint32_t depth, void *user_data)+{+(void)user_data;+return depth > pat_patctl.stackguard_test;+}++++/*************************************************+* EBCDIC support functions *+*************************************************/++#if defined(EBCDIC)+static BOOL+printable(uint32_t c)+{+if ((c >= CHAR_a && c <= CHAR_i) ||+ (c >= CHAR_j && c <= CHAR_r) ||+ (c >= CHAR_s && c <= CHAR_z) ||+ (c >= CHAR_A && c <= CHAR_I) ||+ (c >= CHAR_J && c <= CHAR_R) ||+ (c >= CHAR_S && c <= CHAR_Z) ||+ (c >= CHAR_0 && c <= CHAR_9))+ return TRUE;++switch (c)+ {+ case CHAR_SPACE:+ case CHAR_EXCLAMATION_MARK:+ case CHAR_QUOTATION_MARK:+ case CHAR_NUMBER_SIGN:+ case CHAR_DOLLAR_SIGN:+ case CHAR_PERCENT_SIGN:+ case CHAR_AMPERSAND:+ case CHAR_APOSTROPHE:+ case CHAR_LEFT_PARENTHESIS:+ case CHAR_RIGHT_PARENTHESIS:+ case CHAR_ASTERISK:+ case CHAR_PLUS:+ case CHAR_COMMA:+ case CHAR_MINUS:+ case CHAR_DOT:+ case CHAR_SLASH:+ case CHAR_COLON:+ case CHAR_SEMICOLON:+ case CHAR_LESS_THAN_SIGN:+ case CHAR_EQUALS_SIGN:+ case CHAR_GREATER_THAN_SIGN:+ case CHAR_QUESTION_MARK:+ case CHAR_COMMERCIAL_AT:+ case CHAR_LEFT_SQUARE_BRACKET:+ case CHAR_BACKSLASH:+ case CHAR_RIGHT_SQUARE_BRACKET:+ case CHAR_CIRCUMFLEX_ACCENT:+ case CHAR_UNDERSCORE:+ case CHAR_GRAVE_ACCENT:+ case CHAR_LEFT_CURLY_BRACKET:+ case CHAR_VERTICAL_LINE:+ case CHAR_RIGHT_CURLY_BRACKET:+ case CHAR_TILDE:+ return TRUE;+ }++return FALSE;+}+#endif++#if defined(EBCDIC) && !EBCDIC_IO+static void+ascii_to_ebcdic_str(uint8_t *buf, size_t len)+{+for (size_t i = 0; i < len; ++i)+ buf[i] = ascii_to_ebcdic_1047[buf[i]];+}++static void+ebcdic_to_ascii_str(uint8_t *buf, size_t len)+{+for (size_t i = 0; i < len; ++i)+ buf[i] = ebcdic_1047_to_ascii[buf[i]];+}+#endif++#if defined(EBCDIC)+static uint32_t+ascii_to_ebcdic(uint32_t c)+{+return (c < 256)? ascii_to_ebcdic_1047[c] : c;+}++static uint32_t+ebcdic_to_ascii(uint32_t c)+{+return (c < 256)? ebcdic_1047_to_ascii[c] : c;+}+#endif++++/*************************************************+* Convert UTF-8 character to code point *+*************************************************/++/* This function reads one or more bytes that represent a UTF-8 character,+and returns the codepoint of that character. Note that the function supports+the original UTF-8 definition of RFC 2279, allowing for values in the range 0+to 0x7fffffff, up to 6 bytes long. This makes it possible to generate+codepoints greater than 0x10ffff which are useful for testing PCRE2's error+checking, and also for generating 32-bit non-UTF data values above the UTF+limit.++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+ -6 to 0 => malformed UTF-8 character at offset = (-return)+*/++static int+utf8_to_ord(PCRE2_SPTR8 utf8bytes, PCRE2_SPTR8 end, uint32_t *vptr)+{+uint32_t c = *utf8bytes++;+uint32_t d = c;+int i, j, s;++for (i = -1; i < 6; i++) /* i is number of additional bytes */+ {+ if ((d & 0x80) == 0) break;+ d <<= 1;+ }++if (i == -1) { *vptr = c; return 1; } /* ascii character */+if (i == 0 || i == 6) return 0; /* invalid UTF-8 */++/* i now has a value in the range 1-5 */++s = 6*i;+d = (c & utf8_table3[i]) << s;++for (j = 0; j < i; j++)+ {+ if (utf8bytes >= end) return 0;++ c = *utf8bytes++;+ if ((c & 0xc0) != 0x80) return -(j+1);+ s -= 6;+ d |= (c & 0x3f) << s;+ }++/* Check that encoding was the correct unique one */++for (j = 0; j < (int)utf8_table1_size; j++)+ if (d <= (uint32_t)utf8_table1[j]) break;+if (j != i) return -(i+1);++/* Valid value */++*vptr = d;+return i+1;+}++++#ifdef SUPPORT_PCRE2_16+/*************************************************+* Convert UTF-16 character to code point *+*************************************************/++/* This function reads one or more UTF-16 code units, and returns the+codepoint of that character.++Argument:+ utf16units a pointer to the units vector+ end a pointer to the end of the units vector+ vptr a pointer to an int to receive the value++Returns: > 0 => the number of 16-bit units consumed+ -1 => malformed UTF-16+*/++static int+utf16_to_ord(PCRE2_SPTR16 utf16units, PCRE2_SPTR16 end, uint32_t *vptr)+{+uint32_t c = *utf16units++;++if (c >= 0xdc00 && c <= 0xdfff) return -1;++if (c >= 0xd800 && c < 0xdc00)+ {+ uint32_t c2;++ if (utf16units >= end) return -1;++ c2 = *utf16units++;+ if (c2 < 0xdc00 || c2 > 0xdfff) return -1;+ *vptr = ((c & 0x3ff) << 10) + (c2 & 0x3ff) + 0x10000;+ return 2;+ }++*vptr = c;+return 1;+}+#endif /* SUPPORT_PCRE2_16 */++++/*************************************************+* Convert character value to UTF-8 *+*************************************************/++/* This function takes an integer value in the range 0 - 0x7fffffff+and encodes it as a UTF-8 character in 0 to 6 bytes. It is needed even when the+8-bit library is not supported, to generate UTF-8 output for non-ASCII+characters.++Arguments:+ cvalue the character value+ utf8bytes pointer to buffer for result - at least 6 bytes long++Returns: number of characters placed in the buffer+*/++static int+ord_to_utf8(uint32_t cvalue, uint8_t *utf8bytes)+{+int i, j;+if (cvalue > 0x7fffffffu)+ return -1;+for (i = 0; i < (int)utf8_table1_size; i++)+ if (cvalue <= (uint32_t)utf8_table1[i]) break;+utf8bytes += i;+for (j = i; j > 0; j--)+ {+ *utf8bytes-- = 0x80 | (cvalue & 0x3f);+ cvalue >>= 6;+ }+*utf8bytes = utf8_table2[i] | cvalue;+return i + 1;+}++++/*************************************************+* Print one character *+*************************************************/++/* Print a single character either literally, or as a hex escape, and count how+many printed characters are used.++Arguments:+ c the character+ utf TRUE in UTF mode+ f the FILE to print to, or NULL just to count characters++Returns: number of characters written+*/++static int+pchar(uint32_t c, BOOL utf, FILE *f)+{+int n = 0;+char tempbuffer[16];++if (PRINTABLE(c))+ {+ c = CHAR_OUTPUT(c);+ if (f != NULL) fprintf(f, "%c", c);+ return 1;+ }++c = CHAR_OUTPUT_HEX(c);++if (c < 0x100)+ {+ if (utf)+ {+ if (f != NULL) fprintf(f, "\\x{%02x}", c);+ return 6;+ }+ else+ {+ if (f != NULL) fprintf(f, "\\x%02x", c);+ return 4;+ }+ }++if (f != NULL) n = fprintf(f, "\\x{%02x}", c);+ else n = snprintf(tempbuffer, sizeof(tempbuffer), "\\x{%02x}", c);++return n >= 0 ? n : 0;+}++++/*************************************************+* Expand input buffers *+*************************************************/++/* This function doubles the size of the input buffer and the buffer for+keeping an 8-bit copy of patterns (pbuffer8), and copies the current buffers to+the new ones.++Arguments: none+Returns: nothing (aborts if malloc() fails)+*/++static void+expand_input_buffers(void)+{+size_t new_pbuffer8_size = 2*pbuffer8_size;+uint8_t *new_buffer = (uint8_t *)malloc(new_pbuffer8_size);+uint8_t *new_pbuffer8 = (uint8_t *)malloc(new_pbuffer8_size);++if (new_buffer == NULL || new_pbuffer8 == NULL)+ {+ cfprintf(clr_test_error, stderr, "pcre2test: malloc(%" SIZ_FORM ") failed\n",+ new_pbuffer8_size);+ exit(1);+ }++memcpy(new_buffer, buffer, pbuffer8_size);+memcpy(new_pbuffer8, pbuffer8, pbuffer8_size);++pbuffer8_size = new_pbuffer8_size;++free(buffer);+free(pbuffer8);++buffer = new_buffer;+pbuffer8 = new_pbuffer8;+}++++/*************************************************+* Read or extend an input line *+*************************************************/++/* Input lines are read into buffer, but both patterns and data lines can be+continued over multiple input lines. In addition, if the buffer fills up, we+want to automatically expand it so as to be able to handle extremely large+lines that are needed for certain stress tests, although this is less likely+now that there are repetition features for both patterns and data. When the+input buffer is expanded, the other two buffers must also be expanded likewise,+and the contents of pbuffer, which are a copy of the input for callouts, must+be preserved (for when expansion happens for a data line). This is not the most+optimal way of handling this, but hey, this is just a test program!++Arguments:+ f the file to read+ start where in buffer to start (this *must* be within buffer)+ prompt for stdin or readline()++Returns: pointer to the start of new data+ could be a copy of start, or could be moved+ NULL if no data read and EOF reached+*/++static uint8_t *+extend_inputline(FILE *f, uint8_t *start, const char *prompt)+{+uint8_t *here = start;++for (;;)+ {+ size_t dlen;+ size_t rlen = (size_t)(pbuffer8_size - (here - buffer));++ /* If libreadline or libedit support is required, use readline() to read a+ line if the input is a terminal. Note that readline() removes the trailing+ newline, so we must put it back again, to be compatible with fgets(). */++#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)+ if (INTERACTIVE(f))+ {+ char promptbuf[80];+ int snprintf_rc;+ char *s;+ if (should_print_colour(clr_prompt, stdout) &&+ (snprintf_rc = snprintf(promptbuf, sizeof(promptbuf), "\x1b[%dm%s\x1b[0m", clr_prompt, prompt)) > 0 &&+ snprintf_rc < (int)sizeof(promptbuf))+ s = readline(promptbuf);+ else+ s = readline(prompt);+ if (s == NULL) return (here == start)? NULL : start;+ dlen = strlen(s);+ if (dlen > rlen - 2)+ {+ cfprintf(clr_test_error, outfile, "** Interactive input exceeds buffer space\n");+ exit(1);+ }+ if (dlen > 0) add_history(s);+ memcpy(here, s, dlen);+ here[dlen] = '\n';+ here[dlen+1] = 0;+ free(s);+ return start;+ }+#endif++ if (rlen > 1000)+ {+ int rlen_trunc = (rlen > (unsigned)INT_MAX)? INT_MAX : (int)rlen;++ /* Read the next line by normal means, prompting if the file is a tty. */++ if (INTERACTIVE(f)) cfprintf(clr_prompt, stdout, "%s", prompt);+ if (fgets((char *)here, rlen_trunc, f) == NULL)+ return (here == start)? NULL : start;++ dlen = strlen((char *)here);+ here += dlen;++ /* Check for end of line reached. Take care not to read data from before+ start (dlen will be zero for a file starting with a binary zero). */++ if (here > start && here[-1] == '\n') return start;++ /* If we have not read a newline when reading a file, we have either filled+ the buffer or reached the end of the file. We can detect the former by+ checking that the string fills the buffer, and the latter by feof(). If+ neither of these is true, it means we read a binary zero which has caused+ strlen() to give a short length. This is a hard error because pcre2test+ expects to work with C strings. */++ if (dlen < (unsigned)rlen_trunc - 1 && !feof(f))+ {+ cfprintf(clr_test_error, outfile, "** Binary zero encountered in input\n");+ cfprintf(clr_test_error, outfile, "** pcre2test run abandoned\n");+ exit(1);+ }+ }++ else+ {+ size_t start_offset = start - buffer;+ size_t here_offset = here - buffer;+ expand_input_buffers();+ start = buffer + start_offset;+ here = buffer + here_offset;+ }+ }++PCRE2_UNREACHABLE(); /* Control never reaches here */+}++++/*************************************************+* Case-independent strncmp() function *+*************************************************/++/*+Arguments:+ s first string+ t second string+ n number of characters to compare++Returns: < 0, = 0, or > 0, according to the comparison+*/++static int+strncmpic(const uint8_t *s, const uint8_t *t, size_t n)+{+if (n > 0) do+ {+ int c = tolower(*s++) - tolower(*t++);+ if (c != 0) return c;+ }+while (--n > 0);++return 0;+}++++/*************************************************+* Scan the main modifier list *+*************************************************/++/* This function searches the modifier list for a long modifier name.++Argument:+ p start of the name+ lenp length of the name++Returns: an index in the modifier list, or -1 on failure+*/++static int+scan_modifiers(const uint8_t *p, size_t len)+{+int bot = 0;+int top = MODLISTCOUNT;++while (top > bot)+ {+ int mid = (bot + top)/2;+ size_t mlen = strlen(modlist[mid].name);+ int c = strncmp((const char *)p, modlist[mid].name, (len < mlen)? len : mlen);+ if (c == 0)+ {+ if (len == mlen) return mid;+ c = len > mlen ? 1 : -1;+ }+ if (c > 0) bot = mid + 1; else top = mid;+ }++return -1;+}++++/*************************************************+* Determine how to print an error offset *+*************************************************/++/* Each error code has an associated direction - does it refer+to the characters to the right or to the left of the offset?++Arguments:+ rc the error code associated with the offset+ erroroffset the offset in the pattern where the error occurred++Returns: -1 if the error is unimplemented+ 0 if the offset is to be ignored (should be zero)+ 1 if the error refers to the left of the offset+ 2 if the error refers to the right of the offset+ 3 if the error refers to both sides of the offset+*/++static int+error_direction(int rc, PCRE2_SIZE erroroffset)+{+switch (rc)+ {+ /* These cases are all for things which don't affect a specific part of the+ pattern, and should always return zero offset. */++ case PCRE2_ERROR_NULL_PATTERN:+ case PCRE2_ERROR_BAD_OPTIONS:+ case PCRE2_ERROR_PATTERN_TOO_LARGE:+ case PCRE2_ERROR_HEAP_FAILED:+ case PCRE2_ERROR_UNICODE_NOT_SUPPORTED:+ case PCRE2_ERROR_PARENTHESES_STACK_CHECK:+ case PCRE2_ERROR_PATTERN_TOO_COMPLICATED:+ case PCRE2_ERROR_PATTERN_STRING_TOO_LONG:+ case PCRE2_ERROR_NO_SURROGATES_IN_UTF16:+ case PCRE2_ERROR_BAD_LITERAL_OPTIONS:+ case PCRE2_ERROR_PATTERN_COMPILED_SIZE_TOO_BIG:+ case PCRE2_ERROR_EXTRA_CASING_REQUIRES_UNICODE:+ case PCRE2_ERROR_TURKISH_CASING_REQUIRES_UTF:+ case PCRE2_ERROR_EXTRA_CASING_INCOMPATIBLE:+ return 0;++ /* A few exceptional cases use the errorofset to point rightwards. These are+ used when indicating an error in a capture group or lookaround parentheses.+ It is more user-friendly to identify the capture group by its start. */++ case PCRE2_ERROR_PARENTHESES_NEST_TOO_DEEP:+ case PCRE2_ERROR_LOOKBEHIND_NOT_FIXED_LENGTH:+ case PCRE2_ERROR_TOO_MANY_CONDITION_BRANCHES:+ case PCRE2_ERROR_LOOKBEHIND_TOO_COMPLICATED:+ case PCRE2_ERROR_LOOKBEHIND_INVALID_BACKSLASH_C:+ case PCRE2_ERROR_CALLOUT_NO_STRING_DELIMITER:+ case PCRE2_ERROR_QUERY_BARJX_NEST_TOO_DEEP:+ case PCRE2_ERROR_LOOKBEHIND_TOO_LONG:+ case PCRE2_ERROR_MAX_VAR_LOOKBEHIND_EXCEEDED:+ case PCRE2_ERROR_ECLASS_NEST_TOO_DEEP:+ return 2;++ /* The standard erroroffset should occur just after the affected portion of+ the pattern, unless there is a good reason not to do this. Consistency is+ good, but if there's a specific need then that's more important. */++ case PCRE2_ERROR_END_BACKSLASH:+ case PCRE2_ERROR_END_BACKSLASH_C:+ case PCRE2_ERROR_UNKNOWN_ESCAPE:+ case PCRE2_ERROR_QUANTIFIER_OUT_OF_ORDER:+ case PCRE2_ERROR_QUANTIFIER_TOO_BIG:+ case PCRE2_ERROR_MISSING_SQUARE_BRACKET:+ case PCRE2_ERROR_ESCAPE_INVALID_IN_CLASS:+ case PCRE2_ERROR_CLASS_RANGE_ORDER:+ case PCRE2_ERROR_QUANTIFIER_INVALID:+ case PCRE2_ERROR_INVALID_AFTER_PARENS_QUERY:+ case PCRE2_ERROR_POSIX_CLASS_NOT_IN_CLASS:+ case PCRE2_ERROR_POSIX_NO_SUPPORT_COLLATING:+ case PCRE2_ERROR_MISSING_CLOSING_PARENTHESIS:+ return 1;+ case PCRE2_ERROR_BAD_SUBPATTERN_REFERENCE:+ return 3; /* TODO I'd like to fix this, but some of the cases are _hard_ */+ case PCRE2_ERROR_MISSING_COMMENT_CLOSING:+ case PCRE2_ERROR_UNMATCHED_CLOSING_PARENTHESIS:+ case PCRE2_ERROR_MISSING_CONDITION_CLOSING:+ case PCRE2_ERROR_ZERO_RELATIVE_REFERENCE:+ case PCRE2_ERROR_CONDITION_ASSERTION_EXPECTED:+ case PCRE2_ERROR_BAD_RELATIVE_REFERENCE:+ case PCRE2_ERROR_UNKNOWN_POSIX_CLASS:+ case PCRE2_ERROR_CODE_POINT_TOO_BIG:+ case PCRE2_ERROR_UNSUPPORTED_ESCAPE_SEQUENCE:+ case PCRE2_ERROR_CALLOUT_NUMBER_TOO_BIG:+ case PCRE2_ERROR_MISSING_CALLOUT_CLOSING:+ case PCRE2_ERROR_ESCAPE_INVALID_IN_VERB:+ case PCRE2_ERROR_UNRECOGNIZED_AFTER_QUERY_P:+ case PCRE2_ERROR_MISSING_NAME_TERMINATOR:+ case PCRE2_ERROR_DUPLICATE_SUBPATTERN_NAME:+ case PCRE2_ERROR_INVALID_SUBPATTERN_NAME:+ case PCRE2_ERROR_UNICODE_PROPERTIES_UNAVAILABLE:+ case PCRE2_ERROR_MALFORMED_UNICODE_PROPERTY:+ case PCRE2_ERROR_UNKNOWN_UNICODE_PROPERTY:+ case PCRE2_ERROR_SUBPATTERN_NAME_TOO_LONG:+ case PCRE2_ERROR_TOO_MANY_NAMED_SUBPATTERNS:+ case PCRE2_ERROR_CLASS_INVALID_RANGE:+ case PCRE2_ERROR_OCTAL_BYTE_TOO_BIG:+ return 1;+ case PCRE2_ERROR_DEFINE_TOO_MANY_BRANCHES:+ return 2; /* TODO Not ideally placed; I'd like to fix this */+ case PCRE2_ERROR_BACKSLASH_O_MISSING_BRACE:+ case PCRE2_ERROR_BACKSLASH_G_SYNTAX:+ case PCRE2_ERROR_PARENS_QUERY_R_MISSING_CLOSING:+ case PCRE2_ERROR_VERB_UNKNOWN:+ case PCRE2_ERROR_SUBPATTERN_NUMBER_TOO_BIG:+ case PCRE2_ERROR_SUBPATTERN_NAME_EXPECTED:+ case PCRE2_ERROR_INVALID_OCTAL:+ case PCRE2_ERROR_SUBPATTERN_NAMES_MISMATCH:+ case PCRE2_ERROR_MARK_MISSING_ARGUMENT:+ case PCRE2_ERROR_INVALID_HEXADECIMAL:+ case PCRE2_ERROR_BACKSLASH_C_SYNTAX:+ case PCRE2_ERROR_BACKSLASH_K_SYNTAX:+ case PCRE2_ERROR_BACKSLASH_N_IN_CLASS:+ case PCRE2_ERROR_CALLOUT_STRING_TOO_LONG:+ case PCRE2_ERROR_UNICODE_DISALLOWED_CODE_POINT:+ return 1;+ case PCRE2_ERROR_VERB_NAME_TOO_LONG:+ case PCRE2_ERROR_BACKSLASH_U_CODE_POINT_TOO_BIG:+ case PCRE2_ERROR_MISSING_OCTAL_OR_HEX_DIGITS:+ case PCRE2_ERROR_VERSION_CONDITION_SYNTAX:+ case PCRE2_ERROR_CALLOUT_BAD_STRING_DELIMITER:+ case PCRE2_ERROR_BACKSLASH_C_CALLER_DISABLED:+ case PCRE2_ERROR_BACKSLASH_C_LIBRARY_DISABLED:+ case PCRE2_ERROR_SUPPORTED_ONLY_IN_UNICODE:+ case PCRE2_ERROR_INVALID_HYPHEN_IN_OPTIONS:+ case PCRE2_ERROR_ALPHA_ASSERTION_UNKNOWN:+ case PCRE2_ERROR_SCRIPT_RUN_NOT_AVAILABLE:+ case PCRE2_ERROR_TOO_MANY_CAPTURES:+ case PCRE2_ERROR_MISSING_OCTAL_DIGIT:+ return 1;+ case PCRE2_ERROR_BACKSLASH_K_IN_LOOKAROUND:+ return 3; /* TODO No erroroffset implemented yet, sadly */+ case PCRE2_ERROR_OVERSIZE_PYTHON_OCTAL:+ case PCRE2_ERROR_CALLOUT_CALLER_DISABLED:+ case PCRE2_ERROR_ECLASS_INVALID_OPERATOR:+ case PCRE2_ERROR_ECLASS_UNEXPECTED_OPERATOR:+ case PCRE2_ERROR_ECLASS_EXPECTED_OPERAND:+ case PCRE2_ERROR_ECLASS_MIXED_OPERATORS:+ case PCRE2_ERROR_ECLASS_HINT_SQUARE_BRACKET:+ case PCRE2_ERROR_PERL_ECLASS_UNEXPECTED_EXPR:+ case PCRE2_ERROR_PERL_ECLASS_EMPTY_EXPR:+ case PCRE2_ERROR_PERL_ECLASS_MISSING_CLOSE:+ case PCRE2_ERROR_PERL_ECLASS_UNEXPECTED_CHAR:+ case PCRE2_ERROR_EXPECTED_CAPTURE_GROUP:+ case PCRE2_ERROR_MISSING_OPENING_PARENTHESIS:+ case PCRE2_ERROR_MISSING_NUMBER_TERMINATOR:+ return 1;++ /* These two are a little fiddly. They can be triggered by passed-in options+ (when erroroffset is zero), or by text in the pattern "(*UTF)". We only+ indicate an pattern error in the latter case. */++ case PCRE2_ERROR_UTF_IS_DISABLED:+ case PCRE2_ERROR_UCP_IS_DISABLED:+ return (erroroffset > 0)? 1 : 0;++ case PCRE2_ERROR_UTF8_ERR1:+ case PCRE2_ERROR_UTF8_ERR2:+ case PCRE2_ERROR_UTF8_ERR3:+ case PCRE2_ERROR_UTF8_ERR4:+ case PCRE2_ERROR_UTF8_ERR5:+ case PCRE2_ERROR_UTF8_ERR6:+ case PCRE2_ERROR_UTF8_ERR7:+ case PCRE2_ERROR_UTF8_ERR8:+ case PCRE2_ERROR_UTF8_ERR9:+ case PCRE2_ERROR_UTF8_ERR10:+ case PCRE2_ERROR_UTF8_ERR11:+ case PCRE2_ERROR_UTF8_ERR12:+ case PCRE2_ERROR_UTF8_ERR13:+ case PCRE2_ERROR_UTF8_ERR14:+ case PCRE2_ERROR_UTF8_ERR15:+ case PCRE2_ERROR_UTF8_ERR16:+ case PCRE2_ERROR_UTF8_ERR17:+ case PCRE2_ERROR_UTF8_ERR18:+ case PCRE2_ERROR_UTF8_ERR19:+ case PCRE2_ERROR_UTF8_ERR20:+ case PCRE2_ERROR_UTF8_ERR21:+ case PCRE2_ERROR_UTF16_ERR1:+ case PCRE2_ERROR_UTF16_ERR2:+ case PCRE2_ERROR_UTF16_ERR3:+ case PCRE2_ERROR_UTF32_ERR1:+ case PCRE2_ERROR_UTF32_ERR2:+ return 2;+ }++return -1;+}++++#ifdef SUPPORT_PCRE2_8+/*************************************************+* Show something in a list *+*************************************************/++/* This function just helps to keep the code that uses it tidier. It's used for+various lists of things where there needs to be introductory text before the+first item. As these calls are all in the POSIX-support code, they happen only+when 8-bit mode is supported. */++static void+prmsg(const char **msg, const char *s)+{+cfprintf(clr_test_error, outfile, "%s %s", *msg, s);+*msg = "";+}+#endif /* SUPPORT_PCRE2_8 */++++/*************************************************+* Show control bits *+*************************************************/++/* Called for mutually exclusive controls and for unsupported POSIX controls.+Because the bits are unique, this can be used for both pattern and data control+words.++Arguments:+ clr colour for output+ controls control bits+ controls2 more control bits+ before text to print before++Returns: nothing+*/++static void+show_controls(int clr, uint32_t controls, uint32_t controls2, const char *before)+{+cfprintf(clr, 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%s%s",+ before,+ ((controls & CTL_AFTERTEXT) != 0)? " aftertext" : "",+ ((controls & CTL_ALLAFTERTEXT) != 0)? " allaftertext" : "",+ ((controls & CTL_ALLCAPTURES) != 0)? " allcaptures" : "",+ ((controls & CTL_ALLUSEDTEXT) != 0)? " allusedtext" : "",+ ((controls2 & CTL2_ALLVECTOR) != 0)? " allvector" : "",+ ((controls & CTL_ALTGLOBAL) != 0)? " altglobal" : "",+ ((controls & CTL_BINCODE) != 0)? " bincode" : "",+ ((controls2 & CTL2_BSR_SET) != 0)? " bsr" : "",+ ((controls & CTL_CALLOUT_CAPTURE) != 0)? " callout_capture" : "",+ ((controls2 & CTL2_CALLOUT_EXTRA) != 0)? " callout_extra" : "",+ ((controls & CTL_CALLOUT_INFO) != 0)? " callout_info" : "",+ ((controls & CTL_CALLOUT_NONE) != 0)? " callout_none" : "",+ ((controls2 & CTL2_CALLOUT_NO_WHERE) != 0)? " callout_no_where" : "",+ ((controls & CTL_DFA) != 0)? " dfa" : "",+ ((controls & CTL_EXPAND) != 0)? " expand" : "",+ ((controls & CTL_FINDLIMITS) != 0)? " find_limits" : "",+ ((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" : "",+ ((controls & CTL_JITVERIFY) != 0)? " jitverify" : "",+ ((controls & CTL_MARK) != 0)? " mark" : "",+ ((controls & CTL_MEMORY) != 0)? " memory" : "",+ ((controls2 & CTL2_NL_SET) != 0)? " newline" : "",+ ((controls & CTL_NULLCONTEXT) != 0)? " null_context" : "",+ ((controls2 & CTL2_NULL_REPLACEMENT) != 0)? " null_replacement" : "",+ ((controls2 & CTL2_NULL_SUBJECT) != 0)? " null_subject" : "",+ ((controls2 & CTL2_NULL_SUBSTITUTE_MATCH_DATA) != 0)? " null_substitute_match_data" : "",+ ((controls & CTL_POSIX) != 0)? " posix" : "",+ ((controls & CTL_POSIX_NOSUB) != 0)? " posix_nosub" : "",+ ((controls & CTL_PUSH) != 0)? " push" : "",+ ((controls & CTL_PUSHCOPY) != 0)? " pushcopy" : "",+ ((controls & CTL_PUSHTABLESCOPY) != 0)? " pushtablescopy" : "",+ ((controls & CTL_STARTCHAR) != 0)? " startchar" : "",+ ((controls2 & CTL2_SUBSTITUTE_CALLOUT) != 0)? " substitute_callout" : "",+ ((controls2 & CTL2_SUBSTITUTE_CASE_CALLOUT) != 0)? " substitute_case_callout" : "",+ ((controls2 & CTL2_SUBSTITUTE_EXTENDED) != 0)? " substitute_extended" : "",+ ((controls2 & CTL2_SUBSTITUTE_LITERAL) != 0)? " substitute_literal" : "",+ ((controls2 & CTL2_SUBSTITUTE_MATCHED) != 0)? " substitute_matched" : "",+ ((controls2 & CTL2_SUBSTITUTE_OVERFLOW_LENGTH) != 0)? " substitute_overflow_length" : "",+ ((controls2 & CTL2_SUBSTITUTE_REPLACEMENT_ONLY) != 0)? " substitute_replacement_only" : "",+ ((controls2 & CTL2_SUBSTITUTE_UNKNOWN_UNSET) != 0)? " substitute_unknown_unset" : "",+ ((controls2 & CTL2_SUBSTITUTE_UNSET_EMPTY) != 0)? " substitute_unset_empty" : "",+ ((controls & CTL_USE_LENGTH) != 0)? " use_length" : "",+ ((controls & CTL_UTF8_INPUT) != 0)? " utf8_input" : "",+ ((controls & CTL_ZERO_TERMINATE) != 0)? " zero_terminate" : "");+}++++/*************************************************+* Show compile options *+*************************************************/++/* Called from show_pattern_info() and for unsupported POSIX options.++Arguments:+ clr colour for output+ options an options word+ before text to print before+ after text to print after++Returns: nothing+*/++static void+show_compile_options(int clr, uint32_t options, const char *before, const char *after)+{+if (options == 0) cfprintf(clr, outfile, "%s <none>%s", before, after);+else cfprintf(clr, 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",+ before,+ ((options & PCRE2_ALT_BSUX) != 0)? " alt_bsux" : "",+ ((options & PCRE2_ALT_CIRCUMFLEX) != 0)? " alt_circumflex" : "",+ ((options & PCRE2_ALT_EXTENDED_CLASS) != 0)? " alt_extended_class" : "",+ ((options & PCRE2_ALT_VERBNAMES) != 0)? " alt_verbnames" : "",+ ((options & PCRE2_ALLOW_EMPTY_CLASS) != 0)? " allow_empty_class" : "",+ ((options & PCRE2_ANCHORED) != 0)? " anchored" : "",+ ((options & PCRE2_AUTO_CALLOUT) != 0)? " auto_callout" : "",+ ((options & PCRE2_CASELESS) != 0)? " caseless" : "",+ ((options & PCRE2_DOLLAR_ENDONLY) != 0)? " dollar_endonly" : "",+ ((options & PCRE2_DOTALL) != 0)? " dotall" : "",+ ((options & PCRE2_DUPNAMES) != 0)? " dupnames" : "",+ ((options & PCRE2_ENDANCHORED) != 0)? " endanchored" : "",+ ((options & PCRE2_EXTENDED) != 0)? " extended" : "",+ ((options & PCRE2_EXTENDED_MORE) != 0)? " extended_more" : "",+ ((options & PCRE2_FIRSTLINE) != 0)? " firstline" : "",+ ((options & PCRE2_LITERAL) != 0)? " literal" : "",+ ((options & PCRE2_MATCH_INVALID_UTF) != 0)? " match_invalid_utf" : "",+ ((options & PCRE2_MATCH_UNSET_BACKREF) != 0)? " match_unset_backref" : "",+ ((options & PCRE2_MULTILINE) != 0)? " multiline" : "",+ ((options & PCRE2_NEVER_BACKSLASH_C) != 0)? " never_backslash_c" : "",+ ((options & PCRE2_NEVER_UCP) != 0)? " never_ucp" : "",+ ((options & PCRE2_NEVER_UTF) != 0)? " never_utf" : "",+ ((options & PCRE2_NO_AUTO_CAPTURE) != 0)? " no_auto_capture" : "",+ ((options & PCRE2_NO_AUTO_POSSESS) != 0)? " no_auto_possess" : "",+ ((options & PCRE2_NO_DOTSTAR_ANCHOR) != 0)? " no_dotstar_anchor" : "",+ ((options & PCRE2_NO_UTF_CHECK) != 0)? " no_utf_check" : "",+ ((options & PCRE2_NO_START_OPTIMIZE) != 0)? " no_start_optimize" : "",+ ((options & PCRE2_UCP) != 0)? " ucp" : "",+ ((options & PCRE2_UNGREEDY) != 0)? " ungreedy" : "",+ ((options & PCRE2_USE_OFFSET_LIMIT) != 0)? " use_offset_limit" : "",+ ((options & PCRE2_UTF) != 0)? " utf" : "",+ after);+}+++/*************************************************+* Show compile extra options *+*************************************************/++/* Called from show_pattern_info() and for unsupported POSIX options.++Arguments:+ clr colour for output+ options an options word+ before text to print before+ after text to print after++Returns: nothing+*/++static void+show_compile_extra_options(int clr, uint32_t options, const char *before,+ const char *after)+{+if (options == 0) cfprintf(clr, outfile, "%s <none>%s", before, after);+else cfprintf(clr, outfile, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",+ before,+ ((options & PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK) != 0) ? " allow_lookaround_bsk" : "",+ ((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_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_NEVER_CALLOUT) != 0)? " never_callout" : "",+ ((options & PCRE2_EXTRA_NO_BS0) != 0)? " no_bs0" : "",+ ((options & PCRE2_EXTRA_PYTHON_OCTAL) != 0)? " python_octal" : "",+ ((options & PCRE2_EXTRA_TURKISH_CASING) != 0)? " turkish_casing" : "",+ after);+}+++/*************************************************+* Show optimization flags *+*************************************************/++/*+Arguments:+ clr colour for output+ flags an options word+ before text to print before+ after text to print after++Returns: nothing+*/++static void+show_optimize_flags(int clr, uint32_t flags, const char *before, const char *after)+{+if (flags == 0) cfprintf(clr, outfile, "%s<none>%s", before, after);+else cfprintf(clr, outfile, "%s%s%s%s%s%s%s",+ before,+ ((flags & PCRE2_OPTIM_AUTO_POSSESS) != 0) ? "auto_possess" : "",+ ((flags & PCRE2_OPTIM_AUTO_POSSESS) != 0 && (flags >> 1) != 0) ? "," : "",+ ((flags & PCRE2_OPTIM_DOTSTAR_ANCHOR) != 0) ? "dotstar_anchor" : "",+ ((flags & PCRE2_OPTIM_DOTSTAR_ANCHOR) != 0 && (flags >> 2) != 0) ? "," : "",+ ((flags & PCRE2_OPTIM_START_OPTIMIZE) != 0) ? "start_optimize" : "",+ after);+}+++#ifdef SUPPORT_PCRE2_8+/*************************************************+* Show match options *+*************************************************/++/* Called for unsupported POSIX options. */++static void+show_match_options(int clr, uint32_t options)+{+cfprintf(clr, 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" : "",+ ((options & PCRE2_NOTBOL) != 0)? " notbol" : "",+ ((options & PCRE2_NOTEMPTY) != 0)? " notempty" : "",+ ((options & PCRE2_NOTEMPTY_ATSTART) != 0)? " notempty_atstart" : "",+ ((options & PCRE2_NOTEOL) != 0)? " noteol" : "",+ ((options & PCRE2_PARTIAL_HARD) != 0)? " partial_hard" : "",+ ((options & PCRE2_PARTIAL_SOFT) != 0)? " partial_soft" : "");+}+#endif /* SUPPORT_PCRE2_8 */++++/*************************************************+* Open file for save/load commands *+*************************************************/++/* This function decodes the file name and opens the file.++Arguments:+ buffptr point after the #command+ mode open mode+ fptr points to the FILE variable+ name name of # command++Returns: PR_OK or PR_ABEND+*/++static int+open_file(uint8_t *buffptr, const char *mode, FILE **fptr, const char *name)+{+char *endf;+char *filename = (char *)buffptr;+while (isspace((unsigned char)*filename)) filename++;+endf = filename + strlen(filename);+while (endf > filename && isspace((unsigned char)endf[-1])) endf--;++if (endf == filename)+ {+ cfprintf(clr_test_error, outfile, "** File name expected after %s\n", name);+ return PR_ABEND;+ }++*endf = 0;+*fptr = fopen((const char *)filename, mode);+if (*fptr == NULL)+ {+ cfprintf(clr_test_error, outfile, "** Failed to open \"%s\": %s\n", filename, strerror(errno));+ return PR_ABEND;+ }++return PR_OK;+}+++++/*************************************************+* Substitute case callout transform *+*************************************************/++/* Function to implement our test-only custom case mappings.+To ease implementation, we only work in the ASCII range (so that we don't need+to read & write UTF sequences).+However, we aim to implement case mappings which fairly well represent the range+of interesting behaviours that exist for Unicode codepoints. */++static BOOL+case_transform(int to_case, int num_in, int *num_read, int *num_write,+ uint32_t *c1, uint32_t *c2)+{+/* Let's have one character which aborts the substitution. */+if (*c1 == CHAR_EXCLAMATION_MARK) return FALSE;++/* Default behaviour is to read one character, and write back that same one+character (treating all characters as "uncased"). */+*num_read = *num_write = 1;++/* Add a normal case pair 'a' (l) <-> 'B' (t,u). Standard ASCII letter+behaviour, but with switched letters for testing. */+if (*c1 == CHAR_a && to_case != PCRE2_SUBSTITUTE_CASE_LOWER)+ *c1 = CHAR_B;+else if (*c1 == CHAR_B && to_case == PCRE2_SUBSTITUTE_CASE_LOWER)+ *c1 = CHAR_a;++/* Add a titlecased triplet 'd' (l) <-> 'D' (t) <-> 'Z' (u). Example: the+'dz'/'Dz'/'DZ' ligature character ("Latin Small Letter DZ" <-> "Latin Capital+Letter D with Small Letter Z" <-> "Latin Capital Letter DZ"). */+else if (*c1 == CHAR_d && to_case != PCRE2_SUBSTITUTE_CASE_LOWER)+ *c1 = (to_case == PCRE2_SUBSTITUTE_CASE_TITLE_FIRST)? CHAR_D : CHAR_Z;+else if (*c1 == CHAR_D && to_case != PCRE2_SUBSTITUTE_CASE_TITLE_FIRST)+ *c1 = (to_case == PCRE2_SUBSTITUTE_CASE_LOWER)? CHAR_d : CHAR_Z;+else if (*c1 == CHAR_Z && to_case != PCRE2_SUBSTITUTE_CASE_UPPER)+ *c1 = (to_case == PCRE2_SUBSTITUTE_CASE_LOWER)? CHAR_d : CHAR_D;++/* Expands when uppercased. Example: Esszet 'f' <-> 'SS'. */+else if (*c1 == CHAR_f && to_case != PCRE2_SUBSTITUTE_CASE_LOWER)+ {+ *c1 = CHAR_S;+ *c2 = CHAR_S;+ *num_write = 2;+ }+else if (*c1 == CHAR_s && to_case != PCRE2_SUBSTITUTE_CASE_LOWER)+ *c1 = CHAR_S;+else if (*c1 == CHAR_S && to_case == PCRE2_SUBSTITUTE_CASE_LOWER)+ *c1 = CHAR_s;++/* Expanding and contracting characters, 'o' <-> 'OO'. You can get this purely+due to UTF-8 encoding length, for example uppercase Omega (3 bytes in UTF-8)+lowercases to 2 bytes in UTF-8. */+else if (num_in == 2 && *c1 == CHAR_O && *c2 == CHAR_O &&+ to_case == PCRE2_SUBSTITUTE_CASE_LOWER)+ {+ *c1 = CHAR_o;+ *num_read = 2;+ }+else if (*c1 == CHAR_o && to_case != PCRE2_SUBSTITUTE_CASE_LOWER)+ {+ *c1 = CHAR_O;+ *c2 = CHAR_O;+ *num_write = 2;+ }+else if (num_in == 2 && *c1 == CHAR_p && *c2 == CHAR_p &&+ to_case != PCRE2_SUBSTITUTE_CASE_LOWER)+ {+ *c1 = CHAR_P;+ *num_read = 2;+ }+else if (*c1 == CHAR_P && to_case == PCRE2_SUBSTITUTE_CASE_LOWER)+ {+ *c1 = CHAR_p;+ *c2 = CHAR_p;+ *num_write = 2;+ }++/* Use 'l' -> 'Mn' or 'MN' as an expanding ligature, like 'fi' -> 'Fi' ->+'FI'. */+else if (*c1 == CHAR_l && to_case != PCRE2_SUBSTITUTE_CASE_LOWER)+ {+ *c1 = CHAR_M;+ *c2 = (to_case == PCRE2_SUBSTITUTE_CASE_TITLE_FIRST)? CHAR_n : CHAR_N;+ *num_write = 2;+ }+else if (*c1 == CHAR_M && to_case == PCRE2_SUBSTITUTE_CASE_LOWER)+ *c1 = CHAR_m;+else if (*c1 == CHAR_m && to_case != PCRE2_SUBSTITUTE_CASE_LOWER)+ *c1 = CHAR_M;+else if (*c1 == CHAR_N && to_case == PCRE2_SUBSTITUTE_CASE_LOWER)+ *c1 = CHAR_n;+else if (*c1 == CHAR_n && to_case != PCRE2_SUBSTITUTE_CASE_LOWER)+ *c1 = CHAR_N;++/* An example of a context-dependent mapping, the Greek Sigma. It lowercases+depending on the following character. Use 'c'/'k' -> 'K'. */+else if ((*c1 == CHAR_c || *c1 == CHAR_k) &&+ to_case != PCRE2_SUBSTITUTE_CASE_LOWER)+ *c1 = CHAR_K;+else if (*c1 == CHAR_K && to_case == PCRE2_SUBSTITUTE_CASE_LOWER)+ *c1 = (num_in == 1 || *c2 == CHAR_SPACE)? CHAR_c : CHAR_k;++/* An example of a context-dependent multi mapping, the Dutch IJ. When those+letters appear together, they titlecase 'ij' (l) <-> 'IJ' (t) <-> 'IJ' (u).+Namely, English titlecasing of 'ijnssel' would be 'Ijnssel' (just uppercase the+first letter), but the Dutch rule is 'IJnssel'. */+else if (num_in == 2 && (*c1 == CHAR_i || *c1 == CHAR_I) &&+ (*c2 == CHAR_j || *c2 == CHAR_J) &&+ to_case == PCRE2_SUBSTITUTE_CASE_TITLE_FIRST)+ {+ *c1 = CHAR_I;+ *c2 = CHAR_J;+ *num_read = 2;+ *num_write = 2;+ }+else if (*c1 == CHAR_i && to_case != PCRE2_SUBSTITUTE_CASE_LOWER)+ *c1 = CHAR_I;+else if (*c1 == CHAR_I && to_case == PCRE2_SUBSTITUTE_CASE_LOWER)+ *c1 = CHAR_i;+else if (*c1 == CHAR_j && to_case != PCRE2_SUBSTITUTE_CASE_LOWER)+ *c1 = CHAR_J;+else if (*c1 == CHAR_J && to_case == PCRE2_SUBSTITUTE_CASE_LOWER)+ *c1 = CHAR_j;++return TRUE;+}++++/*************************************************+* Show an entire ovector *+*************************************************/++/* This function is called after partial matching or match failure, when the+"allvector" modifier is set. It is a means of checking the contents of the+entire ovector, to ensure no modification of fields that should be unchanged.++Arguments:+ ovector points to the ovector+ oveccount number of pairs++Returns: nothing+*/++static void+show_ovector(PCRE2_SIZE *ovector, uint32_t oveccount)+{+uint32_t i;+for (i = 0; i < 2*oveccount; i += 2)+ {+ PCRE2_SIZE start = ovector[i];+ PCRE2_SIZE end = ovector[i+1];++ fprintf(outfile, "%2d: ", i/2);+ if (start == PCRE2_UNSET && end == PCRE2_UNSET)+ fprintf(outfile, "<unset>\n");+ else if (start == JUNK_OFFSET && end == JUNK_OFFSET)+ fprintf(outfile, "<unchanged>\n");+ else+ fprintf(outfile, "%ld %ld\n", (unsigned long int)start,+ (unsigned long int)end);+ }+}++++/*************************************************+* Mode-dependent code *+*************************************************/++/* All the mode-independent utilities should go above this section, so that+the mode-dependent code can use them.++The structure is:+ main+ -> calls into usage, command line parsing, top-level dispatch+ -> calls into mode-dependent code to handle input lines+ -> calls into mode-independent utilities++The ordering of the code blocks is therefore:+ - mode-independent utilities (ABOVE THIS SECTION)+ - mode-dependent code to handle input lines (THIS SECTION)+ - usage, command line parsing, top-level dispatch (NEXT SECTION)+ - main (AT THE BOTTOM)+*/++/* --- Repeated pre-processor inclusions to build the mode-dependent code -- */++#undef PCRE2_SUFFIX++#ifdef SUPPORT_PCRE2_8+#define PCRE2_CODE_UNIT_WIDTH 8+#define PCRE2_SUFFIX(a) G(a,8)+#include "pcre2_intmodedep.h"+#include "pcre2test_inc.h"+#undef PCRE2_CODE_UNIT_WIDTH+#undef PCRE2_SUFFIX+#endif++#ifdef SUPPORT_PCRE2_16+#define PCRE2_CODE_UNIT_WIDTH 16+#define PCRE2_SUFFIX(a) G(a,16)+#include "pcre2_intmodedep.h"+#include "pcre2test_inc.h"+#undef PCRE2_CODE_UNIT_WIDTH+#undef PCRE2_SUFFIX+#endif++#ifdef SUPPORT_PCRE2_32+#define PCRE2_CODE_UNIT_WIDTH 32+#define PCRE2_SUFFIX(a) G(a,32)+#include "pcre2_intmodedep.h"+#include "pcre2test_inc.h"+#undef PCRE2_CODE_UNIT_WIDTH+#undef PCRE2_SUFFIX+#endif++#define PCRE2_CODE_UNIT_WIDTH 0+#include "pcre2_intmodedep.h" /* Clear out the stale macros */+#undef PCRE2_CODE_UNIT_WIDTH++#define PCRE2_SUFFIX(a) a++/* --------------------------- Static variables ---------------------------- */++/* Declared after mode-dependent code. */++static int test_mode = DEFAULT_TEST_MODE;++/* -------------------- Mode-dependent dispatch helper --------------------- */++/* When there are three supported bit widths, use a three-way ternary. */++#if defined(SUPPORT_PCRE2_8) && defined(SUPPORT_PCRE2_16) && defined(SUPPORT_PCRE2_32)++#define DISPATCH(opt_ret, fname, fargs) opt_ret \+ ((test_mode == PCRE2TEST_MODE_8)? G(fname,8) fargs : \+ (test_mode == PCRE2TEST_MODE_16)? G(fname,16) fargs : \+ G(fname,32) fargs)++#elif (defined(SUPPORT_PCRE2_8) + defined(SUPPORT_PCRE2_16) + \+ defined(SUPPORT_PCRE2_32)) == 2++/* With some macro trickery, we can make a single definition work to dispatch+between any two bit widths. */++#if defined(SUPPORT_PCRE2_32) && defined(SUPPORT_PCRE2_16)+#define BITONE 32+#define BITTWO 16+#elif defined(SUPPORT_PCRE2_32) && defined(SUPPORT_PCRE2_8)+#define BITONE 32+#define BITTWO 8+#else+#define BITONE 16+#define BITTWO 8+#endif++#define DISPATCH(opt_ret, fname, fargs) opt_ret \+ ((test_mode == G(PCRE2TEST_MODE_,BITONE))? G(fname,BITONE) fargs : \+ G(fname,BITTWO) fargs)++#else /* Only one bit width supported */++#if defined(SUPPORT_PCRE2_32)+#define BITONE 32+#elif defined(SUPPORT_PCRE2_16)+#define BITONE 16+#else+#define BITONE 8+#endif++#define DISPATCH(opt_ret, fname, fargs) \+ opt_ret (G(fname,BITONE) fargs)++#endif++/* -------------------- Mode-dependent dispatch wrappers ------------------- */++static int jit_compile_test(void)+{+DISPATCH(return, pcre2_jit_compile_, (NULL, PCRE2_JIT_TEST_ALLOC));+}++static int pcre2_config(uint32_t what, void *where)+{+DISPATCH(return, pcre2_config_, (what, where));+}++static void config_str(uint32_t what, char *where)+{+DISPATCH(, config_str_, (what, where));+}++static BOOL decode_modifiers(uint8_t *p, int ctx, patctl *pctl, datctl *dctl)+{+DISPATCH(return, decode_modifiers_, (p, ctx, pctl, dctl));+}++static BOOL+print_error_message_file(FILE *file, int errorcode, const char *before,+ const char *after, BOOL badcode_ok)+{+DISPATCH(return, print_error_message_file_, \+ (file, errorcode, before, after, badcode_ok));+}++static int process_command(void)+{+DISPATCH(return, process_command_, ());+}++static int process_pattern(void)+{+DISPATCH(return, process_pattern_, ());+}++static BOOL have_active_pattern(void)+{+DISPATCH(return, have_active_pattern_, ());+}++static void free_active_pattern(void)+{+DISPATCH(, free_active_pattern_, ());+}++static int process_data(void)+{+DISPATCH(return, process_data_, ());+}++static void init_globals(void)+{+DISPATCH(, init_globals_, ());+}++static void free_globals(void)+{+DISPATCH(, free_globals_, ());+}++static void unittest(void)+{+DISPATCH(, unittest_, ());+}++#undef DISPATCH+#undef BITONE+#undef BITTWO++++/*************************************************+* Print PCRE2 version *+*************************************************/++static void+print_version(FILE *f, BOOL include_mode)+{+char buf[VERSION_SIZE];+config_str(PCRE2_CONFIG_VERSION, buf);+fprintf(f, "PCRE2 version %s", buf);+if (include_mode)+ {+ fprintf(f, " (%d-bit)", test_mode);+ }+fprintf(f, "\n");+}++++/*************************************************+* Print Unicode version *+*************************************************/++static void+print_unicode_version(FILE *f)+{+char buf[VERSION_SIZE];+config_str(PCRE2_CONFIG_UNICODE_VERSION, buf);+fprintf(f, "Unicode version %s", buf);+}++++/*************************************************+* Print JIT target *+*************************************************/++static void+print_jit_target(FILE *f)+{+char buf[VERSION_SIZE];+config_str(PCRE2_CONFIG_JITTARGET, buf);+fputs(buf, f);+}++++/*************************************************+* Print newline configuration *+*************************************************/++/* Output is always to stdout.++Arguments:+ rc the return code from PCRE2_CONFIG_NEWLINE+ isc TRUE if called from "-C newline"+Returns: nothing+*/++static void+print_newline_config(uint32_t optval, BOOL isc)+{+if (!isc) printf(" Default newline sequence is ");+if (optval < sizeof(newlines)/sizeof(char *))+ printf("%s\n", newlines[optval]);+else+ printf("a non-standard value: %d\n", optval);+}++++/*************************************************+* Usage function *+*************************************************/++static void+usage(void)+{+printf("Usage: pcre2test [options] [<input file> [<output file>]]\n\n");+printf("Input and output default to stdin and stdout.\n");+#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)+printf("If input is a terminal, readline() is used to read from it.\n");+#else+printf("This version of pcre2test is not linked with readline().\n");+#endif+printf("\nOptions:\n");+#ifdef SUPPORT_PCRE2_8+printf(" -8 use the 8-bit library\n");+#endif+#ifdef SUPPORT_PCRE2_16+printf(" -16 use the 16-bit library\n");+#endif+#ifdef SUPPORT_PCRE2_32+printf(" -32 use the 32-bit library\n");+#endif+printf(" -ac set default pattern modifier PCRE2_AUTO_CALLOUT\n");+printf(" -AC as -ac, but also set subject 'callout_extra' modifier\n");+printf(" -b set default pattern modifier 'fullbincode'\n");+printf(" -C show PCRE2 compile-time options and exit\n");+printf(" -C arg show a specific compile-time option and exit with its\n");+printf(" value if numeric (else 0). The arg can be:\n");+printf(" backslash-C use of \\C is enabled [0, 1]\n");+printf(" bsr \\R type [ANYCRLF, ANY]\n");+printf(" ebcdic compiled for EBCDIC character code [0, 1]\n");+printf(" ebcdic-io if compiled for EBCDIC, whether pcre2test's input\n");+printf(" and output is EBCDIC or ASCII [0, 1]\n");+printf(" ebcdic-nl25 if compiled for EBCDIC, whether NL is 0x25 [0, 1]\n");+printf(" jit just-in-time compiler supported [0, 1]\n");+printf(" jitusable test JIT usability [0, 1, 2, 3]\n");+printf(" linksize internal link size [2, 3, 4]\n");+printf(" newline newline type [CR, LF, CRLF, ANYCRLF, ANY, NUL]\n");+printf(" pcre2-8 8 bit library support enabled [0, 1]\n");+printf(" pcre2-16 16 bit library support enabled [0, 1]\n");+printf(" pcre2-32 32 bit library support enabled [0, 1]\n");+printf(" unicode Unicode and UTF support enabled [0, 1]\n");+printf(" --colo[u]r[=<always,auto,never>]\n");+printf(" show output in colour\n");+printf(" -d set default pattern modifier 'debug'\n");+printf(" -dfa set default subject modifier 'dfa'\n");+printf(" -E preprocess input only (#if ... #endif)\n");+printf(" -error <n,m,..> show messages for error numbers, then exit\n");+printf(" -help show usage information\n");+printf(" -i set default pattern modifier 'info'\n");+printf(" -jit set default pattern modifier 'jit'\n");+printf(" -jitfast set default pattern modifier 'jitfast'\n");+printf(" -jitverify set default pattern modifier 'jitverify'\n");+printf(" -LM list pattern and subject modifiers, then exit\n");+printf(" -LP list non-script properties, then exit\n");+printf(" -LS list supported scripts, then exit\n");+printf(" -malloc exercise malloc() failures\n");+printf(" -q quiet: do not output PCRE2 version number at start\n");+printf(" -pattern <s> set default pattern modifier fields\n");+printf(" -subject <s> set default subject modifier fields\n");+printf(" -S <n> set stack size to <n> mebibytes\n");+printf(" -t [<n>] time compilation and execution, repeating <n> times\n");+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(" -unittest run unit tests, then exit\n");+printf(" -v|--version show PCRE2 version and exit\n");+}++++/*************************************************+* Handle -C option *+*************************************************/++/* This option outputs configuration options and sets an appropriate return+code when asked for a single option. The code is abstracted into a separate+function because of its size.++Most, but not all, of the data is independent of the test mode.++Argument: an option name or NULL+Returns: the return code+*/++static int+c_option(const char *arg)+{+uint32_t optval;+unsigned int i = COPTLISTCOUNT;+int rc, yield = 0;++if (arg != NULL && arg[0] != '-')+ {+ for (i = 0; i < COPTLISTCOUNT; i++)+ if (strcmp(arg, coptlist[i].name) == 0) break;++ if (i >= COPTLISTCOUNT)+ {+ cfprintf(clr_test_error, stderr, "pcre2test: Unknown -C option \"%s\"\n", arg);+ return 0;+ }++ switch (coptlist[i].type)+ {+ case CONF_BSR:+ (void)pcre2_config(coptlist[i].value, &optval);+ printf("%s\n", (optval == PCRE2_BSR_ANYCRLF)? "ANYCRLF" : "ANY");+ break;++ case CONF_FIX:+ yield = coptlist[i].value;+ printf("%d\n", yield);+ break;++ case CONF_INT:+ (void)pcre2_config(coptlist[i].value, &yield);+ printf("%d\n", yield);+ break;++ case CONF_NL:+ (void)pcre2_config(coptlist[i].value, &optval);+ print_newline_config(optval, TRUE);+ break;++ case CONF_JU:+ rc = jit_compile_test();+ switch(rc)+ {+ case 0: yield = 0; break;+ case PCRE2_ERROR_NOMEMORY: yield = 1; break;+ case PCRE2_ERROR_JIT_UNSUPPORTED: yield = 2; break;+ default: yield = 3; break;+ }+ printf("%d\n", yield);+ break;+ }++/* For VMS, return the value by setting a symbol, for certain values only. This+is contributed code which the PCRE2 developers have no means of testing. */++#ifdef __VMS++/* This is the original code provided by the first VMS contributor. */+#ifdef NEVER+ if (copytlist[i].type == CONF_FIX || coptlist[i].type == CONF_INT)+ {+ char ucname[16];+ strcpy(ucname, coptlist[i].name);+ for (i = 0; ucname[i] != 0; i++) ucname[i] = toupper[ucname[i]];+ vms_setsymbol(ucname, 0, optval);+ }+#endif++/* This is the new code, provided by a second VMS contributor. */++ if (coptlist[i].type == CONF_FIX || coptlist[i].type == CONF_INT)+ {+ char nam_buf[22], val_buf[4];+ $DESCRIPTOR(nam, nam_buf);+ $DESCRIPTOR(val, val_buf);++ strcpy(nam_buf, coptlist[i].name);+ nam.dsc$w_length = strlen(nam_buf);+ sprintf(val_buf, "%d", yield);+ val.dsc$w_length = strlen(val_buf);+ lib$set_symbol(&nam, &val);+ }+#endif /* __VMS */++ return yield;+ }++/* No argument for -C: output all configuration information. */++print_version(stdout, FALSE);+printf("Compiled with\n");++#ifdef EBCDIC+printf(" EBCDIC code support: LF is 0x%02x\n", CHAR_LF);+#if defined NATIVE_ZOS+printf(" EBCDIC code page %s or similar\n", pcrz_cpversion());+#endif+#if EBCDIC_IO+printf(" Input/output for pcre2test is EBCDIC\n");+#else+printf(" Input/output for pcre2test is ASCII, not EBCDIC\n");+#endif+#endif++(void)pcre2_config(PCRE2_CONFIG_COMPILED_WIDTHS, &optval);+if (optval & 1) printf(" 8-bit support\n");+if (optval & 2) printf(" 16-bit support\n");+if (optval & 4) printf(" 32-bit support\n");++#ifdef SUPPORT_VALGRIND+printf(" Valgrind support\n");+#endif++(void)pcre2_config(PCRE2_CONFIG_UNICODE, &optval);+if (optval != 0)+ {+ printf(" UTF and UCP support (");+ print_unicode_version(stdout);+ printf(")\n");+ }+else printf(" No Unicode support\n");++(void)pcre2_config(PCRE2_CONFIG_JIT, &optval);+if (optval != 0)+ {+ printf(" Just-in-time compiler support\n");+ printf(" Architecture: ");+ print_jit_target(stdout);+ printf("\n");++ printf(" Can allocate executable memory: ");+ rc = jit_compile_test();+ switch(rc)+ {+ case 0:+ printf("Yes\n");+ break;++ case PCRE2_ERROR_NOMEMORY:+ printf("No (so cannot work)\n");+ break;++ default:+ cfprintf(clr_test_error, stdout, "\n** Unexpected return %d from "+ "pcre2_jit_compile(NULL, PCRE2_JIT_TEST_ALLOC)\n", rc);+ cfprintf(clr_test_error, stdout, "** Should not occur\n");+ yield = 1;+ break;+ }+ }+else+ {+ printf(" No just-in-time compiler support\n");+ }++(void)pcre2_config(PCRE2_CONFIG_NEWLINE, &optval);+print_newline_config(optval, FALSE);+(void)pcre2_config(PCRE2_CONFIG_BSR, &optval);+printf(" \\R matches %s\n",+ (optval == PCRE2_BSR_ANYCRLF)? "CR, LF, or CRLF only" :+ "all Unicode newlines");+(void)pcre2_config(PCRE2_CONFIG_NEVER_BACKSLASH_C, &optval);+printf(" \\C is %ssupported\n", optval? "not ":"");+printf(" Internal link size\n");+(void)pcre2_config(PCRE2_CONFIG_LINKSIZE, &optval);+printf(" Requested = %d\n", optval);+(void)pcre2_config(PCRE2_CONFIG_EFFECTIVE_LINKSIZE, &optval);+printf(" Effective = %d\n", optval);+(void)pcre2_config(PCRE2_CONFIG_PARENSLIMIT, &optval);+printf(" Parentheses nest limit = %d\n", optval);+(void)pcre2_config(PCRE2_CONFIG_HEAPLIMIT, &optval);+printf(" Default heap limit = %d kibibytes\n", optval);+(void)pcre2_config(PCRE2_CONFIG_MATCHLIMIT, &optval);+printf(" Default match limit = %d\n", optval);+(void)pcre2_config(PCRE2_CONFIG_DEPTHLIMIT, &optval);+printf(" Default depth limit = %d\n", optval);++#if defined SUPPORT_LIBREADLINE+printf(" pcre2test has libreadline support\n");+#elif defined SUPPORT_LIBEDIT+printf(" pcre2test has libedit support\n");+#else+printf(" pcre2test has neither libreadline nor libedit support\n");+#endif++return yield;+}+++/*************************************************+* Format one property/script list item *+*************************************************/++#ifdef SUPPORT_UNICODE+static void+format_list_item(int16_t *ff, char *buff, BOOL isscript)+{+int count;+int maxi = 0;+const char *maxs = "";+size_t max = 0;++for (count = 0; ff[count] >= 0; count++) {}++/* Find the name to put first. For scripts, any 3-character name is chosen.+For non-scripts, or if there is no 3-character name, take the longest. */++for (int i = 0; ff[i] >= 0; i++)+ {+ const char *s = PRIV(utt_names) + ff[i];+ size_t len = strlen(s);+ if (isscript && len == 3)+ {+ maxi = i;+ max = len;+ maxs = s;+ break;+ }+ else if (len > max)+ {+ max = len;+ maxi = i;+ maxs = s;+ }+ }++strcpy(buff, maxs);+buff += max;++if (count > 1)+ {+ const char *sep = " (";+ for (int i = 0; i < count; i++)+ {+ if (i == maxi) continue;+ buff += sprintf(buff, "%s%s", sep, PRIV(utt_names) + ff[i]);+ sep = ", ";+ }+ (void)sprintf(buff, ")");+ }+}+#endif /* SUPPORT_UNICODE */++++/*************************************************+* Display scripts or properties *+*************************************************/++#define MAX_SYNONYMS 5++static void+display_properties(BOOL wantscripts)+{+#ifndef SUPPORT_UNICODE+(void)wantscripts;+printf("** This version of PCRE2 was compiled without Unicode support.\n");+#else++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 = wantscripts? ucp_Script_Count : ucp_Bprop_Count;++for (size_t i = 0; i < PRIV(utt_size); i++)+ {+ int k;+ int m = 0;+ int16_t *fv;+ const ucp_type_table *t = PRIV(utt) + i;+ unsigned int value = t->value;++ if (wantscripts)+ {+ if (t->type != PT_SC && t->type != PT_SCX) continue;+ }+ else+ {+ if (t->type != PT_BOOL) continue;+ }++ for (k = 0; k < seencount; k++)+ {+ if (t->type == seentypes[k] && t->value == seenvalues[k]) break;+ }+ if (k < seencount) continue;++ seentypes[seencount] = t->type;+ seenvalues[seencount++] = t->value;++ fv = found[fc++];+ fv[m++] = t->name_offset;++ for (size_t j = i + 1; j < PRIV(utt_size); j++)+ {+ const ucp_type_table *tt = PRIV(utt) + j;+ if (tt->type != t->type || tt->value != value) continue;+ if (m >= MAX_SYNONYMS)+ cfprintf(clr_test_error, stdout, "** Too many synonyms: %s ignored\n",+ PRIV(utt_names) + tt->name_offset);+ else fv[m++] = tt->name_offset;+ }++ fv[m] = -1;+ }++printf("-------------------------- SUPPORTED %s --------------------------\n\n",+ wantscripts? "SCRIPTS" : "PROPERTIES");++if (!wantscripts) printf(+"This release of PCRE2 supports Unicode's general category properties such\n"+"as Lu (upper case letter), bi-directional properties such as Bidi_Class,\n"+"and the following binary (yes/no) properties:\n\n");+++for (int k = 0; k < (n+1)/2; k++)+ {+ int x;+ char buff1[128];+ char buff2[128];++ format_list_item(found[k], buff1, wantscripts);+ x = k + (n+1)/2;+ if (x < n) format_list_item(found[x], buff2, wantscripts);+ else buff2[0] = 0;++ x = printf("%s", buff1);+ while (x++ < colwidth) printf(" ");+ printf("%s\n", buff2);+ }++#endif /* SUPPORT_UNICODE */+}++++/*************************************************+* Display one modifier *+*************************************************/++static void+display_one_modifier(modstruct *m, BOOL for_pattern)+{+uint32_t c = (!for_pattern && (m->which == MOD_PND || m->which == MOD_PNDP))?+ '*' : ' ';+printf("%c%s", c, m->name);+for (size_t i = 0; i < C1MODLISTCOUNT; i++)+ {+ if (strcmp(m->name, c1modlist[i].fullname) == 0)+ printf(" (%c)", c1modlist[i].onechar);+ }+}++++/*************************************************+* Display pattern or subject modifiers *+*************************************************/++/* In order to print in two columns, first scan without printing to get a list+of the modifiers that are required.++Arguments:+ for_pattern TRUE for pattern modifiers, FALSE for subject modifiers+ title string to be used in title++Returns: nothing+*/++static void+display_selected_modifiers(BOOL for_pattern, const char *title)+{+uint32_t i, j;+uint32_t n = 0;+uint32_t list[MODLISTCOUNT];+uint32_t extra[MODLISTCOUNT];++for (i = 0; i < MODLISTCOUNT; i++)+ {+ BOOL is_pattern = TRUE;+ modstruct *m = modlist + i;++ switch (m->which)+ {+ case MOD_CTC: /* Compile context */+ case MOD_PAT: /* Pattern */+ case MOD_PATP: /* Pattern, OK for Perl-compatible test */+ break;++ /* The MOD_PND and MOD_PNDP modifiers are precisely those that affect+ subjects, but can be given with a pattern. We list them as subject+ modifiers, but marked with an asterisk.*/++ case MOD_CTM: /* Match context */+ case MOD_DAT: /* Subject line */+ case MOD_DATP: /* Subject line, OK for Perl-compatible test */+ case MOD_PND: /* As PD, but not default pattern */+ case MOD_PNDP: /* As PND, OK for Perl-compatible test */+ is_pattern = FALSE;+ break;++ case MOD_PD: /* Pattern or subject */+ case MOD_PDP: /* As PD, OK for Perl-compatible test */+ is_pattern = for_pattern;+ break;++ default:+ printf("** Unknown type for modifier \"%s\"\n", m->name);+ PCRE2_DEBUG_UNREACHABLE();+ exit(1);+ }++ if (for_pattern == is_pattern)+ {+ extra[n] = 0;+ for (size_t k = 0; k < C1MODLISTCOUNT; k++)+ {+ if (strcmp(m->name, c1modlist[k].fullname) == 0)+ {+ extra[n] += 4;+ break;+ }+ }+ list[n++] = i;+ }+ }++/* Now print from the list in two columns. */++printf("-------------- %s MODIFIERS --------------\n", title);++for (i = 0, j = (n+1)/2; i < (n+1)/2; i++, j++)+ {+ modstruct *m = modlist + list[i];+ display_one_modifier(m, for_pattern);+ if (j < n)+ {+ size_t k = 27 - strlen(m->name) - extra[i];+ while (k-- > 0) printf(" ");+ display_one_modifier(modlist + list[j], for_pattern);+ }+ printf("\n");+ }+}++++/*************************************************+* Display the list of modifiers *+*************************************************/++static void+display_modifiers(void)+{+printf(+ "An asterisk on a subject modifier means that it may be given on a pattern\n"+ "line, in order to apply to all subjects matched by that pattern. Modifiers\n"+ "that are listed for both patterns and subjects have different effects in\n"+ "each case.\n\n");+display_selected_modifiers(TRUE, "PATTERN");+printf("\n");+display_selected_modifiers(FALSE, "SUBJECT");+}++++/*************************************************+* Main Program *+*************************************************/++int+main(int argc, char **argv)+{+uint32_t yield = 0;+uint32_t op = 1;+BOOL notdone = TRUE;+BOOL quiet = FALSE;+BOOL showtotaltimes = FALSE;+BOOL skipping = FALSE;+BOOL skipping_endif = FALSE;+char *arg_subject = NULL;+char *arg_pattern = NULL;+char *arg_error = NULL;++/* Get buffers from malloc() so that valgrind will check their misuse when+debugging. They grow automatically when very long lines are read. The 16-+and 32-bit buffers (pbuffer16, pbuffer32) are obtained only if needed. */++buffer = (uint8_t *)malloc(pbuffer8_size);+pbuffer8 = (uint8_t *)malloc(pbuffer8_size);++/* The following _setmode() stuff is some Windows magic that tells its runtime+library to translate CRLF into a single LF character. At least, that's what+I've been told: never having used Windows I take this all on trust. Originally+it set 0x8000, but then I was advised that _O_BINARY was better. */++#if defined(_WIN32) || defined(WIN32)+_setmode( _fileno( stdout ), _O_BINARY );+#endif++/* Initialization that does not depend on the running mode. */++locale_name[0] = 0;++patctl_zero(&def_patctl);+datctl_zero(&def_datctl);++/* Scan command line options. */++while (argc > 1 && argv[op][0] == '-' && argv[op][1] != 0)+ {+ char *endptr;+ char *arg = argv[op];+ unsigned long uli;++ /* List modifiers and exit. */++ if (strcmp(arg, "-LM") == 0)+ {+ display_modifiers();+ goto EXIT;+ }++ /* List properties and exit */++ if (strcmp(arg, "-LP") == 0)+ {+ display_properties(FALSE);+ goto EXIT;+ }++ /* List scripts and exit */++ if (strcmp(arg, "-LS") == 0)+ {+ display_properties(TRUE);+ goto EXIT;+ }++ /* Perform additional edge-case and error-handling tests of public API+ functions, which wouldn't otherwise be covered by the standard use of the API+ in pcre2test. */++ if (strcmp(arg, "-unittest") == 0)+ {+ unittest();+ goto EXIT;+ }++ /* Display and/or set return code for configuration options. */++ if (strcmp(arg, "-C") == 0)+ {+ yield = c_option(argv[op + 1]);+ goto EXIT;+ }++ /* Select operating mode. */++ if (strcmp(arg, "-8") == 0)+ {+#ifdef SUPPORT_PCRE2_8+ test_mode = PCRE2TEST_MODE_8;+#else+ cfprintf(clr_test_error, stderr,+ "pcre2test: This version of PCRE2 was built without 8-bit support\n");+ exit(1);+#endif+ }++ else if (strcmp(arg, "-16") == 0)+ {+#ifdef SUPPORT_PCRE2_16+ test_mode = PCRE2TEST_MODE_16;+#else+ cfprintf(clr_test_error, stderr,+ "pcre2test: This version of PCRE2 was built without 16-bit support\n");+ exit(1);+#endif+ }++ else if (strcmp(arg, "-32") == 0)+ {+#ifdef SUPPORT_PCRE2_32+ test_mode = PCRE2TEST_MODE_32;+#else+ cfprintf(clr_test_error, stderr,+ "pcre2test: This version of PCRE2 was built without 32-bit support\n");+ exit(1);+#endif+ }++ /* Set preprocess-only (only handle #if ... #endif) */++ else if (strcmp(arg, "-E") == 0) preprocess_only = TRUE;++ /* Set quiet (no version verification) */++ else if (strcmp(arg, "-q") == 0) quiet = TRUE;++ /* Set system stack size */++ else if (strcmp(arg, "-S") == 0 && argc > 2 &&+ ((uli = strtoul(argv[op+1], &endptr, 10)), *endptr == 0))+ {+#if defined(_WIN32) || defined(WIN32) || defined(__HAIKU__) || defined(NATIVE_ZOS) || defined(__VMS)+ cfprintf(clr_test_error, stderr, "pcre2test: -S is not supported on this OS\n");+ exit(1);+#else+ int rc = 0;+ uint32_t stack_size;+ struct rlimit rlim, rlim_old;+ if (uli > INT32_MAX / (1024 * 1024))+ {+ cfprintf(clr_test_error, stderr, "pcre2test: Argument for -S is too big\n");+ exit(1);+ }+ stack_size = (uint32_t)uli;+ getrlimit(RLIMIT_STACK, &rlim_old);+ rlim = rlim_old;+ rlim.rlim_cur = stack_size * 1024 * 1024;+ if (rlim.rlim_max != RLIM_INFINITY && rlim.rlim_cur > rlim.rlim_max)+ {+ cfprintf(clr_test_error, stderr,+ "pcre2test: requested stack size %luMiB is greater than hard limit ",+ (unsigned long int)stack_size);+ if (rlim.rlim_max % (1024*1024) == 0)+ cfprintf(clr_test_error, stderr, "%luMiB\n", (unsigned long)(rlim.rlim_max/(1024*1024)));+ else if (rlim.rlim_max % 1024 == 0)+ cfprintf(clr_test_error, stderr, "%luKiB\n", (unsigned long)(rlim.rlim_max/1024));+ else+ cfprintf(clr_test_error, stderr, "%lu bytes\n", (unsigned long)(rlim.rlim_max));+ exit(1);+ }+ if (rlim_old.rlim_cur != RLIM_INFINITY && rlim_old.rlim_cur <= INT32_MAX &&+ rlim.rlim_cur > rlim_old.rlim_cur)+ rc = setrlimit(RLIMIT_STACK, &rlim);+ if (rc != 0)+ {+ cfprintf(clr_test_error, stderr, "pcre2test: setting stack size %luMiB failed: %s\n",+ (unsigned long int)stack_size, strerror(errno));+ exit(1);+ }+ op++;+ argc--;+#endif+ }++ /* Set some common pattern and subject controls */++ else if (strcmp(arg, "-AC") == 0)+ {+ def_patctl.options |= PCRE2_AUTO_CALLOUT;+ def_datctl.control2 |= CTL2_CALLOUT_EXTRA;+ }+ else if (strcmp(arg, "-ac") == 0) def_patctl.options |= PCRE2_AUTO_CALLOUT;+ else if (strcmp(arg, "-b") == 0) def_patctl.control |= CTL_FULLBINCODE;+ else if (strcmp(arg, "-d") == 0) def_patctl.control |= CTL_DEBUG;+ else if (strcmp(arg, "-dfa") == 0) def_datctl.control |= CTL_DFA;+ else if (strcmp(arg, "-i") == 0) def_patctl.control |= CTL_INFO;+ else if (strcmp(arg, "-jit") == 0 || strcmp(arg, "-jitverify") == 0 ||+ strcmp(arg, "-jitfast") == 0)+ {+ if (arg[4] == 'v') def_patctl.control |= CTL_JITVERIFY;+ else if (arg[4] == 'f') def_patctl.control |= CTL_JITFAST;+ def_patctl.jit = JIT_DEFAULT; /* full & partial */+#ifndef SUPPORT_JIT+ cfprintf(clr_test_error, stderr, "pcre2test: Warning: JIT support is not available: "+ "-jit[fast|verify] calls functions that do nothing.\n");+#endif+ }++ /* Set timing parameters */++ else if (strcmp(arg, "-t") == 0 || strcmp(arg, "-tm") == 0 ||+ strcmp(arg, "-T") == 0 || strcmp(arg, "-TM") == 0)+ {+ int both = arg[2] == 0;+ showtotaltimes = arg[1] == 'T';+ if (argc > 2 && (uli = strtoul(argv[op+1], &endptr, 10), *endptr == 0))+ {+ if (uli == 0)+ {+ cfprintf(clr_test_error, stderr, "pcre2test: Argument for %s must not be zero\n", arg);+ exit(1);+ }+ if (U32OVERFLOW(uli))+ {+ cfprintf(clr_test_error, stderr, "pcre2test: Argument for %s is too big\n", arg);+ exit(1);+ }+ timeitm = (int)uli;+ op++;+ argc--;+ }+ else timeitm = LOOPREPEAT;+ if (both) timeit = timeitm;+ }++ /* Set malloc testing */++ else if (strcmp(arg, "-malloc") == 0)+ {+ malloc_testing = TRUE;+ }++ /* Give help */++ else if (strcmp(arg, "-help") == 0 ||+ strcmp(arg, "--help") == 0)+ {+ usage();+ goto EXIT;+ }++ /* Show version */++ else if (memcmp(arg, "-v", 2) == 0 ||+ strcmp(arg, "--version") == 0)+ {+ print_version(stdout, FALSE);+ goto EXIT;+ }++ /* The following options save their data for processing once we know what+ the running mode is. */++ else if (strcmp(arg, "-error") == 0)+ {+ arg_error = argv[op+1];+ goto CHECK_VALUE_EXISTS;+ }++ else if (strcmp(arg, "-subject") == 0)+ {+ arg_subject = argv[op+1];+ goto CHECK_VALUE_EXISTS;+ }++ else if (strcmp(arg, "-pattern") == 0)+ {+ arg_pattern = argv[op+1];+ CHECK_VALUE_EXISTS:+ if (argc <= 2)+ {+ cfprintf(clr_test_error, stderr, "pcre2test: Missing value for %s\n", arg);+ yield = 1;+ goto EXIT;+ }+ op++;+ argc--;+ }++ else if (strcmp(arg, "--color") == 0 || strcmp(arg, "--colour") == 0)+ {+ colour_setting = COLOUR_ALWAYS;+ }++ else if (strstr(arg, "--color=") == arg || strstr(arg, "--colour=") == arg)+ {+ char *val = strchr(arg, '=') + 1;+ if (strcmp(val, "always") == 0) colour_setting = COLOUR_ALWAYS;+ else if (strcmp(val, "never") == 0) colour_setting = COLOUR_NEVER;+ else if (strcmp(val, "auto") == 0) colour_setting = COLOUR_AUTO;+ else+ {+ cfprintf(clr_test_error, stderr,+ "pcre2test: Invalid value for \"%.*s\"\n", (int)(val - 1 - arg), arg);+ yield = 1;+ goto EXIT;+ }+ }++ /* Unrecognized option */++ else+ {+ cfprintf(clr_test_error, stderr, "pcre2test: Unknown or malformed option \"%s\"\n", arg);+ usage();+ yield = 1;+ goto EXIT;+ }+ op++;+ argc--;+ }++/* If -error was present, get the error numbers, show the messages, and exit.+We wait to do this until we know which mode we are in. */++if (arg_error != NULL)+ {+ int errcode;+ char *endptr;+ long li;++ /* Loop along a list of error numbers. */++ for (;;)+ {+ li = strtol(arg_error, &endptr, 10);+ if (S32OVERFLOW(li) || (*endptr != 0 && *endptr != ','))+ {+ cfprintf(clr_test_error, stderr, "pcre2test: \"%s\" is not a valid error number list\n", arg_error);+ yield = 1;+ goto EXIT;+ }+ errcode = (int)li;+ printf("Error %d: ", errcode);+ print_error_message_file(stdout, errcode, "", "\n", TRUE);+ if (*endptr == 0) goto EXIT;+ arg_error = endptr + 1;+ }++ PCRE2_UNREACHABLE(); /* Control never reaches here */+ } /* End of -error handling */++/* Initialize things that cannot be done until we know which test mode we are+running in. */++max_oveccount = DEFAULT_OVECCOUNT;++/* Initialise the globals for the current mode. */++init_globals();++/* Handle command line modifier settings, sending any error messages to+stderr. We need to know the mode before modifying the context, and it is tidier+to do them all in the same way. */++outfile = stderr;+if ((arg_pattern != NULL &&+ !decode_modifiers((uint8_t *)arg_pattern, CTX_DEFPAT, &def_patctl, NULL)) ||+ (arg_subject != NULL &&+ !decode_modifiers((uint8_t *)arg_subject, CTX_DEFDAT, NULL, &def_datctl)))+ {+ yield = 1;+ goto EXIT;+ }++/* Sort out the input and output files, defaulting to stdin/stdout. */++infile = stdin;+outfile = stdout;++if (argc > 1 && strcmp(argv[op], "-") != 0)+ {+ infile = fopen(argv[op], INPUT_MODE);+ if (infile == NULL)+ {+ cfprintf(clr_test_error, stderr, "pcre2test: Failed to open \"%s\": %s\n", argv[op], strerror(errno));+ yield = 1;+ goto EXIT;+ }+ }++#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)+if (INTERACTIVE(infile)) using_history();+#endif++if (argc > 2)+ {+ outfile = fopen(argv[op+1], OUTPUT_MODE);+ if (outfile == NULL)+ {+ cfprintf(clr_test_error, stderr, "pcre2test: Failed to open \"%s\": %s\n", argv[op+1], strerror(errno));+ yield = 1;+ goto EXIT;+ }+ }++/* Output a heading line unless quiet, then process input lines. */++if (!quiet) print_version(outfile, TRUE);++#ifdef SUPPORT_PCRE2_8+preg.re_pcre2_code = NULL;+preg.re_match_data = NULL;+#endif++while (notdone)+ {+ const uint8_t *p;+ const uint8_t *p_notsp;+ int rc = PR_OK;+ BOOL expectdata = have_active_pattern();+ BOOL is_pattern_comment;+ BOOL is_data_comment;+#ifdef SUPPORT_PCRE2_8+ expectdata |= preg.re_pcre2_code != NULL;+#endif++ if (extend_inputline(infile, buffer, expectdata? "data> " : " re> ") == NULL)+ break;++ /* Pre-process input lines with #if...#endif. */++ if (skipping_endif)+ {+ if (strncmp((char*)buffer, "#endif", 6) != 0 ||+ !(buffer[6] == 0 || isspace(buffer[6])))+ continue;+ skipping_endif = FALSE;+ }++ /* Begin processing the line. */++ p = p_notsp = buffer;+ while (isspace(*p_notsp)) p_notsp++;++ is_pattern_comment = p[0] == '#' &&+ (isspace(p[1]) || p[1] == '!' || p[1] == 0);+ is_data_comment = expectdata && p_notsp[0] == '\\' && p_notsp[1] == '=' &&+ (isspace(p_notsp[2]) || p_notsp[2] == 0);++ if (!INTERACTIVE(infile))+ cfprintf((is_pattern_comment || is_data_comment)? clr_comment : clr_input,+ outfile, "%s", (char *)buffer);+ fflush(outfile);++ if (preprocess_only && *p != '#') continue;++ /* If we have a pattern set up for testing, or we are skipping after a+ compile failure, a blank line terminates this test. */++ if (expectdata || skipping)+ {+ if (*p_notsp == 0)+ {+#ifdef SUPPORT_PCRE2_8+ if (preg.re_pcre2_code != NULL)+ {+ regfree(&preg);+ preg.re_pcre2_code = NULL;+ preg.re_match_data = NULL;+ }+#endif /* SUPPORT_PCRE2_8 */+ free_active_pattern();+ skipping = FALSE;+ setlocale(LC_CTYPE, "C");+ }++ /* Otherwise, if we are not skipping, and the line is not a data comment+ line starting with "\=", process a data line. */++ else if (!skipping && !is_data_comment)+ {+ rc = process_data();+ }+ }++ /* We do not have a pattern set up for testing. Lines starting with # are+ either comments or special commands. Blank lines are ignored. Otherwise, the+ line must start with a valid delimiter. It is then processed as a pattern+ line. The pattern remains in pbuffer8/16/32 after compilation, for use by+ callouts. Under valgrind, make the unused part of the buffer undefined, to+ catch overruns. */++ else if (*p == '#')+ {+ if (is_pattern_comment) continue;+ rc = process_command();+ }++ else if (strchr("/!\"'`%&-=_:;,@~", *p) != NULL)+ {+ rc = process_pattern();+ dfa_matched = 0;+ }++ else+ {+ if (*p_notsp != 0)+ {+ cfprintf(clr_test_error, outfile, "** Invalid pattern delimiter '%c' (x%x).\n", *buffer,+ *buffer);+ rc = PR_SKIP;+ }+ }++ if (rc == PR_SKIP && !INTERACTIVE(infile)) skipping = TRUE;+ else if (rc == PR_ENDIF) skipping_endif = TRUE;+ else if (rc == PR_ABEND)+ {+ cfprintf(clr_test_error, outfile, "** pcre2test run abandoned\n");+ yield = 1;+ goto EXIT;+ }+ }++/* Finish off a normal run. */++if (skipping_endif)+ {+ cfprintf(clr_test_error, outfile, "** Expected #endif\n");+ yield = 1;+ goto EXIT;+ }++if (INTERACTIVE(infile)) fprintf(outfile, "\n");++if (showtotaltimes)+ {+ const char *pad = "";+ cfprintf(clr_profiling, outfile, "--------------------------------------\n");+ if (timeit > 0)+ {+ cfprintf(clr_profiling, outfile, "Total compile time %8.2f microseconds\n",+ ((1000000 / CLOCKS_PER_SEC) * (double)total_compile_time) / timeit);+ if (total_jit_compile_time > 0)+ cfprintf(clr_profiling, outfile, "Total JIT compile %8.2f microseconds\n",+ ((1000000 / CLOCKS_PER_SEC) * (double)total_jit_compile_time) / \+ timeit);+ pad = " ";+ }+ cfprintf(clr_profiling, outfile, "Total match time %s%8.2f microseconds\n", pad,+ ((1000000 / CLOCKS_PER_SEC) * (double)total_match_time) / timeitm);+ }+++EXIT:++#if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT)+if (infile != NULL && INTERACTIVE(infile)) clear_history();+#endif++if (infile != NULL && infile != stdin) fclose(infile);+if (outfile != NULL && outfile != stdout) fclose(outfile);++#ifdef SUPPORT_PCRE2_8+if (preg.re_pcre2_code != NULL) regfree(&preg);+#endif++free(buffer);+free(dbuffer);+free(pbuffer8);+#ifdef SUPPORT_PCRE2_16+free(pbuffer16);+#endif+#ifdef SUPPORT_PCRE2_32+free(pbuffer32);+#endif+free(dfa_workspace);+free(tables3);+free_globals(); #if defined(__VMS) yield = SS$_NORMAL; /* Return values via DCL symbols */
+ src/c/pcre2/src/pcre2test_inc.h view
@@ -0,0 +1,6349 @@+/*************************************************+* 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+ Original API code Copyright (c) 1997-2012 University of Cambridge+ 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.+-----------------------------------------------------------------------------+*/+++/* This module contains the mode-dependent code which is used by pcre2test.c.+It is #included in pcre2test.c at each supported code unit width, with+PCRE2_SUFFIX set appropriately, just like the functions that comprise the+library. */+++/* ------- Macros for hiding the bit width of this file's members ---------- */++#define pbuffer PCRE2_SUFFIX(pbuffer)+#define pbuffer_size G(pbuffer,_size)++#if PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16+#define utf_to_ord G(G(utf,PCRE2_CODE_UNIT_WIDTH),_to_ord)+#endif++#define compiled_code PCRE2_SUFFIX(compiled_code_)+#define general_context PCRE2_SUFFIX(general_context_)+#define general_context_copy PCRE2_SUFFIX(general_context_copy_)+#define pat_context PCRE2_SUFFIX(pat_context_)+#define default_pat_context PCRE2_SUFFIX(default_pat_context_)+#define con_context PCRE2_SUFFIX(con_context_)+#define default_con_context PCRE2_SUFFIX(default_con_context_)+#define dat_context PCRE2_SUFFIX(dat_context_)+#define default_dat_context PCRE2_SUFFIX(default_dat_context_)+#define match_data PCRE2_SUFFIX(match_data_)+#define jit_stack PCRE2_SUFFIX(jit_stack_)+#define jit_stack_size PCRE2_SUFFIX(jit_stack_size_)+#define patstack PCRE2_SUFFIX(patstack_)+#define patstacknext PCRE2_SUFFIX(patstacknext_)+#define rep_in_buffer PCRE2_SUFFIX(rep_in_buffer_)+#define rep_in_buffer_size PCRE2_SUFFIX(rep_in_buffer_size_)+#define rep_out_buffer PCRE2_SUFFIX(rep_out_buffer_)+#define rep_out_buffer_size PCRE2_SUFFIX(rep_out_buffer_size_)++#define jit_callback PCRE2_SUFFIX(jit_callback_)+#define pcre2_strcmp_c8 PCRE2_SUFFIX(pcre2_strcmp_c8_)+#define pcre2_strlen PCRE2_SUFFIX(pcre2_strlen_)+#define pchars PCRE2_SUFFIX(pchars_)+#define ptrunc PCRE2_SUFFIX(ptrunc_)+#define config_str PCRE2_SUFFIX(config_str_)+#define check_modifier PCRE2_SUFFIX(check_modifier_)+#define decode_modifiers PCRE2_SUFFIX(decode_modifiers_)+#define pattern_info PCRE2_SUFFIX(pattern_info_)+#define show_memory_info PCRE2_SUFFIX(show_memory_info_)+#define show_framesize PCRE2_SUFFIX(show_framesize_)+#define show_heapframes_size PCRE2_SUFFIX(show_heapframes_size_)+#define print_error_message_file PCRE2_SUFFIX(print_error_message_file_)+#define print_error_message PCRE2_SUFFIX(print_error_message_)+#define callout_enumerate_function PCRE2_SUFFIX(callout_enumerate_function_)+#define callout_enumerate_function_void PCRE2_SUFFIX(callout_enumerate_function_void_)+#define callout_enumerate_function_fail PCRE2_SUFFIX(callout_enumerate_function_fail_)+#define show_pattern_info PCRE2_SUFFIX(show_pattern_info_)+#define serial_error PCRE2_SUFFIX(serial_error_)+#define process_command PCRE2_SUFFIX(process_command_)+#define process_pattern PCRE2_SUFFIX(process_pattern_)+#define have_active_pattern PCRE2_SUFFIX(have_active_pattern_)+#define free_active_pattern PCRE2_SUFFIX(free_active_pattern_)+#define check_match_limit PCRE2_SUFFIX(check_match_limit_)+#define substitute_callout_function PCRE2_SUFFIX(substitute_callout_function_)+#define substitute_case_callout_function PCRE2_SUFFIX(substitute_case_callout_function_)+#define callout_function PCRE2_SUFFIX(callout_function_)+#define copy_and_get PCRE2_SUFFIX(copy_and_get_)+#define copy_substitute_string PCRE2_SUFFIX(copy_substitute_string_)+#define process_data PCRE2_SUFFIX(process_data_)+#define init_globals PCRE2_SUFFIX(init_globals_)+#define free_globals PCRE2_SUFFIX(free_globals_)+#define unittest PCRE2_SUFFIX(unittest_)+++/* ---------------------- Mode-dependent variables ------------------------- */++static pcre2_code *compiled_code = NULL;+static pcre2_general_context *general_context = NULL, *general_context_copy = NULL;+static pcre2_compile_context *pat_context = NULL, *default_pat_context = NULL;+static pcre2_convert_context *con_context = NULL, *default_con_context = NULL;+static pcre2_match_context *dat_context = NULL, *default_dat_context = NULL;+static pcre2_match_data *match_data = NULL;++static pcre2_jit_stack *jit_stack = NULL;+static size_t jit_stack_size = 0;++static pcre2_code *patstack[PATSTACKSIZE];+static int patstacknext = 0;++static PCRE2_UCHAR *rep_in_buffer = NULL;+static size_t rep_in_buffer_size = REPLACE_MODSIZE; /* Code units */+static PCRE2_UCHAR *rep_out_buffer = NULL;+static size_t rep_out_buffer_size = REPLACE_BUFFSIZE; /* Code units */++++/*************************************************+* JIT memory callback *+*************************************************/++static pcre2_jit_stack*+jit_callback(void *arg)+{+jit_was_used = TRUE;+return (pcre2_jit_stack *)arg;+}++++/*************************************************+* Compare zero-terminated PCRE2 & 8-bit strings *+*************************************************/++static int+pcre2_strcmp_c8(PCRE2_SPTR str1, const char *str2)+{+PCRE2_UCHAR c1, c2;+while (*str1 != '\0' || *str2 != '\0')+ {+ c1 = *str1++;+ c2 = *str2++;+ if (c1 != c2) return ((c1 > c2) << 1) - 1;+ }+return 0;+}++++/*************************************************+* Find the length of a PCRE2 string *+*************************************************/++static size_t+pcre2_strlen(PCRE2_SPTR str)+{+size_t c = 0;+while (*str++ != 0) c++;+return c;+}++++/*************************************************+* Print character string *+*************************************************/++/* Must handle Unicode strings in UTF mode. Yields number of characters printed.+For printing *MARK strings, a negative length is given, indicating that the+length is in the first code unit. If handed a NULL file, this function just+counts chars without printing (because pchar() does that). */++static int pchars(int clr, PCRE2_SPTR p, ptrdiff_t length, BOOL utf, FILE *f)+{+#if PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16+PCRE2_SPTR end;+uint32_t c = 0;+int yield = 0;++colour_begin(clr, f);++if (length < 0) length = *p++;+end = p + length;+while (length-- > 0)+ {+ if (utf)+ {+ int rc = utf_to_ord(p, end, &c);+ if (rc > 0 && rc <= length + 1) /* Mustn't run over the end */+ {+ length -= rc - 1;+ p += rc;+ yield += pchar(c, utf, f);+ continue;+ }+ }+ c = *p++;+ yield += pchar(c, utf, f);+ }++colour_end(f);+return yield;++#else+int yield = 0;++colour_begin(clr, f);++if (length < 0) length = *p++;+while (length-- > 0)+ {+ uint32_t c = *p++;+ yield += pchar(c, utf, f);+ }++colour_end(f);+return yield;++#endif+}++++/*************************************************+* Print truncated character string *+*************************************************/++/* Must handle Unicode strings in UTF mode. Passed the total input string, and+the offset to print from/to. If left is true, prints up to the offset,+truncated; otherwise prints from the offset to the right, truncated. */++#if PCRE2_CODE_UNIT_WIDTH == 8+static void ptrunc_8(int clr, PCRE2_SPTR p, size_t p_len, size_t offset,+ BOOL left, BOOL utf, FILE *f)+{+PCRE2_SPTR start = p + offset;+PCRE2_SPTR end = p + offset;+size_t printed = 0;++colour_begin(clr, f);++if (left)+ {+ while (start > p && printed < 10)+ {+ printed++;+ start--;+ if (utf)+ { while(start > p && (*start & 0xc0u) == 0x80u) start--; }+ }+ }+else+ {+ while (end < p + p_len && printed < 10)+ {+ printed++;+ end++;+ if (utf)+ { while(end < p + p_len && (*end & 0xc0u) == 0x80u) end++; }+ }+ }++if (left && start > p) fprintf(f, "...");+for (; start < end; start++) fprintf(f, "%c", CHAR_OUTPUT(*start));+if (!left && end < p + p_len) fprintf(f, "...");++colour_end(f);+}++#elif PCRE2_CODE_UNIT_WIDTH == 16+static void ptrunc_16(int clr, PCRE2_SPTR p, size_t p_len, size_t offset,+ BOOL left, BOOL utf, FILE *f)+{+PCRE2_SPTR start = p + offset;+PCRE2_SPTR end = p + offset;+size_t printed = 0;++colour_begin(clr, f);++if (left)+ {+ while (start > p && printed < 10)+ {+ printed++;+ start--;+ if (utf)+ { while(start > p && (*start & 0xfc00u) == 0xdc00u) start--; }+ }+ }+else+ {+ while (end < p + p_len && printed < 10)+ {+ printed++;+ end++;+ if (utf)+ { while(end < p + p_len && (*end & 0xfc00u) == 0xdc00u) end++; }+ }+ }++if (left && start > p) fprintf(f, "...");+while (start < end)+ {+ uint32_t c;+ int rc = utf16_to_ord(start, end, &c);+ if (rc < 0) c = *start++;+ else start += rc;+ if (c > 0xff || (utf && c > 0x7f))+ {+ uint8_t u8buff[6];+ int clen = ord_to_utf8(c, u8buff);+ fprintf(f, "%.*s", clen, u8buff);+ continue;+ }+ fputc((int)c, f);+ }+if (!left && end < p + p_len) fprintf(f, "...");++colour_end(f);+}++#elif PCRE2_CODE_UNIT_WIDTH == 32+static void ptrunc_32(int clr, PCRE2_SPTR p, size_t p_len, size_t offset,+ BOOL left, BOOL utf, FILE *f)+{+PCRE2_SPTR start = p + offset;+PCRE2_SPTR end = p + offset;++colour_begin(clr, f);++if (left)+ {+ start -= (offset > 10)? 10 : offset;+ }+else+ {+ end += (p + p_len - end > 10)? 10 : p + p_len - end;+ }++if (left && start > p) fprintf(f, "...");+while (start < end)+ {+ uint32_t c = *start++;+ if (c > 0xff || (utf && c > 0x7f))+ {+ uint8_t u8buff[6];+ int clen = ord_to_utf8(c, u8buff);+ fprintf(f, "%.*s", clen, u8buff);+ continue;+ }+ fputc((int)c, f);+ }+if (!left && end < p + p_len) fprintf(f, "...");++colour_end(f);+}+#endif++#if PCRE2_CODE_UNIT_WIDTH == 16+/*************************************************+* Convert string to 16-bit *+*************************************************/++/* In UTF mode the input is always interpreted as a string of UTF-8 bytes using+the original UTF-8 definition of RFC 2279, which allows for up to 6 bytes, and+code values from 0 to 0x7fffffff. However, values greater than the later UTF+limit of 0x10ffff cause an error. In non-UTF mode the input is interpreted as+UTF-8 if the utf8_input modifier is set, but an error is generated for values+greater than 0xffff.++If all the input bytes are ASCII, the space needed for a 16-bit string is+exactly double the 8-bit size. Otherwise, the size needed for a 16-bit string+is no more than double, because up to 0xffff uses no more than 3 bytes in UTF-8+but possibly 4 in UTF-16. Higher values use 4 bytes in UTF-8 and up to 4 bytes+in UTF-16. The result is always left in pbuffer16. Impose a minimum size to+save repeated re-sizing.++Note that this function does not object to surrogate values. This is+deliberate; it makes it possible to construct UTF-16 strings that are invalid,+for the purpose of testing that they are correctly faulted.++Arguments:+ p points to a byte string+ utf true in UTF mode+ lenptr points to number of bytes in the string (excluding trailing zero)++Returns: 0 on success, with the length updated to the number of 16-bit+ data items used (excluding the trailing zero)+ OR -1 if a UTF-8 string is malformed+ OR -2 if a value > 0x10ffff is encountered in UTF mode+ OR -3 if a value > 0xffff is encountered when not in UTF mode+*/++static int+to16(uint8_t *p, int utf, PCRE2_SIZE *lenptr)+{+uint16_t *pp;+PCRE2_SIZE len = *lenptr;++if (pbuffer16_size < 2*len + 2)+ {+ if (pbuffer16 != NULL) free(pbuffer16);+ pbuffer16_size = 2*len + 2;+ if (pbuffer16_size < 4096) pbuffer16_size = 4096;+ pbuffer16 = (uint16_t *)malloc(pbuffer16_size);+ if (pbuffer16 == NULL)+ {+ cfprintf(clr_test_error, stderr, "pcre2test: malloc(%" SIZ_FORM ") failed for pbuffer16\n",+ pbuffer16_size);+ exit(1);+ }+ }++pp = pbuffer16;+if (!utf && (pat_patctl.control & CTL_UTF8_INPUT) == 0)+ {+ for (; len > 0; len--) *pp++ = *p++;+ }++else while (len > 0)+ {+ uint32_t c;+ const uint8_t *end = p + len;+ int chlen = utf8_to_ord(p, end, &c);+ if (chlen <= 0) return -1;+ if (!utf && c > 0xffff) return -3;+ if (c > 0x10ffff) return -2;+ p += chlen;+ len -= chlen;+ if (c < 0x10000) *pp++ = c; else+ {+ c -= 0x10000;+ *pp++ = 0xd800 | (c >> 10);+ *pp++ = 0xdc00 | (c & 0x3ff);+ }+ }++*pp = 0;+*lenptr = pp - pbuffer16;+return 0;+}+#endif /* PCRE2_CODE_UNIT_WIDTH == 16 */++++#if PCRE2_CODE_UNIT_WIDTH == 32+/*************************************************+* Convert string to 32-bit *+*************************************************/++/* In UTF mode the input is always interpreted as a string of UTF-8 bytes using+the original UTF-8 definition of RFC 2279, which allows for up to 6 bytes, and+code values from 0 to 0x7fffffff. However, values greater than the later UTF+limit of 0x10ffff cause an error.++In non-UTF mode the input is interpreted as UTF-8 if the utf8_input modifier+is set, and no limit is imposed. There is special interpretation of the 0xff+byte (which is illegal in UTF-8) in this case: it causes the top bit of the+next character to be set. This provides a way of generating 32-bit characters+greater than 0x7fffffff.++If all the input bytes are ASCII, the space needed for a 32-bit string is+exactly four times the 8-bit size. Otherwise, the size needed for a 32-bit+string is no more than four times, because the number of characters must be+less than the number of bytes. The result is always left in pbuffer32. Impose a+minimum size to save repeated re-sizing.++Note that this function does not object to surrogate values. This is+deliberate; it makes it possible to construct UTF-32 strings that are invalid,+for the purpose of testing that they are correctly faulted.++Arguments:+ p points to a byte string+ utf true in UTF mode+ lenptr points to number of bytes in the string (excluding trailing zero)++Returns: 0 on success, with the length updated to the number of 32-bit+ data items used (excluding the trailing zero)+ OR -1 if a UTF-8 string is malformed+ OR -2 if a value > 0x10ffff is encountered in UTF mode+*/++static int+to32(uint8_t *p, int utf, PCRE2_SIZE *lenptr)+{+uint32_t *pp;+PCRE2_SIZE len = *lenptr;++if (pbuffer32_size < 4*len + 4)+ {+ if (pbuffer32 != NULL) free(pbuffer32);+ pbuffer32_size = 4*len + 4;+ if (pbuffer32_size < 8192) pbuffer32_size = 8192;+ pbuffer32 = (uint32_t *)malloc(pbuffer32_size);+ if (pbuffer32 == NULL)+ {+ cfprintf(clr_test_error, stderr, "pcre2test: malloc(%" SIZ_FORM ") failed for pbuffer32\n",+ pbuffer32_size);+ exit(1);+ }+ }++pp = pbuffer32;+if (!utf && (pat_patctl.control & CTL_UTF8_INPUT) == 0)+ {+ for (; len > 0; len--) *pp++ = *p++;+ }++else while (len > 0)+ {+ 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 = utf8_to_ord(p, end, &c);+ if (chlen <= 0) return -1;+ if (utf && c > 0x10ffff) return -2;+ p += chlen;+ len -= chlen;+ *pp++ = c | topbit;+ }++*pp = 0;+*lenptr = pp - pbuffer32;+return 0;+}+#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */++++/*************************************************+* Read a string from pcre2_config() *+*************************************************/++/* Read out a version string from pcre2_config(), transcoding it into an+8-bit buffer.++Arguments:+ what the item to read+ where the 8-bit buffer to receive the string+*/++static void+config_str(uint32_t what, char *where)+{+int r1, r2;+PCRE2_UCHAR buf[VERSION_SIZE];++r1 = pcre2_config(what, NULL);+r2 = pcre2_config(what, buf);+if (r1 < 0 || r1 != r2 || r1 >= VERSION_SIZE)+ {+ cfprintf(clr_test_error, stderr, "pcre2test: Error in pcre2_config(%d)\n", what);+ exit(1);+ }++while (r1-- > 0) where[r1] = (char)buf[r1];+}++++/*************************************************+* Check a modifier and find its field *+*************************************************/++/* This function is called when a modifier has been identified. We check that+it is allowed here and find the field that is to be changed.++Arguments:+ m the modifier list entry+ ctx CTX_PAT => pattern context+ CTX_POPPAT => pattern context for popped pattern+ CTX_DEFPAT => default pattern context+ CTX_DAT => data context+ CTX_DEFDAT => default data context+ pctl point to pattern control block+ dctl point to data control block+ c a single character or 0++Returns: a field pointer or NULL+*/++static void *+check_modifier(modstruct *m, int ctx, patctl *pctl, datctl *dctl, uint32_t c)+{+void *field = NULL;+PCRE2_SIZE offset = m->offset;++if (restrict_for_perl_test) switch(m->which)+ {+ case MOD_PNDP:+ case MOD_PATP:+ case MOD_DATP:+ case MOD_PDP:+ break;++ default:+ cfprintf(clr_test_error, outfile, "** \"%s\" is not allowed in a Perl-compatible test\n",+ m->name);+ return NULL;+ }++switch (m->which)+ {+ case MOD_CTC: /* Compile context modifier */+ if (ctx == CTX_DEFPAT) field = default_pat_context;+ else if (ctx == CTX_PAT) field = pat_context;+ break;++ case MOD_CTM: /* Match context modifier */+ if (ctx == CTX_DEFDAT) field = default_dat_context;+ else if (ctx == CTX_DAT) field = dat_context;+ break;++ case MOD_DAT: /* Data line modifier */+ case MOD_DATP: /* Allowed for Perl test */+ if (dctl != NULL) field = dctl;+ break;++ case MOD_PAT: /* Pattern modifier */+ case MOD_PATP: /* Allowed for Perl test */+ if (pctl != NULL) field = pctl;+ break;++ case MOD_PD: /* Pattern or data line modifier */+ case MOD_PDP: /* Ditto, allowed for Perl test */+ case MOD_PND: /* Ditto, but not default pattern */+ case MOD_PNDP: /* Ditto, allowed for Perl test */+ if (dctl != NULL) field = dctl;+ else if (pctl != NULL && (m->which == MOD_PD || m->which == MOD_PDP ||+ ctx != CTX_DEFPAT))+ field = pctl;+ break;+ }++if (field == NULL)+ {+ if (c == 0)+ cfprintf(clr_test_error, outfile, "** \"%s\" is not valid here\n", m->name);+ else+ cfprintf(clr_test_error, outfile, "** /%c is not valid here\n", c);+ return NULL;+ }++return (char *)field + offset;+}++++/*************************************************+* Decode a modifier list *+*************************************************/++/* A pointer to a control block is NULL when called in cases when that block is+not relevant. They are never all relevant in one call. At least one of patctl+and datctl is NULL. The second argument specifies which context to use for+modifiers that apply to contexts.++Arguments:+ p point to modifier string+ ctx CTX_PAT => pattern context+ CTX_POPPAT => pattern context for popped pattern+ CTX_DEFPAT => default pattern context+ CTX_DAT => data context+ CTX_DEFDAT => default data context+ pctl point to pattern control block+ dctl point to data control block++Returns: TRUE if successful decode, FALSE otherwise+*/++static BOOL+decode_modifiers(uint8_t *p, int ctx, patctl *pctl, datctl *dctl)+{+uint8_t *ep, *pp;+long li;+unsigned long uli;+BOOL first = TRUE;++for (;;)+ {+ void *field;+ modstruct *m;+ BOOL off = FALSE;+ unsigned int i;+ size_t len;+ int index;+ char *endptr;++ /* Skip white space and commas. */++ while (isspace(*p) || *p == ',') p++;+ if (*p == 0) break;++ /* Find the end of the item; lose trailing whitespace at end of line. */++ for (ep = p; *ep != 0 && *ep != ','; ep++);+ if (*ep == 0)+ {+ while (ep > p && isspace(ep[-1])) ep--;+ *ep = 0;+ }++ /* Remember if the first character is '-'. */++ if (*p == '-')+ {+ off = TRUE;+ p++;+ }++ /* Find the length of a full-length modifier name, and scan for it. */++ pp = p;+ while (pp < ep && *pp != '=') pp++;+ index = scan_modifiers(p, pp - p);++ /* If the first modifier is unrecognized, try to interpret it as a sequence+ of single-character abbreviated modifiers. None of these modifiers have any+ associated data. They just set options or control bits. */++ if (index < 0)+ {+ uint32_t cc;+ uint8_t *mp = p;++ if (!first)+ {+ cfprintf(clr_test_error, outfile, "** Unrecognized modifier \"%.*s\"\n", (int)(ep-p), p);+ if (ep - p == 1)+ cfprintf(clr_test_error, outfile, "** Single-character modifiers must come first\n");+ return FALSE;+ }++ first = FALSE;++ for (cc = *p; cc != ',' && cc != '\n' && cc != 0; cc = *(++p))+ {+ for (i = 0; i < C1MODLISTCOUNT; i++)+ if (cc == c1modlist[i].onechar) break;++ if (i >= C1MODLISTCOUNT)+ {+ cfprintf(clr_test_error, outfile, "** Unrecognized modifier '%c' in modifier string "+ "\"%.*s\"\n", *p, (int)(ep-mp), mp);+ return FALSE;+ }++ if (c1modlist[i].index >= 0)+ {+ index = c1modlist[i].index;+ }++ else+ {+ index = scan_modifiers((const uint8_t *)(c1modlist[i].fullname),+ strlen(c1modlist[i].fullname));+ if (index < 0)+ {+ cfprintf(clr_test_error, outfile, "** Internal error: single-character equivalent "+ "modifier \"%s\" not found\n", c1modlist[i].fullname);+ return FALSE;+ }+ c1modlist[i].index = index; /* Cache for next time */+ }++ field = check_modifier(modlist + index, ctx, pctl, dctl, *p);+ if (field == NULL) return FALSE;++ /* /x is a special case; a second appearance changes PCRE2_EXTENDED to+ PCRE2_EXTENDED_MORE. */++ if (cc == 'x' && (*((uint32_t *)field) & PCRE2_EXTENDED) != 0)+ {+ *((uint32_t *)field) &= ~PCRE2_EXTENDED;+ *((uint32_t *)field) |= PCRE2_EXTENDED_MORE;+ }+ else+ *((uint32_t *)field) |= modlist[index].value;+ }++ continue; /* With the next (fullname) modifier */+ }++ /* We have a match on a full-name modifier. Check for the existence of data+ when needed. */++ m = modlist + index; /* Save typing */+ if (m->type != MOD_CTL && m->type != MOD_OPT && m->type != MOD_OPTMZ &&+ (m->type != MOD_IND || *pp == '='))+ {+ if (*pp++ != '=')+ {+ cfprintf(clr_test_error, outfile, "** '=' expected after \"%s\"\n", m->name);+ return FALSE;+ }+ if (off)+ {+ cfprintf(clr_test_error, outfile, "** '-' is not valid for \"%s\"\n", m->name);+ return FALSE;+ }+ }++ /* These on/off types have no data. */++ else if (*pp != ',' && *pp != '\n' && *pp != ' ' && *pp != 0)+ {+ cfprintf(clr_test_error, outfile, "** Unrecognized modifier '%.*s'\n", (int)(ep-p), p);+ return FALSE;+ }++ /* Set the data length for those types that have data. Then find the field+ that is to be set. If check_modifier() returns NULL, it has already output an+ error message. */++ len = ep - pp;+ field = check_modifier(m, ctx, pctl, dctl, 0);+ if (field == NULL) return FALSE;++ /* Process according to data type. */++ switch (m->type)+ {+ case MOD_CTL:+ case MOD_OPT:+ if (off) *((uint32_t *)field) &= ~m->value;+ else *((uint32_t *)field) |= m->value;+ break;++ case MOD_OPTMZ:+ pcre2_set_optimize(field, m->value);+ break;++ case MOD_BSR:+ if (len == 7 && strncmpic(pp, (const uint8_t *)"default", 7) == 0)+ {+#ifdef BSR_ANYCRLF+ *((uint16_t *)field) = PCRE2_BSR_ANYCRLF;+#else+ *((uint16_t *)field) = PCRE2_BSR_UNICODE;+#endif+ if (ctx == CTX_PAT || ctx == CTX_DEFPAT) pctl->control2 &= ~CTL2_BSR_SET;+ else dctl->control2 &= ~CTL2_BSR_SET;+ }+ else+ {+ if (len == 7 && strncmpic(pp, (const uint8_t *)"anycrlf", 7) == 0)+ *((uint16_t *)field) = PCRE2_BSR_ANYCRLF;+ else if (len == 7 && strncmpic(pp, (const uint8_t *)"unicode", 7) == 0)+ *((uint16_t *)field) = PCRE2_BSR_UNICODE;+ else goto INVALID_VALUE;+ if (ctx == CTX_PAT || ctx == CTX_DEFPAT) pctl->control2 |= CTL2_BSR_SET;+ else dctl->control2 |= CTL2_BSR_SET;+ }+ pp = ep;+ break;++ case MOD_CHR: /* A single character */+ *((uint32_t *)field) = *pp++;+ break;++ case MOD_CON: /* A convert type/options list */+ for (;; pp++)+ {+ uint8_t *colon = (uint8_t *)strchr((const char *)pp, ':');+ len = ((colon != NULL && colon < ep)? colon:ep) - pp;+ for (i = 0; i < convertlistcount; i++)+ {+ if (strncmpic(pp, (const uint8_t *)convertlist[i].name, len) == 0)+ {+ if (*((uint32_t *)field) == CONVERT_UNSET)+ *((uint32_t *)field) = convertlist[i].option;+ else+ *((uint32_t *)field) |= convertlist[i].option;+ break;+ }+ }+ if (i >= convertlistcount) goto INVALID_VALUE;+ pp += len;+ if (*pp != ':') break;+ }+ break;++ case MOD_IN2: /* One or two unsigned integers */+ if (!isdigit(*pp)) goto INVALID_VALUE;+ uli = strtoul((const char *)pp, &endptr, 10);+ if (U32OVERFLOW(uli)) goto INVALID_VALUE;+ ((uint32_t *)field)[0] = (uint32_t)uli;+ if (*endptr == ':')+ {+ uli = strtoul((const char *)endptr+1, &endptr, 10);+ if (U32OVERFLOW(uli)) goto INVALID_VALUE;+ ((uint32_t *)field)[1] = (uint32_t)uli;+ }+ else ((uint32_t *)field)[1] = 0;+ pp = (uint8_t *)endptr;+ break;++ /* PCRE2_SIZE_MAX is usually SIZE_MAX, which may be greater, equal to, or+ less than ULONG_MAX. So first test for overflowing the long int, and then+ test for overflowing PCRE2_SIZE_MAX if it is smaller than ULONG_MAX. */++ case MOD_SIZ: /* PCRE2_SIZE value */+ if (!isdigit(*pp)) goto INVALID_VALUE;+ uli = strtoul((const char *)pp, &endptr, 10);+ if (uli == ULONG_MAX) goto INVALID_VALUE;+#if ULONG_MAX > PCRE2_SIZE_MAX+ if (uli > PCRE2_SIZE_MAX) goto INVALID_VALUE;+#endif+ *((PCRE2_SIZE *)field) = (PCRE2_SIZE)uli;+ pp = (uint8_t *)endptr;+ break;++ case MOD_IND: /* Unsigned integer with default */+ if (len == 0)+ {+ *((uint32_t *)field) = (uint32_t)(m->value);+ break;+ }+ PCRE2_FALLTHROUGH /* Fall through */++ case MOD_INT: /* Unsigned integer */+ if (!isdigit(*pp)) goto INVALID_VALUE;+ uli = strtoul((const char *)pp, &endptr, 10);+ if (U32OVERFLOW(uli)) goto INVALID_VALUE;+ *((uint32_t *)field) = (uint32_t)uli;+ pp = (uint8_t *)endptr;+ break;++ case MOD_INS: /* Signed integer */+ if (!isdigit(*pp) && *pp != '-') goto INVALID_VALUE;+ li = strtol((const char *)pp, &endptr, 10);+ if (S32OVERFLOW(li)) goto INVALID_VALUE;+ *((int32_t *)field) = (int32_t)li;+ pp = (uint8_t *)endptr;+ break;++ case MOD_NL:+ for (i = 0; i < sizeof(newlines)/sizeof(char *); i++)+ if (len == strlen(newlines[i]) &&+ strncmpic(pp, (const uint8_t *)newlines[i], len) == 0) break;+ if (i >= sizeof(newlines)/sizeof(char *)) goto INVALID_VALUE;+ if (i == 0)+ {+ pcre2_set_newline(field, NEWLINE_DEFAULT);+ if (ctx == CTX_PAT || ctx == CTX_DEFPAT) pctl->control2 &= ~CTL2_NL_SET;+ else dctl->control2 &= ~CTL2_NL_SET;+ }+ else+ {+ pcre2_set_newline(field, i);+ if (ctx == CTX_PAT || ctx == CTX_DEFPAT) pctl->control2 |= CTL2_NL_SET;+ else dctl->control2 |= CTL2_NL_SET;+ }+ pp = ep;+ break;++ case MOD_NN: /* Name or (signed) number; may be several */+ if (isdigit(*pp) || *pp == '-')+ {+ int ct = MAXCPYGET - 1;+ int32_t value;+ li = strtol((const char *)pp, &endptr, 10);+ if (S32OVERFLOW(li)) goto INVALID_VALUE;+ value = (int32_t)li;+ field = (char *)field - m->offset + m->value; /* Adjust field ptr */+ if (value >= 0) /* Add new number */+ {+ while (*((int32_t *)field) >= 0 && ct-- > 0) /* Skip previous */+ field = (char *)field + sizeof(int32_t);+ if (ct <= 0)+ {+ cfprintf(clr_test_error, outfile, "** Too many numeric \"%s\" modifiers\n", m->name);+ return FALSE;+ }+ }+ *((int32_t *)field) = value;+ if (ct > 0) ((int32_t *)field)[1] = -1;+ pp = (uint8_t *)endptr;+ }++ /* Multiple strings are put end to end. */++ else+ {+ char *nn = (char *)field;+ if (len > 0) /* Add new name */+ {+ if (len > MAX_NAME_SIZE)+ {+ cfprintf(clr_test_error, outfile, "** Group name in \"%s\" is too long\n", m->name);+ return FALSE;+ }+ while (*nn != 0) nn += strlen(nn) + 1;+ if (nn + len + 2 - (char *)field > LENCPYGET)+ {+ cfprintf(clr_test_error, outfile, "** Too many characters in named \"%s\" modifiers\n",+ m->name);+ return FALSE;+ }+ memcpy(nn, pp, len);+ }+ nn[len] = 0 ;+ nn[len+1] = 0;+ pp = ep;+ }+ break;++ case MOD_STR:+ if (len + 1 > m->value)+ {+ cfprintf(clr_test_error, outfile, "** Overlong value for \"%s\" (max %d code units)\n",+ m->name, m->value - 1);+ return FALSE;+ }+ ((uint8_t *)field)[0] = len;+ memcpy(((uint8_t *)field)+1, pp, len);+ ((uint8_t *)field)[len+1] = 0;+ pp = ep;+ break;+ }++ if (*pp != ',' && *pp != '\n' && *pp != ' ' && *pp != 0)+ {+ cfprintf(clr_test_error, outfile, "** Comma expected after modifier item \"%s\"\n", m->name);+ return FALSE;+ }++ p = pp;++ if (ctx == CTX_POPPAT &&+ (pctl->options != 0 ||+ pctl->tables_id != 0 ||+ pctl->locale[0] != MOD_STR_UNSET ||+ (pctl->control & NOTPOP_CONTROLS) != 0))+ {+ cfprintf(clr_test_error, outfile, "** \"%s\" is not valid here\n", m->name);+ return FALSE;+ }+ }++return TRUE;++INVALID_VALUE:+cfprintf(clr_test_error, outfile, "** Invalid value in \"%.*s\"\n", (int)(ep-p), p);+return FALSE;+}++++/*************************************************+* Get info from a pattern *+*************************************************/++/* A wrapped call to pcre2_pattern_info(), applied to the current compiled+pattern.++Arguments:+ what code for the required information+ where where to put the answer+ unsetok PCRE2_ERROR_UNSET is an "expected" result++Returns: the return from pcre2_pattern_info()+*/++static int+pattern_info(int what, void *where, BOOL unsetok)+{+int rc;+(void)pcre2_pattern_info(compiled_code, what, NULL); /* Exercise the code */+rc = pcre2_pattern_info(compiled_code, what, where);+if (rc >= 0) return 0;+if (rc != PCRE2_ERROR_UNSET || !unsetok)+ {+ cfprintf(clr_api_error, outfile, "Error %d from "+ "pcre2_pattern_info_" STR(PCRE2_CODE_UNIT_WIDTH) "(%d)\n", rc, what);+ }+return rc;+}++++/*************************************************+* Show memory usage info for a pattern *+*************************************************/++static void+show_memory_info(void)+{+uint32_t name_count, name_entry_size;+PCRE2_SIZE size, cblock_size, data_size;++cblock_size = sizeof(pcre2_real_code);++(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);++/* The uint32_t variables are cast before multiplying to avoid potential+ integer overflow. */+data_size = CU2BYTES((PCRE2_SIZE)name_count * (PCRE2_SIZE)name_entry_size);++cfprintf(clr_profiling, outfile, "Memory allocation - code size : %" SIZ_FORM "\n", size -+ cblock_size - data_size);+if (data_size != 0)+ cfprintf(clr_profiling, outfile, "Memory allocation - data size : %" SIZ_FORM "\n", data_size);++if (pat_patctl.jit != 0)+ {+ (void)pattern_info(PCRE2_INFO_JITSIZE, &size, FALSE);+ cfprintf(clr_profiling, outfile, "Memory allocation - JIT code : %" SIZ_FORM "\n", size);+ }+}++++/*************************************************+* Show frame size info for a pattern *+*************************************************/++static void+show_framesize(void)+{+PCRE2_SIZE frame_size;+(void)pattern_info(PCRE2_INFO_FRAMESIZE, &frame_size, FALSE);+cfprintf(clr_profiling, 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;+heapframes_size = pcre2_get_match_data_heapframes_size(match_data);+cfprintf(clr_profiling, outfile, "Heapframes size in match_data: %" SIZ_FORM "\n",+ heapframes_size);+}++++/*************************************************+* Get and output an error message *+*************************************************/++static BOOL+print_error_message_file(FILE *file, int errorcode, const char *before,+ const char *after, BOOL badcode_ok)+{+int len;+PCRE2_UCHAR buf[128];++len = pcre2_get_error_message(errorcode, buf, sizeof(buf)/sizeof(*buf));+if (len == PCRE2_ERROR_BADDATA && badcode_ok)+ {+ cfprintf(clr_api_error, file, "%sPCRE2_ERROR_BADDATA (unknown error number)%s", before,+ after);+ }+else if (len < 0)+ {+ cfprintf(clr_test_error, file, "\n** pcre2test internal error: cannot interpret error "+ "number\n** Unexpected return (%d) from pcre2_get_error_message()\n", len);+ }+else if ((unsigned)len != pcre2_strlen(buf))+ {+ cfprintf(clr_test_error, file, "\n** pcre2test: unexpected length %d from pcre2_get_error_message()\n", len);+ return FALSE;+ }+else+ {+ cfprintf(clr_api_error, file, "%s", before);+ pchars(clr_api_error, buf, len, FALSE, file);+ cfprintf(clr_api_error, file, "%s", after);+ }+return len >= 0;+}++static BOOL+print_error_message(int errorcode, const char *before, const char *after)+{+return print_error_message_file(outfile, errorcode, before, after, FALSE);+}+++/*************************************************+* Callback function for callout enumeration *+*************************************************/++/* Testing function to log data inside callout enumeration callbacks.++Argument:+ cb pointer to enumerate block+ callout_data user data++Returns: 0+*/++static int callout_enumerate_function(pcre2_callout_enumerate_block *cb,+ void *callout_data)+{+uint32_t i;+PCRE2_SPTR pattern_string = pbuffer;+BOOL utf = (compiled_code->overall_options & PCRE2_UTF) != 0;+PCRE2_SIZE next_item_length = cb->next_item_length;++(void)callout_data; /* Not currently displayed */++fprintf(outfile, "Callout ");+if (cb->callout_string != NULL)+ {+ uint32_t delimiter = cb->callout_string[-1];+ fprintf(outfile, "%c", CHAR_OUTPUT(delimiter));+ pchars(clr_none, cb->callout_string, cb->callout_string_length, utf, outfile);+ for (i = 0; callout_start_delims[i] != 0; i++)+ if (delimiter == callout_start_delims[i])+ {+ delimiter = callout_end_delims[i];+ break;+ }+ fprintf(outfile, "%c ", CHAR_OUTPUT(delimiter));+ }+else fprintf(outfile, "%d ", cb->callout_number);++if (next_item_length == 0 && pattern_string[cb->pattern_position] != 0)+ next_item_length = 1;+pchars(clr_none, pattern_string+cb->pattern_position, next_item_length, utf, outfile);+fprintf(outfile, "\n");++return 0;+}++static int callout_enumerate_function_void(pcre2_callout_enumerate_block *cb,+ void *callout_data)+{+(void)cb;+(void)callout_data;+return 0;+}++static int callout_enumerate_function_fail(pcre2_callout_enumerate_block *cb,+ void *callout_data)+{+(void)cb;+return *(int *)callout_data;+}++++/*************************************************+* Show information about a pattern *+*************************************************/++/* This function is called after a pattern has been compiled if any of the+information-requesting controls have been set.++Arguments: none++Returns: PR_OK continue processing next line+ PR_SKIP skip to a blank line+ PR_ABEND abort the pcre2test run+*/++static int+show_pattern_info(void)+{+int rc;+uint32_t compile_options, overall_options, extra_options;+BOOL utf = (compiled_code->overall_options & PCRE2_UTF) != 0;++if ((pat_patctl.control & CTL_MEMORY) != 0)+ show_memory_info();++if ((pat_patctl.control2 & CTL2_FRAMESIZE) != 0)+ show_framesize();++if ((pat_patctl.control & (CTL_BINCODE|CTL_FULLBINCODE)) != 0)+ {+ fprintf(outfile, "------------------------------------------------------------------\n");+ pcre2_printint(compiled_code, outfile,+ (pat_patctl.control & CTL_FULLBINCODE) != 0);+ }++if ((pat_patctl.control & CTL_INFO) != 0)+ {+ PCRE2_SPTR nametable;+ uint8_t *start_bits;+ BOOL heap_limit_set, match_limit_set, depth_limit_set;+ uint32_t backrefmax, bsr_convention, capture_count, first_ctype, first_cunit,+ hasbackslashc, hascrorlf, jchanged, last_ctype, last_cunit, match_empty,+ depth_limit, heap_limit, match_limit, minlength, nameentrysize, namecount,+ newline_convention;++ /* These info requests may return PCRE2_ERROR_UNSET. */++ switch(pattern_info(PCRE2_INFO_HEAPLIMIT, &heap_limit, TRUE))+ {+ case 0:+ heap_limit_set = TRUE;+ break;++ case PCRE2_ERROR_UNSET:+ heap_limit_set = FALSE;+ break;++ default:+ return PR_ABEND;+ }++ switch(pattern_info(PCRE2_INFO_MATCHLIMIT, &match_limit, TRUE))+ {+ case 0:+ match_limit_set = TRUE;+ break;++ case PCRE2_ERROR_UNSET:+ match_limit_set = FALSE;+ break;++ default:+ return PR_ABEND;+ }++ switch(pattern_info(PCRE2_INFO_DEPTHLIMIT, &depth_limit, TRUE))+ {+ case 0:+ depth_limit_set = TRUE;+ break;++ case PCRE2_ERROR_UNSET:+ depth_limit_set = FALSE;+ break;++ default:+ return PR_ABEND;+ }++ /* These info requests should always succeed. */++ if (pattern_info(PCRE2_INFO_BACKREFMAX, &backrefmax, FALSE) ++ pattern_info(PCRE2_INFO_BSR, &bsr_convention, FALSE) ++ pattern_info(PCRE2_INFO_CAPTURECOUNT, &capture_count, FALSE) ++ pattern_info(PCRE2_INFO_FIRSTBITMAP, &start_bits, FALSE) ++ pattern_info(PCRE2_INFO_FIRSTCODEUNIT, &first_cunit, FALSE) ++ pattern_info(PCRE2_INFO_FIRSTCODETYPE, &first_ctype, FALSE) ++ pattern_info(PCRE2_INFO_HASBACKSLASHC, &hasbackslashc, FALSE) ++ pattern_info(PCRE2_INFO_HASCRORLF, &hascrorlf, FALSE) ++ pattern_info(PCRE2_INFO_JCHANGED, &jchanged, FALSE) ++ pattern_info(PCRE2_INFO_LASTCODEUNIT, &last_cunit, FALSE) ++ pattern_info(PCRE2_INFO_LASTCODETYPE, &last_ctype, FALSE) ++ pattern_info(PCRE2_INFO_MATCHEMPTY, &match_empty, FALSE) ++ pattern_info(PCRE2_INFO_MINLENGTH, &minlength, FALSE) ++ pattern_info(PCRE2_INFO_NAMECOUNT, &namecount, FALSE) ++ pattern_info(PCRE2_INFO_NAMEENTRYSIZE, &nameentrysize, FALSE) ++ pattern_info(PCRE2_INFO_NAMETABLE, &nametable, FALSE) ++ pattern_info(PCRE2_INFO_NEWLINE, &newline_convention, FALSE)+ != 0)+ return PR_ABEND;++ fprintf(outfile, "Capture group count = %d\n", capture_count);++ if (backrefmax > 0)+ fprintf(outfile, "Max back reference = %d\n", backrefmax);++ if (maxlookbehind > 0)+ fprintf(outfile, "Max lookbehind = %d\n", maxlookbehind);++ if (heap_limit_set)+ fprintf(outfile, "Heap limit = %u\n", heap_limit);++ if (match_limit_set)+ fprintf(outfile, "Match limit = %u\n", match_limit);++ if (depth_limit_set)+ fprintf(outfile, "Depth limit = %u\n", depth_limit);++ if (namecount > 0)+ {+ fprintf(outfile, "Named capture groups:\n");+ for (; namecount > 0; namecount--)+ {+ size_t length = pcre2_strlen(nametable + IMM2_SIZE);+ fprintf(outfile, " ");++ /* In UTF mode the name may be a UTF string containing non-ASCII+ letters and digits. We must output it as a UTF-8 string. In non-UTF mode,+ use the normal string printing functions, which use escapes for all+ non-ASCII characters. */++ if (utf)+ {+#if PCRE2_CODE_UNIT_WIDTH == 32+ PCRE2_SPTR nameptr = nametable + IMM2_SIZE;+ while (*nameptr != 0)+ {+ uint8_t u8buff[6];+ int len = ord_to_utf8(*nameptr++, u8buff);+ fprintf(outfile, "%.*s", len, u8buff);+ }+#endif+#if PCRE2_CODE_UNIT_WIDTH == 16+ PCRE2_SPTR nameptr = nametable + IMM2_SIZE;+ PCRE2_SPTR nameptr_end = nameptr + pcre2_strlen(nameptr);+ while (*nameptr != 0)+ {+ int len;+ uint8_t u8buff[6];+ uint32_t c;+ int ord_rc = utf16_to_ord(nameptr, nameptr_end, &c);+ if (ord_rc > 0) nameptr += ord_rc;+ else c = *nameptr++;+ len = ord_to_utf8(c, u8buff);+ fprintf(outfile, "%.*s", len, u8buff);+ }+#endif+#if PCRE2_CODE_UNIT_WIDTH == 8+ fprintf(outfile, "%s", nametable + IMM2_SIZE);+#endif+ }+ else /* Not UTF mode */+ {+ pchars(clr_none, nametable + IMM2_SIZE, length, FALSE, outfile);+ }++ while (length++ < nameentrysize - IMM2_SIZE) putc(' ', outfile);++ fprintf(outfile, "%3d\n", GET2(nametable, 0));++ nametable = nametable + nameentrysize;+ }+ }++ if (hascrorlf) fprintf(outfile, "Contains explicit CR or LF match\n");+ if (hasbackslashc) fprintf(outfile, "Contains \\C\n");+ if (match_empty) fprintf(outfile, "May match empty string\n");++ pattern_info(PCRE2_INFO_ARGOPTIONS, &compile_options, FALSE);+ pattern_info(PCRE2_INFO_ALLOPTIONS, &overall_options, FALSE);+ pattern_info(PCRE2_INFO_EXTRAOPTIONS, &extra_options, FALSE);++ /* Remove UTF/UCP if they were there only because of forbid_utf. This saves+ cluttering up the verification output of non-UTF test files. */++ if ((pat_patctl.options & PCRE2_NEVER_UTF) == 0)+ {+ compile_options &= ~PCRE2_NEVER_UTF;+ overall_options &= ~PCRE2_NEVER_UTF;+ }++ if ((pat_patctl.options & PCRE2_NEVER_UCP) == 0)+ {+ compile_options &= ~PCRE2_NEVER_UCP;+ overall_options &= ~PCRE2_NEVER_UCP;+ }++ if ((compile_options|overall_options) != 0)+ {+ if (compile_options == overall_options)+ show_compile_options(clr_none, compile_options, "Options:", "\n");+ else+ {+ show_compile_options(clr_none, compile_options, "Compile options:", "\n");+ show_compile_options(clr_none, overall_options, "Overall options:", "\n");+ }+ }++ if (extra_options != 0)+ show_compile_extra_options(clr_none, extra_options, "Extra options:", "\n");++ if (compiled_code->optimization_flags != PCRE2_OPTIMIZATION_ALL)+ show_optimize_flags(clr_none, compiled_code->optimization_flags, "Optimizations: ", "\n");++ if (jchanged) fprintf(outfile, "Duplicate name status changes\n");++ if ((pat_patctl.control2 & CTL2_BSR_SET) != 0 ||+ (compiled_code->flags & PCRE2_BSR_SET) != 0)+ fprintf(outfile, "\\R matches %s\n", (bsr_convention == PCRE2_BSR_UNICODE)?+ "any Unicode newline" : "CR, LF, or CRLF");++ if ((compiled_code->flags & PCRE2_NL_SET) != 0)+ {+ switch (newline_convention)+ {+ case PCRE2_NEWLINE_CR:+ fprintf(outfile, "Forced newline is CR\n");+ break;++ case PCRE2_NEWLINE_LF:+ fprintf(outfile, "Forced newline is LF\n");+ break;++ case PCRE2_NEWLINE_CRLF:+ fprintf(outfile, "Forced newline is CRLF\n");+ break;++ case PCRE2_NEWLINE_ANYCRLF:+ fprintf(outfile, "Forced newline is CR, LF, or CRLF\n");+ break;++ case PCRE2_NEWLINE_ANY:+ fprintf(outfile, "Forced newline is any Unicode newline\n");+ break;++ case PCRE2_NEWLINE_NUL:+ fprintf(outfile, "Forced newline is NUL\n");+ break;++ default:+ break;+ }+ }++ if (first_ctype == 2)+ {+ fprintf(outfile, "First code unit at start or follows newline\n");+ }+ else if (first_ctype == 1)+ {+ const char *caseless =+ ((compiled_code->flags & PCRE2_FIRSTCASELESS) == 0)?+ "" : " (caseless)";+ if (first_cunit != 0xff && PRINTABLE(first_cunit))+ fprintf(outfile, "First code unit = \'%c\'%s\n", CHAR_OUTPUT(first_cunit),+ caseless);+ else+ {+ fprintf(outfile, "First code unit = ");+ if (first_cunit == 0xff)+ fprintf(outfile, "\\xff");+ else+ pchar(first_cunit, FALSE, outfile);+ fprintf(outfile, "%s\n", caseless);+ }+ }+ else if (start_bits != NULL)+ {+ int input;+ int c = 24;+ fprintf(outfile, "Starting code units:");+ for (input = 0; input < 256; input++)+ {+ int i = CHAR_INPUT_HEX(input);+ if ((start_bits[i/8] & (1u << (i&7))) != 0)+ {+ if (c > 75)+ {+ fprintf(outfile, "\n ");+ c = 2;+ }+ if (PRINTABLE(i) && i != CHAR_SPACE)+ {+ fprintf(outfile, " %c", CHAR_OUTPUT(i));+ c += 2;+ }+ else+ {+ fprintf(outfile, " \\x%02x", CHAR_OUTPUT_HEX(i));+ c += 5;+ }+ }+ }+ fprintf(outfile, "\n");+ }++ if (last_ctype != 0)+ {+ const char *caseless =+ ((compiled_code->flags & PCRE2_LASTCASELESS) == 0)?+ "" : " (caseless)";+ if (PRINTABLE(last_cunit))+ fprintf(outfile, "Last code unit = \'%c\'%s\n", CHAR_OUTPUT(last_cunit),+ caseless);+ else+ {+ fprintf(outfile, "Last code unit = ");+ pchar(last_cunit, FALSE, outfile);+ fprintf(outfile, "%s\n", caseless);+ }+ }++ if ((compiled_code->optimization_flags & PCRE2_OPTIM_START_OPTIMIZE) != 0)+ fprintf(outfile, "Subject length lower bound = %d\n", minlength);++ if (pat_patctl.jit != 0 && (pat_patctl.control & CTL_JITVERIFY) != 0)+ {+#ifdef SUPPORT_JIT+ if (compiled_code->executable_jit != NULL)+ fprintf(outfile, "JIT compilation was successful\n");+ else+ {+ cfprintf(clr_api_error, outfile, "JIT compilation was not successful");+ if (jitrc != 0 && !print_error_message(jitrc, " (", ")"))+ return PR_ABEND;+ fprintf(outfile, "\n");+ }+#else+ cfprintf(clr_api_error, outfile, "JIT support is not available in this version of PCRE2\n");+#endif+ }+ }++rc = pcre2_callout_enumerate(compiled_code,+ ((pat_patctl.control & CTL_CALLOUT_INFO) != 0)? callout_enumerate_function :+ /* Exercise the callout enumeration code with a dummy callback to make sure+ it works. */+ callout_enumerate_function_void, NULL);+if (rc != 0)+ {+ cfprintf(clr_api_error, outfile, "Callout enumerate failed: error %d: ", rc);+ if (rc < 0 && !print_error_message(rc, "", "\n"))+ return PR_ABEND;+ return PR_SKIP;+ }++return PR_OK;+}++++/*************************************************+* Handle serialization error *+*************************************************/++/* Print an error message after a serialization failure.++Arguments:+ rc the error code+ msg an initial message for what failed++Returns: FALSE if print_error_message() fails+*/++static BOOL+serial_error(int rc, const char *msg)+{+cfprintf(clr_api_error, outfile, "%s failed: error %d: ", msg, rc);+return print_error_message(rc, "", "\n");+}++++/*************************************************+* Process command line *+*************************************************/++/* This function is called for lines beginning with # and a character that is+not ! or whitespace, when encountered between tests, which means that there is+no compiled pattern (compiled_code is NULL). The line is in buffer.++Arguments: none++Returns: PR_OK continue processing next line+ PR_SKIP skip to a blank line+ PR_ABEND abort the pcre2test run+*/++static int+process_command(void)+{+FILE *f;+PCRE2_SIZE serial_size;+size_t i;+int rc, cmd, yield;+uint16_t first_listed_newline;+const char *cmdname;+size_t cmdlen;+uint8_t *argptr, *serial;+BOOL if_inverted;++yield = PR_OK;+cmd = CMD_UNKNOWN;+cmdlen = 0;++for (i = 0; i < cmdlistcount; i++)+ {+ cmdname = cmdlist[i].name;+ cmdlen = strlen(cmdname);+ if (strncmp((char *)(buffer+1), cmdname, cmdlen) == 0 &&+ (buffer[cmdlen+1] == 0 || isspace(buffer[cmdlen+1])))+ {+ cmd = cmdlist[i].value;+ break;+ }+ }++if (preprocess_only && cmd != CMD_IF && cmd != CMD_ENDIF)+ return PR_OK;++argptr = buffer + cmdlen + 1;++if (restrict_for_perl_test && cmd != CMD_PATTERN && cmd != CMD_SUBJECT &&+ cmd != CMD_IF && cmd != CMD_ENDIF)+ {+ cfprintf(clr_test_error, outfile, "** #%s is not allowed after #perltest\n", cmdname);+ return PR_ABEND;+ }++switch(cmd)+ {+ case CMD_UNKNOWN:+ cfprintf(clr_test_error, outfile, "** Unknown command: %s", buffer);+ break;++ case CMD_FORBID_UTF:+ forbid_utf = PCRE2_NEVER_UTF|PCRE2_NEVER_UCP;+ break;++ case CMD_PERLTEST:+ restrict_for_perl_test = TRUE;+ break;++ /* Set default pattern modifiers */++ case CMD_PATTERN:+ (void)decode_modifiers(argptr, CTX_DEFPAT, &def_patctl, NULL);+ if (def_patctl.jit == 0 && (def_patctl.control & CTL_JITVERIFY) != 0)+ def_patctl.jit = JIT_DEFAULT;+ break;++ /* Set default subject modifiers */++ case CMD_SUBJECT:+ (void)decode_modifiers(argptr, CTX_DEFDAT, NULL, &def_datctl);+ break;++ /* Check the default newline, and if not one of those listed, set up the+ first one to be forced. An empty list unsets. */++ case CMD_NEWLINE_DEFAULT:+ local_newline_default = 0; /* Unset */+ first_listed_newline = 0;+ for (;;)+ {+ while (isspace(*argptr)) argptr++;+ if (*argptr == 0) break;+ for (uint16_t j = 1; j < sizeof(newlines)/sizeof(char *); j++)+ {+ size_t nlen = strlen(newlines[j]);+ if (strncmpic(argptr, (const uint8_t *)newlines[j], nlen) == 0 &&+ isspace(argptr[nlen]))+ {+ if (j == NEWLINE_DEFAULT) return PR_OK; /* Default is valid */+ if (first_listed_newline == 0) first_listed_newline = j;+ }+ }+ while (*argptr != 0 && !isspace(*argptr)) argptr++;+ }+ local_newline_default = first_listed_newline;+ break;++ /* Pop or copy a compiled pattern off the stack. Modifiers that do not affect+ the compiled pattern (e.g. to give information) are permitted. The default+ pattern modifiers are ignored. */++ case CMD_POP:+ case CMD_POPCOPY:+ if (patstacknext <= 0)+ {+ cfprintf(clr_test_error, outfile, "** Can't pop off an empty stack\n");+ return PR_SKIP;+ }+ patctl_zero(&pat_patctl); /* Completely unset */+ if (!decode_modifiers(argptr, CTX_POPPAT, &pat_patctl, NULL))+ return PR_SKIP;++ if (cmd == CMD_POP)+ {+ compiled_code = patstack[--patstacknext];+ }+ else+ {+ compiled_code = pcre2_code_copy(patstack[patstacknext - 1]);+ }++ if (pat_patctl.jit != 0)+ {+ jitrc = pcre2_jit_compile(compiled_code, pat_patctl.jit);+ }++ rc = show_pattern_info();+ if (rc != PR_OK) return rc;+ break;++ /* Save the stack of compiled patterns to a file, then empty the stack. */++ case CMD_SAVE:+ if (patstacknext <= 0)+ {+ cfprintf(clr_test_error, outfile, "** No stacked patterns to save\n");+ return PR_OK;+ }++ rc = open_file(argptr+1, BINARY_OUTPUT_MODE, &f, "#save");+ if (rc != PR_OK) return rc;++ rc = pcre2_serialize_encode((const pcre2_code **)patstack, patstacknext,+ &serial, &serial_size, general_context);+ if (rc < 0)+ {+ fclose(f);+ if (!serial_error(rc, "Serialization")) return PR_ABEND;+ break;+ }++ /* Write the length at the start of the file to make it straightforward to+ get the right memory when re-loading. This saves having to read the file size+ in different operating systems. To allow for different endianness (even+ though reloading with the opposite endianness does not work), write the+ length byte-by-byte. */++ for (i = 0; i < 4; i++) fputc((serial_size >> (i*8)) & 255, f);+ if (fwrite(serial, 1, serial_size, f) != serial_size)+ {+ cfprintf(clr_test_error, outfile, "** Wrong return from fwrite()\n");+ fclose(f);+ return PR_ABEND;+ }++ fclose(f);+ pcre2_serialize_free(serial);+ while(patstacknext > 0)+ {+ compiled_code = patstack[--patstacknext];+ pcre2_code_free(compiled_code);+ }+ compiled_code = NULL;+ break;++ /* Load a set of compiled patterns from a file onto the stack */++ case CMD_LOAD:+ rc = open_file(argptr+1, BINARY_INPUT_MODE, &f, "#load");+ if (rc != PR_OK) return rc;++ serial_size = 0;+ for (i = 0; i < 4; i++) serial_size |= fgetc(f) << (i*8);++ serial = malloc(serial_size);+ if (serial == NULL)+ {+ cfprintf(clr_test_error, outfile, "** Failed to get memory (size %" SIZ_FORM ") for #load\n",+ serial_size);+ fclose(f);+ return PR_ABEND;+ }++ i = fread(serial, 1, serial_size, f);+ fclose(f);++ if (i != serial_size)+ {+ cfprintf(clr_test_error, outfile, "** Wrong return from fread()\n");+ yield = PR_ABEND;+ }+ else+ {+ rc = pcre2_serialize_get_number_of_codes(serial);+ if (rc < 0)+ {+ if (!serial_error(rc, "Get number of codes")) yield = PR_ABEND;+ }+ else+ {+ if (rc + patstacknext > PATSTACKSIZE)+ {+ cfprintf(clr_test_error, outfile, "** Not enough space on pattern stack for %d pattern%s\n",+ rc, (rc == 1)? "" : "s");+ rc = PATSTACKSIZE - patstacknext;+ cfprintf(clr_test_error, outfile, "** Decoding %d pattern%s\n", rc,+ (rc == 1)? "" : "s");+ }+ rc = pcre2_serialize_decode(patstack + patstacknext, rc, serial,+ general_context);+ if (rc < 0)+ {+ if (!serial_error(rc, "Deserialization")) yield = PR_ABEND;+ }+ else patstacknext += rc;+ }+ }++ free(serial);+ break;++ /* Load a set of binary tables into tables3. */++ case CMD_LOADTABLES:+ rc = open_file(argptr+1, BINARY_INPUT_MODE, &f, "#loadtables");+ if (rc != PR_OK) return rc;++ if (tables3 == NULL)+ {+ int r;+ r = pcre2_config(PCRE2_CONFIG_TABLES_LENGTH, &loadtables_length);+ if (r >= 0) tables3 = malloc(loadtables_length);+ }++ if (tables3 == NULL)+ {+ cfprintf(clr_test_error, outfile, "** Failed: malloc/config for #loadtables\n");+ yield = PR_ABEND;+ }+ else if (fread(tables3, 1, loadtables_length, f) != loadtables_length)+ {+ cfprintf(clr_test_error, outfile, "** Wrong return from fread()\n");+ yield = PR_ABEND;+ }++ fclose(f);+ break;++ case CMD_IF:+ if (inside_if)+ {+ cfprintf(clr_test_error, outfile, "** Nested #if not supported\n");+ return PR_ABEND;+ }++ while (isspace(*argptr)) argptr++;+ if_inverted = FALSE;+ if (*argptr == '!')+ {+ argptr++;+ if_inverted = TRUE;+ }+ while (isspace(*argptr)) argptr++;+ for (i = 0; i < COPTLISTCOUNT; i++)+ {+ size_t optlen = strlen(coptlist[i].name);+ const uint8_t *argptr_trail;+ if (coptlist[i].type != CONF_FIX)+ continue;+ if (strncmp((const char*)argptr, coptlist[i].name, optlen) != 0)+ continue;+ argptr_trail = argptr + optlen;+ while (isspace(*argptr_trail)) argptr_trail++;+ if (*argptr_trail == 0 || *argptr_trail == '\n')+ break;+ }+ if (i == COPTLISTCOUNT)+ {+ cfprintf(clr_test_error, outfile, "** Unknown condition: %s\n", buffer);+ return PR_ABEND;+ }++ /* Condition FALSE - skip this line and everything until #endif. */+ if ((coptlist[i].value != 0) == if_inverted)+ yield = PR_ENDIF;++ inside_if = TRUE;+ break;++ case CMD_ENDIF:+ if (!inside_if)+ {+ cfprintf(clr_test_error, outfile, "** Unexpected #endif\n");+ return PR_ABEND;+ }+ inside_if = FALSE;+ break;+ }++return yield;+}++++/*************************************************+* Process pattern line *+*************************************************/++/* This function is called when the input buffer contains the start of a+pattern. The first character is known to be a valid delimiter. The pattern is+read, modifiers are interpreted, and a suitable local context is set up for+this test. The pattern is then compiled.++Arguments: none++Returns: PR_OK continue processing next line+ PR_SKIP skip to a blank line+ PR_ABEND abort the pcre2test run+*/++static int+process_pattern(void)+{+BOOL utf;+uint32_t k;+uint8_t *p = buffer;+unsigned int delimiter = *p++;+int rc, errorcode;+pcre2_compile_context *use_pat_context;+PCRE2_SPTR use_pbuffer;+uint32_t use_forbid_utf = forbid_utf;+PCRE2_SIZE patlen, full_patlen;+PCRE2_SIZE valgrind_access_length;+PCRE2_SIZE erroroffset;++/* The perltest.sh script supports only / as a delimiter. */++if (restrict_for_perl_test && delimiter != '/')+ {+ cfprintf(clr_test_error, outfile, "** The only allowed delimiter after #perltest is '/'\n");+ return PR_ABEND;+ }++/* Initialize the context and pattern/data controls for this test from the+defaults. */++memcpy(pat_context, default_pat_context, sizeof(pcre2_compile_context));+memcpy(&pat_patctl, &def_patctl, sizeof(patctl));++/* Find the end of the pattern, reading more lines if necessary. */++for(;;)+ {+ while (*p != 0)+ {+ if (*p == '\\' && p[1] != 0) p++;+ else if (*p == delimiter) break;+ p++;+ }+ if (*p != 0) break;+ if ((p = extend_inputline(infile, p, " > ")) == NULL)+ {+ cfprintf(clr_test_error, outfile, "** Unexpected EOF\n");+ return PR_ABEND;+ }+ if (!INTERACTIVE(infile)) cfprintf(clr_input, outfile, "%s", (char *)p);+ }++/* If the first character after the delimiter is backslash, make the pattern+end with backslash. This is purely to provide a way of testing for the error+message when a pattern ends with backslash. */++if (p[1] == '\\') *p++ = '\\';++/* Terminate the pattern at the delimiter, and compute the length. */++*p++ = 0;+patlen = p - buffer - 2;++/* Look for modifiers and options after the final delimiter. */++if (!decode_modifiers(p, CTX_PAT, &pat_patctl, NULL)) return PR_SKIP;++/* Note that the match_invalid_utf option also sets utf when passed to+pcre2_compile(). */++utf = (pat_patctl.options & (PCRE2_UTF|PCRE2_MATCH_INVALID_UTF)) != 0;++/* The utf8_input modifier is not allowed in 8-bit mode, and is mutually+exclusive with the utf modifier. */++if ((pat_patctl.control & CTL_UTF8_INPUT) != 0)+ {+#if PCRE2_CODE_UNIT_WIDTH == 8+ cfprintf(clr_test_error, outfile, "** The utf8_input modifier is not allowed in 8-bit mode\n");+ return PR_SKIP;+#else+ if (utf)+ {+ cfprintf(clr_test_error, outfile, "** The utf and utf8_input modifiers are mutually exclusive\n");+ return PR_SKIP;+ }+#endif+ }++/* The convert and posix modifiers are mutually exclusive. */++if (pat_patctl.convert_type != CONVERT_UNSET &&+ (pat_patctl.control & CTL_POSIX) != 0)+ {+ cfprintf(clr_test_error, outfile, "** The convert and posix modifiers are mutually exclusive\n");+ return PR_SKIP;+ }++/* Check for mutually exclusive control modifiers. At present, these are all in+the first control word. */++for (k = 0; k < sizeof(exclusive_pat_controls)/sizeof(uint32_t); k++)+ {+ uint32_t c = pat_patctl.control & exclusive_pat_controls[k];+ if (c != 0 && c != (c & (~c+1)))+ {+ show_controls(clr_test_error, c, 0, "** Not allowed together:");+ fprintf(outfile, "\n");+ return PR_SKIP;+ }+ }++/* Assume full JIT compile for jitverify and/or jitfast if nothing else was+specified. */++if (pat_patctl.jit == 0 &&+ (pat_patctl.control & (CTL_JITVERIFY|CTL_JITFAST)) != 0)+ pat_patctl.jit = JIT_DEFAULT;++/* Now copy the pattern to pbuffer8 for use in 8-bit testing. Convert from hex+if requested (literal strings in quotes may be present within the hexadecimal+pairs). The result must necessarily be fewer characters so will always fit in+pbuffer8. */++if ((pat_patctl.control & CTL_HEXPAT) != 0)+ {+ uint8_t *pp, *pt;+ uint32_t c, d;++ pt = pbuffer8;+ for (pp = buffer + 1; *pp != 0; pp++)+ {+ if (isspace(*pp)) continue;+ c = *pp++;++ /* Handle a literal substring */++ if (c == '\'' || c == '"')+ {+ uint8_t *pq = pp;+ for (;; pp++)+ {+ d = *pp;+ if (d == 0)+ {+ cfprintf(clr_test_error, outfile, "** Missing closing quote in hex pattern: "+ "opening quote is at offset %" PTR_FORM ".\n", pq - buffer - 2);+ return PR_SKIP;+ }+ if (d == c) break;+ *pt++ = d;+ }+ }++ /* Expect a hex pair */++ else+ {+ if (!isxdigit(c))+ {+ cfprintf(clr_test_error, outfile, "** Unexpected non-hex-digit '%c' at offset %"+ PTR_FORM " in hex pattern: quote missing?\n", c, pp - buffer - 2);+ return PR_SKIP;+ }+ if (*pp == 0)+ {+ cfprintf(clr_test_error, outfile, "** Odd number of digits in hex pattern\n");+ return PR_SKIP;+ }+ d = *pp;+ if (!isxdigit(d))+ {+ cfprintf(clr_test_error, outfile, "** Unexpected non-hex-digit '%c' at offset %"+ PTR_FORM " in hex pattern: quote missing?\n", d, pp - buffer - 1);+ return PR_SKIP;+ }+ c = toupper(c);+ d = toupper(d);+ c = isdigit(c)? (c - '0') : (c - 'A' + 10);+ d = isdigit(d)? (d - '0') : (d - 'A' + 10);+ *pt++ = CHAR_OUTPUT(CHAR_INPUT_HEX((c << 4) + d));+ }+ }+ *pt = 0;+ patlen = pt - pbuffer8;+ }++/* If not a hex string, process for repetition expansion if requested. */++else if ((pat_patctl.control & CTL_EXPAND) != 0)+ {+ uint8_t *pp, *pt;++ pt = pbuffer8;+ for (pp = buffer + 1; *pp != 0; pp++)+ {+ uint8_t *pc = pp;+ uint32_t count = 1;+ size_t length = 1;++ /* Check for replication syntax; if not found, the defaults just set will+ prevail and one character will be copied. */++ if (pp[0] == '\\' && pp[1] == '[')+ {+ uint8_t *pe;+ for (pe = pp + 2; *pe != 0; pe++)+ {+ if (pe[0] == ']' && pe[1] == '{')+ {+ size_t clen = pe - pc - 2;+ uint32_t i = 0;+ unsigned long uli;+ char *endptr;++ pe += 2;+ uli = strtoul((const char *)pe, &endptr, 10);+ if (U32OVERFLOW(uli))+ {+ cfprintf(clr_test_error, outfile, "** Pattern repeat count too large\n");+ return PR_SKIP;+ }++ i = (uint32_t)uli;+ pe = (uint8_t *)endptr;+ if (*pe == '}')+ {+ if (i == 0)+ {+ cfprintf(clr_test_error, outfile, "** Zero repeat not allowed\n");+ return PR_SKIP;+ }+ pc += 2;+ count = i;+ length = clen;+ pp = pe;+ break;+ }+ }+ }+ }++ /* Add to output. If the buffer is too small expand it. The function for+ expanding buffers always keeps buffer and pbuffer8 in step as far as their+ size goes. */++ while (pt + count * length > pbuffer8 + pbuffer8_size)+ {+ size_t pc_offset = pc - buffer;+ size_t pp_offset = pp - buffer;+ size_t pt_offset = pt - pbuffer8;+ expand_input_buffers();+ pc = buffer + pc_offset;+ pp = buffer + pp_offset;+ pt = pbuffer8 + pt_offset;+ }++ for (; count > 0; count--)+ {+ memcpy(pt, pc, length);+ pt += length;+ }+ }++ *pt = 0;+ patlen = pt - pbuffer8;++ if ((pat_patctl.control & CTL_INFO) != 0)+ fprintf(outfile, "Expanded: %s\n", pbuffer8);+ }++/* Neither hex nor expanded, just copy the input verbatim. */++else+ {+ strncpy((char *)pbuffer8, (char *)(buffer+1), patlen + 1);+ }++/* Sort out character tables */++if (pat_patctl.locale[0] != MOD_STR_UNSET)+ {+ if (pat_patctl.tables_id != 0)+ {+ cfprintf(clr_test_error, outfile, "** 'Locale' and 'tables' must not both be set\n");+ return PR_SKIP;+ }+ if (setlocale(LC_CTYPE, (const char *)pat_patctl.locale+1) == NULL)+ {+ cfprintf(clr_test_error, outfile, "** Failed to set locale \"%s\"\n", pat_patctl.locale+1);+ return PR_SKIP;+ }+ if (strcmp((const char *)pat_patctl.locale+1, (const char *)locale_name) != 0)+ {+ strncpy((char *)locale_name, (char *)pat_patctl.locale + 1, sizeof(locale_name));+ locale_name[sizeof(locale_name) - 1] = '\0';+ if (locale_tables != NULL)+ {+ pcre2_maketables_free(general_context, locale_tables);+ }+ locale_tables = pcre2_maketables(general_context);+ }+ use_tables = locale_tables;+ }++else switch (pat_patctl.tables_id)+ {+ case 0: use_tables = NULL; break;+ case 1: use_tables = tables1; break;+ case 2: use_tables = tables2; break;++ case 3:+ if (tables3 == NULL)+ {+ cfprintf(clr_test_error, outfile, "** 'Tables = 3' is invalid: binary tables have not "+ "been loaded\n");+ return PR_SKIP;+ }+ use_tables = tables3;+ break;++ default:+ cfprintf(clr_test_error, outfile, "** 'Tables' must specify 0, 1, 2, or 3.\n");+ return PR_SKIP;+ }++pcre2_set_character_tables(pat_context, use_tables);++/* Set up for the stackguard test. */++if (pat_patctl.stackguard_test != 0)+ {+ pcre2_set_compile_recursion_guard(pat_context, stack_guard, NULL);+ }++/* Handle compiling via the POSIX interface, which doesn't support the+timing, showing, or debugging options, nor the ability to pass over+local character tables. Neither does it have 16-bit or 32-bit support. */++if ((pat_patctl.control & CTL_POSIX) != 0)+ {+#if PCRE2_CODE_UNIT_WIDTH != 8+ cfprintf(clr_test_error, outfile, "** The POSIX interface is available only in 8-bit mode\n");+ return PR_SKIP;++#else+ int cflags = 0;+ const char *msg = "** Ignored with POSIX interface:";++ /* Check for features that the POSIX interface does not support. */++ if (pat_patctl.locale[0] != MOD_STR_UNSET) prmsg(&msg, "locale");+ if (pat_patctl.replacement[0] != MOD_STR_UNSET) prmsg(&msg, "replace");+ if (pat_patctl.tables_id != 0) prmsg(&msg, "tables");+ if (pat_patctl.stackguard_test != 0) prmsg(&msg, "stackguard");+ if (timeit > 0) prmsg(&msg, "timing");+ if (pat_patctl.jit != 0) prmsg(&msg, "JIT");++ if ((pat_patctl.options & ~POSIX_SUPPORTED_COMPILE_OPTIONS) != 0)+ {+ show_compile_options(+ clr_test_error,+ pat_patctl.options & (uint32_t)(~POSIX_SUPPORTED_COMPILE_OPTIONS),+ msg, "");+ msg = "";+ }++ if ((pat_context->extra_options &+ (uint32_t)(~POSIX_SUPPORTED_COMPILE_EXTRA_OPTIONS)) != 0)+ {+ show_compile_extra_options(+ clr_test_error,+ pat_context->extra_options &+ (uint32_t)(~POSIX_SUPPORTED_COMPILE_EXTRA_OPTIONS),+ msg, "");+ msg = "";+ }++ if ((pat_patctl.control & (uint32_t)(~POSIX_SUPPORTED_COMPILE_CONTROLS)) != 0 ||+ (pat_patctl.control2 & (uint32_t)(~POSIX_SUPPORTED_COMPILE_CONTROLS2)) != 0)+ {+ show_controls(+ clr_test_error,+ pat_patctl.control & (uint32_t)(~POSIX_SUPPORTED_COMPILE_CONTROLS),+ 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 (pat_context->max_pattern_length != PCRE2_UNSET)+ prmsg(&msg, "max_pattern_length");+ if (pat_context->max_pattern_compiled_length != PCRE2_UNSET)+ prmsg(&msg, "max_pattern_compiled_length");+ if (pat_context->parens_nest_limit != PARENS_NEST_DEFAULT)+ prmsg(&msg, "parens_nest_limit");++ if (msg[0] == 0) fprintf(outfile, "\n");++ /* Translate PCRE2 options to POSIX options and then compile. */++ if (utf) cflags |= REG_UTF;+ if ((pat_patctl.control & CTL_POSIX_NOSUB) != 0) cflags |= REG_NOSUB;+ if ((pat_patctl.options & PCRE2_UCP) != 0) cflags |= REG_UCP;+ if ((pat_patctl.options & PCRE2_CASELESS) != 0) cflags |= REG_ICASE;+ if ((pat_patctl.options & PCRE2_LITERAL) != 0) cflags |= REG_NOSPEC;+ if ((pat_patctl.options & PCRE2_MULTILINE) != 0) cflags |= REG_NEWLINE;+ if ((pat_patctl.options & PCRE2_DOTALL) != 0) cflags |= REG_DOTALL;+ if ((pat_patctl.options & PCRE2_UNGREEDY) != 0) cflags |= REG_UNGREEDY;++ if ((pat_patctl.control & (CTL_HEXPAT|CTL_USE_LENGTH)) != 0)+ {+ preg.re_endp = (char *)pbuffer8 + patlen;+ cflags |= REG_PEND;+ }++#if defined(EBCDIC) && !EBCDIC_IO+ ascii_to_ebcdic_str(pbuffer8, patlen);+#endif++ rc = regcomp(&preg, (char *)pbuffer8, cflags);++ /* Compiling failed */++ if (rc != 0)+ {+ char *regbuffer;+ size_t bsize, usize, strsize;++ preg.re_pcre2_code = NULL; /* In case something was left in there */+ preg.re_match_data = NULL;++ bsize = (pat_patctl.regerror_buffsize >= 0 &&+ (unsigned)pat_patctl.regerror_buffsize <= pbuffer8_size)?+ (unsigned)pat_patctl.regerror_buffsize : pbuffer8_size;+ regbuffer = (char *)pbuffer8 + (pbuffer8_size - bsize);+ usize = regerror(rc, &preg, regbuffer, bsize);+ strsize = ((usize > bsize)? bsize : usize) - 1;++ cfprintf(clr_api_error, outfile, "Failed: POSIX code %d: ", rc);+ if (bsize > 0) pchars(clr_api_error, (PCRE2_SPTR8)regbuffer, strsize, utf, outfile);+ fputs("\n", outfile);+ if (usize > bsize)+ {+ cfprintf(clr_test_error, outfile, "** regerror() message truncated\n");+ }+ if (bsize > 0 && strlen(regbuffer) != strsize)+ {+ cfprintf(clr_test_error, outfile, "** regerror() strlen incorrect\n");+ return PR_ABEND;+ }+ return PR_SKIP;+ }++ /* Compiling succeeded. Check that the values in the preg block are sensible.+ It can happen that pcre2test is accidentally linked with a different POSIX+ library which succeeds, but of course puts different things into preg. In+ this situation, calling regfree() may cause a segfault (or invalid free() in+ valgrind), so ensure that preg.re_pcre2_code is NULL, which suppresses the+ calling of regfree() on exit. */++ if (preg.re_pcre2_code == NULL ||+ ((pcre2_real_code_8 *)preg.re_pcre2_code)->magic_number != MAGIC_NUMBER ||+ ((pcre2_real_code_8 *)preg.re_pcre2_code)->top_bracket != preg.re_nsub ||+ preg.re_match_data == NULL ||+ preg.re_cflags != cflags)+ {+ cfprintf(clr_test_error, outfile,+ "** The regcomp() function returned zero (success), but the values set\n"+ "** in the preg block are not valid for PCRE2. Check that pcre2test is\n"+ "** linked with PCRE2's pcre2posix module (-lpcre2-posix) and not with\n"+ "** some other POSIX regex library.\n**\n");+ preg.re_pcre2_code = NULL;+ return PR_ABEND;+ }++ return PR_OK;+#endif /* PCRE2_CODE_UNIT_WIDTH != 8 */+ }++/* Handle compiling via the native interface. Controls that act later are+ignored with "push". Replacements are locked out. */++if ((pat_patctl.control & (CTL_PUSH|CTL_PUSHCOPY|CTL_PUSHTABLESCOPY)) != 0)+ {+ if (pat_patctl.replacement[0] != MOD_STR_UNSET)+ {+ cfprintf(clr_test_error, outfile, "** Replacement text is not supported with 'push'.\n");+ return PR_OK;+ }+ if ((pat_patctl.control & ~PUSH_SUPPORTED_COMPILE_CONTROLS) != 0 ||+ (pat_patctl.control2 & ~PUSH_SUPPORTED_COMPILE_CONTROLS2) != 0)+ {+ show_controls(clr_test_error, pat_patctl.control & ~PUSH_SUPPORTED_COMPILE_CONTROLS,+ pat_patctl.control2 & ~PUSH_SUPPORTED_COMPILE_CONTROLS2,+ "** Ignored when compiled pattern is stacked with 'push':");+ fprintf(outfile, "\n");+ }+ if ((pat_patctl.control & PUSH_COMPILE_ONLY_CONTROLS) != 0 ||+ (pat_patctl.control2 & PUSH_COMPILE_ONLY_CONTROLS2) != 0)+ {+ show_controls(clr_test_error, pat_patctl.control & PUSH_COMPILE_ONLY_CONTROLS,+ pat_patctl.control2 & PUSH_COMPILE_ONLY_CONTROLS2,+ "** Applies only to compile when pattern is stacked with 'push':");+ fprintf(outfile, "\n");+ }+ }++/* Convert the input in non-8-bit modes. */++errorcode = 0;++#if defined(EBCDIC) && !EBCDIC_IO+ascii_to_ebcdic_str(pbuffer8, patlen);+#endif++#if PCRE2_CODE_UNIT_WIDTH != 8+errorcode = G(to,PCRE2_CODE_UNIT_WIDTH)(pbuffer8, utf, &patlen);+switch(errorcode)+ {+ case -1:+ cfprintf(clr_test_error, outfile, "** Failed: invalid UTF-8 string cannot be "+ "converted to " STR(PCRE2_CODE_UNIT_WIDTH) "-bit string\n");+ return PR_SKIP;++ case -2:+ cfprintf(clr_test_error, outfile, "** Failed: character value greater than 0x10ffff "+ "cannot be converted to UTF\n");+ return PR_SKIP;++ case -3:+ cfprintf(clr_test_error, outfile, "** Failed: character value greater than 0xffff "+ "cannot be converted to 16-bit in non-UTF mode\n");+ return PR_SKIP;++ default:+ break;+ }+#endif++/* When valgrind is supported, detect accesses to the 8-bit buffer now that we+have finished with it. */++#if defined SUPPORT_VALGRIND && PCRE2_CODE_UNIT_WIDTH != 8+VALGRIND_MAKE_MEM_UNDEFINED(pbuffer8, pbuffer8_size);+#endif++/* The pattern is now in pbuffer[8|16|32], with the length in code units in+patlen. If it is to be converted, copy the result back afterwards so that it+ends up back in the usual place. */++if (pat_patctl.convert_type != CONVERT_UNSET)+ {+ int convert_return = PR_OK;+ uint32_t convert_options = pat_patctl.convert_type;+ PCRE2_UCHAR *converted_pattern;+ PCRE2_SIZE converted_length = JUNK_OFFSET;+ BOOL zero_terminate;++ if (pat_patctl.convert_length != CONVERT_UNSET)+ {+ converted_length = pat_patctl.convert_length;+ converted_pattern = malloc(converted_length? CU2BYTES(converted_length) : 1);+ if (converted_pattern == NULL)+ {+ cfprintf(clr_test_error, outfile, "** Failed: malloc failed for converted pattern\n");+ return PR_ABEND;+ }+ }+ else converted_pattern = NULL; /* Let the library allocate */++ if (utf) convert_options |= PCRE2_CONVERT_UTF;+ if ((pat_patctl.options & PCRE2_NO_UTF_CHECK) != 0)+ convert_options |= PCRE2_CONVERT_NO_UTF_CHECK;++ memcpy(con_context, default_con_context, sizeof(pcre2_convert_context));++ if (pat_patctl.convert_glob_escape != 0)+ {+ uint32_t escape = (pat_patctl.convert_glob_escape == '0')? 0 :+ pat_patctl.convert_glob_escape;+ rc = pcre2_set_glob_escape(con_context, CHAR_INPUT(escape));+ if (rc != 0)+ {+ cfprintf(clr_test_error, outfile, "** Invalid glob escape '%c'\n",+ pat_patctl.convert_glob_escape);+ convert_return = PR_SKIP;+ goto CONVERT_FINISH;+ }+ }++ if (pat_patctl.convert_glob_separator != 0)+ {+ uint32_t separator = pat_patctl.convert_glob_separator;+ rc = pcre2_set_glob_separator(con_context, CHAR_INPUT(separator));+ if (rc != 0)+ {+ cfprintf(clr_test_error, outfile, "** Invalid glob separator '%c'\n",+ pat_patctl.convert_glob_separator);+ convert_return = PR_SKIP;+ goto CONVERT_FINISH;+ }+ }++ /* Set up the input buffer in the same way as for pcre2_compile() below. */++ zero_terminate = (pat_patctl.control & (CTL_HEXPAT|CTL_USE_LENGTH)) == 0;++#ifdef SUPPORT_VALGRIND+ VALGRIND_MAKE_MEM_NOACCESS(pbuffer + CU2BYTES(patlen + zero_terminate),+ pbuffer_size - CU2BYTES(patlen + zero_terminate));+#endif++ if (zero_terminate) patlen = PCRE2_ZERO_TERMINATED;+ use_pbuffer = ((pat_patctl.control2 & CTL2_NULL_PATTERN) == 0)? pbuffer : NULL;++ rc = pcre2_pattern_convert(use_pbuffer, patlen, convert_options,+ &converted_pattern, &converted_length, con_context);++#ifdef SUPPORT_VALGRIND+ VALGRIND_MAKE_MEM_UNDEFINED(pbuffer, pbuffer_size);+#endif++ if (rc != 0)+ {+ cfprintf(clr_api_error, outfile, "** Pattern conversion error at offset %" SIZ_FORM ": ",+ converted_length);+ convert_return = print_error_message(rc, "", "\n")? PR_SKIP:PR_ABEND;+ }++ /* Output the converted pattern, then copy it. */++ else+ {+ pchars(clr_none, converted_pattern, converted_length, utf, outfile);+ fprintf(outfile, "\n");++ if (CU2BYTES(converted_length + 1) > pbuffer_size)+ {+ // TODO This seems... unfortunate? There must be some patterns that can+ // expand when converted from glob to regex, but we aren't allowing for+ // that here. Presumably we should expand the buffer rather than moan.+ cfprintf(clr_test_error, outfile, "** Pattern conversion is too long for the buffer\n");+ convert_return = PR_SKIP;+ }+ else+ {+ memcpy(pbuffer, converted_pattern, CU2BYTES(converted_length + 1));+ patlen = converted_length;+ }+ }++ /* Free the converted pattern. */++ CONVERT_FINISH:+ if (pat_patctl.convert_length != CONVERT_UNSET)+ free(converted_pattern);+ else+ pcre2_converted_pattern_free(converted_pattern);++ /* Return if conversion was unsuccessful. */++ if (convert_return != PR_OK) return convert_return;+ }++/* By default we pass a zero-terminated pattern, but a length is passed if+"use_length" was specified or this is a hex pattern (which might contain binary+zeros). When valgrind is supported, arrange for the unused part of the buffer+to be marked as no-access. */++full_patlen = patlen;+valgrind_access_length = patlen;+if ((pat_patctl.control & (CTL_HEXPAT|CTL_USE_LENGTH)) == 0)+ {+ patlen = PCRE2_ZERO_TERMINATED;+ valgrind_access_length += 1; /* For the terminating zero */+ }++#ifdef SUPPORT_VALGRIND+VALGRIND_MAKE_MEM_NOACCESS(pbuffer + valgrind_access_length,+ pbuffer_size - CU2BYTES(valgrind_access_length));+#else /* Valgrind not supported */+(void)valgrind_access_length; /* Avoid compiler warning */+#endif++/* If #newline_default has been used and the library was not compiled with an+appropriate default newline setting, local_newline_default will be non-zero. We+use this if there is no explicit newline modifier. */++if ((pat_patctl.control2 & CTL2_NL_SET) == 0 && local_newline_default != 0)+ {+ pcre2_set_newline(pat_context, local_newline_default);+ }++/* The null_context modifier is used to test calling pcre2_compile() with a+NULL context. */++use_pat_context = ((pat_patctl.control & CTL_NULLCONTEXT) != 0)?+ NULL : pat_context;++/* If PCRE2_LITERAL is set, set use_forbid_utf zero because PCRE2_NEVER_UTF+and PCRE2_NEVER_UCP are invalid with it. */++if ((pat_patctl.options & PCRE2_LITERAL) != 0) use_forbid_utf = 0;++/* Set use_pbuffer to the input buffer or NULL as requested. */++use_pbuffer = ((pat_patctl.control2 & CTL2_NULL_PATTERN) == 0)? pbuffer : NULL;++/* Compile many times when timing. */++if (timeit > 0)+ {+ int i;+ clock_t time_taken = 0;+ for (i = 0; i < timeit; i++)+ {+ clock_t start_time = clock();+ compiled_code = pcre2_compile(use_pbuffer, patlen,+ pat_patctl.options|use_forbid_utf, &errorcode, &erroroffset,+ use_pat_context);+ time_taken += clock() - start_time;+ if (compiled_code != NULL)+ pcre2_code_free(compiled_code);+ }+ total_compile_time += time_taken;+ cfprintf(clr_profiling, outfile, "Compile time %8.4f microseconds\n",+ ((1000000 / CLOCKS_PER_SEC) * (double)time_taken) / timeit);+ }++/* A final compile that is used "for real". */++mallocs_called = 0;+compiled_code = pcre2_compile(use_pbuffer, patlen,+ pat_patctl.options|use_forbid_utf, &errorcode, &erroroffset, use_pat_context);++/* For malloc testing, we repeat the compilation. */++if (malloc_testing)+ {+ for (int i = 0, target_mallocs = mallocs_called; i <= target_mallocs; i++)+ {+ if (compiled_code != NULL)+ pcre2_code_free(compiled_code);++ errorcode = 0;+ erroroffset = 0;+ mallocs_until_failure = i;+ compiled_code = pcre2_compile(use_pbuffer, patlen,+ pat_patctl.options|use_forbid_utf, &errorcode, &erroroffset, use_pat_context);+ mallocs_until_failure = INT_MAX;++ if (i < target_mallocs &&+ !(compiled_code == NULL && errorcode == PCRE2_ERROR_HEAP_FAILED))+ {+ cfprintf(clr_test_error, outfile, "** malloc() compile test did not fail as expected (%d)\n",+ errorcode);+ return PR_ABEND;+ }+ }+ }++/* If valgrind is supported, mark the pbuffer as accessible again. We leave the+pattern in the test-mode's buffer defined because it may be read from a callout+during matching. */++#ifdef SUPPORT_VALGRIND+VALGRIND_MAKE_MEM_UNDEFINED(pbuffer + valgrind_access_length,+ pbuffer_size - CU2BYTES(valgrind_access_length));+#endif++/* Call the JIT compiler if requested. When timing, or testing malloc failures,+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. */++if (compiled_code != NULL && pat_patctl.jit != 0)+ {+ if (timeit > 0)+ {+ int i;+ clock_t time_taken = 0;++ for (i = 0; i < timeit; i++)+ {+ clock_t start_time = clock();+ jitrc = pcre2_jit_compile(compiled_code, pat_patctl.jit);+ time_taken += clock() - start_time;++ pcre2_code_free(compiled_code);+ compiled_code = pcre2_compile(use_pbuffer, patlen,+ pat_patctl.options|use_forbid_utf, &errorcode, &erroroffset,+ use_pat_context);+ if (compiled_code == NULL)+ {+ cfprintf(clr_test_error, outfile, "** Unexpected - pattern compilation not successful\n");+ return PR_ABEND;+ }++ if (jitrc != 0)+ {+ cfprintf(clr_api_error, outfile, "JIT compilation was not successful");+ if (!print_error_message(jitrc, " (", ")\n")) return PR_ABEND;+ break;+ }+ }+ total_jit_compile_time += time_taken;+ if (jitrc == 0)+ cfprintf(clr_profiling, outfile, "JIT compile %8.4f microseconds\n",+ ((1000000 / CLOCKS_PER_SEC) * (double)time_taken) / timeit);+ }++ mallocs_called = 0;+ jitrc = pcre2_jit_compile(compiled_code, pat_patctl.jit);++ /* For malloc testing, we repeat the compilation. */++ if (malloc_testing)+ {+ for (int i = 0, target_mallocs = mallocs_called; i <= target_mallocs; i++)+ {+ pcre2_code_free(compiled_code);+ compiled_code = pcre2_compile(use_pbuffer, patlen,+ pat_patctl.options|use_forbid_utf, &errorcode, &erroroffset,+ use_pat_context);+ if (compiled_code == NULL)+ {+ cfprintf(clr_test_error, outfile, "** Unexpected - pattern compilation not successful\n");+ return PR_ABEND;+ }++ mallocs_until_failure = i;+ jitrc = pcre2_jit_compile(compiled_code, pat_patctl.jit);+ mallocs_until_failure = INT_MAX;++ if (i < target_mallocs && jitrc != PCRE2_ERROR_NOMEMORY)+ {+ cfprintf(clr_test_error, outfile, "** malloc() JIT compile test did not fail as expected (%d)\n",+ jitrc);+ return PR_ABEND;+ }+ }+ }++ /* Check whether JIT compilation failed; but continue with an error message+ if not. */++ if (jitrc != 0 && (pat_patctl.control & CTL_JITVERIFY) != 0)+ {+ cfprintf(clr_api_error, outfile, "JIT compilation was not successful");+ if (!print_error_message(jitrc, " (", ")\n")) return PR_ABEND;+ }+ }++/* Compilation failed; go back for another re, skipping to blank line+if non-interactive. */++if (compiled_code == NULL)+ {+ int direction = error_direction(errorcode, erroroffset);++ cfprintf(clr_api_error, outfile, "Failed: error %d at offset %d: ", errorcode,+ (int)erroroffset);+ if (!print_error_message(errorcode, "", "\n")) return PR_ABEND;++ /* It's important that the erroroffset doesn't slice halfway through a UTF-8+ or UTF-16 character. We can verify this by checking that the input left of the+ erroroffset is valid. Note that if the input is invalid (which is exercised in+ some tests) then the offset will be positioned with the valid part to the left+ of erroroffset. */++#if PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16+ if (utf)+ {+ uint32_t cc;+ int n = 1;+ for (PCRE2_UCHAR *q = pbuffer, *q_end = q + erroroffset; q < q_end && n > 0; q += n)+ n = utf_to_ord(q, q_end, &cc);+ if (n <= 0)+ {+ cfprintf(clr_test_error, outfile, "** Erroroffset %d splits a UTF character\n", (int)erroroffset);+ return PR_ABEND;+ }+ }+#endif++ /* Print the surrounding context around the erroroffset. */++ if (direction < 0)+ {+ cfprintf(clr_test_error, outfile, "** Error code %d not implemented in error_direction().\n", errorcode);+ cfprintf(clr_test_error, outfile, " error_direction() should usually return '1' for newly-added errors,\n");+ cfprintf(clr_test_error, outfile, " and the offset should be just to the right of the bad character.\n");+ return PR_ABEND;+ }++ else if (direction != 0)+ {+ cfprintf(clr_api_error, outfile, " here: ");+ if (erroroffset > 0)+ {+ ptrunc(clr_input, pbuffer, full_patlen, erroroffset, TRUE, utf, outfile);+ fprintf(outfile, " ");+ }+ cfprintf(clr_api_error, outfile, (direction == 1)? "|<--|" : (direction == 2)? "|-->|" : "|<-->|");+ if (erroroffset < full_patlen)+ {+ fprintf(outfile, " ");+ ptrunc(clr_input, pbuffer, full_patlen, erroroffset, FALSE, utf, outfile);+ }+ fprintf(outfile, "\n");+ }++ else if (erroroffset != 0)+ {+ cfprintf(clr_test_error, outfile, "** Unexpected non-zero erroroffset %d for error code %d\n",+ (int)erroroffset, errorcode);+ return PR_ABEND;+ }++ return PR_SKIP;+ }++/* If forbid_utf is non-zero, we are running a non-UTF test. UTF and UCP are+locked out at compile time, but we must also check for occurrences of \P, \p,+and \X, which are only supported when Unicode is supported. */++if (forbid_utf != 0)+ {+ if ((compiled_code->flags & PCRE2_HASBKPORX) != 0)+ {+ cfprintf(clr_test_error, outfile, "** \\P, \\p, and \\X are not allowed after the "+ "#forbid_utf command\n");+ return PR_SKIP;+ }+ }++/* Remember the maximum lookbehind, for partial matching. */++if (pattern_info(PCRE2_INFO_MAXLOOKBEHIND, &maxlookbehind, FALSE) != 0)+ return PR_ABEND;++/* Remember the number of captures. */++if (pattern_info(PCRE2_INFO_CAPTURECOUNT, &maxcapcount, FALSE) < 0)+ return PR_ABEND;++/* If an explicit newline modifier was given, set the information flag in the+pattern so that it is preserved over push/pop. */++if ((pat_patctl.control2 & CTL2_NL_SET) != 0)+ {+ compiled_code->flags |= PCRE2_NL_SET;+ }++/* Output code size and other information if requested. */++rc = show_pattern_info();+if (rc != PR_OK) return rc;++/* The "push" control requests that the compiled pattern be remembered on a+stack. This is mainly for testing the serialization functionality. */++if ((pat_patctl.control & CTL_PUSH) != 0)+ {+ if (patstacknext >= PATSTACKSIZE)+ {+ cfprintf(clr_test_error, outfile, "** Too many pushed patterns (max %d)\n", PATSTACKSIZE);+ return PR_ABEND;+ }+ patstack[patstacknext++] = compiled_code;+ compiled_code = NULL;+ }++/* The "pushcopy" and "pushtablescopy" controls are similar, but push a+copy of the pattern, the latter with a copy of its character tables. This tests+the pcre2_code_copy() and pcre2_code_copy_with_tables() functions. */++if ((pat_patctl.control & (CTL_PUSHCOPY|CTL_PUSHTABLESCOPY)) != 0)+ {+ if (patstacknext >= PATSTACKSIZE)+ {+ cfprintf(clr_test_error, outfile, "** Too many pushed patterns (max %d)\n", PATSTACKSIZE);+ return PR_ABEND;+ }+ if ((pat_patctl.control & CTL_PUSHCOPY) != 0)+ {+ patstack[patstacknext++] = pcre2_code_copy(compiled_code);+ }+ else+ {+ patstack[patstacknext++] = pcre2_code_copy_with_tables(compiled_code);+ }+ }++return PR_OK;+}++++/* Helper to test for an active pattern. */++static BOOL+have_active_pattern(void)+{+return compiled_code != NULL;+}+++/* Helper to free (and null-out) the active pattern. Safe to call even if there+is no active pattern. */++static void+free_active_pattern(void)+{+pcre2_code_free(compiled_code);+compiled_code = NULL;+}++++/*************************************************+* Check heap, match or depth limit *+*************************************************/++/* This is used for DFA, normal, and JIT fast matching. For DFA matching it+should only be called with the third argument set to PCRE2_ERROR_DEPTHLIMIT.++Arguments:+ pp the subject string+ ulen length of subject or PCRE2_ZERO_TERMINATED+ errnumber defines which limit to test+ msg string to include in final message++Returns: the return from the final match function call+*/++static int+check_match_limit(PCRE2_SPTR pp, PCRE2_SIZE ulen, int errnumber, const char *msg)+{+int capcount;+uint32_t min = 0;+uint32_t mid = 64;+uint32_t max = UINT32_MAX;+FILE *saved_outfile = outfile;++pcre2_set_match_limit(dat_context, max);+pcre2_set_depth_limit(dat_context, max);+pcre2_set_heap_limit(dat_context, max);++for (;;)+ {+ 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);++ match_data->memctl.free(match_data->heapframes,+ match_data->memctl.memory_data);+ match_data->heapframes = NULL;+ match_data->heapframes_size = 0;+ }++ /* 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);+ }+ else+ {+ pcre2_set_depth_limit(dat_context, mid);+ }++ /* Do the appropriate match */++ reset_callout_state();+ outfile = NULL; /* Suppress callout output during the repeated search */++ if ((dat_datctl.control & CTL_DFA) != 0)+ {+ stack_start = DFA_START_RWS_SIZE/1024;+ if (dfa_workspace == NULL)+ dfa_workspace = (int *)malloc(DFA_WS_DIMENSION*sizeof(int));+ if (dfa_matched++ == 0)+ dfa_workspace[0] = -1; /* To catch bad restart */+ capcount = pcre2_dfa_match(compiled_code, pp, ulen, dat_datctl.offset,+ dat_datctl.options, match_data,+ dat_context, dfa_workspace, DFA_WS_DIMENSION);+ }++ else if ((pat_patctl.control & CTL_JITFAST) != 0)+ capcount = pcre2_jit_match(compiled_code, pp, ulen, dat_datctl.offset,+ dat_datctl.options, match_data, dat_context);++ else+ {+ capcount = pcre2_match(compiled_code, pp, ulen, dat_datctl.offset,+ dat_datctl.options, match_data, dat_context);+ }++ outfile = saved_outfile;++ if (capcount == errnumber)+ {+ if ((mid & 0x80000000u) != 0)+ {+ cfprintf(clr_test_error, outfile, "** Can't find minimum %s limit: check pattern for "+ "restriction\n", msg);+ break;+ }++ min = mid;+ mid = (mid == max - 1)? max : (max != UINT32_MAX)? (min + max)/2 : mid*2;+ }+ else if (capcount >= 0 ||+ capcount == PCRE2_ERROR_NOMATCH ||+ capcount == PCRE2_ERROR_PARTIAL)+ {+ /* If we've not hit the error with a heap limit less than the size of the+ initial stack frame vector (for pcre2_match()) or the initial stack+ workspace vector (for pcre2_dfa_match()), the heap is not being used, so+ the minimum limit is zero; there's no need to go on. The other limits are+ always greater than zero. */++ if (errnumber == PCRE2_ERROR_HEAPLIMIT && mid < stack_start)+ {+ fprintf(outfile, "Minimum %s limit = 0\n", msg);+ break;+ }+ if (mid == min + 1)+ {+ fprintf(outfile, "Minimum %s limit = %d\n", msg, mid);+ break;+ }+ max = mid;+ mid = (min + max)/2;+ }+ else break; /* Some other error */+ }++return capcount;+}++++/*************************************************+* Substitute callout function *+*************************************************/++/* Called from pcre2_substitute() when the substitute_callout modifier is set.+Print out the data that is passed back.++Arguments:+ scb pointer to substitute callout block+ data_ptr callout data++Returns: nothing+*/++static int+substitute_callout_function(pcre2_substitute_callout_block *scb,+ void *data_ptr)+{+int yield = 0;+BOOL utf = (compiled_code->overall_options & PCRE2_UTF) != 0;+(void)data_ptr; /* Not used */++if (outfile == NULL) goto YIELD;++fprintf(outfile, "%2d(%d) Old %" SIZ_FORM " %" SIZ_FORM " \"",+ scb->subscount, scb->oveccount,+ scb->ovector[0], scb->ovector[1]);++pchars(clr_none, scb->input + scb->ovector[0], scb->ovector[1] - scb->ovector[0],+ utf, outfile);++fprintf(outfile, "\" New %" SIZ_FORM " %" SIZ_FORM " \"",+ scb->output_offsets[0], scb->output_offsets[1]);++pchars(clr_none, scb->output + scb->output_offsets[0],+ scb->output_offsets[1] - scb->output_offsets[0], utf, outfile);++YIELD:++if (scb->subscount == dat_datctl.substitute_stop)+ {+ yield = -1;+ if (outfile != NULL) fprintf(outfile, " STOPPED");+ }+else if (scb->subscount == dat_datctl.substitute_skip)+ {+ yield = +1;+ if (outfile != NULL) fprintf(outfile, " SKIPPED");+ }++if (outfile != NULL) fprintf(outfile, "\"\n");+return yield;+}++++/*************************************************+* Substitute case callout function *+*************************************************/++/* Called from pcre2_substitute() when the substitute_case_callout+modifier is set. The substitute callout block is not identical for all code unit+widths, so we have to duplicate the function for each supported width.++Arguments:+ input the input character+ input_len the length of the input+ output the output buffer+ output_cap the output buffer capacity+ to_case the case conversion type+ data_ptr callout data (unused)++Returns: the number of code units of the output+*/++static PCRE2_SIZE+substitute_case_callout_function(+ PCRE2_SPTR input, PCRE2_SIZE input_len,+ PCRE2_UCHAR *output, PCRE2_SIZE output_cap,+ int to_case, void *data_ptr)+{+PCRE2_UCHAR buf[16];+PCRE2_SPTR input_copy;+PCRE2_SIZE written = 0;++(void)data_ptr; /* Not used */++if (input_len > sizeof(buf)/sizeof(*buf))+ {+ PCRE2_UCHAR *input_buf = malloc(CU2BYTES(input_len));+ if (input_buf == NULL) return ~(PCRE2_SIZE)0;+ memcpy(input_buf, input, CU2BYTES(input_len));+ input_copy = input_buf;+ }+else+ {+ memcpy(buf, input, CU2BYTES(input_len));+ input_copy = buf;+ }++for (PCRE2_SIZE i = 0; i < input_len; )+ {+ int num_in = i + 1 < input_len ? 2 : 1;+ uint32_t c1 = input_copy[i];+ uint32_t c2 = i + 1 < input_len ? input_copy[i + 1] : 0;+ int num_read;+ int num_write;++ if (!case_transform(to_case, num_in, &num_read, &num_write, &c1, &c2))+ {+ written = ~(PCRE2_SIZE)0;+ goto END;+ }++ i += num_read;+ if (to_case == PCRE2_SUBSTITUTE_CASE_TITLE_FIRST)+ to_case = PCRE2_SUBSTITUTE_CASE_LOWER;++ if (written + num_write > output_cap)+ {+ written += num_write;+ }+ else+ {+ if (num_write > 0) output[written++] = c1;+ if (num_write > 1) output[written++] = c2;+ }+ }++END:+if (input_copy != buf) free((PCRE2_UCHAR *)input_copy);++/* Let's be maximally cruel. The case callout is allowed to leave the output+buffer in any state at all if it overflows, so let's use random garbage. */+if (written > output_cap)+ memset(output, time(NULL) & 1 ? 0xcd : 0xdc,+ CU2BYTES(output_cap));++return written;+}++++/*************************************************+* Callout function *+*************************************************/++/* Called from a PCRE2 library as a result of the (?C) item. We print out where+we are in the match (unless suppressed). Yield zero unless more callouts than+the fail count, or the callout data is not zero. The only differences in the+callout block for different code unit widths are that the pointers to the+subject, the most recent MARK, and a callout argument string point to strings+of the appropriate width. Casts can be used to deal with this.++Arguments:+ cb a pointer to a callout block+ callout_data_ptr the provided callout data++Returns: 0 or 1 or an error, as determined by settings+*/++static int+callout_function(pcre2_callout_block *cb, void *callout_data_ptr)+{+FILE *f, *fdefault;+uint32_t i, pre_start, post_start, subject_length;+PCRE2_SIZE current_position;+BOOL utf = (compiled_code->overall_options & PCRE2_UTF) != 0;+BOOL callout_capture = (dat_datctl.control & CTL_CALLOUT_CAPTURE) != 0;+BOOL callout_where = (dat_datctl.control2 & CTL2_CALLOUT_NO_WHERE) == 0;++if (outfile == NULL) goto YIELD;++/* The FILE f is used for echoing the subject string if it is non-NULL. This+happens only once in simple cases, but we want to repeat after any additional+output caused by CALLOUT_EXTRA. */++fdefault = (!first_callout && !callout_capture && cb->callout_string == NULL)?+ NULL : outfile;++if ((dat_datctl.control2 & CTL2_CALLOUT_EXTRA) != 0)+ {+ f = outfile;+ switch (cb->callout_flags)+ {+ case PCRE2_CALLOUT_BACKTRACK:+ fprintf(f, "Backtrack\n");+ break;++ case PCRE2_CALLOUT_STARTMATCH|PCRE2_CALLOUT_BACKTRACK:+ fprintf(f, "Backtrack\nNo other matching paths\n");+ PCRE2_FALLTHROUGH /* Fall through */++ case PCRE2_CALLOUT_STARTMATCH:+ fprintf(f, "New match attempt\n");+ break;++ default:+ f = fdefault;+ break;+ }+ }+else f = fdefault;++/* For a callout with a string argument, show the string first because there+isn't a tidy way to fit it in the rest of the data. */++if (cb->callout_string != NULL)+ {+ uint32_t delimiter = cb->callout_string[-1];+ fprintf(outfile, "Callout (%" SIZ_FORM "): %c",+ cb->callout_string_offset, CHAR_OUTPUT(delimiter));+ pchars(clr_none, cb->callout_string, cb->callout_string_length, utf, outfile);+ for (i = 0; callout_start_delims[i] != 0; i++)+ if (delimiter == callout_start_delims[i])+ {+ delimiter = callout_end_delims[i];+ break;+ }+ fprintf(outfile, "%c", CHAR_OUTPUT(delimiter));+ if (!callout_capture) fprintf(outfile, "\n");+ }++/* Show captured strings if required */++if (callout_capture)+ {+ if (cb->callout_string == NULL)+ fprintf(outfile, "Callout %d:", cb->callout_number);+ fprintf(outfile, " last capture = %d\n", cb->capture_last);+ for (i = 2; i < cb->capture_top * 2; i += 2)+ {+ fprintf(outfile, "%2d: ", i/2);+ if (cb->offset_vector[i] == PCRE2_UNSET)+ fprintf(outfile, "<unset>");+ else+ {+ pchars(clr_none, cb->subject + cb->offset_vector[i],+ cb->offset_vector[i+1] - cb->offset_vector[i], utf, f);+ }+ fprintf(outfile, "\n");+ }+ }++/* Unless suppressed, re-print the subject in canonical form (with escapes for+non-printing characters), the first time, or if giving full details. On+subsequent calls in the same match, we use pchars() just to find the printed+lengths of the substrings. */++if (callout_where)+ {+ if (f != NULL) fprintf(f, "--->");++ /* The subject before the match start. */++ pre_start = pchars(clr_none, cb->subject, cb->start_match, utf, f);++ /* If a lookbehind is involved, the current position may be earlier than the+ match start. If so, use the match start instead. */++ current_position = (cb->current_position >= cb->start_match)?+ cb->current_position : cb->start_match;++ /* The subject between the match start and the current position. */++ post_start = pchars(clr_none, cb->subject + cb->start_match,+ current_position - cb->start_match, utf, f);++ /* Print from the current position to the end. */++ pchars(clr_none, cb->subject + current_position, cb->subject_length - current_position,+ utf, f);++ /* Calculate the total subject printed length (no print). */++ subject_length = pchars(clr_none, cb->subject, cb->subject_length, utf, NULL);++ if (f != NULL) fprintf(f, "\n");++ /* For automatic callouts, show the pattern offset. Otherwise, for a+ numerical callout whose number has not already been shown with captured+ strings, show the number here. A callout with a string argument has been+ displayed above. */++ if (cb->callout_number == 255)+ {+ fprintf(outfile, "%+3d ", (int)cb->pattern_position);+ if (cb->pattern_position > 99) fprintf(outfile, "\n ");+ }+ else+ {+ if (callout_capture || cb->callout_string != NULL) fprintf(outfile, " ");+ else fprintf(outfile, "%3d ", cb->callout_number);+ }++ /* Now show position indicators */++ for (i = 0; i < pre_start; i++) fprintf(outfile, " ");+ fprintf(outfile, "^");++ if (post_start > 0)+ {+ for (i = 0; i < post_start - 1; i++) fprintf(outfile, " ");+ fprintf(outfile, "^");+ }++ for (i = 0; i < subject_length - pre_start - post_start + 4; i++)+ fprintf(outfile, " ");++ if (cb->next_item_length != 0)+ {+ pchars(clr_none, pbuffer + cb->pattern_position, cb->next_item_length, utf, outfile);+ }+ else+ fprintf(outfile, "End of pattern");++ fprintf(outfile, "\n");+ }++/* Show any mark info */++if (cb->mark != last_callout_mark)+ {+ if (cb->mark == NULL)+ fprintf(outfile, "Latest Mark: <unset>\n");+ else+ {+ fprintf(outfile, "Latest Mark: ");+ pchars(clr_none, cb->mark - 1, -1, utf, outfile);+ putc('\n', outfile);+ }+ }++YIELD:++/* Keep count */++first_callout = FALSE;+last_callout_mark = cb->mark;+callout_count++;++/* Show callout data if that determines the return code */++if (callout_data_ptr != NULL)+ {+ int callout_data = *((int32_t *)callout_data_ptr);+ if (callout_data != 0)+ {+ if (outfile != NULL) fprintf(outfile, "Callout data = %d\n", callout_data);+ return callout_data;+ }+ }++/* Otherwise, the callout_error and callout_fail settings provide the return+code. */++if (cb->callout_number == dat_datctl.cerror[0] &&+ callout_count >= dat_datctl.cerror[1])+ return PCRE2_ERROR_CALLOUT;++if (cb->callout_number == dat_datctl.cfail[0] &&+ callout_count >= dat_datctl.cfail[1])+ return 1;++return 0;+}++++/*************************************************+* Handle *MARK and copy/get tests *+*************************************************/++/* This function is called after complete and partial matches. It runs the+tests for substring extraction.++Arguments:+ utf TRUE for utf+ capcount return from pcre2_match()++Returns: FALSE if print_error_message() fails+*/++static BOOL+copy_and_get(BOOL utf, int capcount)+{+int i;+uint8_t *nptr;++/* Test copy strings by number */++for (i = 0; i < MAXCPYGET && dat_datctl.copy_numbers[i] >= 0; i++)+ {+ int rc, rc2;+ PCRE2_SIZE length, length2;+ PCRE2_UCHAR copybuffer[256];+ uint32_t n = (uint32_t)(dat_datctl.copy_numbers[i]);+ length = sizeof(copybuffer)/sizeof(*copybuffer);+ rc = pcre2_substring_copy_bynumber(match_data, n, copybuffer, &length);+ if (rc < 0)+ {+ cfprintf(clr_api_error, outfile, "Copy substring %d failed (%d): ", n, rc);+ if (!print_error_message(rc, "", "\n")) return FALSE;+ }+ else+ {+ fprintf(outfile, "%2dC ", n);+ pchars(clr_none, copybuffer, length, utf, outfile);+ fprintf(outfile, " (%" SIZ_FORM ")\n", length);+ }+ rc2 = pcre2_substring_length_bynumber(match_data, n, &length2);+ if (rc2 < 0)+ {+ cfprintf(clr_api_error, outfile, "Get substring %d length failed (%d): ", n, rc2);+ if (!print_error_message(rc2, "", "\n")) return FALSE;+ }+ else if (rc >= 0 && length2 != length)+ {+ cfprintf(clr_test_error, outfile, "** Mismatched substring lengths: %"+ SIZ_FORM " %" SIZ_FORM "\n", length, length2);+ }+ }++/* Test copy strings by name */++nptr = dat_datctl.copy_names;+for (;;)+ {+ int rc, rc2;+ int groupnumber;+ PCRE2_SIZE length, length2;+ PCRE2_UCHAR copybuffer[256];+ size_t namelen = strlen((const char *)nptr);+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+ PCRE2_SIZE cnl = namelen;+#endif+ if (namelen == 0) break;++#if PCRE2_CODE_UNIT_WIDTH == 8+ strcpy((char *)pbuffer8, (char *)nptr);+#endif+#if defined(EBCDIC) && !EBCDIC_IO+ ascii_to_ebcdic_str(pbuffer8, namelen);+#endif+#if PCRE2_CODE_UNIT_WIDTH == 16+ (void)to16(nptr, utf, &cnl);+#endif+#if PCRE2_CODE_UNIT_WIDTH == 32+ (void)to32(nptr, utf, &cnl);+#endif++ groupnumber = pcre2_substring_number_from_name(compiled_code, pbuffer);+ if (groupnumber < 0 && groupnumber != PCRE2_ERROR_NOUNIQUESUBSTRING)+ cfprintf(clr_api_error, outfile, "Number not found for group \"%s\"\n", nptr);++ length = sizeof(copybuffer)/sizeof(*copybuffer);+ rc = pcre2_substring_copy_byname(match_data, pbuffer, copybuffer, &length);+ if (rc < 0)+ {+ cfprintf(clr_api_error, outfile, "Copy substring \"%s\" failed (%d): ", nptr, rc);+ if (!print_error_message(rc, "", "\n")) return FALSE;+ }+ else+ {+ fprintf(outfile, " C ");+ pchars(clr_none, copybuffer, length, utf, outfile);+ fprintf(outfile, " (%" SIZ_FORM ") %s", length, nptr);+ if (groupnumber >= 0) fprintf(outfile, " (group %d)\n", groupnumber);+ else fprintf(outfile, " (non-unique)\n");+ }+ rc2 = pcre2_substring_length_byname(match_data, pbuffer, &length2);+ if (rc2 < 0)+ {+ cfprintf(clr_api_error, outfile, "Get substring \"%s\" length failed (%d): ", nptr, rc2);+ if (!print_error_message(rc2, "", "\n")) return FALSE;+ }+ else if (rc >= 0 && length2 != length)+ {+ cfprintf(clr_test_error, outfile, "** Mismatched substring lengths: %"+ SIZ_FORM " %" SIZ_FORM "\n", length, length2);+ }+ nptr += namelen + 1;+ }++/* Test get strings by number */++for (i = 0; i < MAXCPYGET && dat_datctl.get_numbers[i] >= 0; i++)+ {+ int rc;+ PCRE2_SIZE length;+ PCRE2_UCHAR *gotbuffer;+ uint32_t n = (uint32_t)(dat_datctl.get_numbers[i]);+ rc = pcre2_substring_get_bynumber(match_data, n, &gotbuffer, &length);+ if (rc < 0)+ {+ cfprintf(clr_api_error, outfile, "Get substring %d failed (%d): ", n, rc);+ if (!print_error_message(rc, "", "\n")) return FALSE;+ }+ else+ {+ fprintf(outfile, "%2dG ", n);+ pchars(clr_none, gotbuffer, length, utf, outfile);+ fprintf(outfile, " (%" SIZ_FORM ")\n", length);+ pcre2_substring_free(gotbuffer);+ }+ }++/* Test get strings by name */++nptr = dat_datctl.get_names;+for (;;)+ {+ PCRE2_SIZE length;+ PCRE2_UCHAR *gotbuffer;+ int rc;+ int groupnumber;+ size_t namelen = strlen((const char *)nptr);+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32+ PCRE2_SIZE cnl = namelen;+#endif+ if (namelen == 0) break;++#if PCRE2_CODE_UNIT_WIDTH == 8+ strcpy((char *)pbuffer8, (char *)nptr);+#endif+#if defined(EBCDIC) && !EBCDIC_IO+ ascii_to_ebcdic_str(pbuffer8, namelen);+#endif+#if PCRE2_CODE_UNIT_WIDTH == 16+ (void)to16(nptr, utf, &cnl);+#endif+#if PCRE2_CODE_UNIT_WIDTH == 32+ (void)to32(nptr, utf, &cnl);+#endif++ groupnumber = pcre2_substring_number_from_name(compiled_code, pbuffer);+ if (groupnumber < 0 && groupnumber != PCRE2_ERROR_NOUNIQUESUBSTRING)+ cfprintf(clr_api_error, outfile, "Number not found for group \"%s\"\n", nptr);++ rc = pcre2_substring_get_byname(match_data, pbuffer, &gotbuffer, &length);+ if (rc < 0)+ {+ cfprintf(clr_api_error, outfile, "Get substring \"%s\" failed (%d): ", nptr, rc);+ if (!print_error_message(rc, "", "\n")) return FALSE;+ }+ else+ {+ fprintf(outfile, " G ");+ pchars(clr_none, gotbuffer, length, utf, outfile);+ fprintf(outfile, " (%" SIZ_FORM ") %s", length, nptr);+ if (groupnumber >= 0) fprintf(outfile, " (group %d)\n", groupnumber);+ else fprintf(outfile, " (non-unique)\n");+ pcre2_substring_free(gotbuffer);+ }+ nptr += namelen + 1;+ }++/* Test getting the complete list of captured strings. */++if ((dat_datctl.control & CTL_GETALL) != 0)+ {+ int rc;+ PCRE2_UCHAR **stringlist;+ PCRE2_SIZE *lengths;+ rc = pcre2_substring_list_get(match_data, &stringlist, &lengths);+ if (rc < 0)+ {+ cfprintf(clr_api_error, outfile, "get substring list failed (%d): ", rc);+ if (!print_error_message(rc, "", "\n")) return FALSE;+ }+ else+ {+ for (i = 0; i < capcount; i++)+ {+ fprintf(outfile, "%2dL ", i);+ pchars(clr_none, stringlist[i], lengths[i], utf, outfile);+ putc('\n', outfile);+ }+ if (stringlist[i] != NULL)+ cfprintf(clr_test_error, outfile, "** string list not terminated by NULL\n");+ pcre2_substring_list_free(stringlist);+ }+ }++return TRUE;+}++++/*************************************************+* Copy a substitution string *+*************************************************/++/* Copy one of the string arguments to pcre2_substitute() from its uint8_t+test input to the appropriate width buffer.+*/++static void+copy_substitute_string(BOOL utf, uint8_t *input, PCRE2_SIZE inlen,+ PCRE2_UCHAR *output, PCRE2_SIZE *outlen)+{+uint32_t c;+uint8_t *input_end = input + inlen;+PCRE2_UCHAR *output_start = output;+PCRE2_SIZE erroroffset;+BOOL badutf = FALSE;++/* When copying the replacement string to a buffer of the appropriate width, no+escape processing is done.++In UTF mode, check for an invalid UTF-8 input string, and if it is invalid, just+copy its code units without UTF interpretation. This provides a means of+checking that an invalid string is detected. Otherwise, UTF-8 can be used to+include wide characters in a replacement. */++if (utf) badutf = valid_utf(input, inlen, &erroroffset);++/* Not UTF or invalid UTF-8: just copy the code units. */++if (!utf || badutf)+ {+ while (input < input_end)+ {+ c = *input++;+#if defined(EBCDIC) && !EBCDIC_IO+ c = ascii_to_ebcdic(c);+#endif+ *output++ = c;+ }+ }++/* Valid UTF-8 replacement string */++else while (input < input_end)+ {+ c = *input++;+ if (HASUTF8EXTRALEN(c)) { GETUTF8INC(c, input); }++#if PCRE2_CODE_UNIT_WIDTH == 8+ output += ord_to_utf8(c, output);++#elif PCRE2_CODE_UNIT_WIDTH == 16+ if (c >= 0x10000u)+ {+ c-= 0x10000u;+ *output++ = 0xd800 | (c >> 10);+ *output++ = 0xdc00 | (c & 0x3ff);+ }+ else *output++ = c;++#elif PCRE2_CODE_UNIT_WIDTH == 32+ *output++ = c;+#endif+ }++*output = 0;+*outlen = output - output_start;+}++++/*************************************************+* Process a data line *+*************************************************/++/* The line is in buffer; it will not be empty.++Arguments: none++Returns: PR_OK continue processing next line+ PR_SKIP skip to a blank line+ PR_ABEND abort the pcre2test run+*/++static int+process_data(void)+{+PCRE2_SIZE ulen, arg_ulen;+uint32_t gmatched;+uint32_t c, k;+uint32_t g_notempty = 0;+uint8_t *p; /* Position within buffer (raw input line) */+size_t len;+size_t needlen; /* Bytes, for sizing dbuffer */+pcre2_match_context *use_dat_context;+BOOL utf;+BOOL subject_literal;++PCRE2_SIZE *ovector;+PCRE2_SPTR ovecsave[2] = { NULL, NULL };+uint32_t oveccount;++PCRE2_UCHAR *q = NULL; /* Typed pointer within dbuffer */+PCRE2_UCHAR *start_rep; /* Position within dbuffer; stashed value of q */+PCRE2_UCHAR *pp; /* Subject pointer within dbuffer */++subject_literal = (pat_patctl.control2 & CTL2_SUBJECT_LITERAL) != 0;++/* Copy the default context and data control blocks to the active ones. Then+copy from the pattern the controls that can be set in either the pattern or the+data. This allows them to be overridden in the data line. We do not do this for+options because those that are common apply separately to compiling and+matching. */++memcpy(dat_context, default_dat_context, sizeof(pcre2_match_context));+memcpy(&dat_datctl, &def_datctl, sizeof(datctl));+dat_datctl.control |= (pat_patctl.control & CTL_ALLPD);+dat_datctl.control2 |= (pat_patctl.control2 & CTL2_ALLPD);+dat_datctl.replacement[0] = pat_patctl.replacement[0];+if (pat_patctl.replacement[0] != MOD_STR_UNSET)+ memcpy(dat_datctl.replacement + 1, pat_patctl.replacement + 1,+ pat_patctl.replacement[0] + 1);+if (dat_datctl.jitstack == 0) dat_datctl.jitstack = pat_patctl.jitstack;++if (dat_datctl.substitute_skip == 0)+ dat_datctl.substitute_skip = pat_patctl.substitute_skip;+if (dat_datctl.substitute_stop == 0)+ dat_datctl.substitute_stop = pat_patctl.substitute_stop;++/* Initialize for scanning the data line. */++#if PCRE2_CODE_UNIT_WIDTH == 8+utf = ((((pat_patctl.control & CTL_POSIX) != 0)?+ ((pcre2_real_code *)preg.re_pcre2_code)->overall_options :+ compiled_code->overall_options) & PCRE2_UTF) != 0;+#else+utf = (compiled_code->overall_options & PCRE2_UTF) != 0;+#endif++start_rep = NULL;+len = strlen((const char *)buffer);+while (len > 0 && isspace(buffer[len-1])) len--;+buffer[len] = 0;+p = buffer;+while (isspace(*p))+ {+ p++;+ len--;+ }++/* Check that the data is well-formed UTF-8 if we're in UTF mode. To create+invalid input to pcre2_match(), you must use \x?? or \x{} sequences. */++if (utf)+ {+ uint8_t *ptmp;+ uint32_t cc;+ int n = 1;+ uint8_t *ptmp_end = p + len;++ for (ptmp = p; n > 0 && *ptmp; ptmp += n)+ n = utf8_to_ord(ptmp, ptmp_end, &cc);+ if (n <= 0)+ {+ cfprintf(clr_test_error, outfile, "** Failed: invalid UTF-8 string cannot be used as input "+ "in UTF mode\n");+ return PR_OK;+ }+ }++#ifdef SUPPORT_VALGRIND+/* Mark the dbuffer as addressable but undefined again. */+if (dbuffer != NULL)+ {+ VALGRIND_MAKE_MEM_UNDEFINED(dbuffer, dbuffer_size);+ }+#endif++/* Allocate a buffer to hold the data line; len+1 is an upper bound on+the number of code units that will be needed (though the buffer may have to be+extended if replication is involved). */++needlen = CU2BYTES(len+1);+if (dbuffer == NULL || needlen >= dbuffer_size)+ {+ 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)+ {+ cfprintf(clr_test_error, stderr, "pcre2test: realloc(%" SIZ_FORM ") failed\n", dbuffer_size);+ exit(1);+ }+ }+q = (PCRE2_UCHAR *)dbuffer;++/* Scan the data line, interpreting data escapes, and put the result into a+buffer of the appropriate width. In UTF mode, input is always UTF-8; otherwise,+in 16- and 32-bit modes, it can be forced to UTF-8 by the utf8_input modifier.+*/++while ((c = *p++) != 0)+ {+ int i = 0;+ size_t replen; /* Bytes, for sizing dbuffer */+ enum force_encoding encoding = FORCE_NONE;++ /* ] may mark the end of a replicated sequence */++ if (c == ']' && start_rep != NULL)+ {+ long li;+ char *endptr;++ if (*p++ != '{')+ {+ cfprintf(clr_test_error, outfile, "** Expected '{' after \\[....]\n");+ return PR_OK;+ }++ li = strtol((const char *)p, &endptr, 10);+ if (S32OVERFLOW(li))+ {+ cfprintf(clr_test_error, outfile, "** Repeat count too large\n");+ return PR_OK;+ }+ i = (int)li;++ p = (uint8_t *)endptr;+ if (*p++ != '}')+ {+ cfprintf(clr_test_error, outfile, "** Expected '}' after \\[...]{...\n");+ return PR_OK;+ }++ if (i-- <= 0)+ {+ cfprintf(clr_test_error, outfile, "** Zero or negative repeat not allowed\n");+ return PR_OK;+ }++ replen = (uint8_t *)q - (uint8_t *)start_rep;+ if (i > 0 && replen > (SIZE_MAX - needlen) / i)+ {+ cfprintf(clr_test_error, outfile, "** Expanded content too large\n");+ return PR_OK;+ }+ needlen += replen * i;++ if (needlen >= dbuffer_size)+ {+ size_t qoffset = (uint8_t *)q - dbuffer;+ size_t rep_offset = (uint8_t *)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)+ {+ cfprintf(clr_test_error, stderr, "pcre2test: realloc(%" SIZ_FORM ") failed\n",+ dbuffer_size);+ exit(1);+ }+ q = (PCRE2_UCHAR *)(dbuffer + qoffset);+ start_rep = (PCRE2_UCHAR *)(dbuffer + rep_offset);+ }++ while (i-- > 0)+ {+ memcpy(q, start_rep, replen);+ q += BYTES2CU(replen);+ }++ start_rep = NULL;+ continue;+ }++ /* Handle a non-escaped character. In non-UTF 32-bit mode with utf8_input+ set, do the fudge for setting the top bit. */++ if (c != '\\' || subject_literal)+ {+ uint32_t topbit = 0;+#if PCRE2_CODE_UNIT_WIDTH == 32+ if (c == 0xff && *p != 0)+ {+ topbit = 0x80000000;+ c = *p++;+ }+#endif+ if ((utf || (pat_patctl.control & CTL_UTF8_INPUT) != 0) &&+ HASUTF8EXTRALEN(c))+ {+ GETUTF8INC(c, p);+ }+ c |= topbit;+ }++ /* Handle backslash escapes */++ else switch ((c = *p++))+ {+ case '\\': break;+ case 'a': c = '\a'; break;+ case 'b': c = '\b'; break;+#if defined(EBCDIC) && !EBCDIC_IO+ /* \e is the odd one out since it's not defined in the C standard,+ precisely because of EBCDIC (apparently EBCDIC 'ESC' character isn't+ an exact match to Latin-1 'ESC', hence '\e' isn't necessarily+ supported by EBCDIC compilers). */+ case 'e': c = '\x1b'; break;+#else+ case 'e': c = CHAR_ESC; break;+#endif+ case 'f': c = '\f'; break;+ case 'n': c = '\n'; break;+ case 'r': c = '\r'; break;+ case 't': c = '\t'; break;+ case 'v': c = '\v'; break;++ case '0': case '1': case '2': case '3':+ case '4': case '5': case '6': case '7':+ c -= '0';+ while (i++ < 2 && *p >= '0' && *p < '8')+ c = c * 8 + (*p++ - '0');+ c = CHAR_OUTPUT(CHAR_INPUT_HEX(c));++ encoding = (utf && c > 255)? FORCE_UTF : FORCE_RAW;+ break;++ case 'o':+ if (*p == '{')+ {+ uint8_t *pt = p;+ c = 0;+ for (pt++; isdigit(*pt) && *pt < '8'; ++i, pt++)+ {+ if (c >= 0x20000000u)+ {+ cfprintf(clr_test_error, outfile, "** \\o{ escape too large\n");+ return PR_OK;+ }+ else c = c * 8 + (*pt - '0');+ }+ c = CHAR_OUTPUT(CHAR_INPUT_HEX(c));+ if (i == 0 || *pt != '}')+ {+ cfprintf(clr_test_error, outfile, "** Malformed \\o{ escape\n");+ return PR_OK;+ }+ else p = pt + 1;+ }+ break;++ case 'x':+ c = 0;+ if (*p == '{')+ {+ uint8_t *pt = p;++ /* We used to have "while (isxdigit(*(++pt)))" here, but it fails+ when isxdigit() is a macro that refers to its argument more than+ once. This is banned by the C Standard, but apparently happens in at+ least one macOS environment. */++ for (pt++; isxdigit(*pt); pt++)+ {+ if (++i == 9)+ {+ cfprintf(clr_test_error, outfile, "** Too many hex digits in \\x{...} item; "+ "using only the first eight.\n");+ while (isxdigit(*pt)) pt++;+ break;+ }+ else c = c * 16 + (tolower(*pt) - (isdigit(*pt)? '0' : 'a' - 10));+ }+ c = CHAR_OUTPUT(CHAR_INPUT_HEX(c));+ if (i == 0 || *pt != '}')+ {+ cfprintf(clr_test_error, outfile, "** Malformed \\x{ escape\n");+ return PR_OK;+ }+ else p = pt + 1;+ }+ else+ {+ /* \x without {} always defines just one byte in 8-bit mode. This+ allows UTF-8 characters to be constructed byte by byte, and also allows+ invalid UTF-8 sequences to be made. Just copy the byte in UTF-8 mode.+ Otherwise, pass it down as data. */++ while (i++ < 2 && isxdigit(*p))+ {+ c = c * 16 + (tolower(*p) - (isdigit(*p)? '0' : 'a' - 10));+ p++;+ }+ c = CHAR_OUTPUT(CHAR_INPUT_HEX(c));+#if PCRE2_CODE_UNIT_WIDTH == 8+ if (utf) encoding = FORCE_RAW;+#endif+ }+ break;++ case 'N':+#ifndef EBCDIC+ if (memcmp(p, "{U+", 3) == 0 && isxdigit(p[3]))+ {+ char *endptr;+ unsigned long uli;++ p += 3;+ errno = 0;+ uli = strtoul((const char *)p, &endptr, 16);+ if (errno == 0 && *endptr == '}' && uli <= UINT32_MAX)+ {+ c = (uint32_t)uli;+ p = (uint8_t *)endptr + 1;+ encoding = FORCE_UTF;+ break;+ }+ }+#endif+ cfprintf(clr_test_error, outfile, "** Malformed \\N{U+ escape\n");+ return PR_OK;++ case 0: /* \ followed by EOF allows for an empty line */+ p--;+ continue;++ case '=': /* \= terminates the data, starts modifiers */+ goto ENDSTRING;++ case '[': /* \[ introduces a replicated character sequence */+ if (start_rep != NULL)+ {+ cfprintf(clr_test_error, outfile, "** Nested replication is not supported\n");+ return PR_OK;+ }+ start_rep = q;+ continue;++ default:+ if (isalnum(c))+ {+ cfprintf(clr_test_error, outfile, "** Unrecognized escape sequence \"\\%c\"\n", c);+ return PR_OK;+ }+ }++ /* We now have a character value in c that may be greater than 255.+ Depending of how we got it, the encoding enum could be set to tell+ us how to encode it, otherwise follow the utf modifier. */++#if PCRE2_CODE_UNIT_WIDTH == 8+ if (encoding == FORCE_RAW || !(utf || encoding == FORCE_UTF))+ {+ if (c > 0xffu)+ {+ cfprintf(clr_test_error, outfile, "** Character \\x{%x} is greater than 255 "+ "and UTF-8 mode is not enabled.\n", c);+ cfprintf(clr_test_error, outfile, "** Truncation will probably give the wrong "+ "result.\n");+ }+ *q++ = (uint8_t)c;+ }+ else+ {+ if (c > 0x7fffffff)+ {+ cfprintf(clr_test_error, outfile, "** Character \\N{U+%x} is greater than 0x7fffffff "+ "and therefore cannot be encoded as UTF-8\n", c);+ return PR_OK;+ }+ else if (encoding == FORCE_UTF && c > MAX_UTF_CODE_POINT)+ cfprintf(clr_test_error, outfile, "** Warning: character \\N{U+%x} is greater than "+ "0x%x and should not be encoded as UTF-8\n",+ c, MAX_UTF_CODE_POINT);+ q += ord_to_utf8(c, q);+ }+#endif+#if PCRE2_CODE_UNIT_WIDTH == 16+ /* Unlike the 8-bit code, there are no forced raw suggestions for the+ 16-bit mode, so assume raw unless utf is preferred */++ if (!(encoding == FORCE_UTF || utf))+ {+ if (c > 0xffffu)+ {+ cfprintf(clr_test_error, outfile, "** Character \\x{%x} is greater than 0xffff "+ "and UTF-16 mode is not enabled.\n", c);+ cfprintf(clr_test_error, outfile, "** Truncation will probably give the wrong "+ "result.\n");+ }+ *q++ = (uint16_t)c;+ }+ else+ {+ if (c > MAX_UTF_CODE_POINT)+ {+ cfprintf(clr_test_error, outfile, "** Failed: character \\N{U+%x} is greater than "+ "0x%x and therefore cannot be encoded as UTF-16\n",+ c, MAX_UTF_CODE_POINT);+ return PR_OK;+ }+ else if (c >= 0x10000u)+ {+ c -= 0x10000u;+ *q++ = 0xd800 | (c >> 10);+ *q++ = 0xdc00 | (c & 0x3ff);+ }+ else+ {+ if (encoding == FORCE_UTF && 0xe000u > c && c >= 0xd800u)+ cfprintf(clr_test_error, outfile, "** Warning: character \\N{U+%x} is a surrogate "+ "and should not be encoded as UTF-16\n", c);+ *q++ = c;+ }+ }+#endif+#if PCRE2_CODE_UNIT_WIDTH == 32+ if (encoding == FORCE_UTF && c > MAX_UTF_CODE_POINT)+ cfprintf(clr_test_error, outfile, "** Warning: character \\N{U+%x} is greater than "+ "0x%x and should not be encoded as UTF-32\n",+ c, MAX_UTF_CODE_POINT);+ *q++ = c;+#endif+ }++ENDSTRING:+*q = 0;+len = (uint8_t *)q - dbuffer; /* Length in bytes */+ulen = BYTES2CU(len); /* Length in code units */+arg_ulen = ulen; /* Value to use in match arg */++/* If the string was terminated by \= we must now interpret modifiers. */++if (p[-1] != 0 && !decode_modifiers(p, CTX_DAT, NULL, &dat_datctl))+ return PR_OK;++/* Setting substitute_{skip,fail} implies a substitute callout. */++if (dat_datctl.substitute_skip != 0 || dat_datctl.substitute_stop != 0)+ dat_datctl.control2 |= CTL2_SUBSTITUTE_CALLOUT;++/* Check for mutually exclusive modifiers. At present, these are all in the+first control word. */++for (k = 0; k < sizeof(exclusive_dat_controls)/sizeof(uint32_t); k++)+ {+ c = dat_datctl.control & exclusive_dat_controls[k];+ if (c != 0 && c != (c & (~c+1)))+ {+ show_controls(clr_test_error, c, 0, "** Not allowed together:");+ fprintf(outfile, "\n");+ return PR_OK;+ }+ }++if (dat_datctl.replacement[0] != MOD_STR_UNSET)+ {+ if ((dat_datctl.control2 & CTL2_SUBSTITUTE_CALLOUT) != 0 &&+ (dat_datctl.control & CTL_NULLCONTEXT) != 0)+ {+ cfprintf(clr_test_error, outfile, "** Replacement callouts are not supported with null_context.\n");+ return PR_OK;+ }++ if ((dat_datctl.control2 & CTL2_SUBSTITUTE_CASE_CALLOUT) != 0 &&+ (dat_datctl.control & CTL_NULLCONTEXT) != 0)+ {+ cfprintf(clr_test_error, outfile, "** Replacement case callouts are not supported with null_context.\n");+ return PR_OK;+ }++ if ((dat_datctl.control & CTL_ALLCAPTURES) != 0)+ cfprintf(clr_test_error, outfile, "** Ignored with replacement text: allcaptures\n");++ if (dat_datctl.substitute_subject[0] != MOD_STR_UNSET &&+ (dat_datctl.control2 & CTL2_SUBSTITUTE_MATCHED) == 0)+ {+ cfprintf(clr_test_error, outfile, "** substitute_subject requires substitute_matched.\n");+ return PR_OK;+ }+ }++else+ {+ if (dat_datctl.substitute_subject[0] != MOD_STR_UNSET)+ {+ cfprintf(clr_test_error, outfile, "** substitute_subject requires replacement text.\n");+ return PR_OK;+ }+ }++/* Warn for modifiers that are ignored for DFA. */++if ((dat_datctl.control & CTL_DFA) != 0)+ {+ if ((dat_datctl.control & CTL_ALLCAPTURES) != 0)+ cfprintf(clr_test_error, outfile, "** Ignored for DFA matching: allcaptures\n");+ if ((dat_datctl.control2 & CTL2_HEAPFRAMES_SIZE) != 0)+ cfprintf(clr_test_error, outfile, "** Ignored for DFA matching: heapframes_size\n");+ }++/* We now have the subject in dbuffer, with len containing the byte length, and+ulen containing the code unit length, with a copy in arg_ulen for use in match+function arguments (this gets changed to PCRE2_ZERO_TERMINATED when the+zero_terminate modifier is present).++Move the data to the end of the buffer so that a read over the end can be+caught by valgrind or other means. If we have explicit valgrind support, mark+the unused start of the buffer unaddressable. If we are using the POSIX+interface, or testing zero-termination, we must include the terminating zero in+the usable data. */++c = ((pat_patctl.control & CTL_POSIX) != 0 ||+ (dat_datctl.control & CTL_ZERO_TERMINATE) != 0)? CU2BYTES(1) : 0;+pp = memmove(dbuffer + dbuffer_size - (len + c), dbuffer, len + c);+#ifdef SUPPORT_VALGRIND+VALGRIND_MAKE_MEM_NOACCESS(dbuffer, dbuffer_size - (len + c));+#endif++#if defined(EBCDIC) && !EBCDIC_IO+ascii_to_ebcdic_str(pp, len);+#endif++/* Now pp points to the subject string, but if null_subject was specified, set+it to NULL to test PCRE2's behaviour. */++if ((dat_datctl.control2 & CTL2_NULL_SUBJECT) != 0) pp = NULL;++/* POSIX matching is only possible in 8-bit mode, and it does not support+timing or other fancy features. Some were checked at compile time, but we need+to check the match-time settings here. */++#if PCRE2_CODE_UNIT_WIDTH == 8+if ((pat_patctl.control & CTL_POSIX) != 0)+ {+ int rc;+ int eflags = 0;+ regmatch_t *pmatch = NULL;+ regmatch_t startend_buf;+ const char *msg = "** Ignored with POSIX interface:";++ if (dat_datctl.cerror[0] != CFORE_UNSET || dat_datctl.cerror[1] != CFORE_UNSET)+ prmsg(&msg, "callout_error");+ if (dat_datctl.cfail[0] != CFORE_UNSET || dat_datctl.cfail[1] != CFORE_UNSET)+ prmsg(&msg, "callout_fail");+ if (dat_datctl.copy_numbers[0] >= 0 || dat_datctl.copy_names[0] != 0)+ prmsg(&msg, "copy");+ if (dat_datctl.get_numbers[0] >= 0 || dat_datctl.get_names[0] != 0)+ prmsg(&msg, "get");+ if (dat_datctl.jitstack != 0) prmsg(&msg, "jitstack");+ if (dat_datctl.offset != 0) prmsg(&msg, "offset");++ if ((dat_datctl.options & ~POSIX_SUPPORTED_MATCH_OPTIONS) != 0)+ {+ cfprintf(clr_test_error, outfile, "%s", msg);+ show_match_options(clr_test_error, 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)+ {+ show_controls(clr_test_error, dat_datctl.control & ~POSIX_SUPPORTED_MATCH_CONTROLS,+ dat_datctl.control2 & ~POSIX_SUPPORTED_MATCH_CONTROLS2, msg);+ msg = "";+ }++ if (msg[0] == 0) fprintf(outfile, "\n");++ if (dat_datctl.oveccount > 0)+ {+ pmatch = (regmatch_t *)malloc(sizeof(regmatch_t) * dat_datctl.oveccount);+ if (pmatch == NULL)+ {+ cfprintf(clr_test_error, outfile, "** Failed to get memory for recording matching "+ "information (size set = %du)\n", dat_datctl.oveccount);+ return PR_ABEND;+ }+ }++ if (dat_datctl.startend[0] != CFORE_UNSET)+ {+ if (pmatch == NULL) pmatch = &startend_buf;+ pmatch[0].rm_so = (regoff_t)dat_datctl.startend[0];+ pmatch[0].rm_eo = (dat_datctl.startend[1] != 0)?+ (regoff_t)dat_datctl.startend[1] : (regoff_t)len;+ eflags |= REG_STARTEND;+ }++ if ((dat_datctl.options & PCRE2_NOTBOL) != 0) eflags |= REG_NOTBOL;+ if ((dat_datctl.options & PCRE2_NOTEOL) != 0) eflags |= REG_NOTEOL;+ if ((dat_datctl.options & PCRE2_NOTEMPTY) != 0) eflags |= REG_NOTEMPTY;++ rc = regexec(&preg, (const char *)pp, dat_datctl.oveccount, pmatch, eflags);+ if (rc != 0)+ {+ size_t usize = regerror(rc, &preg, (char *)pbuffer8, pbuffer8_size);+ cfprintf(clr_api_error, outfile, "No match: POSIX code %d: ", rc);+ pchars(clr_api_error, (PCRE2_SPTR8)pbuffer8, usize - 1, utf, outfile);+ fputs("\n", outfile);+ }+ else if ((pat_patctl.control & CTL_POSIX_NOSUB) != 0)+ fprintf(outfile, "Matched with REG_NOSUB\n");+ else if (dat_datctl.oveccount == 0)+ fprintf(outfile, "Matched without capture\n");+ else+ {+ size_t i, j;+ size_t last_printed = (size_t)dat_datctl.oveccount;+ for (i = 0; i < (size_t)dat_datctl.oveccount; i++)+ {+ if (pmatch[i].rm_so >= 0)+ {+ PCRE2_SIZE start = pmatch[i].rm_so;+ PCRE2_SIZE end = pmatch[i].rm_eo;+ for (j = last_printed + 1; j < i; j++)+ fprintf(outfile, "%2d: <unset>\n", (int)j);+ last_printed = i;+ if (start > end)+ {+ start = pmatch[i].rm_eo;+ end = pmatch[i].rm_so;+ cfprintf(clr_api_error, outfile, "Start of matched string is beyond its end - "+ "displaying from end to start.\n");+ }+ fprintf(outfile, "%2d: ", (int)i);+ pchars(clr_none, pp + start, end - start, utf, outfile);+ fprintf(outfile, "\n");++ if ((i == 0 && (dat_datctl.control & CTL_AFTERTEXT) != 0) ||+ (dat_datctl.control & CTL_ALLAFTERTEXT) != 0)+ {+ fprintf(outfile, "%2d+ ", (int)i);+ /* Note: don't use the start/end variables here because we want to+ show the text from what is reported as the end. */+ pchars(clr_none, pp + pmatch[i].rm_eo, len - pmatch[i].rm_eo, utf, outfile);+ fprintf(outfile, "\n");+ }+ }+ }+ }+ if (pmatch != &startend_buf) free(pmatch);+ return PR_OK;+ }+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */++ /* Handle matching via the native interface. Check for consistency of+modifiers. */++if (dat_datctl.startend[0] != CFORE_UNSET)+ cfprintf(clr_test_error, outfile, "** \\=posix_startend ignored for non-POSIX matching\n");++/* ALLUSEDTEXT is not supported with JIT, but JIT is not used with DFA+matching, even if the JIT compiler was used. */++if ((dat_datctl.control & (CTL_ALLUSEDTEXT|CTL_DFA)) == CTL_ALLUSEDTEXT &&+ compiled_code->executable_jit != NULL)+ {+ cfprintf(clr_test_error, outfile, "** Showing all consulted text is not supported by JIT: ignored\n");+ dat_datctl.control &= ~CTL_ALLUSEDTEXT;+ }++/* Handle passing the subject as zero-terminated. */++if ((dat_datctl.control & CTL_ZERO_TERMINATE) != 0)+ arg_ulen = PCRE2_ZERO_TERMINATED;++/* The nullcontext modifier is used to test calling pcre2_[jit_]match() with a+NULL context. */++use_dat_context = ((dat_datctl.control & CTL_NULLCONTEXT) != 0)?+ NULL : dat_context;++/* Enable display of malloc/free if wanted. We can do this only if either the+pattern or the subject is processed with a context. */++show_memory = (dat_datctl.control & CTL_MEMORY) != 0;++if (show_memory &&+ (pat_patctl.control & dat_datctl.control & CTL_NULLCONTEXT) != 0)+ cfprintf(clr_test_error, outfile, "** \\=memory requires either a pattern or a subject "+ "context: ignored\n");++/* Create and assign a JIT stack if requested. */++if (dat_datctl.jitstack != 0)+ {+ if (dat_datctl.jitstack != jit_stack_size)+ {+ pcre2_jit_stack_free(jit_stack);+ jit_stack = pcre2_jit_stack_create(1, dat_datctl.jitstack * 1024, NULL);+ jit_stack_size = dat_datctl.jitstack;+ }+ pcre2_jit_stack_assign(dat_context, jit_callback, jit_stack);+ }++/* Or de-assign */++else if (jit_stack != NULL)+ {+ pcre2_jit_stack_assign(dat_context, NULL, NULL);+ pcre2_jit_stack_free(jit_stack);+ jit_stack = NULL;+ jit_stack_size = 0;+ }++/* When no JIT stack is assigned, we must ensure that there is a JIT callback+if we want to verify that JIT was actually used. */++if ((pat_patctl.control & CTL_JITVERIFY) != 0 && jit_stack == NULL)+ {+ pcre2_jit_stack_assign(dat_context, jit_callback, NULL);+ }++/* Set up the match callout. The pattern remains in pbuffer8/16/32 after+compilation, for use by the callout. */++if ((dat_datctl.control & CTL_CALLOUT_NONE) == 0)+ {+ pcre2_set_callout(dat_context, callout_function,+ (void *)(&dat_datctl.callout_data));+ }+else+ {+ pcre2_set_callout(dat_context, NULL, NULL); /* No callout */+ }++/* Adjust match_data according to size of offsets required. A size of zero+causes a new match data block to be obtained that exactly fits the pattern. */++if (dat_datctl.oveccount == 0)+ {+ pcre2_match_data_free(match_data);+ match_data = pcre2_match_data_create_from_pattern(compiled_code,+ general_context);+ max_oveccount = pcre2_get_ovector_count(match_data);+ }+else if (dat_datctl.oveccount <= max_oveccount)+ {+ match_data->oveccount = dat_datctl.oveccount;+ }+else+ {+ max_oveccount = dat_datctl.oveccount;+ pcre2_match_data_free(match_data);+ match_data = pcre2_match_data_create(max_oveccount, general_context);+ }++if (match_data == NULL)+ {+ cfprintf(clr_test_error, outfile, "** Failed to get memory for recording matching "+ "information (size requested: %d)\n", dat_datctl.oveccount);+ max_oveccount = 0;+ return PR_ABEND;+ }++ovector = match_data->ovector;+oveccount = pcre2_get_ovector_count(match_data);++/* Helper to clear any cached heap frames from the match_data. */++#define CLEAR_HEAP_FRAMES() \+ do { \+ void *heapframes = (void *)(match_data->heapframes); \+ void *memory_data = match_data->memctl.memory_data; \+ match_data->memctl.free(heapframes, memory_data); \+ match_data->heapframes = NULL; \+ match_data->heapframes_size = 0; \+ } \+ while (0)++/* Replacement processing is ignored for DFA matching. Allow this for+replacements with PCRE2_SUBSTITUTE_MATCHED, even though it won't work, in order+to exercise the error condition. */++if (dat_datctl.replacement[0] != MOD_STR_UNSET &&+ (dat_datctl.control & CTL_DFA) != 0 &&+ (dat_datctl.control2 & CTL2_SUBSTITUTE_MATCHED) == 0)+ {+ cfprintf(clr_test_error, outfile, "** Ignored for DFA matching: replace\n");+ dat_datctl.replacement[0] = MOD_STR_UNSET;+ }++/* 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] != MOD_STR_UNSET)+ {+ int rc;+ uint8_t *pr, *prend;+ PCRE2_UCHAR sbuffer[SUBSTITUTE_SUBJECT_MODSIZE]; /* Staging, not seen by pcre2_substitute() */+ PCRE2_UCHAR *rbptr;+ PCRE2_UCHAR *sbptr;+ uint32_t xoptions;+ uint32_t emoption; /* External match option */+ PCRE2_SIZE j, rlen, full_rlen, nsize, nsize_input, slen;+ pcre2_match_data *smatch_data;++ /* Fill the ovector with junk to detect elements that do not get set+ when they should be (relevant only when "allvector" is specified). */++ for (j = 0; j < 2*oveccount; j++) ovector[j] = JUNK_OFFSET;++ if (timeitm)+ cfprintf(clr_test_error, outfile, "** Timing is not supported with replace: ignored\n");++ if ((dat_datctl.control & CTL_ALTGLOBAL) != 0)+ cfprintf(clr_test_error, outfile, "** Altglobal is not supported with replace: ignored\n");++ /* Check for a test that does substitution after an initial external match.+ If this is set, we run the external match, but leave the interpretation of+ its output to pcre2_substitute(). */++ emoption = ((dat_datctl.control2 & CTL2_SUBSTITUTE_MATCHED) == 0)? 0 :+ PCRE2_SUBSTITUTE_MATCHED;++ if (emoption != 0)+ {+ reset_callout_state();+ if ((dat_datctl.control & CTL_DFA) != 0)+ {+ if (dfa_workspace == NULL)+ dfa_workspace = (int *)malloc(DFA_WS_DIMENSION*sizeof(int));+ dfa_workspace[0] = -1;+ (void)pcre2_dfa_match(compiled_code, pp, arg_ulen,+ dat_datctl.offset, dat_datctl.options, match_data,+ use_dat_context, dfa_workspace, DFA_WS_DIMENSION);+ }+ else if ((pat_patctl.control & CTL_JITFAST) != 0)+ {+ (void)pcre2_jit_match(compiled_code, pp, arg_ulen, dat_datctl.offset,+ dat_datctl.options, match_data, use_dat_context);+ }+ else+ {+ (void)pcre2_match(compiled_code, pp, arg_ulen, dat_datctl.offset,+ dat_datctl.options, match_data, use_dat_context);+ }+ }++ xoptions = emoption |+ (((dat_datctl.control & CTL_GLOBAL) == 0)? 0 :+ PCRE2_SUBSTITUTE_GLOBAL) |+ (((dat_datctl.control2 & CTL2_SUBSTITUTE_EXTENDED) == 0)? 0 :+ PCRE2_SUBSTITUTE_EXTENDED) |+ (((dat_datctl.control2 & CTL2_SUBSTITUTE_LITERAL) == 0)? 0 :+ PCRE2_SUBSTITUTE_LITERAL) |+ (((dat_datctl.control2 & CTL2_SUBSTITUTE_OVERFLOW_LENGTH) == 0)? 0 :+ PCRE2_SUBSTITUTE_OVERFLOW_LENGTH) |+ (((dat_datctl.control2 & CTL2_SUBSTITUTE_REPLACEMENT_ONLY) == 0)? 0 :+ PCRE2_SUBSTITUTE_REPLACEMENT_ONLY) |+ (((dat_datctl.control2 & CTL2_SUBSTITUTE_UNKNOWN_UNSET) == 0)? 0 :+ PCRE2_SUBSTITUTE_UNKNOWN_UNSET) |+ (((dat_datctl.control2 & CTL2_SUBSTITUTE_UNSET_EMPTY) == 0)? 0 :+ PCRE2_SUBSTITUTE_UNSET_EMPTY);++ pr = dat_datctl.replacement+1;+ prend = pr + dat_datctl.replacement[0];++ /* If the replacement starts with '[<number>]' we interpret that as length+ value for the replacement buffer. */++ nsize = rep_out_buffer_size;+ if (pr < prend && *pr == '[')+ {+ PCRE2_SIZE n = 0;+ ++pr;+ for (; pr < prend && (c = *pr) >= '0' && c <= '9'; ++pr)+ n = n * 10 + (c - '0');+ if (pr >= prend || *pr != ']')+ {+ cfprintf(clr_test_error, outfile, "** Bad buffer size in replacement string\n");+ return PR_OK;+ }+ ++pr;+ if (n > nsize)+ {+ cfprintf(clr_test_error, outfile, "** Replacement buffer setting (%" SIZ_FORM ") is too "+ "large (max %" SIZ_FORM ")\n", n, nsize);+ return PR_OK;+ }+ nsize = n;+ }++#ifdef SUPPORT_VALGRIND+ VALGRIND_MAKE_MEM_UNDEFINED(rep_out_buffer, CU2BYTES(nsize));+ VALGRIND_MAKE_MEM_NOACCESS(rep_out_buffer + nsize,+ CU2BYTES(rep_out_buffer_size - nsize));+#endif++ /* Now copy the rest of the replacement string to the buffer. */++#ifdef SUPPORT_VALGRIND+ VALGRIND_MAKE_MEM_UNDEFINED(rep_in_buffer, CU2BYTES(rep_in_buffer_size));+#endif++ copy_substitute_string(utf, pr, prend-pr, rep_in_buffer, &rlen);++#ifdef SUPPORT_VALGRIND+ c = ((dat_datctl.control & CTL_ZERO_TERMINATE) != 0)? 1 : 0;+ VALGRIND_MAKE_MEM_NOACCESS(rep_in_buffer + rlen + c,+ CU2BYTES(rep_in_buffer_size - rlen + c));+#endif++ full_rlen = rlen;+ if ((dat_datctl.control & CTL_ZERO_TERMINATE) != 0)+ rlen = PCRE2_ZERO_TERMINATED;+ rbptr = ((dat_datctl.control2 & CTL2_NULL_REPLACEMENT) == 0)? rep_in_buffer : NULL;++ /* If the substitute_subject modifier is set, then we will modify the+ subject in between the call to pcre2_match and pcre2_substitute. */++ sbptr = pp;+ slen = arg_ulen;++ if (dat_datctl.substitute_subject[0] != MOD_STR_UNSET)+ {+ copy_substitute_string(utf, dat_datctl.substitute_subject+1,+ dat_datctl.substitute_subject[0], sbuffer, &slen);++ /* The buffer pointed to by pp has exactly the correct length (butted up+ against the end of the memory allocation) so it would be possible but+ awkward to extend the subject. However, since pcre2_substitute() won't allow+ changing the length of the subject, and also early-exits if the subject+ pointer changes, we can test all the branches just by supporting shrinking+ the subject. */+ if (slen > ulen)+ {+ cfprintf(clr_test_error, outfile, "** substitute_subject is longer than match subject buffer\n");+ return PR_OK;+ }++ /* In the null-subject case, there's no need to copy. */+ if (pp != NULL)+ {+ memcpy(pp, sbuffer, CU2BYTES(slen));+ if (slen < ulen) ((PCRE2_UCHAR *)pp)[slen] = 0;++ /* If we shrank the subject, adjust the Valgrind readable area. */+#ifdef SUPPORT_VALGRIND+ c = ((dat_datctl.control & CTL_ZERO_TERMINATE) != 0)? 1 : 0;+ VALGRIND_MAKE_MEM_NOACCESS((uint8_t *)pp + CU2BYTES(slen+c),+ (dbuffer + dbuffer_size) - ((uint8_t *)pp + CU2BYTES(slen+c)));+#endif+ }++ if ((dat_datctl.control & CTL_ZERO_TERMINATE) != 0)+ slen = PCRE2_ZERO_TERMINATED;+ }++ /* Set up the required callouts and context, and call pcre2_substitute(). */++ smatch_data = ((CTL2_NULL_SUBSTITUTE_MATCH_DATA & dat_datctl.control2) == 0)?+ match_data : NULL;++ if ((dat_datctl.control2 & CTL2_SUBSTITUTE_CALLOUT) != 0)+ {+ pcre2_set_substitute_callout(dat_context, substitute_callout_function, NULL);+ }+ else+ {+ pcre2_set_substitute_callout(dat_context, NULL, NULL); /* No callout */+ }++ if ((dat_datctl.control2 & CTL2_SUBSTITUTE_CASE_CALLOUT) != 0)+ {+ pcre2_set_substitute_case_callout(dat_context, substitute_case_callout_function, NULL);+ }+ else+ {+ pcre2_set_substitute_case_callout(dat_context, NULL, NULL); /* No callout */+ }++ if (malloc_testing) CLEAR_HEAP_FRAMES();+ reset_callout_state();+ nsize_input = nsize;+ rc = pcre2_substitute(compiled_code, sbptr, slen, dat_datctl.offset,+ dat_datctl.options|xoptions, smatch_data, use_dat_context,+ rbptr, rlen, rep_out_buffer, &nsize);++ /* For malloc testing, we repeat the substitution. */++ if (malloc_testing && (dat_datctl.control2 & CTL2_SUBSTITUTE_CALLOUT) == 0)+ {+ for (int i = 0, target_mallocs = mallocs_called; i <= target_mallocs; i++)+ {+ FILE *saved_outfile = outfile;+ CLEAR_HEAP_FRAMES();+ reset_callout_state();+ mallocs_until_failure = i;+ outfile = NULL; /* Suppress callout output during the malloc repetitions */+ nsize = nsize_input;+ rc = pcre2_substitute(compiled_code, sbptr, slen, dat_datctl.offset,+ dat_datctl.options|xoptions, smatch_data, use_dat_context,+ rbptr, rlen, rep_out_buffer, &nsize);+ mallocs_until_failure = INT_MAX;+ outfile = saved_outfile;++ if (i < target_mallocs && rc != PCRE2_ERROR_NOMEMORY)+ {+ cfprintf(clr_test_error, outfile, "** malloc() Substitution test did not fail as expected (%d)\n",+ rc);+ return PR_ABEND;+ }+ }+ }++ if (rc < 0)+ {+ cfprintf(clr_api_error, outfile, "Failed: error %d", rc);+ if (rc != PCRE2_ERROR_NOMEMORY && nsize != PCRE2_UNSET)+ cfprintf(clr_api_error, outfile, " at offset %ld in replacement", (long int)nsize);+ cfprintf(clr_api_error, outfile, ": ");+ if (!print_error_message(rc, "", "")) return PR_ABEND;+ if (rc == PCRE2_ERROR_NOMEMORY &&+ (xoptions & PCRE2_SUBSTITUTE_OVERFLOW_LENGTH) != 0)+ cfprintf(clr_api_error, outfile, ": %ld code units are needed", (long int)nsize);++ if (rc != PCRE2_ERROR_NOMEMORY && nsize != PCRE2_UNSET)+ {+ cfprintf(clr_api_error, outfile, "\n here: ");+ if (nsize > 0)+ {+ ptrunc(clr_input, rbptr, full_rlen, nsize, TRUE, utf, outfile);+ fprintf(outfile, " ");+ }+ cfprintf(clr_api_error, outfile, "|<--|");+ if (nsize < full_rlen)+ {+ fprintf(outfile, " ");+ ptrunc(clr_input, rbptr, full_rlen, nsize, FALSE, utf, outfile);+ }+ }+ }+ else+ {+ cfprintf(clr_api_error, outfile, "%2d: ", rc);+ pchars(clr_api_error, rep_out_buffer, nsize, utf, outfile);+ }++ fprintf(outfile, "\n");+ show_memory = FALSE;++ /* 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 */++/* When a replacement string is not provided, run a loop for global matching+with one of the basic matching functions. */++for (gmatched = 0;; gmatched++)+ {+ PCRE2_SIZE j;+ int capcount;++ /* Fill the ovector with junk to detect elements that do not get set+ when they should be. */++ for (j = 0; j < 2*oveccount; j++) ovector[j] = JUNK_OFFSET;++ /* When matching is via pcre2_match(), we will detect the use of JIT via the+ stack callback function. */++ jit_was_used = (pat_patctl.control & CTL_JITFAST) != 0;++ /* Do timing if required. */++ if (timeitm > 0)+ {+ int i;+ clock_t start_time, time_taken;+ FILE *saved_outfile = outfile;++ outfile = NULL; /* Suppress callout output during the timing repetitions */++ if ((dat_datctl.control & CTL_DFA) != 0)+ {+ if ((dat_datctl.options & PCRE2_DFA_RESTART) != 0)+ {+ outfile = saved_outfile;+ cfprintf(clr_test_error, outfile, "** Timing DFA restarts is not supported\n");+ return PR_ABEND;+ }+ if (dfa_workspace == NULL)+ dfa_workspace = (int *)malloc(DFA_WS_DIMENSION*sizeof(int));+ start_time = clock();+ for (i = 0; i < timeitm; i++)+ {+ (void)pcre2_dfa_match(compiled_code, pp, arg_ulen,+ dat_datctl.offset, dat_datctl.options | g_notempty, match_data,+ use_dat_context, dfa_workspace, DFA_WS_DIMENSION);+ }+ }++ else if ((pat_patctl.control & CTL_JITFAST) != 0)+ {+ start_time = clock();+ for (i = 0; i < timeitm; i++)+ {+ (void)pcre2_jit_match(compiled_code, pp, arg_ulen,+ dat_datctl.offset, dat_datctl.options | g_notempty, match_data,+ use_dat_context);+ }+ }++ else+ {+ start_time = clock();+ for (i = 0; i < timeitm; i++)+ {+ (void)pcre2_match(compiled_code, pp, arg_ulen,+ dat_datctl.offset, dat_datctl.options | g_notempty, match_data,+ use_dat_context);+ }+ }+ total_match_time += (time_taken = clock() - start_time);++ outfile = saved_outfile;+ cfprintf(clr_profiling, 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|CTL_FINDLIMITS_NOHEAP)) != 0)+ {+ if ((dat_datctl.control & CTL_FINDLIMITS_NOHEAP) == 0 &&+ (compiled_code->executable_jit == NULL ||+ (dat_datctl.options & PCRE2_NO_JIT) != 0))+ {+ (void)check_match_limit(pp, arg_ulen, PCRE2_ERROR_HEAPLIMIT, "heap");+ }++ capcount = check_match_limit(pp, arg_ulen, PCRE2_ERROR_MATCHLIMIT,+ "match");++ if (compiled_code->executable_jit == NULL ||+ (dat_datctl.options & PCRE2_NO_JIT) != 0 ||+ (dat_datctl.control & CTL_DFA) != 0)+ {+ capcount = check_match_limit(pp, arg_ulen, PCRE2_ERROR_DEPTHLIMIT,+ "depth");+ }++ if (capcount == 0)+ {+ cfprintf(clr_api_error, outfile, "Matched, but offsets vector is too small to show all matches\n");+ capcount = dat_datctl.oveccount;+ }+ }++ /* Otherwise just run a single match. */++ else+ {+ /* Run a single DFA or NFA match. */++ if (malloc_testing) CLEAR_HEAP_FRAMES();+ reset_callout_state();+ if ((dat_datctl.control & CTL_DFA) != 0)+ {+ if (dfa_workspace == NULL)+ dfa_workspace = (int *)malloc(DFA_WS_DIMENSION*sizeof(int));+ if (dfa_matched++ == 0)+ dfa_workspace[0] = -1; /* To catch bad restart */+ capcount = pcre2_dfa_match(compiled_code, pp, arg_ulen,+ dat_datctl.offset, dat_datctl.options | g_notempty, match_data,+ use_dat_context, dfa_workspace, DFA_WS_DIMENSION);+ if (capcount == 0)+ {+ cfprintf(clr_api_error, outfile, "Matched, but offsets vector is too small to show all matches\n");+ capcount = dat_datctl.oveccount;+ }+ }+ else+ {+ if ((pat_patctl.control & CTL_JITFAST) != 0)+ capcount = pcre2_jit_match(compiled_code, pp, arg_ulen, dat_datctl.offset,+ dat_datctl.options | g_notempty, match_data, use_dat_context);+ else+ capcount = pcre2_match(compiled_code, pp, arg_ulen, dat_datctl.offset,+ dat_datctl.options | g_notempty, match_data, use_dat_context);+ if (capcount == 0)+ {+ cfprintf(clr_api_error, outfile, "Matched, but too many substrings\n");+ capcount = dat_datctl.oveccount;+ }+ }++ /* For malloc testing, we repeat the matching. */++ if (malloc_testing && (dat_datctl.control & CTL_CALLOUT_NONE) != 0)+ {+ for (int i = 0, target_mallocs = mallocs_called; i <= target_mallocs; i++)+ {+ FILE *saved_outfile = outfile;++ CLEAR_HEAP_FRAMES();+ reset_callout_state();++ mallocs_until_failure = i;+ outfile = NULL; /* Suppress callout output during the malloc repetitions */++ if ((dat_datctl.control & CTL_DFA) != 0)+ {+ if (dfa_matched++ == 0)+ dfa_workspace[0] = -1; /* To catch bad restart */+ capcount = pcre2_dfa_match(compiled_code, pp, arg_ulen,+ dat_datctl.offset, dat_datctl.options | g_notempty, match_data,+ use_dat_context, dfa_workspace, DFA_WS_DIMENSION);+ }+ else+ {+ if ((pat_patctl.control & CTL_JITFAST) != 0)+ capcount = pcre2_jit_match(compiled_code, pp, arg_ulen, dat_datctl.offset,+ dat_datctl.options | g_notempty, match_data, use_dat_context);+ else+ capcount = pcre2_match(compiled_code, pp, arg_ulen, dat_datctl.offset,+ dat_datctl.options | g_notempty, match_data, use_dat_context);+ }++ mallocs_until_failure = INT_MAX;+ outfile = saved_outfile;++ if (capcount == 0)+ capcount = dat_datctl.oveccount;++ if (i < target_mallocs && capcount != PCRE2_ERROR_NOMEMORY)+ {+ cfprintf(clr_test_error, outfile, "** malloc() match test did not fail as expected (%d)\n",+ capcount);+ return PR_ABEND;+ }+ }+ }+ }++ /* Verify that it's safe to call pcre2_next_match with rc < 0. */++ if (capcount < 0 && (dat_datctl.control & CTL_ANYGLOB) != 0)+ {+ BOOL rc_nextmatch;+ PCRE2_SIZE tmp_offset = 0xcd;+ uint32_t tmp_options = 0xcd;+ rc_nextmatch = pcre2_next_match(match_data, &tmp_offset, &tmp_options);+ if (rc_nextmatch || tmp_offset != 0xcd || tmp_options != 0xcd)+ {+ cfprintf(clr_test_error, outfile, "** unexpected pcre2_next_match() for rc < 0\n");+ return PR_ABEND;+ }+ }++ /* The result of the match is now in capcount. First handle a successful+ match. If pp was forced to be NULL (to test NULL handling) it will have been+ treated as an empty string if the length was zero. So, re-create that for+ outputting, preserving the invariant that pp is a valid pointer to a region+ of length len followed by a null. */++ if (capcount >= 0)+ {+ if (pp == NULL)+ {+#ifdef SUPPORT_VALGRIND+ /* Mark the start of dbuffer addressable again. */+ VALGRIND_MAKE_MEM_UNDEFINED(dbuffer, CU2BYTES(1));+#endif+ pp = (PCRE2_UCHAR *)dbuffer;+ *pp = 0;+ }++ if ((unsigned)capcount > oveccount) /* Check for lunatic return value */+ {+ cfprintf(clr_test_error, outfile,+ "** PCRE2 error: returned count %d is too big for ovector count %d\n",+ capcount, oveccount);+ return PR_ABEND;+ }++ /* If PCRE2_COPY_MATCHED_SUBJECT was set, check that things are as they+ should be, but not for fast JIT, where it isn't supported. */++ if ((dat_datctl.options & PCRE2_COPY_MATCHED_SUBJECT) != 0 &&+ (pat_patctl.control & CTL_JITFAST) == 0)+ {+ if ((match_data->flags & PCRE2_MD_COPIED_SUBJECT) == 0)+ cfprintf(clr_test_error, outfile,+ "** PCRE2 error: flag not set after copy_matched_subject\n");++ if (match_data->subject == pp)+ cfprintf(clr_test_error, outfile,+ "** PCRE2 error: copy_matched_subject has not copied\n");++ if (memcmp(match_data->subject, pp, ulen) != 0)+ cfprintf(clr_test_error, outfile,+ "** PCRE2 error: copy_matched_subject mismatch\n");+ }++ /* If this is not the first time round a global loop, check that the+ returned string has advanced.++ There is one known case where this doesn't happen: when you have a+ "badly-behaved" pattern which uses \K in a lookaround, and breaks the core+ sanity rule that start_offset <= ovector[0] <= ovector[1]. An example would+ be /(?<=\Ka)/g matching "aaa".+ * first attempt, start_offset=0: ovector[0]=0, ovector[1]=1+ * second attempt, start_offset=1: ovector[0]=0, ovector[1]=1++ You can see that even though we *always* ensure that start_offset advances,+ this doesn't guarantee to avoid duplicate matches.++ The pcre2test behaviour is to return all the matches found, except in the+ case where two adjacent matches are an exact duplicate. */++ if (gmatched > 0 &&+ !(dat_datctl.offset <= ovector[0] && ovector[0] <= ovector[1]) &&+ pp + ovector[0] == ovecsave[0] && pp + ovector[1] == ovecsave[1])+ {+ cfprintf(clr_api_error, outfile, "global repeat returned the same match as previous\n");+ goto NEXT_MATCH;+ }++ /* Outside of this exceptional case, we check that either we have a+ "badly-behaved" match (note that not all badly-behaved matches are caught+ above, only *duplicate* ones); or else in the well-behaved case the match+ must make progress.++ "Progress" is measured as ovector[1] strictly advancing, or, an empty match+ after a non-empty match. */++ if (gmatched > 0 &&+ (dat_datctl.offset <= ovector[0] && ovector[0] <= ovector[1]) &&+ !(pp + ovector[1] > ovecsave[1] ||+ (ovector[1] == ovector[0] && ovecsave[1] != ovecsave[0] &&+ pp + ovector[1] == ovecsave[1])))+ {+ cfprintf(clr_test_error, outfile,+ "** PCRE2 error: global repeat did not make progress\n");+ return PR_ABEND;+ }++ ovecsave[0] = pp + ovector[0];+ ovecsave[1] = pp + ovector[1];++ /* "allcaptures" requests showing of all captures in the pattern, to check+ unset ones at the end. It may be set on the pattern or the data. Implement+ by setting capcount to the maximum. This is not relevant for DFA matching,+ so ignore it (warning given above). */++ if ((dat_datctl.control & (CTL_ALLCAPTURES|CTL_DFA)) == CTL_ALLCAPTURES)+ {+ capcount = maxcapcount + 1; /* Allow for full match */+ if ((unsigned)capcount > oveccount) capcount = oveccount;+ }++ /* "allvector" request showing the entire ovector. */++ if ((dat_datctl.control2 & CTL2_ALLVECTOR) != 0) capcount = oveccount;++ /* Output the captured substrings. Note that, for the matched string,+ the use of \K in an assertion can make the start later than the end. */++ for (int i = 0; i < 2*capcount; i += 2)+ {+ PCRE2_SIZE lleft, lmiddle, lright;+ PCRE2_SIZE start = ovector[i];+ PCRE2_SIZE end = ovector[i+1];++ if (start > end)+ {+ start = ovector[i+1];+ end = ovector[i];+ cfprintf(clr_api_error, outfile, "Start of matched string is beyond its end - "+ "displaying from end to start.\n");+ }++ fprintf(outfile, "%2d: ", i/2);++ /* Check for an unset group */++ if (start == PCRE2_UNSET && end == PCRE2_UNSET)+ {+ fprintf(outfile, "<unset>\n");+ continue;+ }++ /* Check for silly offsets, in particular, values that have not been+ set when they should have been. However, if we are past the end of the+ captures for this pattern ("allvector" causes this), or if we are DFA+ matching, it isn't an error if the entry is unchanged. */++ if (start > ulen || end > ulen)+ {+ if (((dat_datctl.control & CTL_DFA) != 0 ||+ i >= (int)(2*maxcapcount + 2)) &&+ start == JUNK_OFFSET && end == JUNK_OFFSET)+ fprintf(outfile, "<unchanged>\n");+ else+ cfprintf(clr_test_error, outfile, "** ERROR: bad value(s) for offset(s): 0x%lx 0x%lx\n",+ (unsigned long int)start, (unsigned long int)end);+ continue;+ }++ /* When JIT is not being used, ALLUSEDTEXT may be set. (It if is set with+ JIT, it is disabled above, with a comment.) When the match is done by the+ interpreter, leftchar and rightchar are available, and if ALLUSEDTEXT is+ set, and if the leftmost consulted character is before the start of the+ match or the rightmost consulted character is past the end of the match,+ we want to show all consulted characters for the main matched string, and+ indicate which were lookarounds. */++ if (i == 0)+ {+ BOOL showallused;+ PCRE2_SIZE leftchar, rightchar;++ if ((dat_datctl.control & CTL_ALLUSEDTEXT) != 0)+ {+ leftchar = match_data->leftchar;+ rightchar = match_data->rightchar;+ showallused = i == 0 && (leftchar < start || rightchar > end);+ }+ else showallused = FALSE;++ if (showallused)+ {+ lleft = pchars(clr_none, pp + leftchar, start - leftchar, utf, outfile);+ lmiddle = pchars(clr_none, pp + start, end - start, utf, outfile);+ lright = pchars(clr_none, pp + end, rightchar - end, utf, outfile);+ if ((pat_patctl.control & CTL_JITVERIFY) != 0 && jit_was_used)+ fprintf(outfile, " (JIT)");+ fprintf(outfile, "\n ");+ for (j = 0; j < lleft; j++) fprintf(outfile, "<");+ for (j = 0; j < lmiddle; j++) fprintf(outfile, " ");+ for (j = 0; j < lright; j++) fprintf(outfile, ">");+ }++ /* When a pattern contains \K, the start of match position may be+ different to the start of the matched string. When this is the case,+ show it when requested. */++ else if ((dat_datctl.control & CTL_STARTCHAR) != 0)+ {+ PCRE2_SIZE startchar;+ startchar = pcre2_get_startchar(match_data);+ lleft = pchars(clr_none, pp + startchar, start - startchar, utf, outfile);+ pchars(clr_none, pp+start, end - start, utf, outfile);+ if ((pat_patctl.control & CTL_JITVERIFY) != 0 && jit_was_used)+ fprintf(outfile, " (JIT)");+ if (startchar != start)+ {+ fprintf(outfile, "\n ");+ for (j = 0; j < lleft; j++) fprintf(outfile, "^");+ }+ }++ /* Otherwise, just show the matched string. */++ else+ {+ pchars(clr_none, pp + start, end - start, utf, outfile);+ if ((pat_patctl.control & CTL_JITVERIFY) != 0 && jit_was_used)+ fprintf(outfile, " (JIT)");+ }+ }++ /* Not the main matched string. Just show it unadorned. */++ else+ {+ pchars(clr_none, pp + start, end - start, utf, outfile);+ }++ fprintf(outfile, "\n");++ /* Note: don't use the start/end variables here because we want to+ show the text from what is reported as the end. */++ if ((dat_datctl.control & CTL_ALLAFTERTEXT) != 0 ||+ (i == 0 && (dat_datctl.control & CTL_AFTERTEXT) != 0))+ {+ fprintf(outfile, "%2d+ ", i/2);+ pchars(clr_none, pp + ovector[i+1], ulen - ovector[i+1], utf, outfile);+ fprintf(outfile, "\n");+ }+ }++ /* Output (*MARK) data if requested */++ if ((dat_datctl.control & CTL_MARK) != 0 &&+ match_data->mark != NULL)+ {+ fprintf(outfile, "MK: ");+ pchars(clr_none, match_data->mark - 1, -1, utf, outfile);+ fprintf(outfile, "\n");+ }++ /* Process copy/get strings */++ if (!copy_and_get(utf, capcount)) return PR_ABEND;++ } /* End of handling a successful match */++ /* There was a partial match. The value of ovector[0] is the bumpalong point,+ that is, startchar, not any \K point that might have been passed. When JIT is+ not in use, "allusedtext" may be set, in which case we indicate the leftmost+ consulted character. */++ else if (capcount == PCRE2_ERROR_PARTIAL)+ {+ PCRE2_SIZE leftchar;+ int backlength;+ int rubriclength = 0;++ if ((dat_datctl.control & CTL_ALLUSEDTEXT) != 0)+ {+ leftchar = match_data->leftchar;+ }+ else leftchar = ovector[0];++ cfprintf(clr_api_error, outfile, "Partial match");+ if ((dat_datctl.control & CTL_MARK) != 0 &&+ match_data->mark != NULL)+ {+ fprintf(outfile, ", mark=");+ rubriclength = pchars(clr_none, match_data->mark - 1, -1, utf, outfile);+ rubriclength += 7;+ }+ fprintf(outfile, ": ");+ rubriclength += 15;++ backlength = pchars(clr_input, pp + leftchar, ovector[0] - leftchar, utf, outfile);+ pchars(clr_input, pp + ovector[0], ovector[1] - ovector[0], utf, outfile);++ if ((pat_patctl.control & CTL_JITVERIFY) != 0 && jit_was_used)+ fprintf(outfile, " (JIT)");+ fprintf(outfile, "\n");++ if (backlength != 0)+ {+ for (int i = 0; i < rubriclength; i++) fprintf(outfile, " ");+ for (int i = 0; i < backlength; i++) fprintf(outfile, "<");+ fprintf(outfile, "\n");+ }++ if (ulen != ovector[1])+ cfprintf(clr_test_error, outfile, "** ovector[1] is not equal to the subject length: "+ "%ld != %ld\n", (unsigned long int)ovector[1], (unsigned long int)ulen);++ /* Process copy/get strings */++ if (!copy_and_get(utf, 1)) return PR_ABEND;++ /* "allvector" outputs the entire vector */++ if ((dat_datctl.control2 & CTL2_ALLVECTOR) != 0)+ show_ovector(ovector, oveccount);++ break; /* Out of the /g loop */+ } /* End of handling partial match */++ /* A "normal" match failure. There will be a negative error number in+ capcount. */++ else+ {+ switch(capcount)+ {+ case PCRE2_ERROR_NOMATCH:+ if (gmatched == 0)+ {+ cfprintf(clr_api_error, outfile, "No match");+ if ((dat_datctl.control & CTL_MARK) != 0 &&+ match_data->mark != NULL)+ {+ fprintf(outfile, ", mark = ");+ pchars(clr_none, match_data->mark - 1, -1, utf, outfile);+ }+ if ((pat_patctl.control & CTL_JITVERIFY) != 0 && jit_was_used)+ fprintf(outfile, " (JIT)");+ fprintf(outfile, "\n");++ /* "allvector" outputs the entire vector */++ if ((dat_datctl.control2 & CTL2_ALLVECTOR) != 0)+ show_ovector(ovector, oveccount);+ }+ break;++ case PCRE2_ERROR_BADUTFOFFSET:+ cfprintf(clr_api_error, outfile, "Error %d (bad UTF-" STR(PCRE2_CODE_UNIT_WIDTH)+ " offset)\n", capcount);+ break;++ default:+ cfprintf(clr_api_error, outfile, "Failed: error %d: ", capcount);+ if (!print_error_message(capcount, "", "")) return PR_ABEND;+ if (capcount <= PCRE2_ERROR_UTF8_ERR1 &&+ capcount >= PCRE2_ERROR_UTF32_ERR2)+ {+ PCRE2_SIZE startchar;+ startchar = pcre2_get_startchar(match_data);+ cfprintf(clr_api_error, outfile, " at offset %" SIZ_FORM, startchar);+ }+ fprintf(outfile, "\n");+ break;+ }++ break; /* Out of the /g loop */+ } /* End of failed match handling */++ /* Control reaches here after a match. If we are not doing a global search,+ we are done. Otherwise, we adjust the parameters for the next match and+ continue the matching loop. */++ NEXT_MATCH:++ if ((dat_datctl.control & CTL_ANYGLOB) == 0)+ break;+ else+ {+ PCRE2_SIZE new_start_offset = (PCRE2_SIZE)-1;+ BOOL rc_nextmatch;++ /* Use pcre2_next_match() to safely advance. This guarantees that the start+ offset will advance, except after an empty match, in which case it sets+ the PCRE2_NOTEMPTY_ATSTART flag to ensure the next match does not return a+ duplicate. */++ rc_nextmatch = pcre2_next_match(match_data, &new_start_offset, &g_notempty);+ if (!rc_nextmatch) break; /* Out of the /g loop */++ /* For a normal global (/g) iteration, update the start offset, leaving+ other parameters alone. */++ if ((dat_datctl.control & CTL_GLOBAL) != 0)+ {+ dat_datctl.offset = new_start_offset;+ }++ /* For altglobal, just update the pointer and length. */++ else+ {+ pp += new_start_offset;+ len -= CU2BYTES(new_start_offset);+ ulen -= new_start_offset;+ if (arg_ulen != PCRE2_ZERO_TERMINATED) arg_ulen -= new_start_offset;+ }+ }+ } /* 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;+}++++/*************************************************+* Initialise the mode-dependent globals *+*************************************************/++/* Sets up the global variables used for the current test mode. */++static void+init_globals(void)+{+general_context = pcre2_general_context_create(&my_malloc, &my_free, NULL);+general_context_copy = pcre2_general_context_copy(general_context);+default_pat_context = pcre2_compile_context_create(general_context);+pat_context = pcre2_compile_context_copy(default_pat_context);+default_dat_context = pcre2_match_context_create(general_context);+dat_context = pcre2_match_context_copy(default_dat_context);+default_con_context = pcre2_convert_context_create(general_context);+con_context = pcre2_convert_context_copy(default_con_context);+match_data = pcre2_match_data_create(max_oveccount, general_context);+rep_in_buffer = malloc(sizeof(PCRE2_UCHAR) * rep_in_buffer_size);+rep_out_buffer = malloc(sizeof(PCRE2_UCHAR) * rep_out_buffer_size);++/* Set a default parentheses nest limit that is large enough to run the+standard tests (this also exercises the function). */++pcre2_set_parens_nest_limit(default_pat_context, PARENS_NEST_DEFAULT);+}++/* Frees the global variables used for the current test mode. */++static void+free_globals(void)+{+pcre2_maketables_free(general_context, locale_tables);+pcre2_match_data_free(match_data);+pcre2_code_free(compiled_code);++while(patstacknext-- > 0)+ {+ compiled_code = patstack[patstacknext];+ pcre2_code_free(compiled_code);+ }++pcre2_jit_free_unused_memory(general_context);+if (jit_stack != NULL)+ {+ pcre2_jit_stack_free(jit_stack);+ }++pcre2_general_context_free(general_context);+pcre2_general_context_free(general_context_copy);+pcre2_compile_context_free(pat_context);+pcre2_compile_context_free(default_pat_context);+pcre2_match_context_free(dat_context);+pcre2_match_context_free(default_dat_context);+pcre2_convert_context_free(default_con_context);+pcre2_convert_context_free(con_context);+free(rep_in_buffer);+free(rep_out_buffer);+}++++/*************************************************+* Specific function tests *+*************************************************/++/* For tests exercising a mismatched bitmode, identify a suitable API. */++#if (defined(SUPPORT_PCRE2_8) + defined(SUPPORT_PCRE2_16) + \+ defined(SUPPORT_PCRE2_32)) >= 2++#if defined(SUPPORT_PCRE2_8) && PCRE2_CODE_UNIT_WIDTH != 8+#define BITOTHER 8+#elif defined(SUPPORT_PCRE2_16) && PCRE2_CODE_UNIT_WIDTH != 16+#define BITOTHER 16+#elif defined(SUPPORT_PCRE2_32) && PCRE2_CODE_UNIT_WIDTH != 32+#define BITOTHER 32+#else+#error "One other bit width must be supported"+#endif++#endif++/* These are tests of the public API functions in PCRE2, which wouldn't+otherwise be covered by pcre2test. This usually implies they are error cases,+or edge cases that are hard to hit in the standard flow of compile-match or+compile-substitute.++I think of them as perhaps more like unit tests, although they are still testing+the public API, rather than internal modules.++Inside pcre2test, which can be dynamically linked to lib-pcreX.so, we don't+have access to any non-exported functions. */++static void+unittest(void)+{+int rc;+uint32_t uval;+PCRE2_SIZE sizeval;+PCRE2_UCHAR *sptrval;+const char *failure = NULL;+pcre2_general_context *test_gen_context = NULL, *test_gen_context_copy = NULL;+pcre2_compile_context *test_pat_context = NULL, *test_pat_context_copy = NULL;+pcre2_match_context *test_dat_context = NULL, *test_dat_context_copy = NULL;+pcre2_convert_context *test_con_context = NULL, *test_con_context_copy = NULL;+pcre2_match_data *test_match_data = NULL;+pcre2_code *test_compiled_code = NULL;+PCRE2_UCHAR pattern[] = { CHAR_A, CHAR_B, CHAR_C, 0 };+PCRE2_UCHAR callout_int_pattern[] = {+ CHAR_LEFT_PARENTHESIS, CHAR_QUESTION_MARK, CHAR_C, CHAR_RIGHT_PARENTHESIS, 0 };+PCRE2_UCHAR callout_str_pattern[] = {+ CHAR_LEFT_PARENTHESIS, CHAR_QUESTION_MARK, CHAR_C, CHAR_QUOTATION_MARK,+ CHAR_Z, CHAR_QUOTATION_MARK, CHAR_RIGHT_PARENTHESIS, 0 };+PCRE2_UCHAR capture_pattern[] = {+ CHAR_A, CHAR_LEFT_PARENTHESIS, CHAR_QUESTION_MARK, CHAR_LESS_THAN_SIGN,+ CHAR_N, CHAR_GREATER_THAN_SIGN, CHAR_DOT, CHAR_ASTERISK,+ CHAR_RIGHT_PARENTHESIS, CHAR_Z, 0 };+PCRE2_UCHAR subject_abcz[] = {+ CHAR_A, CHAR_B, CHAR_C, CHAR_Z, 0 };+PCRE2_UCHAR substitute_subject[6];+PCRE2_UCHAR name_n[] = { CHAR_N, 0 };+#ifdef BITOTHER+G(pcre2_code_,BITOTHER) *bitother_code = NULL;+G(PCRE2_,G(UCHAR,BITOTHER)) bitother_pattern[] = { CHAR_A, CHAR_B, CHAR_C, 0 };+#endif+int errorcode;+PCRE2_SIZE erroroffset;+PCRE2_UCHAR errorbuffer[256];+#if PCRE2_CODE_UNIT_WIDTH == 8+char errorbuffer8[256];+regex_t test_preg;+#endif+void *invalid_code = NULL;+const uint8_t *test_tables = NULL;+PCRE2_UCHAR copy_buf[64];+PCRE2_UCHAR **stringlist;+PCRE2_SIZE *lengthslist;+PCRE2_UCHAR replace_buf[64];+pcre2_code *subs_other_code = NULL;++#if PCRE2_CODE_UNIT_WIDTH == 8+memset(&test_preg, 0, sizeof(test_preg));+#endif++#if defined PCRE2_DEBUG && !defined NDEBUG+#define ASSERT(cond, msg) \+ do { \+ if (!(cond)) { failure = msg " at " __FILE__ ":" STR(__LINE__); goto EXIT; } \+ } while (0)+#else+#define ASSERT(cond, msg) \+ do { \+ if (!(cond)) { failure = msg; goto EXIT; } \+ } while (0)+#endif++/* -------------------------- pcre2_config --------------------------------- */++rc = pcre2_config(PCRE2_CONFIG_BSR, NULL);+ASSERT(rc == (int)sizeof(uint32_t), "pcre2_config(NULL)");+rc = pcre2_config(PCRE2_CONFIG_COMPILED_WIDTHS, NULL);+ASSERT(rc == (int)sizeof(uint32_t), "pcre2_config(NULL)");+rc = pcre2_config(PCRE2_CONFIG_DEPTHLIMIT, NULL);+ASSERT(rc == (int)sizeof(uint32_t), "pcre2_config(NULL)");+rc = pcre2_config(PCRE2_CONFIG_EFFECTIVE_LINKSIZE, NULL);+ASSERT(rc == (int)sizeof(uint32_t), "pcre2_config(NULL)");+rc = pcre2_config(PCRE2_CONFIG_HEAPLIMIT, NULL);+ASSERT(rc == (int)sizeof(uint32_t), "pcre2_config(NULL)");+rc = pcre2_config(PCRE2_CONFIG_JIT, NULL);+ASSERT(rc == (int)sizeof(uint32_t), "pcre2_config(NULL)");+rc = pcre2_config(PCRE2_CONFIG_LINKSIZE, NULL);+ASSERT(rc == (int)sizeof(uint32_t), "pcre2_config(NULL)");+rc = pcre2_config(PCRE2_CONFIG_MATCHLIMIT, NULL);+ASSERT(rc == (int)sizeof(uint32_t), "pcre2_config(NULL)");+rc = pcre2_config(PCRE2_CONFIG_NEVER_BACKSLASH_C, NULL);+ASSERT(rc == (int)sizeof(uint32_t), "pcre2_config(NULL)");+rc = pcre2_config(PCRE2_CONFIG_NEWLINE, NULL);+ASSERT(rc == (int)sizeof(uint32_t), "pcre2_config(NULL)");+rc = pcre2_config(PCRE2_CONFIG_PARENSLIMIT, NULL);+ASSERT(rc == (int)sizeof(uint32_t), "pcre2_config(NULL)");+rc = pcre2_config(PCRE2_CONFIG_STACKRECURSE, NULL);+ASSERT(rc == (int)sizeof(uint32_t), "pcre2_config(NULL)");+rc = pcre2_config(PCRE2_CONFIG_TABLES_LENGTH, NULL);+ASSERT(rc == (int)sizeof(uint32_t), "pcre2_config(NULL)");+rc = pcre2_config(PCRE2_CONFIG_UNICODE, NULL);+ASSERT(rc == (int)sizeof(uint32_t), "pcre2_config(NULL)");++#ifdef SUPPORT_JIT+rc = pcre2_config(PCRE2_CONFIG_JITTARGET, NULL);+ASSERT(rc > 0, "pcre2_config(NULL)");+#endif+rc = pcre2_config(PCRE2_CONFIG_UNICODE_VERSION, NULL);+ASSERT(rc > 4, "pcre2_config(NULL)");+rc = pcre2_config(PCRE2_CONFIG_VERSION, NULL);+ASSERT(rc > 4, "pcre2_config(NULL)");++rc = pcre2_config(PCRE2_CONFIG_MATCHLIMIT, &uval);+ASSERT(rc == 0, "pcre2_config(PCRE2_CONFIG_MATCHLIMIT)");++rc = pcre2_config(999, NULL);+ASSERT(rc == PCRE2_ERROR_BADOPTION, "pcre2_config(bad option)");++rc = pcre2_config(999, &uval);+ASSERT(rc == PCRE2_ERROR_BADOPTION, "pcre2_config(bad option)");++rc = pcre2_config(PCRE2_CONFIG_STACKRECURSE, &uval);+ASSERT(rc == 0, "pcre2_config(PCRE2_CONFIG_STACKRECURSE)");++rc = pcre2_config(PCRE2_CONFIG_LINKSIZE, &uval);+ASSERT(rc == 0, "pcre2_config(PCRE2_CONFIG_LINKSIZE)");++/* ------------------------ Context functions ------------------------------ */++test_gen_context = pcre2_general_context_create(NULL, NULL, NULL);+ASSERT(test_gen_context != NULL, "pcre2_general_context_create(null)");+pcre2_general_context_free(test_gen_context);++mallocs_until_failure = 0;+test_gen_context = pcre2_general_context_create(&my_malloc, &my_free, NULL);+ASSERT(test_gen_context == NULL, "pcre2_general_context_create(malloc)");++mallocs_until_failure = 1;+test_gen_context = pcre2_general_context_create(&my_malloc, &my_free, NULL);+ASSERT(test_gen_context != NULL, "pcre2_general_context_create(malloc)");++test_pat_context = pcre2_compile_context_create(test_gen_context);+ASSERT(test_pat_context == NULL, "pcre2_compile_context_create()");+test_dat_context = pcre2_match_context_create(test_gen_context);+ASSERT(test_dat_context == NULL, "pcre2_match_context_create()");+test_con_context = pcre2_convert_context_create(test_gen_context);+ASSERT(test_con_context == NULL, "pcre2_convert_context_create()");++test_pat_context = pcre2_compile_context_create(NULL);+ASSERT(test_pat_context != NULL, "pcre2_compile_context_create(null)");+pcre2_compile_context_free(test_pat_context);+test_dat_context = pcre2_match_context_create(NULL);+ASSERT(test_dat_context != NULL, "pcre2_match_context_create(null)");+pcre2_match_context_free(test_dat_context);+test_con_context = pcre2_convert_context_create(NULL);+ASSERT(test_con_context != NULL, "pcre2_convert_context_create(null)");+pcre2_convert_context_free(test_con_context);++mallocs_until_failure = INT_MAX;+test_pat_context = pcre2_compile_context_create(test_gen_context);+ASSERT(test_pat_context != NULL, "pcre2_compile_context_create()");+test_dat_context = pcre2_match_context_create(test_gen_context);+ASSERT(test_dat_context != NULL, "pcre2_match_context_create()");+test_con_context = pcre2_convert_context_create(test_gen_context);+ASSERT(test_con_context != NULL, "pcre2_convert_context_create()");++mallocs_until_failure = 0;+test_gen_context_copy = pcre2_general_context_copy(test_gen_context);+ASSERT(test_gen_context_copy == NULL, "pcre2_general_context_copy()");+test_pat_context_copy = pcre2_compile_context_copy(test_pat_context);+ASSERT(test_pat_context_copy == NULL, "pcre2_compile_context_copy()");+test_dat_context_copy = pcre2_match_context_copy(test_dat_context);+ASSERT(test_dat_context_copy == NULL, "pcre2_match_context_copy()");+test_con_context_copy = pcre2_convert_context_copy(test_con_context);+ASSERT(test_con_context_copy == NULL, "pcre2_convert_context_copy()");++mallocs_until_failure = INT_MAX;+test_gen_context_copy = pcre2_general_context_copy(test_gen_context);+ASSERT(test_gen_context_copy != NULL, "pcre2_general_context_copy()");+test_pat_context_copy = pcre2_compile_context_copy(test_pat_context);+ASSERT(test_pat_context_copy != NULL, "pcre2_compile_context_copy()");+test_dat_context_copy = pcre2_match_context_copy(test_dat_context);+ASSERT(test_dat_context_copy != NULL, "pcre2_match_context_copy()");+test_con_context_copy = pcre2_convert_context_copy(test_con_context);+ASSERT(test_con_context_copy != NULL, "pcre2_convert_context_copy()");++rc = pcre2_set_compile_extra_options(test_pat_context, 0);+ASSERT(rc == 0, "pcre2_set_compile_extra_options()");++rc = pcre2_set_max_pattern_length(test_pat_context, 10);+ASSERT(rc == 0, "pcre2_set_max_pattern_length()");++rc = pcre2_set_max_pattern_compiled_length(test_pat_context, 256);+ASSERT(rc == 0, "pcre2_set_max_pattern_compiled_length()");++rc = pcre2_set_max_varlookbehind(test_pat_context, 0);+ASSERT(rc == 0, "pcre2_set_max_varlookbehind()");++rc = pcre2_set_offset_limit(test_dat_context, 0);+ASSERT(rc == 0, "pcre2_set_offset_limit()");++rc = pcre2_set_bsr(test_pat_context, 999);+ASSERT(rc == PCRE2_ERROR_BADDATA, "pcre2_set_bsr()");++rc = pcre2_set_newline(test_pat_context, 999);+ASSERT(rc == PCRE2_ERROR_BADDATA, "pcre2_set_newline()");++rc = pcre2_set_recursion_limit(test_dat_context, 10);+ASSERT(rc == 0, "pcre2_set_recursion_limit()");++rc = pcre2_set_recursion_memory_management(test_dat_context, NULL, NULL, NULL);+ASSERT(rc == 0, "pcre2_set_recursion_memory_management()");++rc = pcre2_set_optimize(NULL, PCRE2_OPTIMIZATION_NONE);+ASSERT(rc == PCRE2_ERROR_NULL, "pcre2_set_optimize(null)");++rc = pcre2_set_optimize(test_pat_context, PCRE2_AUTO_POSSESS - 1);+ASSERT(rc == PCRE2_ERROR_BADOPTION, "pcre2_set_optimize(bad option)");++rc = pcre2_set_optimize(test_pat_context, PCRE2_START_OPTIMIZE_OFF + 1);+ASSERT(rc == PCRE2_ERROR_BADOPTION, "pcre2_set_optimize(bad option)");++rc = pcre2_set_glob_escape(test_con_context, 0);+ASSERT(rc == 0, "pcre2_set_glob_escape(0)");++rc = pcre2_set_glob_escape(test_con_context, 1);+ASSERT(rc == PCRE2_ERROR_BADDATA, "pcre2_set_glob_escape(1)");++rc = pcre2_set_glob_escape(test_con_context, 256);+ASSERT(rc == PCRE2_ERROR_BADDATA, "pcre2_set_glob_escape(256)");++/* ----------------------- pcre2_compile ----------------------------------- */++test_compiled_code = pcre2_compile(pattern, PCRE2_ZERO_TERMINATED,+ 0, NULL, &erroroffset, test_pat_context);+ASSERT(test_compiled_code == NULL, "test pattern compilation");++test_compiled_code = pcre2_compile(pattern, PCRE2_ZERO_TERMINATED,+ 0, &errorcode, NULL, test_pat_context);+ASSERT(test_compiled_code == NULL && errorcode == PCRE2_ERROR_NULL_ERROROFFSET, "test pattern compilation");++test_compiled_code = pcre2_compile(pattern, PCRE2_ZERO_TERMINATED,+ 0, &errorcode, &erroroffset, test_pat_context);+ASSERT(test_compiled_code != NULL && errorcode == 100 && erroroffset == 0, "test pattern compilation");++#ifdef BITOTHER+bitother_code = G(pcre2_compile_,BITOTHER)(bitother_pattern,+ PCRE2_ZERO_TERMINATED, 0, &errorcode, &erroroffset, NULL);+ASSERT(bitother_code != NULL, "bitmode mismatch compile");+#endif++/* ---------------------- Match data functions ----------------------------- */++mallocs_until_failure = 0;+test_match_data = pcre2_match_data_create(10, test_gen_context);+ASSERT(test_match_data == NULL, "pcre2_match_data_create()");++test_match_data = pcre2_match_data_create(10, NULL);+ASSERT(test_match_data != NULL, "pcre2_match_data_create()");+ASSERT(pcre2_get_ovector_count(test_match_data) == 10, "pcre2_get_ovector_count()");++sizeval = pcre2_get_match_data_size(test_match_data);+ASSERT(sizeval >= 2, "pcre2_get_match_data_size()");++mallocs_until_failure = INT_MAX;++pcre2_match_data_free(test_match_data);+test_match_data = pcre2_match_data_create(0, test_gen_context);+ASSERT(test_match_data != NULL, "pcre2_match_data_create()");+ASSERT(pcre2_get_ovector_count(test_match_data) == 1, "pcre2_get_ovector_count()");++pcre2_match_data_free(test_match_data);+test_match_data = pcre2_match_data_create_from_pattern(NULL, NULL);+ASSERT(test_match_data == NULL, "pcre2_match_data_create_from_pattern(null)");++test_match_data = pcre2_match_data_create_from_pattern(test_compiled_code, NULL);+ASSERT(test_match_data != NULL, "pcre2_match_data_create_from_pattern()");+ASSERT(pcre2_get_ovector_count(test_match_data) == 1, "pcre2_get_ovector_count()");++mallocs_until_failure = 0;+pcre2_match_data_free(test_match_data);+test_match_data = pcre2_match_data_create_from_pattern(test_compiled_code,+ test_gen_context);+ASSERT(test_match_data == NULL, "pcre2_match_data_create_from_pattern()");++mallocs_until_failure = INT_MAX;+pcre2_match_data_free(test_match_data);+test_match_data = pcre2_match_data_create_from_pattern(test_compiled_code,+ test_gen_context);+ASSERT(test_match_data != NULL, "pcre2_match_data_create_from_pattern()");++rc = pcre2_match(test_compiled_code, pattern, PCRE2_ZERO_TERMINATED, 0,+ PCRE2_COPY_MATCHED_SUBJECT, test_match_data, NULL);+ASSERT(rc == 1, "pcre2_match()");++pcre2_match_data_free(test_match_data);+test_match_data = NULL;++/* ----------------------- pcre2_pattern_info ------------------------------ */++rc = pcre2_pattern_info(NULL, PCRE2_INFO_NEWLINE, &uval);+ASSERT(rc == PCRE2_ERROR_NULL, "pcre2_pattern_info(null)");++rc = pcre2_pattern_info(test_compiled_code, 999, NULL);+ASSERT(rc == PCRE2_ERROR_BADOPTION, "pcre2_pattern_info(bad option)");++rc = pcre2_pattern_info(test_compiled_code, 999, &uval);+ASSERT(rc == PCRE2_ERROR_BADOPTION, "pcre2_pattern_info(bad option)");++invalid_code = malloc(1024);+ASSERT(invalid_code != NULL, "malloc()");+memset(invalid_code, 0, 1024);+rc = pcre2_pattern_info(invalid_code, PCRE2_INFO_NEWLINE, &uval);+ASSERT(rc == PCRE2_ERROR_BADMAGIC, "pcre2_pattern_info(bad magic)");++#ifdef BITOTHER+rc = pcre2_pattern_info((pcre2_code *)bitother_code, PCRE2_INFO_NEWLINE, &uval);+ASSERT(rc == PCRE2_ERROR_BADMODE, "pcre2_pattern_info(bitmode mismatch)");+#endif++#ifdef SUPPORT_JIT+sizeval = 0xcdcdcdcd;+rc = pcre2_pattern_info(test_compiled_code, PCRE2_INFO_JITSIZE, &sizeval);+ASSERT(rc == 0 && sizeval == 0, "pcre2_pattern_info(JIT)");++if (pcre2_jit_compile(test_compiled_code, PCRE2_JIT_COMPLETE) == 0)+ {+ rc = pcre2_pattern_info(test_compiled_code, PCRE2_INFO_JITSIZE, &sizeval);+ ASSERT(rc == 0 && sizeval > 0, "pcre2_pattern_info(JIT after compile)");+ }+#endif++/* ----------------------- POSIX functions --------------------------------- */++#if PCRE2_CODE_UNIT_WIDTH == 8++#if defined(EBCDIC) && !EBCDIC_IO+#define BUFFER_OUTPUT ebcdic_to_ascii_str((uint8_t *)errorbuffer8, sizeof(errorbuffer8));+#else+#define BUFFER_OUTPUT+#endif++rc = pcre2_regcomp(&test_preg, "abc", 0);+ASSERT(rc == 0, "pcre2_regcomp()");++rc = pcre2_regexec(&test_preg, "zabcz", 0, NULL, 0);+ASSERT(rc == 0, "pcre2_regexec(0)");++rc = pcre2_regexec(&test_preg, "zabcz", 0, NULL, REG_STARTEND);+ASSERT(rc == REG_INVARG, "pcre2_regexec(REG_STARTEND)");++memset(errorbuffer8, 0, sizeof(errorbuffer8));+rc = regerror(REG_ASSERT, NULL, errorbuffer8, sizeof(errorbuffer8));+BUFFER_OUTPUT+ASSERT(rc > 0 && rc <= (int)sizeof(errorbuffer8) && rc == (int)strlen(errorbuffer8) + 1, "regerror()");++rc = regerror(REG_NOMATCH, NULL, errorbuffer8, sizeof(errorbuffer8));+BUFFER_OUTPUT+ASSERT(rc > 0 && rc <= (int)sizeof(errorbuffer8) && rc == (int)strlen(errorbuffer8) + 1, "regerror()");++rc = regerror(REG_ASSERT-1, NULL, errorbuffer8, sizeof(errorbuffer8));+BUFFER_OUTPUT+ASSERT(rc == (int)strlen("unknown error code")+1 && strcmp(errorbuffer8, "unknown error code") == 0, "regerror(bad error code)");++rc = regerror(REG_NOMATCH+1, NULL, errorbuffer8, sizeof(errorbuffer8));+BUFFER_OUTPUT+ASSERT(rc == (int)strlen("unknown error code")+1 && strcmp(errorbuffer8, "unknown error code") == 0, "regerror(bad error code)");++#undef BUFFER_OUTPUT++#endif++/* -------------------- pcre2_get_error_message ---------------------------- */++#if defined(EBCDIC) && !EBCDIC_IO+#define BUFFER_OUTPUT ebcdic_to_ascii_str(errorbuffer, sizeof(errorbuffer));+#else+#define BUFFER_OUTPUT+#endif++rc = pcre2_get_error_message(PCRE2_ERROR_BADDATA, NULL, 0);+ASSERT(rc == PCRE2_ERROR_NOMEMORY, "pcre2_get_error_message(null)");++memset(errorbuffer, 0, sizeof(errorbuffer));+rc = pcre2_get_error_message(PCRE2_ERROR_BADDATA, errorbuffer, 0);+BUFFER_OUTPUT+ASSERT(rc == PCRE2_ERROR_NOMEMORY, "pcre2_get_error_message(null)");++rc = pcre2_get_error_message(PCRE2_ERROR_BADDATA, errorbuffer, 4);+BUFFER_OUTPUT+ASSERT(rc == PCRE2_ERROR_NOMEMORY && pcre2_strcmp_c8(errorbuffer, "bad") == 0, "pcre2_get_error_message(null)");++rc = pcre2_get_error_message(PCRE2_ERROR_BADDATA, errorbuffer, 14);+BUFFER_OUTPUT+ASSERT(rc == PCRE2_ERROR_NOMEMORY && pcre2_strcmp_c8(errorbuffer, "bad data valu") == 0, "pcre2_get_error_message(null)");++rc = pcre2_get_error_message(PCRE2_ERROR_BADDATA, errorbuffer, 15);+BUFFER_OUTPUT+ASSERT(rc == 14 && pcre2_strcmp_c8(errorbuffer, "bad data value") == 0, "pcre2_get_error_message(null)");++#undef BUFFER_OUTPUT++/* ----------------------- pcre2_maketables -------------------------------- */++test_tables = pcre2_maketables(NULL);+ASSERT(test_tables != NULL, "pcre2_maketables(null)");+pcre2_maketables_free(NULL, test_tables);++test_tables = pcre2_maketables(test_gen_context);+ASSERT(test_tables != NULL, "pcre2_maketables()");+pcre2_maketables_free(test_gen_context, test_tables);++mallocs_until_failure = 0;+test_tables = pcre2_maketables(test_gen_context);+ASSERT(test_tables == NULL, "pcre2_maketables()");++mallocs_until_failure = INT_MAX;++/* -------------------- pcre2_callout_enumerate ---------------------------- */++rc = pcre2_callout_enumerate(NULL, callout_enumerate_function_void, NULL);+ASSERT(rc == PCRE2_ERROR_NULL, "pcre2_callout_enumerate(null)");++rc = pcre2_callout_enumerate(invalid_code, callout_enumerate_function_void, NULL);+ASSERT(rc == PCRE2_ERROR_BADMAGIC, "pcre2_callout_enumerate(invalid)");++#ifdef BITOTHER+rc = pcre2_callout_enumerate((pcre2_code *)bitother_code, callout_enumerate_function_void, NULL);+ASSERT(rc == PCRE2_ERROR_BADMODE, "pcre2_callout_enumerate(bitmode mismatch)");+#endif++pcre2_code_free(test_compiled_code);+test_compiled_code = pcre2_compile(callout_int_pattern, PCRE2_ZERO_TERMINATED,+ 0, &errorcode, &erroroffset, NULL);+ASSERT(test_compiled_code != NULL, "test pattern compilation");++rc = pcre2_callout_enumerate(test_compiled_code, callout_enumerate_function_void, &errorcode);+ASSERT(rc == 0, "pcre2_callout_enumerate(void)");++errorcode = -12;+rc = pcre2_callout_enumerate(test_compiled_code, callout_enumerate_function_fail, &errorcode);+ASSERT(rc == -12, "pcre2_callout_enumerate(fail)");++pcre2_code_free(test_compiled_code);+test_compiled_code = pcre2_compile(callout_str_pattern, PCRE2_ZERO_TERMINATED,+ 0, &errorcode, &erroroffset, NULL);+ASSERT(test_compiled_code != NULL, "test pattern compilation");++errorcode = -123;+rc = pcre2_callout_enumerate(test_compiled_code, callout_enumerate_function_fail, &errorcode);+ASSERT(rc == -123, "pcre2_callout_enumerate(fail)");++/* ---------------------- Substring functions ------------------------------ */++/* Must handle NULL without crashing. */+pcre2_substring_free(NULL);+pcre2_substring_list_free(NULL);++pcre2_code_free(test_compiled_code);+test_compiled_code = pcre2_compile(capture_pattern, PCRE2_ZERO_TERMINATED,+ 0, &errorcode, &erroroffset, NULL);+ASSERT(test_compiled_code != NULL, "test pattern compilation");++pcre2_match_data_free(test_match_data);+test_match_data = pcre2_match_data_create_from_pattern(+ test_compiled_code, test_gen_context);+ASSERT(test_match_data != NULL, "pcre2_match_data_create()");++rc = pcre2_match(test_compiled_code, subject_abcz, PCRE2_ZERO_TERMINATED, 0,+ 0, test_match_data, NULL);+ASSERT(rc == 2, "pcre2_match()");++/* Test the functions with insufficient buffer size. It hardly seems worth+adding controls to the pcre2test input file format to exercise this case. */++sizeval = 2;+rc = pcre2_substring_copy_byname(test_match_data, name_n, copy_buf, &sizeval);+ASSERT(rc == PCRE2_ERROR_NOMEMORY && sizeval == 2, "pcre2_substring_copy_byname(small buffer)");+sizeval = 3;+rc = pcre2_substring_copy_byname(test_match_data, name_n, copy_buf, &sizeval);+ASSERT(rc == 0 && sizeval == 2, "pcre2_substring_copy_byname(small buffer)");+sizeval = 4;+rc = pcre2_substring_copy_byname(test_match_data, name_n, copy_buf, &sizeval);+ASSERT(rc == 0 && sizeval == 2, "pcre2_substring_copy_byname(small buffer)");++sizeval = 2;+rc = pcre2_substring_copy_bynumber(test_match_data, 1, copy_buf, &sizeval);+ASSERT(rc == PCRE2_ERROR_NOMEMORY && sizeval == 2, "pcre2_substring_copy_bynumber(small buffer)");+sizeval = 3;+rc = pcre2_substring_copy_bynumber(test_match_data, 1, copy_buf, &sizeval);+ASSERT(rc == 0 && sizeval == 2, "pcre2_substring_copy_bynumber(small buffer)");++mallocs_until_failure = 0;++sizeval = 0;+sptrval = NULL;+rc = pcre2_substring_get_byname(test_match_data, name_n, &sptrval, &sizeval);+ASSERT(rc == PCRE2_ERROR_NOMEMORY && sptrval == NULL, "pcre2_substring_get_byname(small buffer)");++sizeval = 0;+rc = pcre2_substring_get_bynumber(test_match_data, 1, &sptrval, &sizeval);+ASSERT(rc == PCRE2_ERROR_NOMEMORY && sptrval == NULL, "pcre2_substring_get_bynumber(small buffer)");++mallocs_until_failure = INT_MAX;++/* Test some unusual conditions, for which again it doesn't seem worth adding+pcre2test controls. */++sizeval = 0;+rc = pcre2_substring_length_bynumber(test_match_data, 1, &sizeval);+ASSERT(rc == 0 && sizeval == 2, "pcre2_substring_length_bynumber()");+rc = pcre2_substring_length_bynumber(test_match_data, 1, NULL);+ASSERT(rc == 0, "pcre2_substring_length_bynumber()");++sizeval = 0;+rc = pcre2_substring_length_byname(test_match_data, name_n, &sizeval);+ASSERT(rc == 0 && sizeval == 2, "pcre2_substring_length_byname()");+rc = pcre2_substring_length_byname(test_match_data, name_n, NULL);+ASSERT(rc == 0, "pcre2_substring_length_byname()");++/* Test pcre2_substring_list_get() with some NULL inputs. */++rc = pcre2_substring_list_get(test_match_data, &stringlist, &lengthslist);+ASSERT(rc == 0 && stringlist != NULL && lengthslist != NULL, "pcre2_substring_list_get()");+pcre2_substring_list_free(stringlist);++stringlist = NULL;+rc = pcre2_substring_list_get(test_match_data, &stringlist, NULL);+ASSERT(rc == 0 && stringlist != NULL, "pcre2_substring_list_get()");+pcre2_substring_list_free(stringlist);++mallocs_until_failure = 0;++stringlist = NULL;+rc = pcre2_substring_list_get(test_match_data, &stringlist, &lengthslist);+ASSERT(rc == PCRE2_ERROR_NOMEMORY && stringlist == NULL, "pcre2_substring_list_get()");++mallocs_until_failure = INT_MAX;++/* Test after an unsuccessful match. */++rc = pcre2_match(test_compiled_code, subject_abcz, PCRE2_ZERO_TERMINATED, 2,+ 0, test_match_data, NULL);+ASSERT(rc == PCRE2_ERROR_NOMATCH, "pcre2_match()");++sizeval = 4;+rc = pcre2_substring_copy_byname(test_match_data, name_n, copy_buf, &sizeval);+ASSERT(rc == PCRE2_ERROR_NOMATCH, "pcre2_substring_copy_byname(no match)");+rc = pcre2_substring_copy_bynumber(test_match_data, 1, copy_buf, &sizeval);+ASSERT(rc == PCRE2_ERROR_NOMATCH, "pcre2_substring_copy_bynumber(no match)");+rc = pcre2_substring_get_byname(test_match_data, name_n, &sptrval, &sizeval);+ASSERT(rc == PCRE2_ERROR_NOMATCH && sptrval == NULL, "pcre2_substring_get_byname(no match)");+rc = pcre2_substring_get_bynumber(test_match_data, 1, &sptrval, &sizeval);+ASSERT(rc == PCRE2_ERROR_NOMATCH && sptrval == NULL, "pcre2_substring_get_bynumber(no match)");++/* ------------- pcre2_substitute with PCRE2_SUBSTITUTE_MATCHED ------------ */++/* There are some specific edge cases here that would be a pain to exercise via+the standard pcre2test modifiers. The documentation is clear that when you do+a match externally and pass it in with PCRE2_SUBSTITUTE_MATCHED, you must also+pass the same match options. Here we test what happens when you don't. */++pcre2_code_free(test_compiled_code);+test_compiled_code = pcre2_compile(pattern, PCRE2_ZERO_TERMINATED,+ 0, &errorcode, &erroroffset, NULL);+ASSERT(test_compiled_code != NULL, "test pattern compilation");++subs_other_code = pcre2_compile(pattern, PCRE2_ZERO_TERMINATED,+ 0, &errorcode, &erroroffset, NULL);+ASSERT(subs_other_code != NULL, "test pattern compilation");++pcre2_match_data_free(test_match_data);+test_match_data = pcre2_match_data_create_from_pattern(+ test_compiled_code, NULL);+ASSERT(test_match_data != NULL, "pcre2_match_data_create()");++memcpy(substitute_subject, subject_abcz, sizeof(subject_abcz));+rc = pcre2_match(test_compiled_code, substitute_subject, PCRE2_ZERO_TERMINATED,+ 0, 0, test_match_data, NULL);+ASSERT(rc == 1, "pcre2_match()");++/* Baseline, should succeed */+memcpy(substitute_subject, subject_abcz, sizeof(subject_abcz));+sizeval = sizeof(replace_buf)/sizeof(*replace_buf);+rc = pcre2_substitute(test_compiled_code, substitute_subject,+ PCRE2_ZERO_TERMINATED, 0, PCRE2_SUBSTITUTE_MATCHED, test_match_data, NULL,+ NULL, 0, replace_buf, &sizeval);+ASSERT(rc == 1, "pcre2_substitute(baseline)");++/* Move the subject pointer, but keep the contents and length the same */+memcpy(substitute_subject+1, subject_abcz, sizeof(subject_abcz));+sizeval = sizeof(replace_buf)/sizeof(*replace_buf);+rc = pcre2_substitute(test_compiled_code, substitute_subject+1,+ PCRE2_ZERO_TERMINATED, 0, PCRE2_SUBSTITUTE_MATCHED, test_match_data, NULL,+ NULL, 0, replace_buf, &sizeval);+ASSERT(rc == PCRE2_ERROR_DIFFSUBSSUBJECT, "pcre2_substitute(moved)");++/* Keep the subject pointer the same but extend its length */+memcpy(substitute_subject, subject_abcz, sizeof(subject_abcz));+substitute_subject[4] = CHAR_Y;+substitute_subject[5] = 0;+sizeval = sizeof(replace_buf)/sizeof(*replace_buf);+rc = pcre2_substitute(test_compiled_code, substitute_subject,+ PCRE2_ZERO_TERMINATED, 0, PCRE2_SUBSTITUTE_MATCHED, test_match_data, NULL,+ NULL, 0, replace_buf, &sizeval);+ASSERT(rc == PCRE2_ERROR_DIFFSUBSSUBJECT, "pcre2_substitute(extended)");++/* Change the offset */+memcpy(substitute_subject, subject_abcz, sizeof(subject_abcz));+sizeval = sizeof(replace_buf)/sizeof(*replace_buf);+rc = pcre2_substitute(test_compiled_code, substitute_subject,+ PCRE2_ZERO_TERMINATED, 1, PCRE2_SUBSTITUTE_MATCHED, test_match_data, NULL,+ NULL, 0, replace_buf, &sizeval);+ASSERT(rc == PCRE2_ERROR_DIFFSUBSOFFSET, "pcre2_substitute(offset)");++/* Change the options */+memcpy(substitute_subject, subject_abcz, sizeof(subject_abcz));+sizeval = sizeof(replace_buf)/sizeof(*replace_buf);+rc = pcre2_substitute(test_compiled_code, substitute_subject,+ PCRE2_ZERO_TERMINATED, 0, PCRE2_SUBSTITUTE_MATCHED | PCRE2_NOTEMPTY,+ test_match_data, NULL, NULL, 0, replace_buf, &sizeval);+ASSERT(rc == PCRE2_ERROR_DIFFSUBSOPTIONS, "pcre2_substitute(options)");++/* Change the pattern */+memcpy(substitute_subject, subject_abcz, sizeof(subject_abcz));+sizeval = sizeof(replace_buf)/sizeof(*replace_buf);+rc = pcre2_substitute(subs_other_code, substitute_subject,+ PCRE2_ZERO_TERMINATED, 0, PCRE2_SUBSTITUTE_MATCHED, test_match_data, NULL,+ NULL, 0, replace_buf, &sizeval);+ASSERT(rc == PCRE2_ERROR_DIFFSUBSPATTERN, "pcre2_substitute(pattern)");++/* ------------------------------------------------------------------------- */++#undef ASSERT+EXIT:++mallocs_until_failure = INT_MAX;++#if PCRE2_CODE_UNIT_WIDTH == 8+pcre2_regfree(&test_preg);+#endif++if (test_compiled_code != NULL) pcre2_code_free(test_compiled_code);+#ifdef BITOTHER+if (bitother_code != NULL) G(pcre2_code_free_,BITOTHER)(bitother_code);+#endif+if (subs_other_code != NULL) pcre2_code_free(subs_other_code);++if (test_match_data != NULL) pcre2_match_data_free(test_match_data);++if (test_con_context_copy != NULL) pcre2_convert_context_free(test_con_context_copy);+if (test_dat_context_copy != NULL) pcre2_match_context_free(test_dat_context_copy);+if (test_pat_context_copy != NULL) pcre2_compile_context_free(test_pat_context_copy);+if (test_gen_context_copy != NULL) pcre2_general_context_free(test_gen_context_copy);+if (test_con_context != NULL) pcre2_convert_context_free(test_con_context);+if (test_dat_context != NULL) pcre2_match_context_free(test_dat_context);+if (test_pat_context != NULL) pcre2_compile_context_free(test_pat_context);+if (test_gen_context != NULL) pcre2_general_context_free(test_gen_context);++free(invalid_code);++if (failure != NULL)+ {+ cfprintf(clr_test_error, stderr, "pcre2test: Unit test error in %s\n", failure);+ exit(1);+ }+}++#undef BITOTHER+++/* -------------------- Undo the macro definitions --------------------------*/++#undef pbuffer+#undef pbuffer_size++#undef utf_to_ord++#undef compiled_code+#undef general_context+#undef general_context_copy+#undef pat_context+#undef default_pat_context+#undef con_context+#undef default_con_context+#undef dat_context+#undef default_dat_context+#undef match_data+#undef jit_stack+#undef jit_stack_size+#undef patstack+#undef patstacknext+#undef rep_in_buffer+#undef rep_in_buffer_size+#undef rep_out_buffer+#undef rep_out_buffer_size++#undef jit_callback+#undef pcre2_strcmp_c8+#undef pcre2_strlen+#undef pchars+#undef ptrunc+#undef config_str+#undef check_modifier+#undef decode_modifiers+#undef pattern_info+#undef show_memory_info+#undef show_framesize+#undef show_heapframes_size+#undef print_error_message_file+#undef print_error_message+#undef callout_enumerate_function+#undef callout_enumerate_function_void+#undef callout_enumerate_function_fail+#undef show_pattern_info+#undef serial_error+#undef process_command+#undef process_pattern+#undef have_active_pattern+#undef free_active_pattern+#undef check_match_limit+#undef substitute_callout_function+#undef substitute_case_callout_function+#undef callout_function+#undef copy_and_get+#undef copy_substitute_string+#undef process_data+#undef init_globals+#undef free_globals+#undef unittest++++/* End of pcre2test_inc.h */
− src/c/pcre2/src/sljit/allocator_src/sljitExecAllocatorApple.c
@@ -1,137 +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.- */--#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
@@ -1,327 +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 ]-*/--/* 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
@@ -1,89 +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.- */--#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
@@ -1,62 +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.- */--#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
@@ -1,40 +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.- */--#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
@@ -1,72 +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.- */--#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
@@ -1,172 +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.- */--#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
@@ -1,141 +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-- 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
@@ -1,102 +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-- 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
@@ -1,142 +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.- */--#ifndef SLJIT_CONFIG_H_-#define SLJIT_CONFIG_H_--#ifdef __cplusplus-extern "C" {-#endif--/*- This file contains the basic configuration options for the SLJIT compiler- and their default values. These options can be overridden in the- sljitConfigPre.h header file when SLJIT_HAVE_CONFIG_PRE is set to a- non-zero value.-*/--/* --------------------------------------------------------------------- */-/* Utilities */-/* --------------------------------------------------------------------- */--/* Implements a stack like data structure (by using mmap / VirtualAlloc */-/* or a custom allocator). */-#ifndef SLJIT_UTIL_STACK-/* Enabled by default */-#define SLJIT_UTIL_STACK 1-#endif--/* Uses user provided allocator to allocate the stack (see SLJIT_UTIL_STACK) */-#ifndef SLJIT_UTIL_SIMPLE_STACK_ALLOCATION-/* Disabled by default */-#define SLJIT_UTIL_SIMPLE_STACK_ALLOCATION 0-#endif--/* Single threaded application. Does not require any locks. */-#ifndef SLJIT_SINGLE_THREADED-/* Disabled by default. */-#define SLJIT_SINGLE_THREADED 0-#endif--/* --------------------------------------------------------------------- */-/* Configuration */-/* --------------------------------------------------------------------- */--/* If SLJIT_STD_MACROS_DEFINED is not defined, the application should- define SLJIT_MALLOC, SLJIT_FREE, SLJIT_MEMCPY, and NULL. */-#ifndef SLJIT_STD_MACROS_DEFINED-/* Disabled by default. */-#define SLJIT_STD_MACROS_DEFINED 0-#endif--/* Executable code allocation:- If SLJIT_EXECUTABLE_ALLOCATOR is not defined, the application should- 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--/* When SLJIT_PROT_EXECUTABLE_ALLOCATOR is enabled SLJIT uses- an allocator which does not set writable and executable- permission flags at the same time.- Instead, it creates a shared memory segment (usually backed by a file)- and maps it twice, with different permissions, depending on the use- case.- The trade-off is increased use of virtual memory, incompatibility with- fork(), and some possible additional security risks by the use of- publicly accessible files for the generated code. */-#ifndef SLJIT_PROT_EXECUTABLE_ALLOCATOR-/* Disabled by default. */-#define SLJIT_PROT_EXECUTABLE_ALLOCATOR 0-#endif--/* When SLJIT_WX_EXECUTABLE_ALLOCATOR is enabled SLJIT uses an- allocator which does not set writable and executable permission- flags at the same time.- Instead, it creates a new independent map on each invocation and- switches permissions at the underlying pages as needed.- The trade-off is increased memory use and degraded performance. */-#ifndef SLJIT_WX_EXECUTABLE_ALLOCATOR-/* Disabled by default. */-#define SLJIT_WX_EXECUTABLE_ALLOCATOR 0-#endif--#endif /* !SLJIT_EXECUTABLE_ALLOCATOR */--/* Return with error when an invalid argument is passed. */-#ifndef SLJIT_ARGUMENT_CHECKS-/* Disabled by default */-#define SLJIT_ARGUMENT_CHECKS 0-#endif--/* Debug checks (assertions, etc.). */-#ifndef SLJIT_DEBUG-/* Enabled by default */-#define SLJIT_DEBUG 1-#endif--/* Verbose operations. */-#ifndef SLJIT_VERBOSE-/* Enabled by default */-#define SLJIT_VERBOSE 1-#endif--/*- SLJIT_IS_FPU_AVAILABLE- The availability of the FPU can be controlled by SLJIT_IS_FPU_AVAILABLE.- zero value - FPU is NOT present.- nonzero value - FPU is present.-*/--/* For further configurations, see the beginning of sljitConfigInternal.h */--#ifdef __cplusplus-} /* extern "C" */-#endif--#endif /* SLJIT_CONFIG_H_ */
− src/c/pcre2/src/sljit/sljitConfigCPU.h
@@ -1,188 +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.- */--#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
@@ -1,907 +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.- */--#ifndef SLJIT_CONFIG_INTERNAL_H_-#define SLJIT_CONFIG_INTERNAL_H_--#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \- || (defined SLJIT_DEBUG && SLJIT_DEBUG && (!defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE)))-#include <stdio.h>-#endif--#if (defined SLJIT_DEBUG && SLJIT_DEBUG \- && (!defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE) || !defined(SLJIT_HALT_PROCESS)))-#include <stdlib.h>-#endif--#ifdef __cplusplus-extern "C" {-#endif--/*- SLJIT defines the following architecture dependent types and macros:-- Types:- sljit_s8, sljit_u8 : signed and unsigned 8 bit integer type- sljit_s16, sljit_u16 : signed and unsigned 16 bit integer type- sljit_s32, sljit_u32 : signed and unsigned 32 bit integer type- sljit_sw, sljit_uw : signed and unsigned machine word, enough to store a pointer- sljit_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-- Macros for feature detection (boolean):- SLJIT_32BIT_ARCHITECTURE : 32 bit architecture- SLJIT_64BIT_ARCHITECTURE : 64 bit architecture- SLJIT_LITTLE_ENDIAN : little endian architecture- SLJIT_BIG_ENDIAN : big endian architecture- 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:- SLJIT_NUMBER_OF_REGISTERS : number of available registers- SLJIT_NUMBER_OF_SCRATCH_REGISTERS : number of available scratch registers- SLJIT_NUMBER_OF_SAVED_REGISTERS : number of available saved registers- 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- SLJIT_F64_SHIFT : the shift required to apply when accessing- a double precision floating point array by index- SLJIT_PREF_SHIFT_REG : x86 systems prefers ecx for shifting by register- 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-*/--/***********************************************************/-/* Intel Control-flow Enforcement Technology (CET) spport. */-/***********************************************************/--#ifdef SLJIT_CONFIG_X86--#if defined(__CET__) && !(defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET)-#define SLJIT_CONFIG_X86_CET 1-#endif--#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined(__GNUC__)-#include <x86intrin.h>-#endif--#endif /* SLJIT_CONFIG_X86 */--/**********************************/-/* External function definitions. */-/**********************************/--/* General macros:- Note: SLJIT is designed to be independent from them as possible.-- In release mode (SLJIT_DEBUG is not defined) only the following- external functions are needed:-*/--#ifndef SLJIT_MALLOC-#define SLJIT_MALLOC(size, allocator_data) (malloc(size))-#endif--#ifndef SLJIT_FREE-#define SLJIT_FREE(ptr, allocator_data) (free(ptr))-#endif--#ifndef SLJIT_MEMCPY-#define SLJIT_MEMCPY(dest, src, len) (memcpy(dest, src, len))-#endif--#ifndef SLJIT_MEMMOVE-#define SLJIT_MEMMOVE(dest, src, len) (memmove(dest, src, len))-#endif--#ifndef SLJIT_ZEROMEM-#define SLJIT_ZEROMEM(dest, len) (memset(dest, 0, len))-#endif--/***************************/-/* Compiler helper macros. */-/***************************/--#if !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY)--#if defined(__GNUC__) && (__GNUC__ >= 3)-#define SLJIT_LIKELY(x) __builtin_expect((x), 1)-#define SLJIT_UNLIKELY(x) __builtin_expect((x), 0)-#else-#define SLJIT_LIKELY(x) (x)-#define SLJIT_UNLIKELY(x) (x)-#endif--#endif /* !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY) */--#ifndef SLJIT_INLINE-/* Inline functions. Some old compilers do not support them. */-#ifdef __SUNPRO_C-#if __SUNPRO_C < 0x560-#define SLJIT_INLINE-#else-#define SLJIT_INLINE inline-#endif /* __SUNPRO_C */-#else-#define SLJIT_INLINE __inline-#endif-#endif /* !SLJIT_INLINE */--#ifndef SLJIT_NOINLINE-/* Not inline functions. */-#if defined(__GNUC__)-#define SLJIT_NOINLINE __attribute__ ((noinline))-#else-#define SLJIT_NOINLINE-#endif-#endif /* !SLJIT_INLINE */--#ifndef SLJIT_UNUSED_ARG-/* Unused arguments. */-#define SLJIT_UNUSED_ARG(arg) (void)arg-#endif--/*********************************/-/* Type of public API functions. */-/*********************************/--#ifndef SLJIT_API_FUNC_ATTRIBUTE-#if (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC)-/* Static ABI functions. For all-in-one programs. */--#if defined(__GNUC__)-/* Disable unused warnings in gcc. */-#define SLJIT_API_FUNC_ATTRIBUTE static __attribute__((unused))-#else-#define SLJIT_API_FUNC_ATTRIBUTE static-#endif--#else-#define SLJIT_API_FUNC_ATTRIBUTE-#endif /* (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC) */-#endif /* defined SLJIT_API_FUNC_ATTRIBUTE */--/****************************/-/* Instruction cache flush. */-/****************************/--#ifdef __APPLE__-#include <AvailabilityMacros.h>-#endif--/*- * TODO:- *- * clang >= 15 could be safe to enable below- * older versions are known to abort in some targets- * https://github.com/PhilipHazel/pcre2/issues/92- *- * 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__)--/*- * 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 is broken- */-#if !defined(SLJIT_CONFIG_PPC)-#define SLJIT_CACHE_FLUSH(from, to) \- __builtin___clear_cache((char*)(from), (char*)(to))-#endif--#endif /* gcc >= 10 */-#endif /* (!defined SLJIT_CACHE_FLUSH && defined __has_builtin) */--#ifndef SLJIT_CACHE_FLUSH--#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \- || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)--/* Not required to implement on archs with unified caches. */-#define SLJIT_CACHE_FLUSH(from, to)--#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,- although the compilation is successful. */-#include <libkern/OSCacheControl.h>-#define SLJIT_CACHE_FLUSH(from, to) \- sys_icache_invalidate((void*)(from), (size_t)((char*)(to) - (char*)(from)))--#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)--/* The __clear_cache() implementation of GCC is a dummy function on PowerPC. */-#define SLJIT_CACHE_FLUSH(from, to) \- ppc_cache_flush((from), (to))-#define SLJIT_CACHE_FLUSH_OWN_IMPL 1--#elif defined(_WIN32)--#define SLJIT_CACHE_FLUSH(from, to) \- FlushInstructionCache(GetCurrentProcess(), (void*)(from), (char*)(to) - (char*)(from))--#elif (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) || defined(__clang__)--#define SLJIT_CACHE_FLUSH(from, to) \- __builtin___clear_cache((char*)(from), (char*)(to))--#elif defined __ANDROID__--/* Android ARMv7 with gcc lacks __clear_cache; use cacheflush instead. */-#include <sys/cachectl.h>-#define SLJIT_CACHE_FLUSH(from, to) \- cacheflush((long)(from), (long)(to), 0)--#else--/* Call __ARM_NR_cacheflush on ARM-Linux or the corresponding MIPS syscall. */-#define SLJIT_CACHE_FLUSH(from, to) \- __clear_cache((char*)(from), (char*)(to))--#endif--#endif /* !SLJIT_CACHE_FLUSH */--/******************************************************/-/* Integer and floating point type definitions. */-/******************************************************/--/* 8 bit byte type. */-typedef unsigned char sljit_u8;-typedef signed char sljit_s8;--/* 16 bit half-word type. */-typedef unsigned short int sljit_u16;-typedef signed short int sljit_s16;--/* 32 bit integer type. */-typedef unsigned int sljit_u32;-typedef signed int sljit_s32;--/* Machine word type. Enough for storing a pointer.- 32 bit for 32 bit machines.- 64 bit for 64 bit machines. */-#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)-/* Just to have something. */-#define SLJIT_WORD_SHIFT 0-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_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;-typedef int sljit_sw;-#else-#define SLJIT_64BIT_ARCHITECTURE 1-#define SLJIT_WORD_SHIFT 3-#ifdef _WIN32-#ifdef __GNUC__-/* These types do not require windows.h */-typedef unsigned long long sljit_uw;-typedef long long sljit_sw;-#else-typedef unsigned __int64 sljit_uw;-typedef __int64 sljit_sw;-#endif-#else /* !_WIN32 */-typedef unsigned long int sljit_uw;-typedef long int sljit_sw;-#endif /* _WIN32 */-#endif--typedef sljit_sw sljit_sp;-typedef sljit_uw sljit_up;--/* Floating point types. */-typedef float sljit_f32;-typedef double sljit_f64;--/* Shift for pointer sized data. */-#define SLJIT_POINTER_SHIFT SLJIT_WORD_SHIFT--/* Shift for double precision sized data. */-#define SLJIT_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_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)-#ifdef _WIN64-#define SLJIT_W(w) (w##ll)-#else /* !windows */-#define SLJIT_W(w) (w##l)-#endif /* windows */-#else /* 32 bit */-#define SLJIT_W(w) (w)-#endif /* unknown */--#endif /* !SLJIT_W */--/*************************/-/* Endianness detection. */-/*************************/--#if !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN)--/* These macros are mostly useful for the applications. */-#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)--#ifdef __LITTLE_ENDIAN__-#define SLJIT_LITTLE_ENDIAN 1-#else-#define SLJIT_BIG_ENDIAN 1-#endif--#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)--#ifdef __MIPSEL__-#define SLJIT_LITTLE_ENDIAN 1-#else-#define SLJIT_BIG_ENDIAN 1-#endif--#ifndef SLJIT_MIPS_REV--/* 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-#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).- * It also sets the __mips macro to 64 or 32 for -mipsN when N <= 5- * (should be set to N exactly) so we cannot rely on this too.- */-#define SLJIT_MIPS_REV 1-#endif--#endif /* !SLJIT_MIPS_REV */--#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)--#define SLJIT_BIG_ENDIAN 1--#else-#define SLJIT_LITTLE_ENDIAN 1-#endif--#endif /* !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN) */--/* Sanity check. */-#if (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)-#error "Exactly one endianness must be selected"-#endif--#if !(defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && !(defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)-#error "Exactly one endianness must be selected"-#endif--#ifndef SLJIT_UNALIGNED--#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 && 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. */-#define SLJIT_DETECT_SSE2 1-#endif--/*****************************************************************************************/-/* Calling convention of functions generated by SLJIT or called from the generated code. */-/*****************************************************************************************/--#ifndef SLJIT_FUNC-#define SLJIT_FUNC-#endif /* !SLJIT_FUNC */--#ifndef SLJIT_INDIRECT_CALL-#if ((defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) && (!defined _CALL_ELF || _CALL_ELF == 1)) \- || ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && defined _AIX)-/* It seems certain ppc compilers use an indirect addressing for functions- which makes things complicated. */-#define SLJIT_INDIRECT_CALL 1-#endif-#endif /* SLJIT_INDIRECT_CALL */--/* The offset which needs to be subtracted from the return address to-determine the next executed instruction after return. */-#ifndef SLJIT_RETURN_ADDRESS_OFFSET-#define SLJIT_RETURN_ADDRESS_OFFSET 0-#endif /* SLJIT_RETURN_ADDRESS_OFFSET */--/***************************************************/-/* Functions of the built-in executable allocator. */-/***************************************************/--#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)-SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size);-SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr);-SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);-#define SLJIT_BUILTIN_MALLOC_EXEC(size, exec_allocator_data) sljit_malloc_exec(size)-#define SLJIT_BUILTIN_FREE_EXEC(ptr, exec_allocator_data) sljit_free_exec(ptr)--#ifndef SLJIT_MALLOC_EXEC-#define SLJIT_MALLOC_EXEC(size, exec_allocator_data) SLJIT_BUILTIN_MALLOC_EXEC((size), (exec_allocator_data))-#endif /* SLJIT_MALLOC_EXEC */--#ifndef SLJIT_FREE_EXEC-#define SLJIT_FREE_EXEC(ptr, exec_allocator_data) SLJIT_BUILTIN_FREE_EXEC((ptr), (exec_allocator_data))-#endif /* SLJIT_FREE_EXEC */--#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)-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. */-/**********************************************/--#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)--#define SLJIT_NUMBER_OF_REGISTERS 12-#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_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-#define SLJIT_LOCALS_OFFSET_BASE 0-#else /* _WIN64 */-#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8-#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 10-#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-#define SLJIT_MASKED_SHIFT 1-#define SLJIT_MASKED_SHIFT32 1--#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)-/* Add +1 for double alignment. */-#define SLJIT_LOCALS_OFFSET_BASE ((3 + 1) * (sljit_s32)sizeof(sljit_sw))-#else-#define SLJIT_LOCALS_OFFSET_BASE (3 * (sljit_s32)sizeof(sljit_sw))-#endif /* SLJIT_CONFIG_PPC_64 || _AIX */--#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)--#define SLJIT_NUMBER_OF_REGISTERS 21-#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)-#define SLJIT_LOCALS_OFFSET_BASE (4 * (sljit_s32)sizeof(sljit_sw))-#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 13-#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 6-#else-#define SLJIT_LOCALS_OFFSET_BASE 0-#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_RISCV && SLJIT_CONFIG_RISCV)--#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)--/*- * https://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_zSeries.html#STACKFRAME- *- * 160- * .. FR6- * .. FR4- * .. FR2- * 128 FR0- * 120 R15 (used for SP)- * 112 R14- * 104 R13- * 96 R12- * ..- * 48 R6- * ..- * 16 R2- * 8 RESERVED- * 0 SP- */-#define SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE 160--#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--#define SLJIT_LOCALS_OFFSET (SLJIT_LOCALS_OFFSET_BASE)--#define SLJIT_NUMBER_OF_SCRATCH_REGISTERS \- (SLJIT_NUMBER_OF_REGISTERS - SLJIT_NUMBER_OF_SAVED_REGISTERS)--#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. */-/********************************/--#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_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. */-/*************************************/--#if (defined SLJIT_DEBUG && SLJIT_DEBUG)--#if !defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE)--/* SLJIT_HALT_PROCESS must halt the process. */-#ifndef SLJIT_HALT_PROCESS-#define SLJIT_HALT_PROCESS() \- abort();-#endif /* !SLJIT_HALT_PROCESS */--#endif /* !SLJIT_ASSERT || !SLJIT_UNREACHABLE */--/* Feel free to redefine these two macros. */-#ifndef SLJIT_ASSERT--#define SLJIT_ASSERT(x) \- do { \- if (SLJIT_UNLIKELY(!(x))) { \- printf("Assertion failed at " __FILE__ ":%d\n", __LINE__); \- SLJIT_HALT_PROCESS(); \- } \- } while (0)--#endif /* !SLJIT_ASSERT */--#ifndef SLJIT_UNREACHABLE--#define SLJIT_UNREACHABLE() \- do { \- printf("Should never been reached " __FILE__ ":%d\n", __LINE__); \- SLJIT_HALT_PROCESS(); \- } while (0)--#endif /* !SLJIT_UNREACHABLE */--#else /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */--/* Forcing empty, but valid statements. */-#undef SLJIT_ASSERT-#undef SLJIT_UNREACHABLE--#define SLJIT_ASSERT(x) \- do { } while (0)-#define SLJIT_UNREACHABLE() \- do { } while (0)--#endif /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */--#ifndef SLJIT_COMPILE_ASSERT--#define SLJIT_COMPILE_ASSERT(x, description) \- switch(0) { case 0: case ((x) ? 1 : 0): break; }--#endif /* !SLJIT_COMPILE_ASSERT */--#ifdef __cplusplus-} /* extern "C" */-#endif--#endif /* SLJIT_CONFIG_INTERNAL_H_ */
− src/c/pcre2/src/sljit/sljitLir.c
@@ -1,3561 +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.- */--#include "sljitLir.h"--#ifdef _WIN32--#include <windows.h>--#endif /* _WIN32 */--#if !(defined SLJIT_STD_MACROS_DEFINED && SLJIT_STD_MACROS_DEFINED)--/* These libraries are needed for the macros below. */-#include <stdlib.h>-#include <string.h>--#endif /* SLJIT_STD_MACROS_DEFINED */--#define CHECK_ERROR() \- do { \- if (SLJIT_UNLIKELY(compiler->error)) \- return compiler->error; \- } while (0)--#define CHECK_ERROR_PTR() \- do { \- if (SLJIT_UNLIKELY(compiler->error)) \- return NULL; \- } while (0)--#define FAIL_IF(expr) \- do { \- if (SLJIT_UNLIKELY(expr)) \- return compiler->error; \- } while (0)--#define PTR_FAIL_IF(expr) \- do { \- if (SLJIT_UNLIKELY(expr)) \- return NULL; \- } while (0)--#define FAIL_IF_NULL(ptr) \- do { \- if (SLJIT_UNLIKELY(!(ptr))) { \- compiler->error = SLJIT_ERR_ALLOC_FAILED; \- return SLJIT_ERR_ALLOC_FAILED; \- } \- } while (0)--#define PTR_FAIL_IF_NULL(ptr) \- do { \- if (SLJIT_UNLIKELY(!(ptr))) { \- compiler->error = SLJIT_ERR_ALLOC_FAILED; \- return NULL; \- } \- } while (0)--#define PTR_FAIL_WITH_EXEC_IF(ptr) \- do { \- if (SLJIT_UNLIKELY(!(ptr))) { \- compiler->error = SLJIT_ERR_EX_ALLOC_FAILED; \- return NULL; \- } \- } while (0)--#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)--#define SSIZE_OF(type) ((sljit_s32)sizeof(sljit_ ## type))--#define VARIABLE_FLAG_SHIFT (10)-/* 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
@@ -1,2466 +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.- */--#ifndef SLJIT_LIR_H_-#define SLJIT_LIR_H_--/*- ------------------------------------------------------------------------- Stack-Less JIT compiler for multiple architectures (x86, ARM, PowerPC)- -------------------------------------------------------------------------- Short description- 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, 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" */-#endif--#endif /* SLJIT_LIR_H_ */
− src/c/pcre2/src/sljit/sljitNativeARM_32.c
@@ -1,4636 +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.- */--#ifdef __SOFTFP__-#define ARM_ABI_INFO " ABI:softfp"-#else-#define ARM_ABI_INFO " ABI:hardfp"-#endif--SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)-{-#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)- return "ARMv7" SLJIT_CPUINFO ARM_ABI_INFO;-#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
@@ -1,3491 +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 "ARM-64" SLJIT_CPUINFO;-}--/* Length of an instruction word */-typedef sljit_u32 sljit_ins;--#define TMP_ZERO (0)--#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)-#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)-#define TMP_LR (SLJIT_NUMBER_OF_REGISTERS + 4)-#define TMP_FP (SLJIT_NUMBER_OF_REGISTERS + 5)--#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)-#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)--/* r18 - platform register, currently not used */-static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 8] = {- 31, 0, 1, 2, 3, 4, 5, 6, 7, 11, 12, 13, 14, 15, 16, 17, 8, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 31, 9, 10, 30, 29-};--static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {- 0, 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 15, 14, 13, 12, 11, 10, 9, 8, 30, 31-};--#define W_OP ((sljit_ins)1 << 31)-#define RD(rd) ((sljit_ins)reg_map[rd])-#define RT(rt) ((sljit_ins)reg_map[rt])-#define RN(rn) ((sljit_ins)reg_map[rn] << 5)-#define RT2(rt2) ((sljit_ins)reg_map[rt2] << 10)-#define RM(rm) ((sljit_ins)reg_map[rm] << 16)-#define VD(vd) ((sljit_ins)freg_map[vd])-#define VT(vt) ((sljit_ins)freg_map[vt])-#define VT2(vt) ((sljit_ins)freg_map[vt] << 10)-#define VN(vn) ((sljit_ins)freg_map[vn] << 5)-#define VM(vm) ((sljit_ins)freg_map[vm] << 16)--/* --------------------------------------------------------------------- */-/* Instrucion forms */-/* --------------------------------------------------------------------- */--#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)-{- sljit_ins* inst = (sljit_ins*)addr;- sljit_u32 dst;- SLJIT_UNUSED_ARG(executable_offset);-- SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 0);-- dst = inst[0] & 0x1f;- SLJIT_ASSERT((inst[0] & 0xffe00000) == MOVZ && (inst[1] & 0xffe00000) == (MOVK | (1 << 21)));- inst[0] = MOVZ | dst | (((sljit_u32)new_target & 0xffff) << 5);- inst[1] = MOVK | dst | (((sljit_u32)(new_target >> 16) & 0xffff) << 5) | (1 << 21);- inst[2] = MOVK | dst | (((sljit_u32)(new_target >> 32) & 0xffff) << 5) | (2 << 21);- inst[3] = MOVK | dst | ((sljit_u32)(new_target >> 48) << 5) | (3 << 21);-- 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 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/sljitNativeARM_T2_32.c
@@ -1,4302 +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)-{-#ifdef __SOFTFP__- return "ARM-Thumb2" SLJIT_CPUINFO " ABI:softfp";-#else- return "ARM-Thumb2" SLJIT_CPUINFO " ABI:hardfp";-#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)--/* 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 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)-{- sljit_u16 *inst = (sljit_u16*)addr;- SLJIT_UNUSED_ARG(executable_offset);-- SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 0);- modify_imm32_const(inst, new_target);- SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 1);- inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);- SLJIT_CACHE_FLUSH(inst, inst + 4);-}--SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)-{- sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);-}
− src/c/pcre2/src/sljit/sljitNativeLOONGARCH_64.c
@@ -1,3765 +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 "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
@@ -1,472 +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.- */--/* 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))- return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);-- if (imm < 0 && imm >= SIMM_MIN)- return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);-- FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));- return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : 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 >> 16), DR(dst)));- return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));-}--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;-- CHECK_ERROR();- CHECK(check_sljit_emit_fset64(compiler, freg, value));-- u.value = value;-- 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));-- 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;-}--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);-- CHECK_ERROR();- CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));-- op = GET_OPCODE(op);- if (reg & REG_PAIR_MASK) {- reg2 = REG_PAIR_SECOND(reg);- reg = REG_PAIR_FIRST(reg);-- inst |= T(reg2);-- 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)));-- 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);- }-#endif /* SLJIT_MIPS_REV >= 2 */- }-- 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 (op == SLJIT_COPY_TO_F64)- FAIL_IF(push_inst(compiler, mthc | inst, MOVABLE_INS));- else- FAIL_IF(push_inst(compiler, mfhc | inst, DR(reg)));--#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)-{- sljit_ins *inst = (sljit_ins *)addr;- SLJIT_UNUSED_ARG(executable_offset);-- SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);- SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI);- inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);- inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);- 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);-}--static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr, sljit_u32 *extra_space)-{- sljit_u32 is_tail_call = *extra_space & SLJIT_CALL_RETURN;- sljit_u32 offset = 0;- sljit_s32 float_arg_count = 0;- sljit_s32 word_arg_count = 0;- sljit_s32 types = 0;- sljit_ins prev_ins = NOP;- 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_REG2] == 4 && freg_map[TMP_FREG1] == 12);-- arg_types >>= SLJIT_ARG_SHIFT;-- /* See ABI description in sljit_emit_enter. */-- while (arg_types) {- types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);- *offsets_ptr = (sljit_u8)offset;-- switch (arg_types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- if (offset & 0x7) {- offset += sizeof(sljit_sw);- *offsets_ptr = (sljit_u8)offset;- }-- if (word_arg_count == 0 && float_arg_count <= 1)- *offsets_ptr = (sljit_u8)(254 + float_arg_count);-- offset += sizeof(sljit_f64);- float_arg_count++;- break;- case SLJIT_ARG_TYPE_F32:- if (word_arg_count == 0 && float_arg_count <= 1)- *offsets_ptr = (sljit_u8)(254 + float_arg_count);-- offset += sizeof(sljit_f32);- float_arg_count++;- break;- default:- offset += sizeof(sljit_sw);- word_arg_count++;- break;- }-- arg_types >>= SLJIT_ARG_SHIFT;- offsets_ptr++;- }-- /* Stack is aligned to 16 bytes. */- SLJIT_ASSERT(offset <= 8 * sizeof(sljit_sw));-- if (offset > 4 * sizeof(sljit_sw) && (!is_tail_call || offset > compiler->args_size)) {- if (is_tail_call) {- offset = (offset + sizeof(sljit_sw) + 15) & ~(sljit_uw)0xf;- FAIL_IF(emit_stack_frame_release(compiler, (sljit_s32)offset, &prev_ins));- *extra_space = offset;- } else {- FAIL_IF(push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-16), DR(SLJIT_SP)));- *extra_space = 16;- }- } else {- if (is_tail_call)- FAIL_IF(emit_stack_frame_release(compiler, 0, &prev_ins));- *extra_space = 0;- }-- while (types) {- --offsets_ptr;-- switch (types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- 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);- 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_fmt(FMT_D) | FS(SLJIT_FR0) | FD(TMP_FREG1);-- float_arg_count--;- break;- case SLJIT_ARG_TYPE_F32:- if (*offsets_ptr < 4 * sizeof (sljit_sw))- ins = MFC1 | TA(4 + (*offsets_ptr >> 2)) | FS(float_arg_count);- else if (*offsets_ptr < 254)- ins = SWC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(*offsets_ptr);- else if (*offsets_ptr == 254)- ins = MOV_fmt(FMT_S) | FS(SLJIT_FR0) | FD(TMP_FREG1);-- float_arg_count--;- break;- default:- if (*offsets_ptr >= 4 * sizeof (sljit_sw))- ins = SW | S(SLJIT_SP) | T(word_arg_count) | IMM(*offsets_ptr);- else if ((*offsets_ptr >> 2) != word_arg_count - 1)- ins = ADDU | S(word_arg_count) | TA(0) | DA(4 + (*offsets_ptr >> 2));- else if (*offsets_ptr == 0)- ins = ADDU | S(SLJIT_R0) | TA(0) | DA(4);-- word_arg_count--;- break;- }-- if (ins != NOP) {- if (prev_ins != NOP)- FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));- prev_ins = ins;- ins = NOP;- }-- types >>= SLJIT_ARG_SHIFT;- }-- *ins_ptr = prev_ins;-- 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_u32 extra_space = 0;- sljit_ins ins = NOP;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));-- jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));- PTR_FAIL_IF(!jump);- set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);-- 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);-- if (ins == NOP && compiler->delay_slot != UNMOVABLE_INS)- jump->flags |= IS_MOVABLE;-- if (!(type & SLJIT_CALL_RETURN) || extra_space > 0) {- 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));-- 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;-- if (type & SLJIT_CALL_RETURN)- PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG,- SLJIT_MEM1(SLJIT_SP), (sljit_sw)(extra_space - sizeof(sljit_sw))));-- if (type & SLJIT_CALL_RETURN)- PTR_FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));-- PTR_FAIL_IF(push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(extra_space),- (type & SLJIT_CALL_RETURN) ? UNMOVABLE_INS : DR(SLJIT_SP)));- 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_u32 extra_space = (sljit_u32)type;- sljit_ins ins;-- 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, 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));-- /* Register input. */- if (!(type & SLJIT_CALL_RETURN) || extra_space > 0)- FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));- else- FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));- FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));-- if (extra_space == 0)- return SLJIT_SUCCESS;-- if (type & SLJIT_CALL_RETURN)- FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG,- SLJIT_MEM1(SLJIT_SP), (sljit_sw)(extra_space - sizeof(sljit_sw))));-- if (type & SLJIT_CALL_RETURN)- FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));-- return push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(extra_space),- (type & SLJIT_CALL_RETURN) ? UNMOVABLE_INS : DR(SLJIT_SP));-}
− src/c/pcre2/src/sljit/sljitNativeMIPS_64.c
@@ -1,387 +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.- */--/* 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;- sljit_s32 shift2;- sljit_s32 inv = 0;- sljit_ins ins;- sljit_uw uimm;-- if (!(imm & ~0xffff))- return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);-- if (imm < 0 && imm >= SIMM_MIN)- return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);-- if (imm <= 0x7fffffffl && imm >= -0x80000000l) {- FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));- return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;- }-- /* Zero extended number. */- uimm = (sljit_uw)imm;- if (imm < 0) {- uimm = ~(sljit_uw)imm;- inv = 1;- }-- while (!(uimm & 0xff00000000000000l)) {- shift -= 8;- uimm <<= 8;- }-- if (!(uimm & 0xf000000000000000l)) {- shift -= 4;- uimm <<= 4;- }-- if (!(uimm & 0xc000000000000000l)) {- shift -= 2;- uimm <<= 2;- }-- if ((sljit_sw)uimm < 0) {- uimm >>= 1;- shift += 1;- }- SLJIT_ASSERT(((uimm & 0xc000000000000000l) == 0x4000000000000000l) && (shift > 0) && (shift <= 32));-- if (inv)- uimm = ~uimm;-- FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(uimm >> 48), dst_ar));- if (uimm & 0x0000ffff00000000l)- FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 32), dst_ar));-- imm &= (1l << shift) - 1;- if (!(imm & ~0xffff)) {- ins = (shift == 32) ? DSLL32 : DSLL;- if (shift < 32)- ins |= SH_IMM(shift);- FAIL_IF(push_inst(compiler, ins | TA(dst_ar) | DA(dst_ar), dst_ar));- return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);- }-- /* Double shifts needs to be performed. */- uimm <<= 32;- shift2 = shift - 16;-- while (!(uimm & 0xf000000000000000l)) {- shift2 -= 4;- uimm <<= 4;- }-- if (!(uimm & 0xc000000000000000l)) {- shift2 -= 2;- uimm <<= 2;- }-- if (!(uimm & 0x8000000000000000l)) {- shift2--;- uimm <<= 1;- }-- SLJIT_ASSERT((uimm & 0x8000000000000000l) && (shift2 > 0) && (shift2 <= 16));-- FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift - shift2), dst_ar));- FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 48), dst_ar));- FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift2), dst_ar));-- imm &= (1l << shift2) - 1;- return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);-}--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 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(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;- }-- 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;-}--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));-- inst = T(reg) | FS(freg);-- 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)));--#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;-}--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 + 6, 0);- inst[0] = (inst[0] & 0xffff0000) | ((sljit_ins)(new_target >> 48) & 0xffff);- inst[1] = (inst[1] & 0xffff0000) | ((sljit_ins)(new_target >> 32) & 0xffff);- inst[3] = (inst[3] & 0xffff0000) | ((sljit_ins)(new_target >> 16) & 0xffff);- inst[5] = (inst[5] & 0xffff0000) | ((sljit_ins)new_target & 0xffff);- SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 1);- inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);- SLJIT_CACHE_FLUSH(inst, inst + 6);-}--SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)-{- sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);-}--static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr)-{- sljit_s32 arg_count = 0;- sljit_s32 word_arg_count = 0;- sljit_s32 float_arg_count = 0;- sljit_s32 types = 0;- sljit_ins prev_ins = *ins_ptr;- sljit_ins ins = NOP;-- SLJIT_ASSERT(reg_map[TMP_REG2] == 4 && freg_map[TMP_FREG1] == 12);-- 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:- case SLJIT_ARG_TYPE_F32:- arg_count++;- float_arg_count++;- break;- default:- arg_count++;- word_arg_count++;- break;- }-- arg_types >>= SLJIT_ARG_SHIFT;- }-- while (types) {- switch (types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- if (arg_count != float_arg_count)- ins = MOV_fmt(FMT_D) | FS(float_arg_count) | FD(arg_count);- else if (arg_count == 1)- 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_fmt(FMT_S) | FS(float_arg_count) | FD(arg_count);- else if (arg_count == 1)- ins = MOV_fmt(FMT_S) | FS(SLJIT_FR0) | FD(TMP_FREG1);- arg_count--;- float_arg_count--;- break;- default:- if (arg_count != word_arg_count)- ins = DADDU | S(word_arg_count) | TA(0) | D(arg_count);- else if (arg_count == 1)- ins = DADDU | S(SLJIT_R0) | TA(0) | DA(4);- arg_count--;- word_arg_count--;- break;- }-- if (ins != NOP) {- if (prev_ins != NOP)- FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));- prev_ins = ins;- ins = NOP;- }-- types >>= SLJIT_ARG_SHIFT;- }-- *ins_ptr = prev_ins;-- 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_ins ins = NOP;-- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));-- jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));- PTR_FAIL_IF(!jump);- set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);-- if (type & SLJIT_CALL_RETURN)- PTR_FAIL_IF(emit_stack_frame_release(compiler, 0, &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);-- if (ins == NOP && compiler->delay_slot != UNMOVABLE_INS)- jump->flags |= IS_MOVABLE;-- if (!(type & SLJIT_CALL_RETURN)) {- 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));-- 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;-}--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_ins ins = NOP;-- 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, 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));-- FAIL_IF(call_with_args(compiler, arg_types, &ins));-- /* Register input. */- if (!(type & SLJIT_CALL_RETURN))- FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));- else- FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));- return push_inst(compiler, ins, UNMOVABLE_INS);-}
− src/c/pcre2/src/sljit/sljitNativeMIPS_common.c
@@ -1,4259 +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.- */--/* Latest MIPS architecture. */--#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
@@ -1,485 +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.- */--/* ppc 32-bit arch dependent functions. */--static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)-{- if (imm <= SIMM_MAX && imm >= SIMM_MIN)- return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));-- if (!(imm & ~0xffff))- return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));-- FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));- 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) | 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:- case SLJIT_MOV_S32:- case SLJIT_MOV_P:- SLJIT_ASSERT(src1 == TMP_REG1);- if (dst != src2)- return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));- return SLJIT_SUCCESS;-- case SLJIT_MOV_U8:- case SLJIT_MOV_S8:- SLJIT_ASSERT(src1 == TMP_REG1);- 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));- }- else if ((flags & REG_DEST) && op == SLJIT_MOV_S8)- return push_inst(compiler, EXTSB | S(src2) | A(dst));- else {- SLJIT_ASSERT(dst == src2);- }- return SLJIT_SUCCESS;-- case SLJIT_MOV_U16:- case SLJIT_MOV_S16:- SLJIT_ASSERT(src1 == TMP_REG1);- 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));- }- else {- SLJIT_ASSERT(dst == src2);- }- return SLJIT_SUCCESS;-- 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. */- return push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));- }-- if (flags & ALT_FORM2) {- /* Flags does not set: BIN_IMM_EXTS unnecessary. */- SLJIT_ASSERT(src2 == TMP_REG2);-- 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) | (((imm >> 16) & 0xffff) + ((imm >> 15) & 0x1))));- src1 = dst;- }-- return push_inst(compiler, ADDI | D(dst) | A(src1) | (imm & 0xffff));- }- if (flags & ALT_FORM3) {- SLJIT_ASSERT(src2 == TMP_REG2);- return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);- }- SLJIT_ASSERT(!(flags & ALT_FORM4));- if (!(flags & ALT_SET_FLAGS))- return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));- if (flags & ALT_FORM5)- return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));- return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));-- case SLJIT_ADDC:- return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));-- case SLJIT_SUB:- if (flags & ALT_FORM1) {- if (flags & ALT_FORM2) {- FAIL_IF(push_inst(compiler, CMPLI | CRD(0) | A(src1) | compiler->imm));- if (!(flags & ALT_FORM3))- return SLJIT_SUCCESS;- return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));- }- FAIL_IF(push_inst(compiler, CMPL | CRD(0) | A(src1) | B(src2)));- if (!(flags & ALT_FORM3))- return SLJIT_SUCCESS;- return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));- }-- if (flags & ALT_FORM2) {- if (flags & ALT_FORM3) {- FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm));- if (!(flags & ALT_FORM4))- return SLJIT_SUCCESS;- return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));- }- FAIL_IF(push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2)));- if (!(flags & ALT_FORM4))- return SLJIT_SUCCESS;- return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));- }-- if (flags & ALT_FORM3) {- /* Setting XER SO is not enough, CR SO is also needed. */- if (src1 != TMP_ZERO)- return push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));- return push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2));- }-- if (flags & ALT_FORM4) {- /* Flags does not set: BIN_IMM_EXTS unnecessary. */- SLJIT_ASSERT(src2 == TMP_REG2);- return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);- }-- if (!(flags & ALT_SET_FLAGS)) {- SLJIT_ASSERT(src1 != TMP_ZERO);- return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));- }-- if (flags & ALT_FORM5)- return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));-- if (src1 != TMP_ZERO)- return push_inst(compiler, SUBF | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));- return push_inst(compiler, NEG | RC(ALT_SET_FLAGS) | D(dst) | A(src2));-- case SLJIT_SUBC:- return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));-- case SLJIT_MUL:- if (flags & ALT_FORM1) {- SLJIT_ASSERT(src2 == TMP_REG2);- return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);- }- return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));-- case SLJIT_AND:- if (flags & ALT_FORM1) {- SLJIT_ASSERT(src2 == TMP_REG2);- return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);- }- if (flags & ALT_FORM2) {- SLJIT_ASSERT(src2 == TMP_REG2);- return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);- }- return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));-- case SLJIT_OR:- if (flags & ALT_FORM1) {- SLJIT_ASSERT(src2 == TMP_REG2);- return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);- }- if (flags & ALT_FORM2) {- SLJIT_ASSERT(src2 == TMP_REG2);- return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);- }- if (flags & ALT_FORM3) {- SLJIT_ASSERT(src2 == TMP_REG2);- 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));-- case SLJIT_XOR:- if (flags & ALT_FORM1) {- SLJIT_ASSERT(src2 == TMP_REG2);- return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);- }- if (flags & ALT_FORM2) {- SLJIT_ASSERT(src2 == TMP_REG2);- return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);- }- if (flags & ALT_FORM3) {- SLJIT_ASSERT(src2 == TMP_REG2);- 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);- 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);- 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);- 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();- return SLJIT_SUCCESS;-}--static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value)-{- FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 16)));- return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));-}--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;- SLJIT_UNUSED_ARG(executable_offset);-- SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);- SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDIS && (inst[1] & 0xfc000000) == ORI);- inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);- inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);- SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);- inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);- SLJIT_CACHE_FLUSH(inst, inst + 2);-}
− src/c/pcre2/src/sljit/sljitNativePPC_64.c
@@ -1,719 +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.- */--/* ppc 64-bit arch dependent functions. */--#if defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM)-#define ASM_SLJIT_CLZ(src, dst) \- __asm__ volatile ( "cntlzd %0, %1" : "=r"(dst) : "r"(src) )-#elif defined(__xlc__)-#error "Please enable GCC syntax for inline assembly statements"-#else-#error "Must implement count leading zeroes"-#endif--/* 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)-{- sljit_uw tmp;- sljit_uw shift;- sljit_uw tmp2;- sljit_uw shift2;-- if (imm <= SIMM_MAX && imm >= SIMM_MIN)- return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));-- if (((sljit_uw)imm >> 16) == 0)- return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));-- if (imm <= 0x7fffffffl && imm >= -0x80000000l) {- FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));- 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);- SLJIT_ASSERT(shift > 0);- shift--;- tmp = ((sljit_uw)imm << shift);-- if ((tmp & ~0xffff000000000000ul) == 0) {- FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));- shift += 15;- 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_SLDI_NEG(reg, shift);- }-- /* Cut out the 16 bit from immediate. */- shift += 15;- tmp2 = (sljit_uw)imm & (((sljit_uw)1 << (63 - shift)) - 1);-- if (tmp2 <= 0xffff) {- FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));- 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_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;- }-- ASM_SLJIT_CLZ(tmp2, shift2);- tmp2 <<= shift2;-- if ((tmp2 & ~0xffff000000000000ul) == 0) {- FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));- shift2 += 15;- shift += (63 - shift2);- FAIL_IF(PUSH_SLDI_NEG(reg, shift));- FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | (sljit_ins)(tmp2 >> 48)));- 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_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));-}--#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)) { \- FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \- src2 = TMP_REG2; \- }--#define BIN_EXTS() \- if (flags & ALT_SIGN_EXT) { \- if (flags & REG1_SOURCE) { \- FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \- src1 = TMP_REG1; \- } \- if (flags & REG2_SOURCE) { \- FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \- src2 = TMP_REG2; \- } \- }--#define BIN_IMM_EXTS() \- if ((flags & (ALT_SIGN_EXT | REG1_SOURCE)) == (ALT_SIGN_EXT | REG1_SOURCE)) { \- FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \- src1 = TMP_REG1; \- }--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:- SLJIT_ASSERT(src1 == TMP_REG1);- if (dst != src2)- return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));- return SLJIT_SUCCESS;-- case SLJIT_MOV_U32:- case SLJIT_MOV_S32:- SLJIT_ASSERT(src1 == TMP_REG1);- 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, CLRLDI(dst, src2, 32));- }- else {- SLJIT_ASSERT(dst == src2);- }- return SLJIT_SUCCESS;-- case SLJIT_MOV_U8:- case SLJIT_MOV_S8:- SLJIT_ASSERT(src1 == TMP_REG1);- if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {- if (op == SLJIT_MOV_S8)- return push_inst(compiler, EXTSB | S(src2) | A(dst));- 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));- else {- SLJIT_ASSERT(dst == src2);- }- return SLJIT_SUCCESS;-- case SLJIT_MOV_U16:- case SLJIT_MOV_S16:- SLJIT_ASSERT(src1 == TMP_REG1);- if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {- if (op == SLJIT_MOV_S16)- return push_inst(compiler, EXTSH | S(src2) | A(dst));- return push_inst(compiler, CLRLDI(dst, src2, 48));- }- else {- SLJIT_ASSERT(dst == src2);- }- return SLJIT_SUCCESS;-- case SLJIT_CLZ:- SLJIT_ASSERT(src1 == TMP_REG1);- return push_inst(compiler, ((flags & ALT_FORM1) ? CNTLZW : CNTLZD) | 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, ((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, SLDI(32) | S(src1) | A(TMP_REG1)));- src1 = TMP_REG1;- 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, SRDI(32) | S(dst) | A(dst));- return SLJIT_SUCCESS;- }-- if (flags & ALT_FORM2) {- /* Flags does not set: BIN_IMM_EXTS unnecessary. */- SLJIT_ASSERT(src2 == TMP_REG2);-- 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) | (((imm >> 16) & 0xffff) + ((imm >> 15) & 0x1))));- src1 = dst;- }-- return push_inst(compiler, ADDI | D(dst) | A(src1) | (imm & 0xffff));- }- if (flags & ALT_FORM3) {- SLJIT_ASSERT(src2 == TMP_REG2);- BIN_IMM_EXTS();- return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);- }- if (flags & ALT_FORM4) {- if (flags & ALT_FORM5)- FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm));- else- FAIL_IF(push_inst(compiler, ADD | D(dst) | A(src1) | B(src2)));- return push_inst(compiler, CMPI | A(dst) | 0);- }- if (!(flags & ALT_SET_FLAGS))- return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));- BIN_EXTS();- if (flags & ALT_FORM5)- return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));- return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));-- case SLJIT_ADDC:- BIN_EXTS();- return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));-- case SLJIT_SUB:- if (flags & ALT_FORM1) {- if (flags & ALT_FORM2) {- FAIL_IF(push_inst(compiler, CMPLI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));- if (!(flags & ALT_FORM3))- return SLJIT_SUCCESS;- return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));- }- FAIL_IF(push_inst(compiler, CMPL | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));- if (!(flags & ALT_FORM3))- return SLJIT_SUCCESS;- return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));- }-- if (flags & ALT_FORM2) {- if (flags & ALT_FORM3) {- FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));- if (!(flags & ALT_FORM4))- return SLJIT_SUCCESS;- return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));- }- FAIL_IF(push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));- if (!(flags & ALT_FORM4))- return SLJIT_SUCCESS;- return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));- }-- if (flags & ALT_FORM3) {- if (flags & ALT_SIGN_EXT) {- if (src1 != TMP_ZERO) {- FAIL_IF(push_inst(compiler, SLDI(32) | S(src1) | A(TMP_REG1)));- src1 = TMP_REG1;- }- if (src2 != TMP_ZERO) {- 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. */- if (src1 != TMP_ZERO)- FAIL_IF(push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)));- else- 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, SRDI(32) | S(dst) | A(dst));- return SLJIT_SUCCESS;- }-- if (flags & ALT_FORM4) {- /* Flags does not set: BIN_IMM_EXTS unnecessary. */- SLJIT_ASSERT(src2 == TMP_REG2);- return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);- }-- if (!(flags & ALT_SET_FLAGS)) {- SLJIT_ASSERT(src1 != TMP_ZERO);- return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));- }-- BIN_EXTS();- if (flags & ALT_FORM5)- return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));-- if (src1 != TMP_ZERO)- return push_inst(compiler, SUBF | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));- return push_inst(compiler, NEG | RC(ALT_SET_FLAGS) | D(dst) | A(src2));-- case SLJIT_SUBC:- BIN_EXTS();- return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));-- case SLJIT_MUL:- if (flags & ALT_FORM1) {- SLJIT_ASSERT(src2 == TMP_REG2);- return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);- }- BIN_EXTS();- if (flags & ALT_FORM2)- return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));- return push_inst(compiler, MULLD | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));-- case SLJIT_AND:- if (flags & ALT_FORM1) {- SLJIT_ASSERT(src2 == TMP_REG2);- return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);- }- if (flags & ALT_FORM2) {- SLJIT_ASSERT(src2 == TMP_REG2);- return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);- }- return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));-- case SLJIT_OR:- if (flags & ALT_FORM1) {- SLJIT_ASSERT(src2 == TMP_REG2);- return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);- }- if (flags & ALT_FORM2) {- SLJIT_ASSERT(src2 == TMP_REG2);- return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);- }- if (flags & ALT_FORM3) {- SLJIT_ASSERT(src2 == TMP_REG2);- 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));-- case SLJIT_XOR:- if (flags & ALT_FORM1) {- SLJIT_ASSERT(src2 == TMP_REG2);- return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);- }- if (flags & ALT_FORM2) {- SLJIT_ASSERT(src2 == TMP_REG2);- return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);- }- if (flags & ALT_FORM3) {- SLJIT_ASSERT(src2 == TMP_REG2);- 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) {- imm &= 0x1f;- return push_inst(compiler, SLWI(imm) | RC(flags) | S(src1) | A(dst));- }-- 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) {- 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));- }-- 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) {- imm &= 0x1f;- return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (imm << 11));- }-- 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();- return SLJIT_SUCCESS;-}--static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src)-{- sljit_s32 arg_count = 0;- sljit_s32 word_arg_count = 0;- sljit_s32 types = 0;- sljit_s32 reg = 0;-- if (src)- reg = *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:- case SLJIT_ARG_TYPE_F32:- arg_count++;- break;- default:- arg_count++;- word_arg_count++;-- if (arg_count != word_arg_count && arg_count == reg) {- FAIL_IF(push_inst(compiler, OR | S(reg) | A(TMP_CALL_REG) | B(reg)));- *src = TMP_CALL_REG;- }- break;- }-- arg_types >>= SLJIT_ARG_SHIFT;- }-- while (types) {- switch (types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- case SLJIT_ARG_TYPE_F32:- arg_count--;- break;- default:- if (arg_count != word_arg_count)- FAIL_IF(push_inst(compiler, OR | S(word_arg_count) | A(arg_count) | B(word_arg_count)));-- arg_count--;- word_arg_count--;- break;- }-- types >>= SLJIT_ARG_SHIFT;- }-- return SLJIT_SUCCESS;-}--static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value)-{- FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 48)));- FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value >> 32)));- 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;- SLJIT_UNUSED_ARG(executable_offset);-- SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 0);- inst[0] = (inst[0] & 0xffff0000u) | ((sljit_ins)(new_target >> 48) & 0xffff);- inst[1] = (inst[1] & 0xffff0000u) | ((sljit_ins)(new_target >> 32) & 0xffff);- inst[3] = (inst[3] & 0xffff0000u) | ((sljit_ins)(new_target >> 16) & 0xffff);- inst[4] = (inst[4] & 0xffff0000u) | ((sljit_ins)new_target & 0xffff);- 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/sljitNativePPC_common.c
@@ -1,3161 +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 "PowerPC" SLJIT_CPUINFO;-}--/* Length of an instruction word.- Both for ppc-32 and ppc-64. */-typedef sljit_u32 sljit_ins;--#if ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && (defined _AIX)) \- || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)-#define SLJIT_PPC_STACK_FRAME_V2 1-#endif--#ifdef _AIX-#include <sys/cache.h>-#endif--#if (defined _CALL_ELF && _CALL_ELF == 2)-#define SLJIT_PASS_ENTRY_ADDR_TO_CALL 1-#endif--#if (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL)--static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)-{-#ifdef _AIX- _sync_cache_range((caddr_t)from, (int)((size_t)to - (size_t)from));-#elif defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM)-# if defined(_ARCH_PWR) || defined(_ARCH_PWR2)- /* Cache flush for POWER architecture. */- while (from < to) {- __asm__ volatile (- "clf 0, %0\n"- "dcs\n"- : : "r"(from)- );- from++;- }- __asm__ volatile ( "ics" );-# elif defined(_ARCH_COM) && !defined(_ARCH_PPC)-# error "Cache flush is not implemented for PowerPC/POWER common mode."-# else- /* Cache flush for PowerPC architecture. */- while (from < to) {- __asm__ volatile (- "dcbf 0, %0\n"- "sync\n"- "icbi 0, %0\n"- : : "r"(from)- );- from++;- }- __asm__ volatile ( "isync" );-# endif-# ifdef __xlc__-# warning "This file may fail to compile if -qfuncsect is used"-# endif-#elif defined(__xlc__)-#error "Please enable GCC syntax for inline assembly statements with -qasm=gcc"-#else-#error "This platform requires a cache flush implementation."-#endif /* _AIX */-}--#endif /* (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL) */--#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)-#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)-#define TMP_ZERO (SLJIT_NUMBER_OF_REGISTERS + 4)--#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_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
@@ -1,142 +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_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
@@ -1,222 +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_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
@@ -1,3121 +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)-{-#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
@@ -1,4526 +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.- */--#include <sys/auxv.h>--#ifdef __ARCH__-#define ENABLE_STATIC_FACILITY_DETECTION 1-#else-#define ENABLE_STATIC_FACILITY_DETECTION 0-#endif-#define ENABLE_DYNAMIC_FACILITY_DETECTION 1--SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)-{- return "s390x" SLJIT_CPUINFO;-}--/* 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 */-#undef WHEN2-#undef EVAL--#undef tmp1-#undef tmp0--/* TODO(carenas): undef other macros that spill like is_u12? */
− src/c/pcre2/src/sljit/sljitNativeX86_32.c
@@ -1,1685 +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.- */--/* x86 32-bit arch dependent functions. */--/* --------------------------------------------------------------------- */-/* Operators */-/* --------------------------------------------------------------------- */--static sljit_s32 emit_do_imm(struct sljit_compiler *compiler, sljit_u8 opcode, sljit_sw imm)-{- sljit_u8 *inst;-- inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_sw));- FAIL_IF(!inst);- INC_SIZE(1 + sizeof(sljit_sw));- *inst++ = opcode;- sljit_unaligned_store_sw(inst, imm);- return SLJIT_SUCCESS;-}--/* Size contains the flags as well. */-static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw size,- /* The register or immediate operand. */- sljit_s32 a, sljit_sw imma,- /* The general operand (not immediate). */- sljit_s32 b, sljit_sw immb)-{- sljit_u8 *inst;- sljit_u8 *buf_ptr;- sljit_u8 reg_map_b;- sljit_uw flags = size;- sljit_uw inst_size;-- /* 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. */- SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0);- /* 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_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;-}--static sljit_s32 skip_frames_before_return(struct sljit_compiler *compiler)-{- sljit_sw size;-- /* Don't adjust shadow stack if it isn't enabled. */- if (!cpu_has_shadow_stack())- return SLJIT_SUCCESS;-- SLJIT_ASSERT(compiler->args_size >= 0);- SLJIT_ASSERT(compiler->local_size > 0);-- size = compiler->local_size;- size += (1 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0)- + (compiler->saveds <= 3 ? compiler->saveds : 3)) * SSIZE_OF(sw);-- return adjust_shadow_stack(compiler, SLJIT_MEM1(SLJIT_SP), size);-}
− src/c/pcre2/src/sljit/sljitNativeX86_64.c
@@ -1,1398 +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.- */--/* x86 64-bit arch dependent functions. */--/* --------------------------------------------------------------------- */-/* Operators */-/* --------------------------------------------------------------------- */--static sljit_s32 emit_load_imm64(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)-{- sljit_u8 *inst;-- inst = (sljit_u8*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_sw));- FAIL_IF(!inst);- INC_SIZE(2 + sizeof(sljit_sw));- 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;-}--static sljit_s32 emit_do_imm32(struct sljit_compiler *compiler, sljit_u8 rex, sljit_u8 opcode, sljit_sw imm)-{- sljit_u8 *inst;- sljit_uw length = (rex ? 2 : 1) + sizeof(sljit_s32);-- inst = (sljit_u8*)ensure_buf(compiler, 1 + length);- FAIL_IF(!inst);- INC_SIZE(length);- if (rex)- *inst++ = rex;- *inst++ = opcode;- sljit_unaligned_store_s32(inst, (sljit_s32)imm);- return SLJIT_SUCCESS;-}--static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw size,- /* The register or immediate operand. */- sljit_s32 a, sljit_sw imma,- /* The general operand (not immediate). */- sljit_s32 b, sljit_sw immb)-{- sljit_u8 *inst;- sljit_u8 *buf_ptr;- sljit_u8 rex = 0;- sljit_u8 reg_lmap_b;- sljit_uw flags = size;- sljit_uw inst_size;-- /* The immediate operand must be 32 bit. */- 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. */- SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0);- /* 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_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 (!compiler->mode32 && !(flags & EX86_NO_REXW))- rex |= REX_W;- else if (flags & EX86_REX)- rex |= REX;-- if (flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66))- inst_size++;-- /* Calculate size of b. */- if (b & SLJIT_MEM) {- 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 (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);- }-- 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)) {- if (reg_map[b] >= 8)- rex |= REX_B;- } else if (freg_map[b] >= 8)- rex |= REX_B;-- 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) {- SLJIT_ASSERT(imma <= (compiler->mode32 ? 0x1f : 0x3f));- 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_s32);- } 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)) {- if (reg_map[a] >= 8)- rex |= REX_R;- }- else if (freg_map[a] >= 8)- rex |= REX_R;- }-- if (rex)- inst_size++;-- inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size);- PTR_FAIL_IF(!inst);-- /* Encoding prefixes. */- 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;-- /* 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)- *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_lmap[a] << 3);- else- *buf_ptr = U8(freg_lmap[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_lmap[b] : freg_lmap[b]));- buf_ptr++;- } 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)) {- if (immb != 0 || reg_lmap_b == 5) {- if (immb <= 127 && immb >= -128)- *buf_ptr |= 0x40;- else- *buf_ptr |= 0x80;- }-- if (!(b & OFFS_REG_MASK))- *buf_ptr++ |= reg_lmap_b;- else {- 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) {- if (immb <= 127 && immb >= -128)- *buf_ptr++ = U8(immb); /* 8 bit displacement. */- else {- sljit_unaligned_store_s32(buf_ptr, (sljit_s32)immb); /* 32 bit displacement. */- buf_ptr += sizeof(sljit_s32);- }- }- } 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[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 (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_s32(buf_ptr, (sljit_s32)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);-- 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* 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_ADDR) && (jump->u.target <= 0xffffffff);-- /* The relative jump below specialized for this case. */- SLJIT_ASSERT(reg_map[TMP_REG2] >= 8 && TMP_REG2 != SLJIT_TMP_DEST_REG);-- if (type < SLJIT_JUMP) {- /* Invert type. */- code_ptr[0] = U8(get_jump_code(type ^ 0x1) - 0x10);- code_ptr[1] = short_addr ? (6 + 3) : (10 + 3);- code_ptr += 2;- }-- 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_ADDR))- jump->flags |= PATCH_MD;- else if (short_addr)- sljit_unaligned_store_s32(code_ptr, (sljit_s32)jump->u.target);- else- sljit_unaligned_store_sw(code_ptr, (sljit_sw)jump->u.target);-- code_ptr += short_addr ? sizeof(sljit_s32) : sizeof(sljit_sw);-- 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 + 3;-}--static sljit_u8* generate_mov_addr_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_sw executable_offset)-{- sljit_uw addr;- sljit_sw diff;- SLJIT_UNUSED_ARG(executable_offset);-- 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;-- if (addr > 0xffffffffl) {- diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);-- 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;- }-- jump->flags |= PATCH_MD;- return code_ptr;- }-- 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[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);- }-- 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 = SLJIT_KEPT_SAVEDS_COUNT(options);- sljit_s32 saved_regs_size, tmp, i;-#ifdef _WIN64- sljit_s32 saved_float_regs_size;- sljit_s32 saved_float_regs_offset = 0;- sljit_s32 float_arg_count = 0;-#endif /* _WIN64 */- sljit_u8 *inst;-- 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);-- 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 - saved_arg_count, 1);-- tmp = SLJIT_S0 - saveds;- 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);- INC_SIZE(size);- if (reg_map[i] >= 8)- *inst++ = REX_B;- PUSH_REG(reg_lmap[i]);- }-- for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {- size = reg_map[i] >= 8 ? 2 : 1;- inst = (sljit_u8*)ensure_buf(compiler, 1 + size);- FAIL_IF(!inst);- INC_SIZE(size);- if (reg_map[i] >= 8)- *inst++ = REX_B;- PUSH_REG(reg_lmap[i]);- }--#ifdef _WIN64- local_size += SLJIT_LOCALS_OFFSET;- 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);- local_size = saved_float_regs_offset + saved_float_regs_size;- }-#else /* !_WIN64 */- SLJIT_ASSERT(SLJIT_LOCALS_OFFSET == 0);-#endif /* _WIN64 */-- arg_types >>= SLJIT_ARG_SHIFT;-- while (arg_types > 0) {- if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {- tmp = 0;-#ifndef _WIN64- switch (word_arg_count) {- case 0:- tmp = SLJIT_R2;- break;- case 1:- tmp = SLJIT_R1;- break;- case 2:- tmp = TMP_REG1;- break;- default:- tmp = SLJIT_R3;- break;- }-#else /* !_WIN64 */- switch (word_arg_count + float_arg_count) {- case 0:- tmp = SLJIT_R3;- break;- case 1:- tmp = SLJIT_R1;- break;- case 2:- tmp = SLJIT_R2;- break;- default:- tmp = TMP_REG1;- break;- }-#endif /* _WIN64 */- if (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) {- if (tmp != SLJIT_R0 + word_arg_count)- EMIT_MOV(compiler, SLJIT_R0 + word_arg_count, 0, tmp, 0);- } else {- EMIT_MOV(compiler, SLJIT_S0 - saved_arg_count, 0, tmp, 0);- saved_arg_count++;- }- word_arg_count++;- } else {-#ifdef _WIN64- SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);- float_arg_count++;- if (float_arg_count != float_arg_count + word_arg_count)- FAIL_IF(emit_sse2_load(compiler, (arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F32,- float_arg_count, float_arg_count + word_arg_count, 0));-#endif /* _WIN64 */- }- arg_types >>= SLJIT_ARG_SHIFT;- }-- local_size = ((local_size + saved_regs_size + 0xf) & ~0xf) - saved_regs_size;- compiler->local_size = local_size;--#ifdef _WIN64- if (local_size > 0) {- if (local_size <= 4 * 4096) {- if (local_size > 4096)- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096);- if (local_size > 2 * 4096)- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 2);- if (local_size > 3 * 4096)- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 3);- }- else {- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, local_size >> 12);-- EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_MEM1(SLJIT_SP), -4096);- BINARY_IMM32(SUB, 4096, SLJIT_SP, 0);- BINARY_IMM32(SUB, 1, TMP_REG1, 0);-- inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);- FAIL_IF(!inst);-- INC_SIZE(2);- inst[0] = JNE_i8;- inst[1] = (sljit_u8)-21;- local_size &= 0xfff;- }-- if (local_size > 0)- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -local_size);- }-#endif /* _WIN64 */-- if (local_size > 0)- BINARY_IMM32(SUB, local_size, SLJIT_SP, 0);--#ifdef _WIN64- if (saved_float_regs_size > 0) {- compiler->mode32 = 1;-- tmp = SLJIT_FS0 - fsaveds;- for (i = SLJIT_FS0; i > tmp; i--) {- 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--) {- FAIL_IF(emit_groupf(compiler, MOVAPS_xm_x | EX86_SSE2, i, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset));- saved_float_regs_offset += 16;- }- }-#endif /* _WIN64 */-- 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 saved_regs_size;-#ifdef _WIN64- sljit_s32 saved_float_regs_size;-#endif /* _WIN64 */-- 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);--#ifdef _WIN64- local_size += SLJIT_LOCALS_OFFSET;- 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;-#else /* !_WIN64 */- SLJIT_ASSERT(SLJIT_LOCALS_OFFSET == 0);-#endif /* _WIN64 */-- /* Including the return address saved by the call instruction. */- 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, sljit_s32 is_return_to)-{- sljit_uw size;- sljit_s32 local_size, i, tmp;- sljit_u8 *inst;-#ifdef _WIN64- sljit_s32 saved_float_regs_offset;- sljit_s32 fscratches = compiler->fscratches;- sljit_s32 fsaveds = compiler->fsaveds;-#endif /* _WIN64 */--#ifdef _WIN64- saved_float_regs_offset = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sse2_reg);-- if (saved_float_regs_offset > 0) {- compiler->mode32 = 1;- saved_float_regs_offset = (compiler->local_size - saved_float_regs_offset) & ~0xf;-- tmp = SLJIT_FS0 - fsaveds;- for (i = SLJIT_FS0; i > tmp; i--) {- 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--) {- 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 */-- 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;- inst = (sljit_u8*)ensure_buf(compiler, 1 + size);- FAIL_IF(!inst);- INC_SIZE(size);- if (reg_map[i] >= 8)- *inst++ = REX_B;- POP_REG(reg_lmap[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);- INC_SIZE(size);- if (reg_map[i] >= 8)- *inst++ = REX_B;- 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)-{- CHECK_ERROR();- CHECK(check_sljit_emit_return_void(compiler));-- compiler->mode32 = 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)-{- 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 */-/* --------------------------------------------------------------------- */--#ifndef _WIN64--static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src_ptr)-{- sljit_s32 src = src_ptr ? (*src_ptr) : 0;- sljit_s32 word_arg_count = 0;-- SLJIT_ASSERT(reg_map[SLJIT_R1] == 6 && reg_map[SLJIT_R3] == 1 && reg_map[TMP_REG1] == 2);- SLJIT_ASSERT(!(src & SLJIT_MEM));-- /* Remove return value. */- 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 == 0)- return SLJIT_SUCCESS;-- if (word_arg_count >= 3) {- if (src == SLJIT_R2)- *src_ptr = TMP_REG1;- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R2, 0);- }-- return emit_mov(compiler, SLJIT_R2, 0, SLJIT_R0, 0);-}--#else--static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src_ptr)-{- sljit_s32 src = src_ptr ? (*src_ptr) : 0;- sljit_s32 arg_count = 0;- sljit_s32 word_arg_count = 0;- sljit_s32 float_arg_count = 0;- sljit_s32 types = 0;- sljit_s32 data_trandfer = 0;- static sljit_u8 word_arg_regs[5] = { 0, SLJIT_R3, SLJIT_R1, SLJIT_R2, TMP_REG1 };-- SLJIT_ASSERT(reg_map[SLJIT_R3] == 1 && reg_map[SLJIT_R1] == 2 && reg_map[SLJIT_R2] == 8 && reg_map[TMP_REG1] == 9);- SLJIT_ASSERT(!(src & SLJIT_MEM));-- 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:- case SLJIT_ARG_TYPE_F32:- arg_count++;- float_arg_count++;-- if (arg_count != float_arg_count)- data_trandfer = 1;- break;- default:- arg_count++;- word_arg_count++;-- if (arg_count != word_arg_count || arg_count != word_arg_regs[arg_count]) {- data_trandfer = 1;-- if (src == word_arg_regs[arg_count]) {- EMIT_MOV(compiler, TMP_REG2, 0, src, 0);- *src_ptr = TMP_REG2;- }- }- break;- }-- arg_types >>= SLJIT_ARG_SHIFT;- }-- if (!data_trandfer)- return SLJIT_SUCCESS;-- while (types) {- switch (types & SLJIT_ARG_MASK) {- case SLJIT_ARG_TYPE_F64:- if (arg_count != float_arg_count)- FAIL_IF(emit_sse2_load(compiler, 0, arg_count, float_arg_count, 0));- arg_count--;- float_arg_count--;- break;- case SLJIT_ARG_TYPE_F32:- if (arg_count != float_arg_count)- FAIL_IF(emit_sse2_load(compiler, 1, arg_count, float_arg_count, 0));- arg_count--;- float_arg_count--;- break;- default:- if (arg_count != word_arg_count || arg_count != word_arg_regs[arg_count])- EMIT_MOV(compiler, word_arg_regs[arg_count], 0, word_arg_count, 0);- arg_count--;- word_arg_count--;- break;- }-- 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)-{- CHECK_ERROR_PTR();- CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));-- compiler->mode32 = 0;-- 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, 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_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));-- compiler->mode32 = 0;-- if (src & SLJIT_MEM) {- ADJUST_LOCAL_OFFSET(src, srcw);- EMIT_MOV(compiler, TMP_REG2, 0, src, srcw);- src = TMP_REG2;- }-- if (type & SLJIT_CALL_RETURN) {- 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, 0));- }-- if ((type & 0xff) != SLJIT_CALL_REG_ARG)- FAIL_IF(call_with_args(compiler, arg_types, &src));-- if (type & SLJIT_CALL_RETURN)- type = SLJIT_JUMP;-- SLJIT_SKIP_CHECKS(compiler);- return sljit_emit_ijump(compiler, type, src, srcw);-}--static sljit_s32 emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)-{- sljit_u8 *inst;-- if (FAST_IS_REG(dst)) {- 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);- INC_SIZE(2);- *inst++ = REX_B;- POP_REG(reg_lmap[dst]);- return SLJIT_SUCCESS;- }-- /* REX_W is not necessary (src is not immediate). */- compiler->mode32 = 1;- 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;-- if (FAST_IS_REG(src)) {- if (reg_map[src] < 8) {- inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 1);- FAIL_IF(!inst);-- INC_SIZE(1 + 1);- PUSH_REG(reg_lmap[src]);- }- else {- inst = (sljit_u8*)ensure_buf(compiler, 1 + 2 + 1);- FAIL_IF(!inst);-- INC_SIZE(2 + 1);- *inst++ = REX_B;- PUSH_REG(reg_lmap[src]);- }- }- else {- /* REX_W is not necessary (src is not immediate). */- compiler->mode32 = 1;- 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 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);-}--/* --------------------------------------------------------------------- */-/* 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)-{- sljit_u8* inst;- sljit_s32 dst_r;-- compiler->mode32 = 0;-- if (src == SLJIT_IMM) {- if (FAST_IS_REG(dst)) {- 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);- FAIL_IF(!inst);- *inst = MOV_rm_i32;- compiler->mode32 = 0;- return SLJIT_SUCCESS;- }-- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;-- if ((dst & SLJIT_MEM) && FAST_IS_REG(src))- dst_r = src;- else {- if (sign) {- inst = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);- FAIL_IF(!inst);- *inst = MOVSXD_r_rm;- } else {- compiler->mode32 = 1;- EMIT_MOV(compiler, dst_r, 0, src, srcw);- compiler->mode32 = 0;- }- }-- if (dst & SLJIT_MEM) {- compiler->mode32 = 1;- inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);- FAIL_IF(!inst);- *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;-}--static sljit_s32 skip_frames_before_return(struct sljit_compiler *compiler)-{- sljit_s32 tmp, size;-- /* Don't adjust shadow stack if it isn't enabled. */- if (!cpu_has_shadow_stack())- return SLJIT_SUCCESS;-- size = compiler->local_size;- tmp = compiler->scratches;- if (tmp >= SLJIT_FIRST_SAVED_REG)- size += (tmp - SLJIT_FIRST_SAVED_REG + 1) * SSIZE_OF(sw);- tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;- if (SLJIT_S0 >= tmp)- size += (SLJIT_S0 - tmp + 1) * SSIZE_OF(sw);-- return adjust_shadow_stack(compiler, SLJIT_MEM1(SLJIT_SP), size);-}
− src/c/pcre2/src/sljit/sljitNativeX86_common.c
@@ -1,5001 +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 "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)-{- SLJIT_UNUSED_ARG(executable_offset);-- SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + sizeof(sljit_uw)), 0);-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)- sljit_unaligned_store_sw((void*)addr, (sljit_sw)(new_target - (addr + 4) - (sljit_uw)executable_offset));-#else- sljit_unaligned_store_sw((void*)addr, (sljit_sw)new_target);-#endif- SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + sizeof(sljit_uw)), 1);-}--SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)-{- SLJIT_UNUSED_ARG(executable_offset);-- SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + sizeof(sljit_sw)), 0);- sljit_unaligned_store_sw((void*)addr, new_constant);- SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + sizeof(sljit_sw)), 1);-}
− src/c/pcre2/src/sljit/sljitSerialize.c
@@ -1,516 +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 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/sljitUtils.c
@@ -1,344 +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.- */--/* ------------------------------------------------------------------------ */-/* Locks */-/* ------------------------------------------------------------------------ */--/* Executable Allocator */--#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) \- && !(defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR)-#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)-#define SLJIT_ALLOCATOR_LOCK()-#define SLJIT_ALLOCATOR_UNLOCK()-#elif !(defined _WIN32)-#include <pthread.h>--static pthread_mutex_t allocator_lock = PTHREAD_MUTEX_INITIALIZER;--#define SLJIT_ALLOCATOR_LOCK() pthread_mutex_lock(&allocator_lock)-#define SLJIT_ALLOCATOR_UNLOCK() pthread_mutex_unlock(&allocator_lock)-#else /* windows */-static HANDLE allocator_lock;--static SLJIT_INLINE void allocator_grab_lock(void)-{- HANDLE lock;- if (SLJIT_UNLIKELY(!InterlockedCompareExchangePointer(&allocator_lock, NULL, NULL))) {- lock = CreateMutex(NULL, FALSE, NULL);- if (InterlockedCompareExchangePointer(&allocator_lock, lock, NULL))- CloseHandle(lock);- }- WaitForSingleObject(allocator_lock, INFINITE);-}--#define SLJIT_ALLOCATOR_LOCK() allocator_grab_lock()-#define SLJIT_ALLOCATOR_UNLOCK() ReleaseMutex(allocator_lock)-#endif /* thread implementation */-#endif /* SLJIT_EXECUTABLE_ALLOCATOR && !SLJIT_WX_EXECUTABLE_ALLOCATOR */--/* ------------------------------------------------------------------------ */-/* Stack */-/* ------------------------------------------------------------------------ */--#if ((defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) \- && !(defined SLJIT_UTIL_SIMPLE_STACK_ALLOCATION && SLJIT_UTIL_SIMPLE_STACK_ALLOCATION)) \- || ((defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) \- && !((defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR) \- || (defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR)))--#ifndef _WIN32-/* Provides mmap function. */-#include <sys/types.h>-#include <sys/mman.h>--#ifndef MAP_ANON-#ifdef MAP_ANONYMOUS-#define MAP_ANON MAP_ANONYMOUS-#endif /* MAP_ANONYMOUS */-#endif /* !MAP_ANON */--#ifndef MAP_ANON--#include <fcntl.h>--#ifdef O_CLOEXEC-#define SLJIT_CLOEXEC O_CLOEXEC-#else /* !O_CLOEXEC */-#define SLJIT_CLOEXEC 0-#endif /* O_CLOEXEC */--/* Some old systems do not have MAP_ANON. */-static int dev_zero = -1;--#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)--static SLJIT_INLINE int open_dev_zero(void)-{- dev_zero = open("/dev/zero", O_RDWR | SLJIT_CLOEXEC);-- return dev_zero < 0;-}--#else /* !SLJIT_SINGLE_THREADED */--#include <pthread.h>--static pthread_mutex_t dev_zero_mutex = PTHREAD_MUTEX_INITIALIZER;--static SLJIT_INLINE int open_dev_zero(void)-{- pthread_mutex_lock(&dev_zero_mutex);- if (SLJIT_UNLIKELY(dev_zero < 0))- dev_zero = open("/dev/zero", O_RDWR | SLJIT_CLOEXEC);-- pthread_mutex_unlock(&dev_zero_mutex);- return dev_zero < 0;-}--#endif /* SLJIT_SINGLE_THREADED */-#undef SLJIT_CLOEXEC-#endif /* !MAP_ANON */-#endif /* !_WIN32 */-#endif /* open_dev_zero */--#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) \- || (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)--#ifdef _WIN32--static SLJIT_INLINE sljit_uw get_page_alignment(void) {- SYSTEM_INFO si;- static sljit_uw sljit_page_align = 0;- if (!sljit_page_align) {- GetSystemInfo(&si);- sljit_page_align = (sljit_uw)si.dwPageSize - 1;- }- return sljit_page_align;-}--#else--#include <unistd.h>--static SLJIT_INLINE sljit_uw get_page_alignment(void) {- static sljit_uw sljit_page_align = 0;-- sljit_sw align;-- if (!sljit_page_align) {-#ifdef _SC_PAGESIZE- align = sysconf(_SC_PAGESIZE);-#else- align = getpagesize();-#endif- /* Should never happen. */- if (align < 0)- align = 4096;- sljit_page_align = (sljit_uw)align - 1;- }- return sljit_page_align;-}--#endif /* _WIN32 */--#endif /* get_page_alignment() */--#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)--#if (defined SLJIT_UTIL_SIMPLE_STACK_ALLOCATION && SLJIT_UTIL_SIMPLE_STACK_ALLOCATION)--SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data)-{- struct sljit_stack *stack;- void *ptr;-- SLJIT_UNUSED_ARG(allocator_data);-- if (start_size > max_size || start_size < 1)- return NULL;-- stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data);- if (stack == NULL)- return NULL;-- ptr = SLJIT_MALLOC(max_size, allocator_data);- if (ptr == NULL) {- SLJIT_FREE(stack, allocator_data);- return NULL;- }-- stack->min_start = (sljit_u8 *)ptr;- stack->end = stack->min_start + max_size;- stack->start = stack->end - start_size;- stack->top = stack->end;- return stack;-}--SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)-{- SLJIT_UNUSED_ARG(allocator_data);- SLJIT_FREE((void*)stack->min_start, allocator_data);- SLJIT_FREE(stack, allocator_data);-}--SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start)-{- if ((new_start < stack->min_start) || (new_start >= stack->end))- return NULL;- stack->start = new_start;- return new_start;-}--#else /* !SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */--#ifdef _WIN32--SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)-{- SLJIT_UNUSED_ARG(allocator_data);- VirtualFree((void*)stack->min_start, 0, MEM_RELEASE);- SLJIT_FREE(stack, allocator_data);-}--#else /* !_WIN32 */--SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)-{- SLJIT_UNUSED_ARG(allocator_data);- munmap((void*)stack->min_start, (size_t)(stack->end - stack->min_start));- SLJIT_FREE(stack, allocator_data);-}--#endif /* _WIN32 */--SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data)-{- struct sljit_stack *stack;- void *ptr;- sljit_uw page_align;-- SLJIT_UNUSED_ARG(allocator_data);-- if (start_size > max_size || start_size < 1)- return NULL;-- stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data);- if (stack == NULL)- return NULL;-- /* Align max_size. */- page_align = get_page_alignment();- max_size = (max_size + page_align) & ~page_align;--#ifdef _WIN32- ptr = VirtualAlloc(NULL, max_size, MEM_RESERVE, PAGE_READWRITE);- if (!ptr) {- SLJIT_FREE(stack, allocator_data);- return NULL;- }-- stack->min_start = (sljit_u8 *)ptr;- stack->end = stack->min_start + max_size;- stack->start = stack->end;-- if (sljit_stack_resize(stack, stack->end - start_size) == NULL) {- sljit_free_stack(stack, allocator_data);- return NULL;- }-#else /* !_WIN32 */-#ifdef MAP_ANON- ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);-#else /* !MAP_ANON */- if (SLJIT_UNLIKELY((dev_zero < 0) && open_dev_zero())) {- SLJIT_FREE(stack, allocator_data);- return NULL;- }- ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0);-#endif /* MAP_ANON */- if (ptr == MAP_FAILED) {- SLJIT_FREE(stack, allocator_data);- return NULL;- }- stack->min_start = (sljit_u8 *)ptr;- stack->end = stack->min_start + max_size;- stack->start = stack->end - start_size;-#endif /* _WIN32 */-- stack->top = stack->end;- return stack;-}--SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start)-{-#if defined _WIN32 || defined(POSIX_MADV_DONTNEED)- sljit_uw aligned_old_start;- sljit_uw aligned_new_start;- sljit_uw page_align;-#endif-- if ((new_start < stack->min_start) || (new_start >= stack->end))- return NULL;--#ifdef _WIN32- page_align = get_page_alignment();-- aligned_new_start = (sljit_uw)new_start & ~page_align;- aligned_old_start = ((sljit_uw)stack->start) & ~page_align;- if (aligned_new_start != aligned_old_start) {- if (aligned_new_start < aligned_old_start) {- if (!VirtualAlloc((void*)aligned_new_start, aligned_old_start - aligned_new_start, MEM_COMMIT, PAGE_READWRITE))- return NULL;- }- else {- if (!VirtualFree((void*)aligned_old_start, aligned_new_start - aligned_old_start, MEM_DECOMMIT))- return NULL;- }- }-#elif defined(POSIX_MADV_DONTNEED)- if (stack->start < new_start) {- page_align = get_page_alignment();-- aligned_new_start = (sljit_uw)new_start & ~page_align;- aligned_old_start = ((sljit_uw)stack->start) & ~page_align;-- if (aligned_new_start > aligned_old_start) {- posix_madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, POSIX_MADV_DONTNEED);-#ifdef MADV_FREE- madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, MADV_FREE);-#endif /* MADV_FREE */- }- }-#endif /* _WIN32 */-- stack->start = new_start;- return new_start;-}--#endif /* SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */--#endif /* SLJIT_UTIL_STACK */
src/c/pcre2_chartables.c view
@@ -19,10 +19,6 @@ pcre2_dftables manually with the -L option to build tables using the LC_ALL locale. */ -#ifdef HAVE_CONFIG_H-#include "config.h"-#endif- #include "pcre2_internal.h" const uint8_t PRIV(default_tables)[] = {
src/hs/Text/Regex/Pcre2.hs view
@@ -226,9 +226,11 @@ _regex, -- ** Type-indexed capture groups- Captures(),+ Captures,+ CapturesInfo, capture, _capture,+ predictCapturesInfo, -- * Options @@ -244,6 +246,7 @@ DepthLimit, DollarEndOnly, DotAll,+ Dupnames, EndAnchored, EscapedCrIsLf, Extended,@@ -296,6 +299,7 @@ supportsJit, jitTarget, linkSize,+ effectivelinkSize, defaultMatchLimit, defaultNewline, defaultIsNeverBackslashC,
src/hs/Text/Regex/Pcre2/Foreign.hs view
@@ -58,6 +58,9 @@ :: Ptr Pcre2_general_context -> IO () +foreign import capi safe "pcre2.h &pcre2_general_context_free_8"+ pcre2_general_context_finalizer :: FinalizerPtr Pcre2_general_context+ -- * The compile context foreign import capi safe "pcre2.h" pcre2_compile_context_create@@ -72,6 +75,9 @@ :: Ptr Pcre2_compile_context -> IO () +foreign import capi safe "pcre2.h &pcre2_compile_context_free_8"+ pcre2_compile_context_finalizer :: FinalizerPtr Pcre2_compile_context+ -- ** Compile context setters -- TODO Maybe this goes next to wherever errors appear in the docs?@@ -137,6 +143,9 @@ :: Ptr Pcre2_match_context -> IO () +foreign import capi safe "pcre2.h &pcre2_match_context_free_8"+ pcre2_match_context_finalizer :: FinalizerPtr Pcre2_match_context+ -- ** Match context setters foreign import capi unsafe "pcre2.h" pcre2_set_callout@@ -183,6 +192,7 @@ constant ''CUInt "CONFIG_BSR" constant ''CUInt "CONFIG_COMPILED_WIDTHS" constant ''CUInt "CONFIG_DEPTHLIMIT"+constant ''CUInt "CONFIG_EFFECTIVE_LINKSIZE" -- ^ @since 2.2.3 constant ''CUInt "CONFIG_HEAPLIMIT" constant ''CUInt "CONFIG_JIT" constant ''CUInt "CONFIG_JITTARGET"@@ -215,6 +225,9 @@ :: Ptr Pcre2_code -> IO () +foreign import capi safe "pcre2.h &pcre2_code_free_8"+ pcre2_code_finalizer :: FinalizerPtr Pcre2_code+ foreign import capi safe "pcre2.h" pcre2_code_copy :: Ptr Pcre2_code -> IO (Ptr Pcre2_code)@@ -435,6 +448,9 @@ :: Ptr Pcre2_match_data -> IO () +foreign import capi safe "pcre2.h &pcre2_match_data_free_8"+ pcre2_match_data_finalizer :: FinalizerPtr Pcre2_match_data+ -- * Matching a pattern foreign import capi safe "pcre2.h" pcre2_match@@ -633,6 +649,13 @@ :: CInt -> Ptr PCRE2_UCHAR -> PCRE2_SIZE+ -> IO CInt++-- * Iterating over all matches+foreign import capi safe "pcre2.h" pcre2_next_match+ :: Ptr Pcre2_match_data+ -> Ptr PCRE2_SIZE+ -> Ptr CUInt -> IO CInt -- * Pattern serialization
src/hs/Text/Regex/Pcre2/Internal.hs view
@@ -10,14 +10,12 @@ import Control.Applicative (Alternative(..)) import Control.Exception import Control.Monad+import Control.Monad.Cont import Control.Monad.State.Strict import Data.Either (partitionEithers) import Data.Foldable (foldl', toList)-import Data.Function (fix) import Data.Functor.Identity (Identity(..)) import Data.IORef-import Data.IntMap.Strict (IntMap)-import qualified Data.IntMap.Strict as IM import Data.List.NonEmpty (NonEmpty(..)) import Data.Maybe (fromMaybe) import Data.Monoid (Alt(..), First)@@ -28,7 +26,6 @@ import Data.Typeable (cast) import Foreign import Foreign.C.Types (CInt(..), CUChar, CUInt(..))-import qualified Foreign.Concurrent as Conc import Lens.Micro import Lens.Micro.Extras (preview, view) import System.IO.Unsafe (unsafePerformIO)@@ -36,24 +33,6 @@ -- * General utilities -type FfiWrapper f = f -> IO (FunPtr f)---- | There is no @nullForeignPtr@ to pass to `withForeignPtr`, so we have to--- fake it with a `Maybe`.-withForeignOrNullPtr :: Maybe (ForeignPtr a) -> (Ptr a -> IO b) -> IO b-withForeignOrNullPtr = maybe ($ nullPtr) withForeignPtr---- | Helper so we never leak untracked 'Ptr's.-mkForeignPtr :: (Ptr a -> IO ()) -> IO (Ptr a) -> IO (ForeignPtr a)-mkForeignPtr finalize create = create >>= Conc.newForeignPtr <*> finalize---- | Helper so we never leak untracked 'FunPtr's.-mkFunPtr :: ForeignPtr b -> IO (FunPtr a) -> IO (FunPtr a)-mkFunPtr anchor create = do- funPtr <- create- Conc.addForeignPtrFinalizer anchor $ freeHaskellFunPtr funPtr- return funPtr- bitOr :: (Foldable t, Bits a) => t a -> a bitOr = foldl' (.|.) zeroBits @@ -63,21 +42,34 @@ (line, _ : rest) -> (line ++ "\n") : unchompedLines rest (lastLine, "") -> [lastLine | not $ null lastLine] --- | Equivalent to @flip fix@.------ Used to express a recursive function of one argument that is called only once--- on an initial value:------ > let go x = ... in go x0------ as:------ > fix1 x0 $ \go x -> ...-fix1 :: a -> ((a -> b) -> a -> b) -> b-fix1 x f = fix f x+-- ** FFI utilities --- ** Fast @Text@ slicing+type FfiWrapper f = f -> IO (FunPtr f) +foreign import ccall "wrapper" mkRecursionGuard :: FfiWrapper+ (CUInt -> Ptr a -> IO CInt)++foreign import ccall "wrapper" mkCallout :: FfiWrapper+ (Ptr block -> Ptr a -> IO CInt)++-- | A register to save any exception caught in a user-supplied function so we+-- can rethrow it after returning from C.+type ERef = IORef (Maybe SomeException)++saveE :: ERef -> SomeException -> IO ()+saveE eRef = writeIORef eRef . Just++-- | Create an `ERef` and allow it to be used in the creation of a `FunPtr`+-- wrapping a user-supplied function. Ensure the @FunPtr@ is freed and any+-- exception is rethrown.+mkFunPtrWithERef :: (ERef -> IO (FunPtr a)) -> ContT r IO (FunPtr a)+mkFunPtrWithERef mkFunPtr = ContT $ \continue -> do+ eRef <- newIORef Nothing+ let rethrow = readIORef eRef >>= mapM_ throwIO+ bracket (mkFunPtr eRef) freeHaskellFunPtr continue <* rethrow++-- ** Fast `Text` slicing+ data Slice = Slice {-# UNPACK #-} !Text.I8 {-# UNPACK #-} !Text.I8@@ -127,46 +119,41 @@ -- ** Streaming support --- | A @FreeT@-style stream.-data Stream b m a+-- | A @FreeT@-style stream based on the `IO` monad.+data Stream b 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.+ | StreamYield !b (Stream b a) -- ^ Yield a value and keep going.+ | StreamEffect (IO (Stream b a)) -- ^ Have an effect and keep going. deriving (Functor) -instance (Functor m) => Applicative (Stream b m) where+instance Applicative (Stream b) where pure = StreamPure- StreamPure f <*> sx = f <$> sx- StreamYield y sf <*> sx = StreamYield y $ sf <*> sx- StreamEffect msf <*> sx = StreamEffect $ msf <&> (<*> sx)+ (<*>) = ap -instance (Functor m) => Monad (Stream b m) where+instance Monad (Stream b) where StreamPure x >>= f = f x StreamYield y sx >>= f = StreamYield y $ sx >>= f StreamEffect msx >>= f = StreamEffect $ msx <&> (>>= f) -instance MonadTrans (Stream b) where- lift = StreamEffect . fmap StreamPure--instance (MonadIO m) => MonadIO (Stream b m) where- liftIO = lift . liftIO+instance MonadIO (Stream b) where+ liftIO = StreamEffect . fmap StreamPure -streamYield :: b -> Stream b m ()+streamYield :: b -> Stream b () streamYield y = StreamYield y $ StreamPure () -- | Effectfully transform yielded values.-mapMS :: (Functor m) => (b -> m c) -> Stream b m a -> Stream c m a-mapMS f = fix $ \go -> \case- StreamPure x -> StreamPure x- StreamYield y sx -> StreamEffect $ f y <&> \y' -> StreamYield y' $ go sx- StreamEffect ms -> StreamEffect $ go <$> ms+streamMap :: (b -> IO c) -> Stream b a -> Stream c a+streamMap f = go where+ go (StreamPure x) = StreamPure x+ go (StreamYield y sx) = StreamEffect $ f y <&> \y' -> StreamYield y' $ go sx+ go (StreamEffect ms) = StreamEffect $ go <$> ms --- | Unsafely, lazily tear down a `Stream` into a pure list of values yielded.-unsafeLazyStreamToList :: Stream b IO a -> [b]-unsafeLazyStreamToList = fix $ \continue -> \case+-- | Unsafely tear down a `Stream` into a lazy, pure list of values yielded.+unsafeStreamToLazyList :: Stream b a -> [b]+unsafeStreamToLazyList = \case StreamPure _ -> []- StreamYield y s -> y : continue s- StreamEffect ms -> continue $ unsafePerformIO ms+ StreamYield y s -> y : unsafeStreamToLazyList s+ StreamEffect ms -> unsafeStreamToLazyList $ unsafePerformIO ms -- * Assembling inputs into @Matcher@s and @Subber@s @@ -178,12 +165,10 @@ -- 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 ()+type Matcher = Text -> Stream MatchData () --- | A substitution function. It takes a subject and produces the number of--- 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)+-- | A substitution function.+type Subber = Text -> IO Text -- ** Options @@ -207,102 +192,107 @@ -- options and pattern items, please see the [C API -- documentation](https://pcre.org/current/doc/html/pcre2api.html). data Option- = NoOptions -- ^ `mempty`- | TwoOptions Option Option -- ^ `<>`+ = NoOptions -- ^ `mempty`+ | TwoOptions Option Option -- ^ `<>` - | AllowEmptyClass -- ^ Make @[]@ not match anything, rather than counting+ | AllowEmptyClass -- ^ Make @[]@ not match anything, rather than counting -- the @]@ as the first character of the class.- | AltBsux -- ^ Like `AltBsuxLegacy`, except with ECMAScript 6 hex literal+ | AltBsux -- ^ Like `AltBsuxLegacy`, except with ECMAScript 6 hex literal -- feature for @\\u@.- | AltBsuxLegacy -- ^ Behave like ECMAScript 5 for @\\U@, @\\u@, and @\\x@.+ | AltBsuxLegacy -- ^ Behave like ECMAScript 5 for @\\U@, @\\u@, and @\\x@. -- See 'AltBsux'.- | AltCircumflex -- ^ Match a @^@ after a newline at the end of the subject.+ | AltCircumflex -- ^ Match a @^@ after a newline at the end of the subject. -- Only relevant in multiline mode.- | AltVerbNames -- ^ Enable backslash escapes in verb names. E.g.,+ | AltVerbNames -- ^ Enable backslash escapes in verb names. E.g., -- @(*MARK:L\\(O\\)L)@.- | Anchored -- ^ Equivalent to beginning pattern with @^@.- | BadEscapeIsLiteral -- ^ Do not throw an error for unrecognized or+ | Anchored -- ^ Equivalent to beginning pattern with @^@.+ | BadEscapeIsLiteral -- ^ Do not throw an error for unrecognized or -- malformed escapes. /"This is a dangerous option."/- | Bsr Bsr -- ^ Override what @\\R@ matches (default given by `defaultBsr`).- | Caseless -- ^ Case-insensitive match. Equivalent to @(?i)@.- | DepthLimit Word32 -- ^ Override maximum depth of nested backtracking+ | Bsr Bsr -- ^ Override what @\\R@ matches (default given by `defaultBsr`).+ | Caseless -- ^ Case-insensitive match. Equivalent to @(?i)@.+ | DepthLimit Word32 -- ^ Override maximum depth of nested backtracking -- (default given by `defaultDepthLimit`). Equivalent to -- @(*LIMIT_DEPTH=@/number/@)@.- | DollarEndOnly -- ^ Don't match @$@ with a newline at the end of the+ | DollarEndOnly -- ^ Don't match @$@ with a newline at the end of the -- subject.- | DotAll -- ^ A dot also matches a (single-character) newline. Equivalent+ | DotAll -- ^ A dot also matches a (single-character) newline. Equivalent -- to @(?s)@.- | EndAnchored -- ^ More or less like ending pattern with @$@.- | EscapedCrIsLf -- ^ Interpret @\\r@ as @\\n@.- | Extended -- ^ In the pattern, ignore whitespace, and enable comments+ | Dupnames -- ^ Disable the duplicate name constraint, allowing multiple+ -- capture group names within a pattern to be identical. Equivalent to+ -- @(?J)@.+ --+ -- @since 2.2.3+ | EndAnchored -- ^ More or less like ending pattern with @$@.+ | EscapedCrIsLf -- ^ Interpret @\\r@ as @\\n@.+ | Extended -- ^ In the pattern, ignore whitespace, and enable comments -- starting with @#@. Equivalent to @(?x)@.- | ExtendedMore -- ^ Like `Extended` but also ignore spaces and tabs within+ | ExtendedMore -- ^ Like `Extended` but also ignore spaces and tabs within -- @[]@.- | FirstLine -- ^ The match must begin in the first line of the subject.- | HeapLimit Word32 -- ^ Override maximum heap memory (in kibibytes) used to+ | FirstLine -- ^ The match must begin in the first line of the subject.+ | HeapLimit Word32 -- ^ Override maximum heap memory (in kibibytes) used to -- hold backtracking information (default given by `defaultHeapLimit`). -- Equivalent to @(*LIMIT_HEAP=@/number/@)@.- | Literal -- ^ Treat the pattern as a literal string.- | MatchLimit Word32 -- ^ Override maximum value of the main matching loop's+ | Literal -- ^ Treat the pattern as a literal string.+ | MatchLimit Word32 -- ^ Override maximum value of the main matching loop's -- internal counter (default given by `defaultMatchLimit`), as a simple CPU -- throttle. Equivalent to @(*LIMIT_MATCH=@/number/@)@.- | MatchLine -- ^ Only match complete lines. Equivalent to bracketing the+ | MatchLine -- ^ Only match complete lines. Equivalent to bracketing the -- pattern with @^(?:@/pattern/@)$@.- | MatchUnsetBackRef -- ^ A backreference to an unset capture group matches+ | MatchUnsetBackRef -- ^ A backreference to an unset capture group matches -- an empty string.- | MatchWord -- ^ Only match subjects that have word boundaries at the+ | MatchWord -- ^ Only match subjects that have word boundaries at the -- beginning and end. Equivalent to bracketing the pattern with -- @\\b(?:@/pattern/@)\\b@.- | MaxPatternLength Word64 -- ^ Default is `maxBound`.- | Multiline -- ^ @^@ and @$@ mean "beginning\/end of a line" rather than+ | MaxPatternLength Word64 -- ^ Default is `maxBound`.+ | Multiline -- ^ @^@ and @$@ mean "beginning\/end of a line" rather than -- "beginning\/end of the subject". Equivalent to @(?m)@.- | NeverBackslashC -- ^ Do not allow the unsafe @\\C@ sequence.- | NeverUcp -- ^ Don't count Unicode characters in some character classes+ | NeverBackslashC -- ^ Do not allow the unsafe @\\C@ sequence.+ | NeverUcp -- ^ Don't count Unicode characters in some character classes -- such as @\\d@. Overrides @(*UCP)@.- | Newline Newline -- ^ Override what a newline is (default given by+ | Newline Newline -- ^ Override what a newline is (default given by -- `defaultNewline`). Equivalent to @(*CRLF)@ or similar.- | NoAutoCapture -- ^ Disable numbered capturing parentheses.- | NoAutoPossess -- ^ Turn off some optimizations, possibly resulting in some- -- callouts not being called.- | NoDotStarAnchor -- ^ Turn off an optimization involving @.*@, possibly+ | NoAutoCapture -- ^ Disable numbered capturing parentheses.+ | NoAutoPossess -- ^ Turn off some optimizations, possibly resulting in+ -- some callouts not being called.+ | NoDotStarAnchor -- ^ Turn off an optimization involving @.*@, possibly -- resulting in some callouts not being called.- | NoStartOptimize -- ^ Turn off some optimizations normally performed at the- -- beginning of a pattern.- | NotBol -- ^ First character of subject is not the __b__eginning __o__f+ | NoStartOptimize -- ^ Turn off some optimizations normally performed at+ -- the beginning of a pattern.+ | NotBol -- ^ First character of subject is not the __b__eginning __o__f -- __l__ine. Only affects @^@.- | NotEmpty -- ^ The 0th capture doesn't match if it would be empty.- | NotEmptyAtStart -- ^ The 0th capture doesn't match if it would be empty+ | NotEmpty -- ^ The 0th capture doesn't match if it would be empty.+ | NotEmptyAtStart -- ^ The 0th capture doesn't match if it would be empty -- and at the beginning of the subject.- | NotEol -- ^ End of subject is not the __e__nd __o__f __l__ine. Only+ | NotEol -- ^ End of subject is not the __e__nd __o__f __l__ine. Only -- affects @$@.- | OffsetLimit Word64 -- ^ Limit how far an unanchored search can advance in+ | OffsetLimit Word64 -- ^ Limit how far an unanchored search can advance in -- the subject.- | ParensLimit Word32 -- ^ Override max depth of nested parentheses (default+ | ParensLimit Word32 -- ^ Override max depth of nested parentheses (default -- given by `defaultParensLimit`).- | PartialHard -- ^ If the subject ends without finding a complete match,+ | PartialHard -- ^ If the subject ends without finding a complete match, -- stop trying alternatives and signal a partial match immediately. -- Currently we do this by throwing a `Pcre2Exception` but we should do -- better.- | PartialSoft -- ^ If the subject ends and all alternatives have been tried,- -- but no complete match is found, signal a partial match. Currently we do- -- this by throwing a `Pcre2Exception` but we should do better.- | SubGlobal -- ^ /Affects `subOpt`./ Replace all, rather than just the+ | PartialSoft -- ^ If the subject ends and all alternatives have been+ -- tried, but no complete match is found, signal a partial match. Currently+ -- we do this by throwing a `Pcre2Exception` but we should do better.+ | SubGlobal -- ^ /Affects `subOpt`./ Replace all, rather than just the -- first.- | SubLiteral -- ^ /Affects `subOpt`./ Treat the replacement as a literal+ | SubLiteral -- ^ /Affects `subOpt`./ Treat the replacement as a literal -- string.- | SubReplacementOnly -- ^ /Affects `subOpt`./ Return just the rendered+ | SubReplacementOnly -- ^ /Affects `subOpt`./ Return just the rendered -- replacement instead of it within the subject. With `SubGlobal`, all -- results are concatenated.- | SubUnknownUnset -- ^ /Affects `subOpt`./ References in the replacement to- -- non-existent captures don't error but are treated as unset.- | SubUnsetEmpty -- ^ /Affects `subOpt`./ References in the replacement to+ | SubUnknownUnset -- ^ /Affects `subOpt`./ References in the replacement+ -- to non-existent captures don't error but are treated as unset.+ | SubUnsetEmpty -- ^ /Affects `subOpt`./ References in the replacement to -- unset captures don't error but are treated as empty.- | Ucp -- ^ Count Unicode characters in some character classes such as @\\d@.- -- Incompatible with `NeverUcp`.- | Ungreedy -- ^ Invert the effect of @?@. Without it, quantifiers are+ | Ucp -- ^ Count Unicode characters in some character classes such as+ -- @\\d@. Incompatible with `NeverUcp`.+ | Ungreedy -- ^ Invert the effect of @?@. Without it, quantifiers are -- non-greedy; with it, they are greedy. Equivalent to @(?U)@. - | UnsafeCompileRecGuard (Int -> IO Bool) -- ^ Run the given guard on every+ | UnsafeCompileRecGuard (Int -> IO Bool) -- ^ Run the given guard on every -- new descent into a level of parentheses, passing the current depth as -- argument. Returning @False@ aborts pattern compilation with an -- exception. Multiples of this option before the rightmost are ignored.@@ -311,13 +301,13 @@ -- /two passes, both times triggering the recursion guard. Also, it is/ -- /triggered at the beginning of the pattern, passing 0. None of this is/ -- /documented; expect the unexpected in the presence of side effects!/- | UnsafeCallout (CalloutInfo -> IO CalloutResult) -- ^ Run the given callout- -- at every callout point (see+ | UnsafeCallout (CalloutInfo -> IO CalloutResult) -- ^ Run the given+ -- callout at every callout point (see -- [the docs](https://pcre.org/current/doc/html/pcre2callout.html) for more -- info). Multiples of this option before the rightmost are ignored.- | AutoCallout -- ^ Run callout for every pattern item. Only relevant if a+ | AutoCallout -- ^ Run callout for every pattern item. Only relevant if a -- callout is set.- | UnsafeSubCallout (SubCalloutInfo -> IO SubCalloutResult) -- ^ Run the+ | UnsafeSubCallout (SubCalloutInfo -> IO SubCalloutResult) -- ^ Run the -- given callout on every substitution. This is at most once unless -- `SubGlobal` is set. Multiples of this option before the rightmost are -- ignored.@@ -330,8 +320,8 @@ -- | What @\\R@, __b__ack__s__lash __R__, can mean. data Bsr- = BsrUnicode -- ^ any Unicode line ending sequence- | BsrAnyCrlf -- ^ @\\r@, @\\n@, or @\\r\\n@+ = BsrUnicode -- ^ any Unicode line ending sequence+ | BsrAnyCrlf -- ^ @\\r@, @\\n@, or @\\r\\n@ deriving (Eq, Show) -- | C to Haskell.@@ -339,7 +329,8 @@ bsrFromC x | x == pcre2_BSR_UNICODE = BsrUnicode | x == pcre2_BSR_ANYCRLF = BsrAnyCrlf- | otherwise = error $ "bsrFromC: bad value " ++ show x+ | otherwise = error $+ "Text.Regex.Pcre2.Internal.bsrFromC: bad value " ++ show x -- | Haskell to C. bsrToC :: Bsr -> CUInt@@ -348,12 +339,12 @@ -- | What's considered a newline. data Newline- = NewlineCr -- ^ @\\r@ only- | NewlineLf -- ^ @\\n@ only- | NewlineCrlf -- ^ @\\r\\n@ only- | NewlineAny -- ^ any Unicode line ending sequence- | NewlineAnyCrlf -- ^ any of the above- | NewlineNul -- ^ binary zero+ = NewlineCr -- ^ @\\r@ only+ | NewlineLf -- ^ @\\n@ only+ | NewlineCrlf -- ^ @\\r\\n@ only+ | NewlineAny -- ^ any Unicode line ending sequence+ | NewlineAnyCrlf -- ^ any of the above+ | NewlineNul -- ^ binary zero deriving (Eq, Show) -- | C to Haskell.@@ -365,7 +356,8 @@ | x == pcre2_NEWLINE_ANY = NewlineAny | x == pcre2_NEWLINE_ANYCRLF = NewlineAnyCrlf | x == pcre2_NEWLINE_NUL = NewlineNul- | otherwise = error $ "newlineFromC: bad value " ++ show x+ | otherwise = error $+ "Text.Regex.Pcre2.Internal.newlineFromC: bad value " ++ show x -- | Haskell to C. newlineToC :: Newline -> CUInt@@ -377,70 +369,81 @@ newlineToC NewlineNul = pcre2_NEWLINE_NUL -- | Input for user-defined callouts.-data CalloutInfo- = CalloutInfo{- -- | The index of which callout point we're on.- calloutIndex :: CalloutIndex,- -- | The captures that have been set so far.- calloutCaptures :: NonEmpty (Maybe Text),- -- | The original subject.- calloutSubject :: Text,- -- | The name of the most recently passed @(*MARK)@, @(*PRUNE)@, or- -- @(*THEN)@, if any.- calloutMark :: Maybe Text,- -- | Is this the first callout after the start of matching?- calloutIsFirst :: Bool,- -- | Has a backtrack occurred since the previous callout, or the- -- beginning of matching if no previous callouts?- calloutBacktracked :: Bool}+data CalloutInfo = CalloutInfo{+ -- | The index of which callout point we're on.+ calloutIndex :: CalloutIndex,+ -- | The captures that have been set so far.+ calloutCaptures :: NonEmpty (Maybe Text),+ -- | The original subject.+ calloutSubject :: Text,+ -- | The name of the most recently passed @(*MARK)@, @(*PRUNE)@, or+ -- @(*THEN)@, if any.+ calloutMark :: Maybe Text,+ -- | Is this the first callout after the start of matching?+ calloutIsFirst :: Bool,+ -- | Has a backtrack occurred since the previous callout, or the beginning+ -- of matching if no previous callouts?+ calloutBacktracked :: Bool}+ deriving (Show, Eq) -- | What caused the callout. data CalloutIndex- = CalloutNumber Int -- ^ Numerical callout.- | CalloutName Text -- ^ String callout.- | CalloutAuto Int Int -- ^ The item located at this half-open range of+ = CalloutNumber Int -- ^ Numerical callout.+ | CalloutName Text -- ^ String callout.+ | CalloutAuto Int Int -- ^ The item located at this half-open range of -- offsets within the pattern. See `AutoCallout`. deriving (Show, Eq) -- | Callout functions return one of these values, which dictates what happens -- next in the match. data CalloutResult- = CalloutProceed -- ^ Keep going.- | CalloutNoMatchHere -- ^ Fail the current capture, but not the whole match.- -- For example, backtracking may occur.- | CalloutNoMatch -- ^ Fail the whole match.+ = CalloutProceed -- ^ Keep going.+ | CalloutNoMatchHere -- ^ Fail the current capture, but not the whole+ -- match. For example, backtracking may occur.+ | CalloutNoMatch -- ^ Fail the whole match. deriving (Show, Eq) +-- | Haskell to C.+calloutResultToC :: CalloutResult -> CInt+calloutResultToC CalloutProceed = 0+calloutResultToC CalloutNoMatchHere = 1+calloutResultToC CalloutNoMatch = pcre2_ERROR_NOMATCH+ -- | Input for user-defined substitution callouts.-data SubCalloutInfo- = SubCalloutInfo{- -- | The 1-based index of which substitution we're on. Only goes past 1- -- during global substitutions.- subCalloutSubsCount :: Int,- -- | The captures that have been set so far.- subCalloutCaptures :: NonEmpty (Maybe Text),- -- | The original subject.- subCalloutSubject :: Text,- -- | The replacement.- subCalloutReplacement :: Text}+data SubCalloutInfo = SubCalloutInfo{+ -- | The 1-based index of which substitution we're on. Only goes past 1+ -- during global substitutions.+ subCalloutSubsCount :: Int,+ -- | The captures that have been set so far.+ subCalloutCaptures :: NonEmpty (Maybe Text),+ -- | The original subject.+ subCalloutSubject :: Text,+ -- | The replacement.+ subCalloutReplacement :: Text}+ deriving (Show, Eq) -- | Substitution callout functions return one of these values, which dictates -- what happens next in the substitution. data SubCalloutResult- = SubCalloutAccept -- ^ Succeed, and keep going if in global mode.- | SubCalloutSkip -- ^ Do not perform this substitution, but keep going if in- -- global mode.- | SubCalloutAbort -- ^ Do not perform this or any subsequent substitutions.+ = SubCalloutAccept -- ^ Succeed, and keep going if in global mode.+ | SubCalloutSkip -- ^ Do not perform this substitution, but keep going if+ -- in global mode.+ | SubCalloutAbort -- ^ Do not perform this or any subsequent substitutions. deriving (Show, Eq) +-- | Haskell to C.+subCalloutResultToC :: SubCalloutResult -> CInt+subCalloutResultToC SubCalloutAccept = 0+subCalloutResultToC SubCalloutSkip = 1+subCalloutResultToC SubCalloutAbort = -1+ -- ** Lower-level representation of options and C data -type CompileContext = ForeignPtr Pcre2_compile_context-type Code = ForeignPtr Pcre2_code-type MatchContext = ForeignPtr Pcre2_match_context-type MatchData = ForeignPtr Pcre2_match_data+type Code = ForeignPtr Pcre2_code+type MatchContext = ForeignPtr Pcre2_match_context+type MatchData = ForeignPtr Pcre2_match_data -- | An `Option` can result in multiple \"plans\". applyOption :: Option -> [AppliedOption]@@ -458,6 +461,7 @@ Caseless -> [CompileOption pcre2_CASELESS] DollarEndOnly -> [CompileOption pcre2_DOLLAR_ENDONLY] DotAll -> [CompileOption pcre2_DOTALL]+ Dupnames -> [CompileOption pcre2_DUPNAMES] EndAnchored -> [CompileOption pcre2_ENDANCHORED] Extended -> [CompileOption pcre2_EXTENDED] ExtendedMore -> [CompileOption pcre2_EXTENDED_MORE]@@ -507,12 +511,6 @@ SubUnknownUnset -> [MatchOption pcre2_SUBSTITUTE_UNKNOWN_UNSET] SubUnsetEmpty -> [MatchOption pcre2_SUBSTITUTE_UNSET_EMPTY] - -- CalloutOption- UnsafeCallout f -> [CalloutOption f]-- -- SubCalloutOption- UnsafeSubCallout f -> [SubCalloutOption f]- -- MatchContextOption DepthLimit limit -> ctxUpd MatchContextOption pcre2_set_depth_limit (fromIntegral limit)@@ -524,21 +522,26 @@ CompileOption pcre2_USE_OFFSET_LIMIT : ctxUpd MatchContextOption pcre2_set_offset_limit (fromIntegral limit) + -- CalloutOption+ UnsafeCallout f -> [CalloutOption f]++ -- SubCalloutOption+ UnsafeSubCallout f -> [SubCalloutOption f]+ where- ctxUpd ctor f x = [ctor $ \ctx -> withForeignPtr ctx applyAndCheck] where- applyAndCheck ctxPtr = f ctxPtr x >>= check (== 0)+ ctxUpd ctor f x = [ctor $ \ctxPtr -> f ctxPtr x >>= check (== 0)] -- | Intermediate representation of options expressing what effect they'll have -- on which stage of regex compilation\/execution. Also provide fake @Prism'@s. data AppliedOption = CompileOption !CUInt | CompileExtraOption !CUInt- | CompileContextOption !(CompileContext -> IO ())+ | CompileContextOption !(Ptr Pcre2_compile_context -> IO ()) | CompileRecGuardOption !(Int -> IO Bool) | MatchOption !CUInt+ | MatchContextOption !(Ptr Pcre2_match_context -> IO ()) | CalloutOption !(CalloutInfo -> IO CalloutResult) | SubCalloutOption !(SubCalloutInfo -> IO SubCalloutResult)- | MatchContextOption !(MatchContext -> IO ()) _CompileOption f = \case CompileOption x -> CompileOption <$> f x; o -> pure o@@ -550,12 +553,12 @@ \case CompileRecGuardOption x -> CompileRecGuardOption <$> f x; o -> pure o _MatchOption f = \case MatchOption x -> MatchOption <$> f x; o -> pure o+_MatchContextOption f =+ \case MatchContextOption x -> MatchContextOption <$> f x; o -> pure o _CalloutOption f = \case CalloutOption x -> CalloutOption <$> f x; o -> pure o _SubCalloutOption f = \case SubCalloutOption x -> SubCalloutOption <$> f x; o -> pure o-_MatchContextOption f =- \case MatchContextOption x -> MatchContextOption <$> f x; o -> pure o -- ** Extracting options at the right times --@@ -571,84 +574,72 @@ extractOptsOf prism = state $ partitionEithers . map discrim where discrim opt = maybe (Right opt) Left $ opt ^? prism --- | Prepare to compile a `Code`.-extractCompileEnv :: ExtractOpts CompileEnv-extractCompileEnv = do- ctxUpds <- extractOptsOf _CompileContextOption- xtraOpts <- bitOr <$> extractOptsOf _CompileExtraOption- recGuard <- preview _last <$> extractOptsOf _CompileRecGuardOption+-- | Helper for `extractCode`. Create a @pcre2_compile_context@ pointer if+-- necessary, apply any options, return it, and clean up after use.+mkCompileCtxPtr+ :: CUInt -- ^ extra compile options+ -> [Ptr Pcre2_compile_context -> IO ()] -- ^ updates to the context+ -> Maybe (Int -> IO Bool) -- ^ user recursion guard function+ -> ContT r IO (Ptr Pcre2_compile_context)+mkCompileCtxPtr 0 [] Nothing = return nullPtr+mkCompileCtxPtr xtraOpts ctxUpds recGuard = do+ ctxPtr <- ContT $ bracket+ (pcre2_compile_context_create nullPtr)+ pcre2_compile_context_free - if null ctxUpds && xtraOpts == 0 && null recGuard- then return CompileEnv{- compileEnvCtx = Nothing,- compileEnvERef = Nothing}+ liftIO $ forM_ ctxUpds $ \update -> update ctxPtr - else liftIO $ do- ctx <- mkForeignPtr pcre2_compile_context_free $- pcre2_compile_context_create nullPtr+ when (xtraOpts /= 0) $ liftIO $+ pcre2_set_compile_extra_options ctxPtr xtraOpts >>= check (== 0) - forM_ ctxUpds $ \update -> update ctx+ forM_ recGuard $ \f -> do+ funPtr <- mkFunPtrWithERef $ \eRef -> mkRecursionGuard $ \depth _ ->+ try (f (fromIntegral depth) >>= evaluate) >>= \case+ Right success -> return $ if success then 0 else 1+ Left e -> saveE eRef e >> return 1+ liftIO $ pcre2_set_compile_recursion_guard ctxPtr funPtr nullPtr >>=+ check (== 0) - when (xtraOpts /= 0) $ withForeignPtr ctx $ \ctxPtr ->- pcre2_set_compile_extra_options ctxPtr xtraOpts >>= check (== 0)+ return ctxPtr - compileEnvERef <- forM recGuard $ \f -> do- eRef <- newIORef Nothing- funPtr <- mkFunPtr ctx $ mkRecursionGuard $ \depth _ -> do- resultOrE <- try $ f (fromIntegral depth) >>= evaluate- case resultOrE of- Right success -> return $ if success then 0 else 1- Left e -> writeIORef eRef (Just e) >> return 1- withForeignPtr ctx $ \ctxPtr ->- pcre2_set_compile_recursion_guard ctxPtr funPtr nullPtr >>=- check (== 0)- return eRef+-- | Compile a @pcre2_code@, which is what PCRE2 calls a compiled pattern.+extractCode :: Text -> ExtractOpts Code+extractCode patt = do+ opts <- bitOr <$> extractOptsOf _CompileOption - return CompileEnv{compileEnvCtx = Just ctx, ..}+ xtraOpts <- bitOr <$> extractOptsOf _CompileExtraOption+ ctxUpds <- extractOptsOf _CompileContextOption+ recGuard <- preview _last <$> extractOptsOf _CompileRecGuardOption --- | Inputs to `Code` compilation besides the pattern.-data CompileEnv = CompileEnv{- compileEnvCtx :: !(Maybe CompileContext),- -- | A register for catching exceptions thrown in recursion guards, if- -- needed.- compileEnvERef :: !(Maybe (IORef (Maybe SomeException)))}+ liftIO $ evalContT $ do+ (pattPtr, pattCUs) <- ContT $ Text.useAsPtr patt . curry+ errorCodePtr <- ContT alloca+ errorOffPtr <- ContT alloca --- | Compile a `Code`.-extractCode :: Text -> CompileEnv -> ExtractOpts Code-extractCode patt CompileEnv{..} = do- opts <- bitOr <$> extractOptsOf _CompileOption+ ctxPtr <- mkCompileCtxPtr xtraOpts ctxUpds recGuard - liftIO $ mkForeignPtr pcre2_code_free $- Text.useAsPtr patt $ \pattPtr pattCUs ->- alloca $ \errorCodePtr ->- alloca $ \errorOffPtr ->- withForeignOrNullPtr compileEnvCtx $ \ctxPtr -> do- codePtr <- pcre2_compile- (toCUs pattPtr)- (fromIntegral pattCUs)- (opts .|. pcre2_UTF)- errorCodePtr- errorOffPtr- ctxPtr- when (codePtr == nullPtr) $ do- -- Re-throw exception (if any) from recursion guard (if any)- forM_ compileEnvERef $ readIORef >=> mapM_ throwIO- -- Otherwise throw PCRE2 error- errorCode <- peek errorCodePtr- offCUs <- peek errorOffPtr- throwIO $ Pcre2CompileException errorCode patt offCUs+ codePtr <- liftIO $ pcre2_compile+ (toCUs pattPtr)+ (fromIntegral pattCUs)+ (opts .|. pcre2_UTF)+ errorCodePtr+ errorOffPtr+ ctxPtr+ when (codePtr == nullPtr) $ liftIO $ do+ errorCode <- peek errorCodePtr+ offCUs <- peek errorOffPtr+ throwIO $ Pcre2CompileException errorCode patt offCUs - return codePtr+ liftIO $ newForeignPtr pcre2_code_finalizer codePtr --- | `Code` and auxiliary compiled data used in preparation for a match or--- substitution. This remains constant for the lifetime of a `Matcher` or--- `Subber`.+-- | `Code` and auxiliary data used in preparation for a match or substitution.+-- This remains for the lifetime of a `Matcher` or `Subber`. data MatchEnv = MatchEnv{- matchEnvCode :: Code,- matchEnvOpts :: CUInt,- matchEnvCtx :: Maybe MatchContext,- matchEnvCallout :: Maybe (CalloutInfo -> IO CalloutResult),- matchEnvSubCallout :: Maybe (SubCalloutInfo -> IO SubCalloutResult)}+ matchEnvCode :: !Code,+ matchEnvOpts :: !CUInt,+ matchEnvCtx :: !(Maybe MatchContext),+ matchEnvCallout :: !(Maybe (CalloutInfo -> IO CalloutResult)),+ matchEnvSubCallout :: !(Maybe (SubCalloutInfo -> IO SubCalloutResult))} -- | Prepare a matching function after compiling the underlying @pcre2_code@. extractMatchEnv :: Code -> ExtractOpts MatchEnv@@ -658,9 +649,10 @@ matchEnvCtx <- extractOptsOf _MatchContextOption >>= \case [] -> return Nothing ctxUpds -> liftIO $ Just <$> do- ctx <- mkForeignPtr pcre2_match_context_free $- pcre2_match_context_create nullPtr- forM_ ctxUpds $ \update -> update ctx+ ctx <- pcre2_match_context_create nullPtr >>=+ newForeignPtr pcre2_match_context_finalizer+ withForeignPtr ctx $ \ctxPtr ->+ forM_ ctxUpds $ \update -> update ctxPtr return ctx matchEnvCallout <- preview _last <$> extractOptsOf _CalloutOption@@ -673,58 +665,58 @@ userMatchEnv :: Option -> Text -> IO MatchEnv userMatchEnv option patt = runStateT extractAll (applyOption option) <&> \case (matchEnv, []) -> matchEnv- _ -> error "BUG! Options not fully extracted"+ _ -> error+ "Text.Regex.Pcre2.Internal.userMatchEnv: options not fully extracted" where- extractAll = extractCompileEnv >>= extractCode patt >>= extractMatchEnv+ extractAll = extractCode patt >>= extractMatchEnv -- | A `MatchEnv` is sufficient to fully implement a matching function.-matcherWithEnv :: MatchEnv -> Matcher-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+matcherFromEnv :: MatchEnv -> Matcher+matcherFromEnv matchEnv@MatchEnv{..} subject = do+ (subjForeignPtr, subjCUs) <- liftIO $ Text.asForeignPtr subject+ matchData <- liftIO $ withForeignPtr matchEnvCode $ \codePtr ->+ pcre2_match_data_create_from_pattern codePtr nullPtr >>=+ newForeignPtr pcre2_match_data_finalizer -- 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)- (fromIntegral subjCUs)- curOff- matchEnvOpts- matchDataPtr- ctxPtr+ evalContT $ callCC $ \stop -> do+ (continue, curOff) <- label 0 + result <- liftIO $ evalContT $ do+ codePtr <- ContT $ withForeignPtr matchEnvCode+ subjPtr <- ContT $ withForeignPtr subjForeignPtr+ matchDataPtr <- ContT $ withForeignPtr matchData+ ctxPtr <- mkMatchCtxPtr matchEnv subject++ liftIO $ pcre2_match+ codePtr+ (toCUs subjPtr)+ (fromIntegral subjCUs)+ curOff+ matchEnvOpts+ matchDataPtr+ ctxPtr+ -- Handle no match and errors- unless (result == pcre2_ERROR_NOMATCH) $ do- when (result == pcre2_ERROR_CALLOUT) $- liftIO $ maybeRethrow matchTempEnvRef- liftIO $ check (> 0) result+ when (result == pcre2_ERROR_NOMATCH) $ stop ()+ liftIO $ check (> 0) result - streamYield matchData+ lift $ streamYield matchData - -- Determine next starting offset- nextOff <- liftIO $ do- ovecPtr <- withForeignPtr matchData- pcre2_get_ovector_pointer- curOffEnd <- peekElemOff ovecPtr 1- -- Prevent infinite loop upon empty match- return $ max curOffEnd (curOff + 1)+ -- Determine next starting offset+ nextOff <- liftIO $ do+ 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- unless (nextOff > fromIntegral subjCUs) $ continue nextOff+ -- Handle end of subject+ unless (nextOff > fromIntegral subjCUs) $ continue nextOff -- | Helper to generate public matching functions. pureUserMatcher :: Option -> Text -> Matcher pureUserMatcher option patt =- matcherWithEnv $ unsafePerformIO $ userMatchEnv option patt+ matcherFromEnv $ unsafePerformIO $ userMatchEnv option patt -- | A `Subber` works by first writing results to a reasonably-sized buffer. If -- we run out of room, PCRE2 allows us to simulate the rest of the substitution@@ -739,69 +731,79 @@ -- -- * those substitution callouts that had run the first time. ----- Therefore, the first time, log the substitution callout indexes that had run--- along with their results, and replay the log the second time, returning those--- same results without re-incurring effects.-subberWithEnv :: MatchEnv -> Text -> Subber-subberWithEnv firstMatchEnv@MatchEnv{..} replacement subject =- withForeignPtr matchEnvCode $ \codePtr ->- Text.useAsPtr subject $ \subjPtr subjCUs ->- Text.useAsPtr replacement $ \replPtr replCUs ->- with (fromIntegral initOutLen) $ \outLenPtr -> do- let run :: CUInt -> Ptr Pcre2_match_context -> PCRE2_SPTR -> IO CInt- run curOpts ctxPtr outBufPtr = pcre2_substitute- codePtr- (toCUs subjPtr)- (fromIntegral subjCUs)- 0- (matchEnvOpts .|. curOpts)- nullPtr- ctxPtr- (toCUs replPtr)- (fromIntegral replCUs)- outBufPtr- outLenPtr+-- Therefore, the first time, log the substitution callout results, and replay+-- the log the second time, returning them without re-incurring effects.+subberFromEnvAndRepl :: MatchEnv -> Text -> Subber+subberFromEnvAndRepl matchEnv0@MatchEnv{..} replacement subject = evalContT $ do+ codePtr <- ContT $ withForeignPtr matchEnvCode+ (subjPtr, subjCUs) <- ContT $ Text.useAsPtr subject . curry+ (replPtr, replCUs) <- ContT $ Text.useAsPtr replacement . curry+ outLenPtr <- ContT $ with $ fromIntegral initOutLen - checkAndGetOutput :: CInt -> PCRE2_SPTR -> IO (CInt, Text)- checkAndGetOutput 0 _ = return (0, subject)- checkAndGetOutput result outBufPtr = do- check (> 0) result- outLen <- peek outLenPtr- out <- Text.fromPtr (fromCUs outBufPtr) (fromIntegral outLen)- return (result, out)+ let run :: CUInt -> Ptr Pcre2_match_context -> PCRE2_SPTR -> IO CInt+ run curOpts ctxPtr outBufPtr = pcre2_substitute+ codePtr+ (toCUs subjPtr)+ (fromIntegral subjCUs)+ 0+ (matchEnvOpts .|. curOpts)+ nullPtr+ ctxPtr+ (toCUs replPtr)+ (fromIntegral replCUs)+ outBufPtr+ outLenPtr - MatchTempEnv{..} <- mkMatchTempEnv firstMatchEnv subject- firstAttempt <- withForeignOrNullPtr matchTempEnvCtx $ \ctxPtr ->- allocaArray initOutLen $ \outBufPtr -> do- result <- run pcre2_SUBSTITUTE_OVERFLOW_LENGTH ctxPtr outBufPtr- maybeRethrow matchTempEnvRef- if result == pcre2_ERROR_NOMEMORY- then Left <$> case matchTempEnvRef of- Nothing -> return IM.empty- Just ref -> calloutStateSubsLog <$> readIORef ref- else Right <$> checkAndGetOutput result outBufPtr+ checkAndGetOutput :: CInt -> PCRE2_SPTR -> IO Text+ checkAndGetOutput 0 _ = return subject+ checkAndGetOutput result outBufPtr = do+ check (> 0) result+ outLen <- peek outLenPtr+ Text.fromPtr (fromCUs outBufPtr) (fromIntegral outLen) - case firstAttempt of- Right resultAndOutput -> return resultAndOutput- Left subsLog -> do- -- The output was bigger than we guessed. Try again.- computedOutLen <- fromIntegral <$> peek outLenPtr- let finalMatchEnv = firstMatchEnv{- -- Do not run regular callouts again.- matchEnvCallout = Nothing,- -- Do not run any substitution callouts run previously.- matchEnvSubCallout = fastFwd <$> matchEnvSubCallout}- fastFwd f = \info ->- case subsLog IM.!? subCalloutSubsCount info of- Just result -> return result- Nothing -> f info- MatchTempEnv{..} <- mkMatchTempEnv finalMatchEnv subject- withForeignOrNullPtr matchTempEnvCtx $ \ctxPtr ->- allocaArray computedOutLen $ \outBufPtr -> do- result <- run 0 ctxPtr outBufPtr- maybeRethrow matchTempEnvRef- checkAndGetOutput result outBufPtr+ callCC $ \stop -> do+ -- Prepare first attempt.+ maybeLogRef <- forM matchEnvSubCallout $ \_ -> liftIO $ newIORef []+ let logging logRef f info = do+ r <- f info+ modifyIORef' logRef (r :)+ return r+ matchEnv1 = matchEnv0{+ matchEnvSubCallout =+ logging <$> maybeLogRef <*> matchEnvSubCallout} + -- Run first attempt and return early if success.+ maybeOut1 <- liftIO $ evalContT $ do+ ctxPtr <- mkMatchCtxPtr matchEnv1 subject+ outBufPtr <- ContT $ allocaArray initOutLen+ result1 <- liftIO $+ run pcre2_SUBSTITUTE_OVERFLOW_LENGTH ctxPtr outBufPtr+ if result1 == pcre2_ERROR_NOMEMORY+ then return Nothing+ else liftIO $ Just <$> checkAndGetOutput result1 outBufPtr+ mapM_ stop maybeOut1++ -- The output was bigger than we guessed. Prepare second attempt.+ computedOutLen <- liftIO $ fromIntegral <$> peek outLenPtr+ -- Prepare the log to be replayed in FIFO order.+ forM_ maybeLogRef $ \logRef -> liftIO $ modifyIORef logRef reverse+ let replaying logRef f info = readIORef logRef >>= \case+ r : rs -> writeIORef logRef rs >> return r+ [] -> f info+ matchEnv2 = matchEnv0{+ -- Do not run regular callouts again.+ matchEnvCallout = Nothing,+ -- Do not run any substitution callouts run previously.+ matchEnvSubCallout =+ replaying <$> maybeLogRef <*> matchEnvSubCallout}++ -- Run second attempt.+ ctxPtr <- mkMatchCtxPtr matchEnv2 subject+ outBufPtr <- ContT $ allocaArray computedOutLen+ liftIO $ do+ result2 <- run 0 ctxPtr outBufPtr+ checkAndGetOutput result2 outBufPtr+ where -- Guess the size of the output to be <= 2x that of the subject. initOutLen = Text.lengthWord8 subject * 2@@ -810,103 +812,45 @@ -- `pureUserMatcher`. pureUserSubber :: Option -> Text -> Text -> Subber pureUserSubber option patt =- subberWithEnv $ unsafePerformIO $ userMatchEnv option patt+ subberFromEnvAndRepl $ unsafePerformIO $ userMatchEnv option patt -- | Generate per-call data for @pcre2_match()@ etc., to accommodate callouts.------ We need to save and inspect state that occurs in potentially concurrent--- matches. This means a new state ref for each match, which means a new--- `FunPtr` to close on it, which means a new match context to set it to.-mkMatchTempEnv- :: MatchEnv- -> Text -- ^ Callout info requires access to the original subject.- -> IO MatchTempEnv-mkMatchTempEnv MatchEnv{..} subject- | null matchEnvCallout && null matchEnvSubCallout = return MatchTempEnv{- matchTempEnvCtx = matchEnvCtx,- matchTempEnvRef = Nothing}+-- Analogous to `mkCompileCtxPtr`.+mkMatchCtxPtr :: MatchEnv -> Text -> ContT r IO (Ptr Pcre2_match_context)+mkMatchCtxPtr MatchEnv{..} subject+ | null matchEnvCallout && null matchEnvSubCallout =+ maybe (return nullPtr) (ContT . withForeignPtr) matchEnvCtx | otherwise = do- stateRef <- newIORef CalloutState{- calloutStateException = Nothing,- calloutStateSubsLog = IM.empty}-- ctx <- mkForeignPtr pcre2_match_context_free $ case matchEnvCtx of- -- No pre-existing match context, so create one afresh.- Nothing -> pcre2_match_context_create nullPtr- -- Pre-existing match context, so copy it.- Just ctx -> withForeignPtr ctx pcre2_match_context_copy-- -- Install C function pointers in the @pcre2_match_context@. When- -- dereferenced and called, they will force the user-supplied Haskell- -- callout functions and their results, catching any exceptions and- -- saving them.+ ctxPtr <- ContT $+ let acquireCtxPtr = case matchEnvCtx of+ -- No pre-existing match context, so create one afresh.+ Nothing -> pcre2_match_context_create nullPtr+ -- Pre-existing match context, so copy it.+ Just ctx -> withForeignPtr ctx pcre2_match_context_copy+ in bracket acquireCtxPtr pcre2_match_context_free - -- Install callout, if any forM_ matchEnvCallout $ \f -> do- funPtr <- mkFunPtr ctx $ mkCallout $ \blockPtr _ -> do+ funPtr <- mkFunPtrWithERef $ \eRef -> mkCallout $ \blockPtr _ -> do info <- getCalloutInfo subject blockPtr- resultOrE <- try $ f info >>= evaluate- case resultOrE of- Right result -> return $ case result of- CalloutProceed -> 0- CalloutNoMatchHere -> 1- CalloutNoMatch -> pcre2_ERROR_NOMATCH- Left e -> do- modifyIORef' stateRef $ _calloutStateException ?~ e- return pcre2_ERROR_CALLOUT- withForeignPtr ctx $ \ctxPtr ->- pcre2_set_callout ctxPtr funPtr nullPtr >>= check (== 0)+ try (f info >>= evaluate) >>= \case+ Right result -> return $ calloutResultToC result+ Left e -> saveE eRef e >> return pcre2_ERROR_CALLOUT+ liftIO $ pcre2_set_callout ctxPtr funPtr nullPtr >>= check (== 0) - -- Install substitution callout, if any forM_ matchEnvSubCallout $ \f -> do- funPtr <- mkFunPtr ctx $ mkCallout $ \blockPtr _ -> do+ funPtr <- mkFunPtrWithERef $ \eRef -> mkCallout $ \blockPtr _ -> do info <- getSubCalloutInfo subject blockPtr- resultOrE <- try $ f info >>= evaluate- case resultOrE of- Right result -> do- modifyIORef' stateRef $ over _calloutStateSubsLog $- IM.insert (subCalloutSubsCount info) result- return $ case result of- SubCalloutAccept -> 0- SubCalloutSkip -> 1- SubCalloutAbort -> -1- Left e -> do- modifyIORef' stateRef $ _calloutStateException ?~ e- return (-1)- withForeignPtr ctx $ \ctxPtr ->- pcre2_set_substitute_callout ctxPtr funPtr nullPtr >>=- check (== 0)-- return MatchTempEnv{- matchTempEnvCtx = Just ctx,- matchTempEnvRef = Just stateRef}---- | Per-call data for @pcre2_match()@ etc.-data MatchTempEnv = MatchTempEnv{- matchTempEnvCtx :: !(Maybe MatchContext),- matchTempEnvRef :: !(Maybe (IORef CalloutState))}---- | Data computed during callouts that will be stashed in an IORef and--- inspected after @pcre2_match()@ or similar completes. `Lens'`s included.-data CalloutState = CalloutState{- calloutStateException :: !(Maybe SomeException),- calloutStateSubsLog :: !(IntMap SubCalloutResult)}--_calloutStateException f CalloutState{..} =- f calloutStateException <&> \calloutStateException -> CalloutState{..}-_calloutStateSubsLog f CalloutState{..} =- f calloutStateSubsLog <&> \calloutStateSubsLog -> CalloutState{..}--foreign import ccall "wrapper" mkRecursionGuard :: FfiWrapper- (CUInt -> Ptr a -> IO CInt)+ try (f info >>= evaluate) >>= \case+ Right result -> return $ subCalloutResultToC result+ Left e -> saveE eRef e >> return (-1)+ liftIO $ pcre2_set_substitute_callout ctxPtr funPtr nullPtr >>=+ check (== 0) -foreign import ccall "wrapper" mkCallout :: FfiWrapper- (Ptr block -> Ptr a -> IO CInt)+ return ctxPtr -- | Within a callout, marshal the original subject and @pcre2_callout_block@--- data to Haskell and present to the user function. Ensure no pointers are--- leaked!+-- data to Haskell and present to the user function. getCalloutInfo :: Text -> Ptr Pcre2_callout_block -> IO CalloutInfo getCalloutInfo calloutSubject blockPtr = do calloutIndex <- do@@ -949,7 +893,7 @@ -- | Within a substitution callout, marshal the original subject and -- @pcre2_substitute_callout_block@ data to Haskell and present to the user--- function. Ensure no pointers are leaked!+-- function. getSubCalloutInfo :: Text -> Ptr Pcre2_substitute_callout_block -> IO SubCalloutInfo getSubCalloutInfo subCalloutSubject blockPtr = do@@ -974,10 +918,6 @@ return SubCalloutInfo{..} --- | If there was a callout and it threw an exception, rethrow it.-maybeRethrow :: Maybe (IORef CalloutState) -> IO ()-maybeRethrow = mapM_ $ readIORef >=> mapM_ throwIO . calloutStateException- -- * Packaging @Matcher@s and @Subber@s as public API functions -- | The most general form of a matching function, which can also be used as a@@ -993,8 +933,8 @@ in Text.concat $ foldr mkSegments termSegments beforeAndAfter 0 where- sliceAndCaptureTs = unsafeLazyStreamToList $- mapMS (fromMatch >=> mapM enrichWithCapture) $ matcher subject+ sliceAndCaptureTs = unsafeStreamToLazyList $+ streamMap (fromMatch >=> mapM enrichWithCapture) $ matcher subject enrichWithCapture slice = do capture <- evaluate $ smartSlice subject slice return (slice, capture)@@ -1034,7 +974,7 @@ -- Template Haskell-generated @ViewPatterns@. type FromMatch t = MatchData -> IO (t Slice) --- | Read all specifically indexed captures' offsets from match results.+-- | Read all specifically-indexed captures' offsets from match results. getWhitelistedSlices :: (Traversable t) => t Int -> FromMatch t getWhitelistedSlices whitelist matchData = withForeignPtr matchData $ \matchDataPtr -> do@@ -1110,10 +1050,10 @@ -- >>> 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- -> Text -- ^ replacement- -> Text -- ^ subject- -> Text -- ^ result+ :: Text -- ^ pattern+ -> Text -- ^ replacement+ -> Text -- ^ subject+ -> Text -- ^ result sub = subOpt mempty -- | Perform substitutions globally.@@ -1129,7 +1069,7 @@ -- @ subOpt :: Option -> Text -> Text -> Text -> Text subOpt option patt replacement =- snd . unsafePerformIO . pureUserSubber option patt replacement+ unsafePerformIO . pureUserSubber option patt replacement -- | Given a pattern, produce a traversal (0 or more targets) that focuses from -- a subject to each non-empty list of captures that pattern matches.@@ -1294,10 +1234,18 @@ jitTarget :: Maybe Text jitTarget = getConfigString pcre2_CONFIG_JITTARGET --- | Number of bytes used for internal linkage in compiled regexes.+-- | Number of bytes PCRE2 was instructed to use for internal linkage in+-- compiled regexes. linkSize :: Int linkSize = fromIntegral $ getConfigNumeric pcre2_CONFIG_LINKSIZE +-- | Number of bytes actually used for internal linkage in compiled regexes.+--+-- @since 2.2.3+effectivelinkSize :: Int+effectivelinkSize =+ fromIntegral $ getConfigNumeric pcre2_CONFIG_EFFECTIVE_LINKSIZE+ -- | See `MatchLimit`. defaultMatchLimit :: Int defaultMatchLimit = fromIntegral $ getConfigNumeric pcre2_CONFIG_MATCHLIMIT@@ -1331,6 +1279,5 @@ -- | Version of the built-in C library. The versioning scheme is that PCRE -- legacy is 8.x and PCRE2 is 10.x, so this should be @10.@/something/. pcreVersion :: Text-pcreVersion = case getConfigString pcre2_CONFIG_VERSION of- Just v -> v- Nothing -> error "pcreVersion: unable to get string"+pcreVersion = fromMaybe e $ getConfigString pcre2_CONFIG_VERSION where+ e = error "Text.Regex.Pcre2.Internal.pcreVersion: unable to get string"
src/hs/Text/Regex/Pcre2/TH.hs view
@@ -44,9 +44,7 @@ -- information about the number and names of those captures. -- -- 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.+-- `capture`\/`_capture`, relying on type inference. -- -- After obtaining `Captures` it's recommended to immediately consume them and -- transform them into application-level data, to avoid leaking the types.@@ -56,6 +54,8 @@ -- | The kind of `Captures`'s @info@. The first number is the total number of -- parenthesized captures, and the list is a lookup table from capture names to -- numbers.+--+-- @since 2.2.3 type CapturesInfo = (Nat, [(Symbol, Nat)]) -- | Look up the number of a capture at compile time, either by number or by@@ -97,9 +97,18 @@ -- | Like `capture` but focus from a `Captures` to a capture. _capture :: forall i info num. (CaptNum i info ~ num, KnownNat num) => Lens' (Captures info) Text-_capture = _Captures . singular (ix $ fromInteger $ natVal @num Proxy) where- _Captures f (Captures cs) = Captures <$> f cs+_capture = _Captures . singular (ix $ fromInteger $ natVal @num Proxy) +_Captures :: Lens' (Captures info) (NonEmpty Text)+_Captures f (Captures cs) = Captures <$> f cs++-- | Extract the underlying captures from a Template Haskell-generated+-- @Captures@. This loses type-level information.+--+-- @since 2.2.3+getCaptures :: Captures info -> NonEmpty Text+getCaptures = view _Captures+ -- | Unexported, top-level `IORef` that's created upon the first runtime -- evaluation of a Template Haskell `Matcher`. globalMatcherCache :: IORef (Map Text Matcher)@@ -117,12 +126,24 @@ in (Map.insert patt matcher cache, matcher) -- | From options and pattern, determine number of parenthesized captures, along--- with a list of their names (each indexed and in index order).+-- with a list of their names (each indexed and in index order). This may be+-- used to validate that a pattern not known at compile time has certain+-- required named captures, and construct a safe way of indexing them, for+-- example.+--+-- >>> predictCapturesInfo mempty "foo (?<bar>...) (?<a>[[:alpha:]]) (ba*z)"+-- (3,[("bar" 1),("a",2)])+--+-- It is in @IO@ in order to facilitate catching `Pcre2CompileException`s. Note+-- that the resultant regex is discarded, as are any @Option@s that only have+-- effect at match time.+--+-- Used internally to produce `CapturesInfo`.+--+-- @since 2.2.3 predictCapturesInfo :: Option -> Text -> IO (Int, [(Text, Int)]) predictCapturesInfo option patt = do- code <- evalStateT- (extractCompileEnv >>= extractCode patt)- (applyOption option)+ code <- evalStateT (extractCode patt) (applyOption option) withForeignPtr code $ \codePtr -> do count <- getCodeInfo @CUInt codePtr pcre2_INFO_NAMECOUNT@@ -138,10 +159,7 @@ (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)+ groupName <- Text.fromPtr0 $ fromCUs groupNamePtr return (groupName, groupNumber) hiCaptNum <- getCodeInfo @CUInt codePtr pcre2_INFO_CAPTURECOUNT@@ -162,7 +180,7 @@ -- if needed. capturesInfoQ :: String -> Q (Maybe Type) capturesInfoQ s = predictCapturesInfoQ s >>= \case- -- No parenthesized captures, so need for Captures, so no info.+ -- No parenthesized captures, so no need for Captures, so no info. (0, _) -> return Nothing -- One or more parenthesized captures. Produce@@ -217,6 +235,16 @@ Nothing -> matchE Just info -> capturesE `appTypeE` return info +-- | A default quasi-quoter.+zeroQQ :: QuasiQuoter+zeroQQ = QuasiQuoter{+ quoteExp = cannotProduce "an expression",+ quotePat = cannotProduce "a pattern",+ quoteType = cannotProduce "a type",+ quoteDec = cannotProduce "declarations"}+ where+ cannotProduce what _ = fail $ "Cannot produce " ++ what+ -- | === As an expression -- -- @@@ -257,7 +285,7 @@ -- -- If there are no named captures, this simply acts as a guard. regex :: QuasiQuoter-regex = QuasiQuoter{+regex = zeroQQ{ quoteExp = mkQuoteExp [e| matchTH |] [e| capturesTH |], quotePat = \s -> predictCapturesInfoQ s >>= \info -> case snd info of@@ -266,10 +294,7 @@ (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],-- quoteType = \_ -> fail "regex: cannot produce a type",- quoteDec = \_ -> fail "regex: cannot produce declarations"}+ f name r = conP '(:) [varP $ mkName $ Text.unpack name, r]} -- | An optical variant of `regex`\/a type-annotated variant of `_captures`. Can -- only be used as an expression.@@ -287,9 +312,4 @@ -- > -- > -- There are 15 competing standards _regex :: QuasiQuoter-_regex = QuasiQuoter{- quoteExp = mkQuoteExp [e| _matchTH |] [e| _capturesTH |],-- quotePat = \_ -> fail "_regex: cannot produce a pattern",- quoteType = \_ -> fail "_regex: cannot produce a type",- quoteDec = \_ -> fail "_regex: cannot produce declarations"}+_regex = zeroQQ{quoteExp = mkQuoteExp [e| _matchTH |] [e| _capturesTH |]}
src/hs/Text/Regex/Pcre2/Unsafe.hs view
@@ -12,6 +12,9 @@ -- the [C API docs](https://pcre.org/current/doc/html/pcre2callout.html) -- for more information. module Text.Regex.Pcre2.Unsafe (+ -- ** Un-refining @Captures@+ getCaptures,+ -- ** Options Option( AutoCallout,@@ -29,3 +32,4 @@ where import Text.Regex.Pcre2.Internal+import Text.Regex.Pcre2.TH
test/Spec.hs view
@@ -204,9 +204,20 @@ result `shouldBe` "There are 15 competing standards" describe "Captures" $ do- it "have a predictable Show instance" $ do- cs <- [regex|a(b)(?<c>c)|] "abc"+ let mkCaptures = [regex|a(b)(?<c>c)|] "abc"++ it "has a predictable Show instance" $ do+ cs <- mkCaptures show cs `shouldBe` "Captures (\"abc\" :| [\"b\",\"c\"])"++ it "can have its underlying list extracted" $ do+ cs <- mkCaptures+ getCaptures cs `shouldBe` "abc" :| ["b", "c"]++ describe "predictCapturesInfo" $ do+ it ("analyzes captures groups' names" `issue` 45) $ do+ predictCapturesInfo mempty "foo (?<bar>...) (?<a>[[:alpha:]]) (ba*z)"+ `shouldReturn` (3, [("bar", 1), ("a", 2)]) describe "an unset capture" $ do it "is treated as empty" $ do