tpy-lang 0.3.0.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tpy_lang-0.3.0.dev0.dist-info/METADATA +151 -0
- tpy_lang-0.3.0.dev0.dist-info/RECORD +333 -0
- tpy_lang-0.3.0.dev0.dist-info/WHEEL +4 -0
- tpy_lang-0.3.0.dev0.dist-info/entry_points.txt +3 -0
- tpyc/__init__.py +104 -0
- tpyc/__main__.py +6 -0
- tpyc/_buildinfo.py +1 -0
- tpyc/_data/docs/LANGUAGE_FEATURES.md +6278 -0
- tpyc/_data/docs/STDLIB_ROADMAP.md +1258 -0
- tpyc/_data/docs/TPY_FOR_AGENTS.md +556 -0
- tpyc/_data/lib/tpy/_bindings/__init__.py +6 -0
- tpyc/_data/lib/tpy/_bindings/pcre2.py +173 -0
- tpyc/_data/lib/tpy/_bindings/posix_socket.py +161 -0
- tpyc/_data/lib/tpy/_functools_macros.py +80 -0
- tpyc/_data/lib/tpy/_macro_helpers.py +161 -0
- tpyc/_data/lib/tpy/argparse.py +2062 -0
- tpyc/_data/lib/tpy/asyncio/__init__.py +744 -0
- tpyc/_data/lib/tpy/asyncio/_executor.py +515 -0
- tpyc/_data/lib/tpy/base64.py +410 -0
- tpyc/_data/lib/tpy/bisect.py +39 -0
- tpyc/_data/lib/tpy/builtins.py +38 -0
- tpyc/_data/lib/tpy/dataclasses.py +354 -0
- tpyc/_data/lib/tpy/enum.py +23 -0
- tpyc/_data/lib/tpy/functools.py +33 -0
- tpyc/_data/lib/tpy/hashlib.py +206 -0
- tpyc/_data/lib/tpy/heapq.py +118 -0
- tpyc/_data/lib/tpy/io.py +395 -0
- tpyc/_data/lib/tpy/json.py +221 -0
- tpyc/_data/lib/tpy/math.py +406 -0
- tpyc/_data/lib/tpy/random.py +597 -0
- tpyc/_data/lib/tpy/re.py +467 -0
- tpyc/_data/lib/tpy/socket.py +379 -0
- tpyc/_data/lib/tpy/struct.py +178 -0
- tpyc/_data/lib/tpy/sys.py +40 -0
- tpyc/_data/lib/tpy/time.py +39 -0
- tpyc/_data/lib/tpy/tpy/__init__.py +78 -0
- tpyc/_data/lib/tpy/tpy/_bootstrap/__init__.py +10 -0
- tpyc/_data/lib/tpy/tpy/_bootstrap/_decorators.py +37 -0
- tpyc/_data/lib/tpy/tpy/_bootstrap/_extern.py +64 -0
- tpyc/_data/lib/tpy/tpy/_builtins/__init__.py +11 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_bytes.py +378 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_dict.py +151 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_exceptions.py +125 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_funcs.py +681 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_io.py +97 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_list.py +127 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_range.py +52 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_set.py +139 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_super.py +11 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_types.py +661 -0
- tpyc/_data/lib/tpy/tpy/_core/__init__.py +23 -0
- tpyc/_data/lib/tpy/tpy/_core/_bytes_view.py +129 -0
- tpyc/_data/lib/tpy/tpy/_core/_containers.py +137 -0
- tpyc/_data/lib/tpy/tpy/_core/_functions.py +40 -0
- tpyc/_data/lib/tpy/tpy/_core/_types.py +2061 -0
- tpyc/_data/lib/tpy/tpy/_typing/__init__.py +77 -0
- tpyc/_data/lib/tpy/tpy/_version.py +29 -0
- tpyc/_data/lib/tpy/tpy/bits.py +28 -0
- tpyc/_data/lib/tpy/tpy/coro/__init__.py +127 -0
- tpyc/_data/lib/tpy/tpy/extern.py +8 -0
- tpyc/_data/lib/tpy/tpy/mem.py +49 -0
- tpyc/_data/lib/tpy/tpy/unsafe.py +195 -0
- tpyc/_data/lib/tpy/tpy/version.py +21 -0
- tpyc/_data/lib/tpy/typing.py +13 -0
- tpyc/_data/runtime/cpp/include/tpy/any.hpp +461 -0
- tpyc/_data/runtime/cpp/include/tpy/as_ostream.hpp +117 -0
- tpyc/_data/runtime/cpp/include/tpy/async.hpp +76 -0
- tpyc/_data/runtime/cpp/include/tpy/bigint.hpp +1343 -0
- tpyc/_data/runtime/cpp/include/tpy/builtins.hpp +400 -0
- tpyc/_data/runtime/cpp/include/tpy/bytes_ops.hpp +469 -0
- tpyc/_data/runtime/cpp/include/tpy/container_ops.hpp +487 -0
- tpyc/_data/runtime/cpp/include/tpy/copy_iter.hpp +82 -0
- tpyc/_data/runtime/cpp/include/tpy/core.hpp +558 -0
- tpyc/_data/runtime/cpp/include/tpy/dict_ops.hpp +289 -0
- tpyc/_data/runtime/cpp/include/tpy/dunder.hpp +750 -0
- tpyc/_data/runtime/cpp/include/tpy/dynamic.hpp +44 -0
- tpyc/_data/runtime/cpp/include/tpy/enum.hpp +40 -0
- tpyc/_data/runtime/cpp/include/tpy/file.hpp +245 -0
- tpyc/_data/runtime/cpp/include/tpy/fixed_int.hpp +317 -0
- tpyc/_data/runtime/cpp/include/tpy/format.hpp +954 -0
- tpyc/_data/runtime/cpp/include/tpy/frame_slot.hpp +120 -0
- tpyc/_data/runtime/cpp/include/tpy/generator.hpp +47 -0
- tpyc/_data/runtime/cpp/include/tpy/iterable_ops.hpp +122 -0
- tpyc/_data/runtime/cpp/include/tpy/itertools.hpp +749 -0
- tpyc/_data/runtime/cpp/include/tpy/next_iter.hpp +82 -0
- tpyc/_data/runtime/cpp/include/tpy/ordered_map.hpp +518 -0
- tpyc/_data/runtime/cpp/include/tpy/ordered_set.hpp +337 -0
- tpyc/_data/runtime/cpp/include/tpy/own_iter.hpp +54 -0
- tpyc/_data/runtime/cpp/include/tpy/pascal_graph_sdl.hpp +192 -0
- tpyc/_data/runtime/cpp/include/tpy/printing.hpp +302 -0
- tpyc/_data/runtime/cpp/include/tpy/protocols.hpp +61 -0
- tpyc/_data/runtime/cpp/include/tpy/range.hpp +115 -0
- tpyc/_data/runtime/cpp/include/tpy/ranges.hpp +212 -0
- tpyc/_data/runtime/cpp/include/tpy/set_ops.hpp +265 -0
- tpyc/_data/runtime/cpp/include/tpy/slice.hpp +47 -0
- tpyc/_data/runtime/cpp/include/tpy/span_iter.hpp +42 -0
- tpyc/_data/runtime/cpp/include/tpy/stdlib/math.hpp +41 -0
- tpyc/_data/runtime/cpp/include/tpy/stdlib/pcre2_h.hpp +96 -0
- tpyc/_data/runtime/cpp/include/tpy/stdlib/random.hpp +25 -0
- tpyc/_data/runtime/cpp/include/tpy/stdlib/socket_h.hpp +145 -0
- tpyc/_data/runtime/cpp/include/tpy/stdlib/time.hpp +62 -0
- tpyc/_data/runtime/cpp/include/tpy/system.hpp +121 -0
- tpyc/_data/runtime/cpp/include/tpy/throwable.hpp +55 -0
- tpyc/_data/runtime/cpp/include/tpy/tpy.hpp +156 -0
- tpyc/_data/runtime/cpp/include/tpy/type_name.hpp +77 -0
- tpyc/_data/runtime/cpp/include/tpy/type_traits.hpp +240 -0
- tpyc/_data/runtime/cpp/include/tpy/uninit_array_storage.hpp +250 -0
- tpyc/_data/runtime/cpp/include/tpy/uninit_heap_storage.hpp +277 -0
- tpyc/_data/runtime/cpp/include/tpy/varargs.hpp +174 -0
- tpyc/_data/runtime/cpp/include/tpy/variant_ref.hpp +118 -0
- tpyc/_data/runtime/cpp/src/stdlib/socket_impl.cpp +104 -0
- tpyc/_data/runtime/cpp/third_party/README.md +58 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/AUTHORS +36 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/CMakeLists.txt +1233 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/COPYING +5 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/ChangeLog +3097 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/HACKING +853 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/INSTALL +368 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/LICENCE +94 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/NEWS +492 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/NON-AUTOTOOLS-BUILD +430 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/README +956 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/cmake/COPYING-CMAKE-SCRIPTS +22 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/cmake/FindEditline.cmake +16 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/cmake/FindPackageHandleStandardArgs.cmake +58 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/cmake/FindReadline.cmake +29 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/cmake/pcre2-config-version.cmake.in +15 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/cmake/pcre2-config.cmake.in +148 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/config-cmake.h.in +56 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-16.pc.in +13 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-32.pc.in +13 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-8.pc.in +13 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-posix.pc.in +13 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/pcre2-config.in +121 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/config.h +483 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/config.h.generic +483 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/config.h.in +460 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2.h +1010 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2.h.generic +1010 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2.h.in +1010 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_auto_possess.c +1371 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_chartables.c +196 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_chartables.c.dist +196 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_chkdint.c +96 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_compile.c +11001 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_config.c +252 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_context.c +510 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_convert.c +1189 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_dfa_match.c +4119 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_dftables.c +297 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_error.c +345 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_extuni.c +162 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_find_bracket.c +219 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_fuzzsupport.c +792 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_internal.h +2084 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_intmodedep.h +940 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_compile.c +14972 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_match.c +200 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_misc.c +234 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_neon_inc.h +354 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_simd_inc.h +2355 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_test.c +2528 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_maketables.c +165 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_match.c +7777 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_match_data.c +185 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_newline.c +243 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ord2utf.c +120 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_pattern_info.c +432 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_printint.c +886 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_script_run.c +344 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_serialize.c +286 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_string_utils.c +237 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_study.c +1915 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_substitute.c +1009 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_substring.c +550 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_tables.c +234 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ucd.c +5460 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ucp.h +396 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ucptables.c +1533 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_valid_utf.c +398 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_xclass.c +308 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2demo.c +497 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2grep.c +4606 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2posix.c +425 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2posix.h +187 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2posix_test.c +209 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2test.c +9708 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorApple.c +137 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorCore.c +327 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorFreeBSD.c +89 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorPosix.c +62 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorWindows.c +40 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitProtExecAllocatorNetBSD.c +72 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitProtExecAllocatorPosix.c +172 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitWXExecAllocatorPosix.c +141 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitWXExecAllocatorWindows.c +102 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitConfig.h +142 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitConfigCPU.h +188 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitConfigInternal.h +907 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitLir.c +3561 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitLir.h +2466 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeARM_32.c +4636 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeARM_64.c +3491 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeARM_T2_32.c +4302 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeLOONGARCH_64.c +3765 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeMIPS_32.c +472 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeMIPS_64.c +387 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeMIPS_common.c +4259 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativePPC_32.c +485 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativePPC_64.c +719 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativePPC_common.c +3161 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeRISCV_32.c +142 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeRISCV_64.c +222 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeRISCV_common.c +3121 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeS390X.c +4526 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeX86_32.c +1685 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeX86_64.c +1398 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeX86_common.c +5001 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitSerialize.c +516 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitUtils.c +344 -0
- tpyc/_data/runtime/cpp/third_party/pcre2.sources.txt +54 -0
- tpyc/_data/runtime/cpp/third_party/pcre2.vendor.json +7 -0
- tpyc/build/__init__.py +7 -0
- tpyc/build/pcre2.py +122 -0
- tpyc/build/third_party.py +413 -0
- tpyc/cli.py +822 -0
- tpyc/codegen_cpp/__init__.py +18 -0
- tpyc/codegen_cpp/builtins.py +484 -0
- tpyc/codegen_cpp/context.py +2064 -0
- tpyc/codegen_cpp/expressions.py +5940 -0
- tpyc/codegen_cpp/functions.py +1913 -0
- tpyc/codegen_cpp/gen_async.py +3258 -0
- tpyc/codegen_cpp/gen_generators.py +657 -0
- tpyc/codegen_cpp/generator.py +2258 -0
- tpyc/codegen_cpp/match.py +1997 -0
- tpyc/codegen_cpp/param_const.py +172 -0
- tpyc/codegen_cpp/protocols.py +907 -0
- tpyc/codegen_cpp/records.py +1654 -0
- tpyc/codegen_cpp/resumable_cfg.py +1651 -0
- tpyc/codegen_cpp/statements.py +4963 -0
- tpyc/codegen_cpp/string_dispatch.py +76 -0
- tpyc/codegen_cpp/test_context.py +46 -0
- tpyc/codegen_cpp/test_param_const.py +113 -0
- tpyc/codegen_cpp/test_resumable_cfg.py +182 -0
- tpyc/codegen_cpp/type_resolution.py +53 -0
- tpyc/codegen_cpp/types.py +436 -0
- tpyc/codegen_cpp/variant_access.py +135 -0
- tpyc/coercions.py +749 -0
- tpyc/compilation_context.py +57 -0
- tpyc/compiler.py +3945 -0
- tpyc/cycle_detection.py +358 -0
- tpyc/diagnostics.py +135 -0
- tpyc/dump_types.py +353 -0
- tpyc/frontend_diagnostics.py +47 -0
- tpyc/frontend_ir/__init__.py +140 -0
- tpyc/frontend_ir/lower.py +1098 -0
- tpyc/frontend_ir/nodes.py +718 -0
- tpyc/frontend_ir/resolver_adapter.py +151 -0
- tpyc/frontend_plugin.py +209 -0
- tpyc/install_docs.py +81 -0
- tpyc/liveness.py +756 -0
- tpyc/macro_api.py +1724 -0
- tpyc/macro_loader.py +497 -0
- tpyc/module_names.py +64 -0
- tpyc/modules/__init__.py +31 -0
- tpyc/modules/defs.py +89 -0
- tpyc/modules/registry.py +36 -0
- tpyc/modules/resolver.py +192 -0
- tpyc/modules/type_resolution.py +629 -0
- tpyc/namespace.py +172 -0
- tpyc/parse/__init__.py +84 -0
- tpyc/parse/imports.py +490 -0
- tpyc/parse/nodes.py +1732 -0
- tpyc/parse/parser.py +4043 -0
- tpyc/parse/resolve_refs.py +466 -0
- tpyc/parse/type_resolver.py +1060 -0
- tpyc/prescan.py +254 -0
- tpyc/qnames.py +149 -0
- tpyc/repl.py +529 -0
- tpyc/repl_backends.py +848 -0
- tpyc/sema/__init__.py +21 -0
- tpyc/sema/analyzer.py +3625 -0
- tpyc/sema/bound_check.py +72 -0
- tpyc/sema/builder_trace.py +684 -0
- tpyc/sema/calls.py +5406 -0
- tpyc/sema/compatibility.py +2107 -0
- tpyc/sema/context.py +1243 -0
- tpyc/sema/expressions.py +3737 -0
- tpyc/sema/flow_facts.py +199 -0
- tpyc/sema/init_tracker.py +150 -0
- tpyc/sema/list_literals.py +69 -0
- tpyc/sema/literal_utils.py +27 -0
- tpyc/sema/local_deduction.py +1088 -0
- tpyc/sema/macros.py +179 -0
- tpyc/sema/match.py +1177 -0
- tpyc/sema/method_expansion.py +347 -0
- tpyc/sema/methods.py +2197 -0
- tpyc/sema/mutation_propagation.py +268 -0
- tpyc/sema/narrowing.py +857 -0
- tpyc/sema/numeric_lattice.py +160 -0
- tpyc/sema/operators.py +402 -0
- tpyc/sema/overloads.py +841 -0
- tpyc/sema/protocols.py +1209 -0
- tpyc/sema/reach_analysis.py +202 -0
- tpyc/sema/registration.py +3156 -0
- tpyc/sema/scope_tracker.py +193 -0
- tpyc/sema/statements.py +4426 -0
- tpyc/sema/type_ops.py +1879 -0
- tpyc/sema/value_range.py +181 -0
- tpyc/symbol_binding.py +259 -0
- tpyc/test_c3_mro.py +208 -0
- tpyc/test_cli_argv.py +52 -0
- tpyc/test_compiler.py +559 -0
- tpyc/test_contains_type_param.py +101 -0
- tpyc/test_cycle_detection.py +221 -0
- tpyc/test_dump_types.py +225 -0
- tpyc/test_install_docs.py +65 -0
- tpyc/test_local_cpp_form.py +135 -0
- tpyc/test_macro_loader.py +76 -0
- tpyc/test_method_expansion.py +254 -0
- tpyc/test_nominal_identity.py +182 -0
- tpyc/test_overloads.py +410 -0
- tpyc/test_parse.py +303 -0
- tpyc/test_parse_type_ref.py +506 -0
- tpyc/test_parse_version_info.py +58 -0
- tpyc/test_reach_analysis.py +72 -0
- tpyc/test_ref_type.py +216 -0
- tpyc/test_send_sync_substitution.py +276 -0
- tpyc/test_tuple_mutation_propagation.py +206 -0
- tpyc/test_type_def_registry.py +1729 -0
- tpyc/test_union_types.py +195 -0
- tpyc/type_def_registry.py +975 -0
- tpyc/typesys.py +5104 -0
|
@@ -0,0 +1,3121 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Stack-less Just-In-Time compiler
|
|
3
|
+
*
|
|
4
|
+
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* Redistribution and use in source and binary forms, with or without modification, are
|
|
7
|
+
* permitted provided that the following conditions are met:
|
|
8
|
+
*
|
|
9
|
+
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
10
|
+
* conditions and the following disclaimer.
|
|
11
|
+
*
|
|
12
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
13
|
+
* of conditions and the following disclaimer in the documentation and/or other materials
|
|
14
|
+
* provided with the distribution.
|
|
15
|
+
*
|
|
16
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
|
17
|
+
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
18
|
+
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
19
|
+
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
20
|
+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
21
|
+
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
|
22
|
+
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
23
|
+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
24
|
+
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
|
|
28
|
+
{
|
|
29
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
30
|
+
return "RISC-V-32" SLJIT_CPUINFO;
|
|
31
|
+
#else /* !SLJIT_CONFIG_RISCV_32 */
|
|
32
|
+
return "RISC-V-64" SLJIT_CPUINFO;
|
|
33
|
+
#endif /* SLJIT_CONFIG_RISCV_32 */
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* Length of an instruction word
|
|
37
|
+
Both for riscv-32 and riscv-64 */
|
|
38
|
+
typedef sljit_u32 sljit_ins;
|
|
39
|
+
|
|
40
|
+
#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
|
|
41
|
+
#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
|
|
42
|
+
#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
|
|
43
|
+
#define TMP_ZERO 0
|
|
44
|
+
|
|
45
|
+
/* Flags are kept in volatile registers. */
|
|
46
|
+
#define EQUAL_FLAG (SLJIT_NUMBER_OF_REGISTERS + 5)
|
|
47
|
+
#define RETURN_ADDR_REG TMP_REG2
|
|
48
|
+
#define OTHER_FLAG (SLJIT_NUMBER_OF_REGISTERS + 6)
|
|
49
|
+
|
|
50
|
+
#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
|
|
51
|
+
#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
|
|
52
|
+
|
|
53
|
+
static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
|
|
54
|
+
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
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
|
|
58
|
+
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,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/* --------------------------------------------------------------------- */
|
|
62
|
+
/* Instrucion forms */
|
|
63
|
+
/* --------------------------------------------------------------------- */
|
|
64
|
+
|
|
65
|
+
#define RD(rd) ((sljit_ins)reg_map[rd] << 7)
|
|
66
|
+
#define RS1(rs1) ((sljit_ins)reg_map[rs1] << 15)
|
|
67
|
+
#define RS2(rs2) ((sljit_ins)reg_map[rs2] << 20)
|
|
68
|
+
#define FRD(rd) ((sljit_ins)freg_map[rd] << 7)
|
|
69
|
+
#define FRS1(rs1) ((sljit_ins)freg_map[rs1] << 15)
|
|
70
|
+
#define FRS2(rs2) ((sljit_ins)freg_map[rs2] << 20)
|
|
71
|
+
#define IMM_I(imm) ((sljit_ins)(imm) << 20)
|
|
72
|
+
#define IMM_S(imm) ((((sljit_ins)(imm) & 0xfe0) << 20) | (((sljit_ins)(imm) & 0x1f) << 7))
|
|
73
|
+
|
|
74
|
+
/* Represents funct(i) parts of the instructions. */
|
|
75
|
+
#define OPC(o) ((sljit_ins)(o))
|
|
76
|
+
#define F3(f) ((sljit_ins)(f) << 12)
|
|
77
|
+
#define F12(f) ((sljit_ins)(f) << 20)
|
|
78
|
+
#define F7(f) ((sljit_ins)(f) << 25)
|
|
79
|
+
|
|
80
|
+
#define ADD (F7(0x0) | F3(0x0) | OPC(0x33))
|
|
81
|
+
#define ADDI (F3(0x0) | OPC(0x13))
|
|
82
|
+
#define AND (F7(0x0) | F3(0x7) | OPC(0x33))
|
|
83
|
+
#define ANDI (F3(0x7) | OPC(0x13))
|
|
84
|
+
#define AUIPC (OPC(0x17))
|
|
85
|
+
#define BEQ (F3(0x0) | OPC(0x63))
|
|
86
|
+
#define BNE (F3(0x1) | OPC(0x63))
|
|
87
|
+
#define BLT (F3(0x4) | OPC(0x63))
|
|
88
|
+
#define BGE (F3(0x5) | OPC(0x63))
|
|
89
|
+
#define BLTU (F3(0x6) | OPC(0x63))
|
|
90
|
+
#define BGEU (F3(0x7) | OPC(0x63))
|
|
91
|
+
#define DIV (F7(0x1) | F3(0x4) | OPC(0x33))
|
|
92
|
+
#define DIVU (F7(0x1) | F3(0x5) | OPC(0x33))
|
|
93
|
+
#define EBREAK (F12(0x1) | F3(0x0) | OPC(0x73))
|
|
94
|
+
#define FADD_S (F7(0x0) | F3(0x7) | OPC(0x53))
|
|
95
|
+
#define FDIV_S (F7(0xc) | F3(0x7) | OPC(0x53))
|
|
96
|
+
#define FEQ_S (F7(0x50) | F3(0x2) | OPC(0x53))
|
|
97
|
+
#define FLD (F3(0x3) | OPC(0x7))
|
|
98
|
+
#define FLE_S (F7(0x50) | F3(0x0) | OPC(0x53))
|
|
99
|
+
#define FLT_S (F7(0x50) | F3(0x1) | OPC(0x53))
|
|
100
|
+
/* These conversion opcodes are partly defined. */
|
|
101
|
+
#define FCVT_S_D (F7(0x20) | OPC(0x53))
|
|
102
|
+
#define FCVT_S_W (F7(0x68) | OPC(0x53))
|
|
103
|
+
#define FCVT_S_WU (F7(0x68) | F12(0x1) | OPC(0x53))
|
|
104
|
+
#define FCVT_W_S (F7(0x60) | F3(0x1) | OPC(0x53))
|
|
105
|
+
#define FMUL_S (F7(0x8) | F3(0x7) | OPC(0x53))
|
|
106
|
+
#define FMV_X_W (F7(0x70) | F3(0x0) | OPC(0x53))
|
|
107
|
+
#define FMV_W_X (F7(0x78) | F3(0x0) | OPC(0x53))
|
|
108
|
+
#define FSD (F3(0x3) | OPC(0x27))
|
|
109
|
+
#define FSGNJ_S (F7(0x10) | F3(0x0) | OPC(0x53))
|
|
110
|
+
#define FSGNJN_S (F7(0x10) | F3(0x1) | OPC(0x53))
|
|
111
|
+
#define FSGNJX_S (F7(0x10) | F3(0x2) | OPC(0x53))
|
|
112
|
+
#define FSUB_S (F7(0x4) | F3(0x7) | OPC(0x53))
|
|
113
|
+
#define FSW (F3(0x2) | OPC(0x27))
|
|
114
|
+
#define JAL (OPC(0x6f))
|
|
115
|
+
#define JALR (F3(0x0) | OPC(0x67))
|
|
116
|
+
#define LD (F3(0x3) | OPC(0x3))
|
|
117
|
+
#define LUI (OPC(0x37))
|
|
118
|
+
#define LW (F3(0x2) | OPC(0x3))
|
|
119
|
+
#define MUL (F7(0x1) | F3(0x0) | OPC(0x33))
|
|
120
|
+
#define MULH (F7(0x1) | F3(0x1) | OPC(0x33))
|
|
121
|
+
#define MULHU (F7(0x1) | F3(0x3) | OPC(0x33))
|
|
122
|
+
#define OR (F7(0x0) | F3(0x6) | OPC(0x33))
|
|
123
|
+
#define ORI (F3(0x6) | OPC(0x13))
|
|
124
|
+
#define REM (F7(0x1) | F3(0x6) | OPC(0x33))
|
|
125
|
+
#define REMU (F7(0x1) | F3(0x7) | OPC(0x33))
|
|
126
|
+
#define SD (F3(0x3) | OPC(0x23))
|
|
127
|
+
#define SLL (F7(0x0) | F3(0x1) | OPC(0x33))
|
|
128
|
+
#define SLLI (IMM_I(0x0) | F3(0x1) | OPC(0x13))
|
|
129
|
+
#define SLT (F7(0x0) | F3(0x2) | OPC(0x33))
|
|
130
|
+
#define SLTI (F3(0x2) | OPC(0x13))
|
|
131
|
+
#define SLTU (F7(0x0) | F3(0x3) | OPC(0x33))
|
|
132
|
+
#define SLTUI (F3(0x3) | OPC(0x13))
|
|
133
|
+
#define SRL (F7(0x0) | F3(0x5) | OPC(0x33))
|
|
134
|
+
#define SRLI (IMM_I(0x0) | F3(0x5) | OPC(0x13))
|
|
135
|
+
#define SRA (F7(0x20) | F3(0x5) | OPC(0x33))
|
|
136
|
+
#define SRAI (IMM_I(0x400) | F3(0x5) | OPC(0x13))
|
|
137
|
+
#define SUB (F7(0x20) | F3(0x0) | OPC(0x33))
|
|
138
|
+
#define SW (F3(0x2) | OPC(0x23))
|
|
139
|
+
#define XOR (F7(0x0) | F3(0x4) | OPC(0x33))
|
|
140
|
+
#define XORI (F3(0x4) | OPC(0x13))
|
|
141
|
+
|
|
142
|
+
#define SIMM_MAX (0x7ff)
|
|
143
|
+
#define SIMM_MIN (-0x800)
|
|
144
|
+
#define BRANCH_MAX (0xfff)
|
|
145
|
+
#define BRANCH_MIN (-0x1000)
|
|
146
|
+
#define JUMP_MAX (0xfffff)
|
|
147
|
+
#define JUMP_MIN (-0x100000)
|
|
148
|
+
|
|
149
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
150
|
+
#define S32_MAX (0x7ffff7ffl)
|
|
151
|
+
#define S32_MIN (-0x80000000l)
|
|
152
|
+
#define S44_MAX (0x7fffffff7ffl)
|
|
153
|
+
#define S52_MAX (0x7ffffffffffffl)
|
|
154
|
+
#endif
|
|
155
|
+
|
|
156
|
+
static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
|
|
157
|
+
{
|
|
158
|
+
sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
|
|
159
|
+
FAIL_IF(!ptr);
|
|
160
|
+
*ptr = ins;
|
|
161
|
+
compiler->size++;
|
|
162
|
+
return SLJIT_SUCCESS;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
static sljit_s32 push_imm_s_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_sw imm)
|
|
166
|
+
{
|
|
167
|
+
return push_inst(compiler, ins | IMM_S(imm));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)
|
|
171
|
+
{
|
|
172
|
+
sljit_sw diff;
|
|
173
|
+
sljit_uw target_addr;
|
|
174
|
+
sljit_ins *inst;
|
|
175
|
+
|
|
176
|
+
inst = (sljit_ins *)jump->addr;
|
|
177
|
+
|
|
178
|
+
if (jump->flags & SLJIT_REWRITABLE_JUMP)
|
|
179
|
+
goto exit;
|
|
180
|
+
|
|
181
|
+
if (jump->flags & JUMP_ADDR)
|
|
182
|
+
target_addr = jump->u.target;
|
|
183
|
+
else {
|
|
184
|
+
SLJIT_ASSERT(jump->u.label != NULL);
|
|
185
|
+
target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
diff = (sljit_sw)target_addr - (sljit_sw)inst - executable_offset;
|
|
189
|
+
|
|
190
|
+
if (jump->flags & IS_COND) {
|
|
191
|
+
diff += SSIZE_OF(ins);
|
|
192
|
+
|
|
193
|
+
if (diff >= BRANCH_MIN && diff <= BRANCH_MAX) {
|
|
194
|
+
inst--;
|
|
195
|
+
inst[0] = (inst[0] & 0x1fff07f) ^ 0x1000;
|
|
196
|
+
jump->flags |= PATCH_B;
|
|
197
|
+
jump->addr = (sljit_uw)inst;
|
|
198
|
+
return inst;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
diff -= SSIZE_OF(ins);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (diff >= JUMP_MIN && diff <= JUMP_MAX) {
|
|
205
|
+
if (jump->flags & IS_COND) {
|
|
206
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
207
|
+
inst[-1] -= (sljit_ins)(1 * sizeof(sljit_ins)) << 7;
|
|
208
|
+
#else
|
|
209
|
+
inst[-1] -= (sljit_ins)(5 * sizeof(sljit_ins)) << 7;
|
|
210
|
+
#endif
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
jump->flags |= PATCH_J;
|
|
214
|
+
return inst;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
218
|
+
if (diff >= S32_MIN && diff <= S32_MAX) {
|
|
219
|
+
if (jump->flags & IS_COND)
|
|
220
|
+
inst[-1] -= (sljit_ins)(4 * sizeof(sljit_ins)) << 7;
|
|
221
|
+
|
|
222
|
+
jump->flags |= PATCH_REL32;
|
|
223
|
+
inst[1] = inst[0];
|
|
224
|
+
return inst + 1;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (target_addr <= (sljit_uw)S32_MAX) {
|
|
228
|
+
if (jump->flags & IS_COND)
|
|
229
|
+
inst[-1] -= (sljit_ins)(4 * sizeof(sljit_ins)) << 7;
|
|
230
|
+
|
|
231
|
+
jump->flags |= PATCH_ABS32;
|
|
232
|
+
inst[1] = inst[0];
|
|
233
|
+
return inst + 1;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (target_addr <= S44_MAX) {
|
|
237
|
+
if (jump->flags & IS_COND)
|
|
238
|
+
inst[-1] -= (sljit_ins)(2 * sizeof(sljit_ins)) << 7;
|
|
239
|
+
|
|
240
|
+
jump->flags |= PATCH_ABS44;
|
|
241
|
+
inst[3] = inst[0];
|
|
242
|
+
return inst + 3;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (target_addr <= S52_MAX) {
|
|
246
|
+
if (jump->flags & IS_COND)
|
|
247
|
+
inst[-1] -= (sljit_ins)(1 * sizeof(sljit_ins)) << 7;
|
|
248
|
+
|
|
249
|
+
jump->flags |= PATCH_ABS52;
|
|
250
|
+
inst[4] = inst[0];
|
|
251
|
+
return inst + 4;
|
|
252
|
+
}
|
|
253
|
+
#endif
|
|
254
|
+
|
|
255
|
+
exit:
|
|
256
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
257
|
+
inst[1] = inst[0];
|
|
258
|
+
return inst + 1;
|
|
259
|
+
#else
|
|
260
|
+
inst[5] = inst[0];
|
|
261
|
+
return inst + 5;
|
|
262
|
+
#endif
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
266
|
+
|
|
267
|
+
static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
|
|
268
|
+
{
|
|
269
|
+
sljit_uw addr;
|
|
270
|
+
sljit_sw diff;
|
|
271
|
+
SLJIT_UNUSED_ARG(executable_offset);
|
|
272
|
+
|
|
273
|
+
SLJIT_ASSERT(jump->flags < ((sljit_uw)6 << JUMP_SIZE_SHIFT));
|
|
274
|
+
if (jump->flags & JUMP_ADDR)
|
|
275
|
+
addr = jump->u.target;
|
|
276
|
+
else
|
|
277
|
+
addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);
|
|
278
|
+
|
|
279
|
+
diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
|
|
280
|
+
|
|
281
|
+
if (diff >= S32_MIN && diff <= S32_MAX) {
|
|
282
|
+
SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));
|
|
283
|
+
jump->flags |= PATCH_REL32;
|
|
284
|
+
return 1;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (addr <= S32_MAX) {
|
|
288
|
+
SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));
|
|
289
|
+
jump->flags |= PATCH_ABS32;
|
|
290
|
+
return 1;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (addr <= S44_MAX) {
|
|
294
|
+
SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));
|
|
295
|
+
jump->flags |= PATCH_ABS44;
|
|
296
|
+
return 3;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (addr <= S52_MAX) {
|
|
300
|
+
SLJIT_ASSERT(jump->flags >= ((sljit_uw)4 << JUMP_SIZE_SHIFT));
|
|
301
|
+
jump->flags |= PATCH_ABS52;
|
|
302
|
+
return 4;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
SLJIT_ASSERT(jump->flags >= ((sljit_uw)5 << JUMP_SIZE_SHIFT));
|
|
306
|
+
return 5;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
#endif /* SLJIT_CONFIG_RISCV_64 */
|
|
310
|
+
|
|
311
|
+
static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump, sljit_sw executable_offset)
|
|
312
|
+
{
|
|
313
|
+
sljit_uw flags = jump->flags;
|
|
314
|
+
sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
|
|
315
|
+
sljit_ins *ins = (sljit_ins*)jump->addr;
|
|
316
|
+
sljit_u32 reg = (flags & JUMP_MOV_ADDR) ? *ins : TMP_REG1;
|
|
317
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
318
|
+
sljit_sw high;
|
|
319
|
+
#endif
|
|
320
|
+
SLJIT_UNUSED_ARG(executable_offset);
|
|
321
|
+
|
|
322
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
323
|
+
if (flags & PATCH_REL32) {
|
|
324
|
+
addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(ins, executable_offset);
|
|
325
|
+
|
|
326
|
+
SLJIT_ASSERT((sljit_sw)addr >= S32_MIN && (sljit_sw)addr <= S32_MAX);
|
|
327
|
+
|
|
328
|
+
if ((addr & 0x800) != 0)
|
|
329
|
+
addr += 0x1000;
|
|
330
|
+
|
|
331
|
+
ins[0] = AUIPC | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);
|
|
332
|
+
|
|
333
|
+
if (!(flags & JUMP_MOV_ADDR)) {
|
|
334
|
+
SLJIT_ASSERT((ins[1] & 0x707f) == JALR);
|
|
335
|
+
ins[1] = (ins[1] & 0xfffff) | IMM_I(addr);
|
|
336
|
+
} else
|
|
337
|
+
ins[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(addr);
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
#endif
|
|
341
|
+
|
|
342
|
+
if ((addr & 0x800) != 0)
|
|
343
|
+
addr += 0x1000;
|
|
344
|
+
|
|
345
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
346
|
+
ins[0] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);
|
|
347
|
+
#else /* !SLJIT_CONFIG_RISCV_32 */
|
|
348
|
+
|
|
349
|
+
if (flags & PATCH_ABS32) {
|
|
350
|
+
SLJIT_ASSERT(addr <= S32_MAX);
|
|
351
|
+
ins[0] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);
|
|
352
|
+
} else if (flags & PATCH_ABS44) {
|
|
353
|
+
high = (sljit_sw)addr >> 12;
|
|
354
|
+
SLJIT_ASSERT((sljit_uw)high <= 0x7fffffff);
|
|
355
|
+
|
|
356
|
+
if (high > S32_MAX) {
|
|
357
|
+
SLJIT_ASSERT((high & 0x800) != 0);
|
|
358
|
+
ins[0] = LUI | RD(reg) | (sljit_ins)0x80000000u;
|
|
359
|
+
ins[1] = XORI | RD(reg) | RS1(reg) | IMM_I(high);
|
|
360
|
+
} else {
|
|
361
|
+
if ((high & 0x800) != 0)
|
|
362
|
+
high += 0x1000;
|
|
363
|
+
|
|
364
|
+
ins[0] = LUI | RD(reg) | (sljit_ins)(high & ~0xfff);
|
|
365
|
+
ins[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(high);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
ins[2] = SLLI | RD(reg) | RS1(reg) | IMM_I(12);
|
|
369
|
+
ins += 2;
|
|
370
|
+
} else {
|
|
371
|
+
high = (sljit_sw)addr >> 32;
|
|
372
|
+
|
|
373
|
+
if ((addr & 0x80000000l) != 0)
|
|
374
|
+
high = ~high;
|
|
375
|
+
|
|
376
|
+
if (flags & PATCH_ABS52) {
|
|
377
|
+
SLJIT_ASSERT(addr <= S52_MAX);
|
|
378
|
+
ins[0] = LUI | RD(TMP_REG3) | (sljit_ins)(high << 12);
|
|
379
|
+
} else {
|
|
380
|
+
if ((high & 0x800) != 0)
|
|
381
|
+
high += 0x1000;
|
|
382
|
+
ins[0] = LUI | RD(TMP_REG3) | (sljit_ins)(high & ~0xfff);
|
|
383
|
+
ins[1] = ADDI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(high);
|
|
384
|
+
ins++;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
ins[1] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);
|
|
388
|
+
ins[2] = SLLI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I((flags & PATCH_ABS52) ? 20 : 32);
|
|
389
|
+
ins[3] = XOR | RD(reg) | RS1(reg) | RS2(TMP_REG3);
|
|
390
|
+
ins += 3;
|
|
391
|
+
}
|
|
392
|
+
#endif /* !SLJIT_CONFIG_RISCV_32 */
|
|
393
|
+
|
|
394
|
+
if (!(flags & JUMP_MOV_ADDR)) {
|
|
395
|
+
SLJIT_ASSERT((ins[1] & 0x707f) == JALR);
|
|
396
|
+
ins[1] = (ins[1] & 0xfffff) | IMM_I(addr);
|
|
397
|
+
} else
|
|
398
|
+
ins[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(addr);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
static void reduce_code_size(struct sljit_compiler *compiler)
|
|
402
|
+
{
|
|
403
|
+
struct sljit_label *label;
|
|
404
|
+
struct sljit_jump *jump;
|
|
405
|
+
struct sljit_const *const_;
|
|
406
|
+
SLJIT_NEXT_DEFINE_TYPES;
|
|
407
|
+
sljit_uw total_size;
|
|
408
|
+
sljit_uw size_reduce = 0;
|
|
409
|
+
sljit_sw diff;
|
|
410
|
+
|
|
411
|
+
label = compiler->labels;
|
|
412
|
+
jump = compiler->jumps;
|
|
413
|
+
const_ = compiler->consts;
|
|
414
|
+
SLJIT_NEXT_INIT_TYPES();
|
|
415
|
+
|
|
416
|
+
while (1) {
|
|
417
|
+
SLJIT_GET_NEXT_MIN();
|
|
418
|
+
|
|
419
|
+
if (next_min_addr == SLJIT_MAX_ADDRESS)
|
|
420
|
+
break;
|
|
421
|
+
|
|
422
|
+
if (next_min_addr == next_label_size) {
|
|
423
|
+
label->size -= size_reduce;
|
|
424
|
+
|
|
425
|
+
label = label->next;
|
|
426
|
+
next_label_size = SLJIT_GET_NEXT_SIZE(label);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (next_min_addr == next_const_addr) {
|
|
430
|
+
const_->addr -= size_reduce;
|
|
431
|
+
const_ = const_->next;
|
|
432
|
+
next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
if (next_min_addr != next_jump_addr)
|
|
437
|
+
continue;
|
|
438
|
+
|
|
439
|
+
jump->addr -= size_reduce;
|
|
440
|
+
if (!(jump->flags & JUMP_MOV_ADDR)) {
|
|
441
|
+
total_size = JUMP_MAX_SIZE;
|
|
442
|
+
|
|
443
|
+
if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) {
|
|
444
|
+
if (jump->flags & JUMP_ADDR) {
|
|
445
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
446
|
+
if (jump->u.target <= S32_MAX)
|
|
447
|
+
total_size = 2;
|
|
448
|
+
else if (jump->u.target <= S44_MAX)
|
|
449
|
+
total_size = 4;
|
|
450
|
+
else if (jump->u.target <= S52_MAX)
|
|
451
|
+
total_size = 5;
|
|
452
|
+
#endif /* SLJIT_CONFIG_RISCV_64 */
|
|
453
|
+
} else {
|
|
454
|
+
/* Unit size: instruction. */
|
|
455
|
+
diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;
|
|
456
|
+
|
|
457
|
+
if ((jump->flags & IS_COND) && (diff + 1) <= (BRANCH_MAX / SSIZE_OF(ins)) && (diff + 1) >= (BRANCH_MIN / SSIZE_OF(ins)))
|
|
458
|
+
total_size = 0;
|
|
459
|
+
else if (diff >= (JUMP_MIN / SSIZE_OF(ins)) && diff <= (JUMP_MAX / SSIZE_OF(ins)))
|
|
460
|
+
total_size = 1;
|
|
461
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
462
|
+
else if (diff >= (S32_MIN / SSIZE_OF(ins)) && diff <= (S32_MAX / SSIZE_OF(ins)))
|
|
463
|
+
total_size = 2;
|
|
464
|
+
#endif /* SLJIT_CONFIG_RISCV_64 */
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
size_reduce += JUMP_MAX_SIZE - total_size;
|
|
469
|
+
jump->flags |= total_size << JUMP_SIZE_SHIFT;
|
|
470
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
471
|
+
} else {
|
|
472
|
+
total_size = 5;
|
|
473
|
+
|
|
474
|
+
if (!(jump->flags & JUMP_ADDR)) {
|
|
475
|
+
/* Real size minus 1. Unit size: instruction. */
|
|
476
|
+
diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;
|
|
477
|
+
|
|
478
|
+
if (diff >= (S32_MIN / SSIZE_OF(ins)) && diff <= (S32_MAX / SSIZE_OF(ins)))
|
|
479
|
+
total_size = 1;
|
|
480
|
+
} else if (jump->u.target < S32_MAX)
|
|
481
|
+
total_size = 1;
|
|
482
|
+
else if (jump->u.target < S44_MAX)
|
|
483
|
+
total_size = 3;
|
|
484
|
+
else if (jump->u.target <= S52_MAX)
|
|
485
|
+
total_size = 4;
|
|
486
|
+
|
|
487
|
+
size_reduce += 5 - total_size;
|
|
488
|
+
jump->flags |= total_size << JUMP_SIZE_SHIFT;
|
|
489
|
+
#endif /* !SLJIT_CONFIG_RISCV_64 */
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
jump = jump->next;
|
|
493
|
+
next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
compiler->size -= size_reduce;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
|
|
500
|
+
{
|
|
501
|
+
struct sljit_memory_fragment *buf;
|
|
502
|
+
sljit_ins *code;
|
|
503
|
+
sljit_ins *code_ptr;
|
|
504
|
+
sljit_ins *buf_ptr;
|
|
505
|
+
sljit_ins *buf_end;
|
|
506
|
+
sljit_uw word_count;
|
|
507
|
+
SLJIT_NEXT_DEFINE_TYPES;
|
|
508
|
+
sljit_sw executable_offset;
|
|
509
|
+
sljit_uw addr;
|
|
510
|
+
|
|
511
|
+
struct sljit_label *label;
|
|
512
|
+
struct sljit_jump *jump;
|
|
513
|
+
struct sljit_const *const_;
|
|
514
|
+
|
|
515
|
+
CHECK_ERROR_PTR();
|
|
516
|
+
CHECK_PTR(check_sljit_generate_code(compiler));
|
|
517
|
+
|
|
518
|
+
reduce_code_size(compiler);
|
|
519
|
+
|
|
520
|
+
code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);
|
|
521
|
+
PTR_FAIL_WITH_EXEC_IF(code);
|
|
522
|
+
|
|
523
|
+
reverse_buf(compiler);
|
|
524
|
+
buf = compiler->buf;
|
|
525
|
+
|
|
526
|
+
code_ptr = code;
|
|
527
|
+
word_count = 0;
|
|
528
|
+
label = compiler->labels;
|
|
529
|
+
jump = compiler->jumps;
|
|
530
|
+
const_ = compiler->consts;
|
|
531
|
+
SLJIT_NEXT_INIT_TYPES();
|
|
532
|
+
SLJIT_GET_NEXT_MIN();
|
|
533
|
+
|
|
534
|
+
do {
|
|
535
|
+
buf_ptr = (sljit_ins*)buf->memory;
|
|
536
|
+
buf_end = buf_ptr + (buf->used_size >> 2);
|
|
537
|
+
do {
|
|
538
|
+
*code_ptr = *buf_ptr++;
|
|
539
|
+
if (next_min_addr == word_count) {
|
|
540
|
+
SLJIT_ASSERT(!label || label->size >= word_count);
|
|
541
|
+
SLJIT_ASSERT(!jump || jump->addr >= word_count);
|
|
542
|
+
SLJIT_ASSERT(!const_ || const_->addr >= word_count);
|
|
543
|
+
|
|
544
|
+
/* These structures are ordered by their address. */
|
|
545
|
+
if (next_min_addr == next_label_size) {
|
|
546
|
+
label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
|
|
547
|
+
label->size = (sljit_uw)(code_ptr - code);
|
|
548
|
+
label = label->next;
|
|
549
|
+
next_label_size = SLJIT_GET_NEXT_SIZE(label);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
if (next_min_addr == next_jump_addr) {
|
|
553
|
+
if (!(jump->flags & JUMP_MOV_ADDR)) {
|
|
554
|
+
word_count = word_count - 1 + (jump->flags >> JUMP_SIZE_SHIFT);
|
|
555
|
+
jump->addr = (sljit_uw)code_ptr;
|
|
556
|
+
code_ptr = detect_jump_type(jump, code, executable_offset);
|
|
557
|
+
SLJIT_ASSERT((jump->flags & PATCH_B) || ((sljit_uw)code_ptr - jump->addr < (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins)));
|
|
558
|
+
} else {
|
|
559
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
560
|
+
word_count += 1;
|
|
561
|
+
jump->addr = (sljit_uw)code_ptr;
|
|
562
|
+
code_ptr += 1;
|
|
563
|
+
#else /* !SLJIT_CONFIG_RISCV_32 */
|
|
564
|
+
word_count += jump->flags >> JUMP_SIZE_SHIFT;
|
|
565
|
+
addr = (sljit_uw)code_ptr;
|
|
566
|
+
code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset);
|
|
567
|
+
jump->addr = addr;
|
|
568
|
+
#endif /* SLJIT_CONFIG_RISCV_32 */
|
|
569
|
+
}
|
|
570
|
+
jump = jump->next;
|
|
571
|
+
next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
|
|
572
|
+
} else if (next_min_addr == next_const_addr) {
|
|
573
|
+
const_->addr = (sljit_uw)code_ptr;
|
|
574
|
+
const_ = const_->next;
|
|
575
|
+
next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
SLJIT_GET_NEXT_MIN();
|
|
579
|
+
}
|
|
580
|
+
code_ptr++;
|
|
581
|
+
word_count++;
|
|
582
|
+
} while (buf_ptr < buf_end);
|
|
583
|
+
|
|
584
|
+
buf = buf->next;
|
|
585
|
+
} while (buf);
|
|
586
|
+
|
|
587
|
+
if (label && label->size == word_count) {
|
|
588
|
+
label->u.addr = (sljit_uw)code_ptr;
|
|
589
|
+
label->size = (sljit_uw)(code_ptr - code);
|
|
590
|
+
label = label->next;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
SLJIT_ASSERT(!label);
|
|
594
|
+
SLJIT_ASSERT(!jump);
|
|
595
|
+
SLJIT_ASSERT(!const_);
|
|
596
|
+
SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
|
|
597
|
+
|
|
598
|
+
jump = compiler->jumps;
|
|
599
|
+
while (jump) {
|
|
600
|
+
do {
|
|
601
|
+
if (!(jump->flags & (PATCH_B | PATCH_J)) || (jump->flags & JUMP_MOV_ADDR)) {
|
|
602
|
+
load_addr_to_reg(jump, executable_offset);
|
|
603
|
+
break;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
addr = (jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
|
|
607
|
+
buf_ptr = (sljit_ins *)jump->addr;
|
|
608
|
+
addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
|
|
609
|
+
|
|
610
|
+
if (jump->flags & PATCH_B) {
|
|
611
|
+
SLJIT_ASSERT((sljit_sw)addr >= BRANCH_MIN && (sljit_sw)addr <= BRANCH_MAX);
|
|
612
|
+
addr = ((addr & 0x800) >> 4) | ((addr & 0x1e) << 7) | ((addr & 0x7e0) << 20) | ((addr & 0x1000) << 19);
|
|
613
|
+
buf_ptr[0] |= (sljit_ins)addr;
|
|
614
|
+
break;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
SLJIT_ASSERT((sljit_sw)addr >= JUMP_MIN && (sljit_sw)addr <= JUMP_MAX);
|
|
618
|
+
addr = (addr & 0xff000) | ((addr & 0x800) << 9) | ((addr & 0x7fe) << 20) | ((addr & 0x100000) << 11);
|
|
619
|
+
buf_ptr[0] = JAL | RD((jump->flags & IS_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | (sljit_ins)addr;
|
|
620
|
+
} while (0);
|
|
621
|
+
|
|
622
|
+
jump = jump->next;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
compiler->error = SLJIT_ERR_COMPILED;
|
|
626
|
+
compiler->executable_offset = executable_offset;
|
|
627
|
+
compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);
|
|
628
|
+
|
|
629
|
+
code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
|
|
630
|
+
code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
|
|
631
|
+
|
|
632
|
+
SLJIT_CACHE_FLUSH(code, code_ptr);
|
|
633
|
+
SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
|
|
634
|
+
return code;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
|
638
|
+
{
|
|
639
|
+
switch (feature_type) {
|
|
640
|
+
case SLJIT_HAS_FPU:
|
|
641
|
+
#ifdef SLJIT_IS_FPU_AVAILABLE
|
|
642
|
+
return (SLJIT_IS_FPU_AVAILABLE) != 0;
|
|
643
|
+
#elif defined(__riscv_float_abi_soft)
|
|
644
|
+
return 0;
|
|
645
|
+
#else
|
|
646
|
+
return 1;
|
|
647
|
+
#endif /* SLJIT_IS_FPU_AVAILABLE */
|
|
648
|
+
case SLJIT_HAS_ZERO_REGISTER:
|
|
649
|
+
case SLJIT_HAS_COPY_F32:
|
|
650
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
651
|
+
case SLJIT_HAS_COPY_F64:
|
|
652
|
+
#endif /* !SLJIT_CONFIG_RISCV_64 */
|
|
653
|
+
return 1;
|
|
654
|
+
default:
|
|
655
|
+
return 0;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)
|
|
660
|
+
{
|
|
661
|
+
switch (type) {
|
|
662
|
+
case SLJIT_UNORDERED_OR_EQUAL:
|
|
663
|
+
case SLJIT_ORDERED_NOT_EQUAL:
|
|
664
|
+
return 2;
|
|
665
|
+
|
|
666
|
+
case SLJIT_UNORDERED:
|
|
667
|
+
case SLJIT_ORDERED:
|
|
668
|
+
return 1;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
return 0;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
/* --------------------------------------------------------------------- */
|
|
675
|
+
/* Entry, exit */
|
|
676
|
+
/* --------------------------------------------------------------------- */
|
|
677
|
+
|
|
678
|
+
/* Creates an index in data_transfer_insts array. */
|
|
679
|
+
#define LOAD_DATA 0x01
|
|
680
|
+
#define WORD_DATA 0x00
|
|
681
|
+
#define BYTE_DATA 0x02
|
|
682
|
+
#define HALF_DATA 0x04
|
|
683
|
+
#define INT_DATA 0x06
|
|
684
|
+
#define SIGNED_DATA 0x08
|
|
685
|
+
/* Separates integer and floating point registers */
|
|
686
|
+
#define GPR_REG 0x0f
|
|
687
|
+
#define DOUBLE_DATA 0x10
|
|
688
|
+
#define SINGLE_DATA 0x12
|
|
689
|
+
|
|
690
|
+
#define MEM_MASK 0x1f
|
|
691
|
+
|
|
692
|
+
#define ARG_TEST 0x00020
|
|
693
|
+
#define ALT_KEEP_CACHE 0x00040
|
|
694
|
+
#define CUMULATIVE_OP 0x00080
|
|
695
|
+
#define IMM_OP 0x00100
|
|
696
|
+
#define MOVE_OP 0x00200
|
|
697
|
+
#define SRC2_IMM 0x00400
|
|
698
|
+
|
|
699
|
+
#define UNUSED_DEST 0x00800
|
|
700
|
+
#define REG_DEST 0x01000
|
|
701
|
+
#define REG1_SOURCE 0x02000
|
|
702
|
+
#define REG2_SOURCE 0x04000
|
|
703
|
+
#define SLOW_SRC1 0x08000
|
|
704
|
+
#define SLOW_SRC2 0x10000
|
|
705
|
+
#define SLOW_DEST 0x20000
|
|
706
|
+
#define MEM_USE_TMP2 0x40000
|
|
707
|
+
|
|
708
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
709
|
+
#define STACK_STORE SW
|
|
710
|
+
#define STACK_LOAD LW
|
|
711
|
+
#else
|
|
712
|
+
#define STACK_STORE SD
|
|
713
|
+
#define STACK_LOAD LD
|
|
714
|
+
#endif
|
|
715
|
+
|
|
716
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
717
|
+
#include "sljitNativeRISCV_32.c"
|
|
718
|
+
#else
|
|
719
|
+
#include "sljitNativeRISCV_64.c"
|
|
720
|
+
#endif
|
|
721
|
+
|
|
722
|
+
#define STACK_MAX_DISTANCE (-SIMM_MIN)
|
|
723
|
+
|
|
724
|
+
static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw);
|
|
725
|
+
|
|
726
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
|
|
727
|
+
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
|
|
728
|
+
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
|
729
|
+
{
|
|
730
|
+
sljit_s32 i, tmp, offset;
|
|
731
|
+
sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);
|
|
732
|
+
|
|
733
|
+
CHECK_ERROR();
|
|
734
|
+
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
|
|
735
|
+
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
|
|
736
|
+
|
|
737
|
+
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1);
|
|
738
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
739
|
+
if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
|
|
740
|
+
if ((local_size & SSIZE_OF(sw)) != 0)
|
|
741
|
+
local_size += SSIZE_OF(sw);
|
|
742
|
+
local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
|
|
743
|
+
}
|
|
744
|
+
#else
|
|
745
|
+
local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
|
|
746
|
+
#endif
|
|
747
|
+
local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
|
|
748
|
+
compiler->local_size = local_size;
|
|
749
|
+
|
|
750
|
+
if (local_size <= STACK_MAX_DISTANCE) {
|
|
751
|
+
/* Frequent case. */
|
|
752
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-local_size)));
|
|
753
|
+
offset = local_size - SSIZE_OF(sw);
|
|
754
|
+
local_size = 0;
|
|
755
|
+
} else {
|
|
756
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(STACK_MAX_DISTANCE)));
|
|
757
|
+
local_size -= STACK_MAX_DISTANCE;
|
|
758
|
+
|
|
759
|
+
if (local_size > STACK_MAX_DISTANCE)
|
|
760
|
+
FAIL_IF(load_immediate(compiler, TMP_REG1, local_size, TMP_REG3));
|
|
761
|
+
offset = STACK_MAX_DISTANCE - SSIZE_OF(sw);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(RETURN_ADDR_REG), offset));
|
|
765
|
+
|
|
766
|
+
tmp = SLJIT_S0 - saveds;
|
|
767
|
+
for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {
|
|
768
|
+
offset -= SSIZE_OF(sw);
|
|
769
|
+
FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(i), offset));
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
|
|
773
|
+
offset -= SSIZE_OF(sw);
|
|
774
|
+
FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(i), offset));
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
778
|
+
/* This alignment is valid because offset is not used after storing FPU regs. */
|
|
779
|
+
if ((offset & SSIZE_OF(sw)) != 0)
|
|
780
|
+
offset -= SSIZE_OF(sw);
|
|
781
|
+
#endif
|
|
782
|
+
|
|
783
|
+
tmp = SLJIT_FS0 - fsaveds;
|
|
784
|
+
for (i = SLJIT_FS0; i > tmp; i--) {
|
|
785
|
+
offset -= SSIZE_OF(f64);
|
|
786
|
+
FAIL_IF(push_imm_s_inst(compiler, FSD | RS1(SLJIT_SP) | FRS2(i), offset));
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
|
|
790
|
+
offset -= SSIZE_OF(f64);
|
|
791
|
+
FAIL_IF(push_imm_s_inst(compiler, FSD | RS1(SLJIT_SP) | FRS2(i), offset));
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
if (local_size > STACK_MAX_DISTANCE)
|
|
795
|
+
FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RS1(SLJIT_SP) | RS2(TMP_REG1)));
|
|
796
|
+
else if (local_size > 0)
|
|
797
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-local_size)));
|
|
798
|
+
|
|
799
|
+
if (options & SLJIT_ENTER_REG_ARG)
|
|
800
|
+
return SLJIT_SUCCESS;
|
|
801
|
+
|
|
802
|
+
arg_types >>= SLJIT_ARG_SHIFT;
|
|
803
|
+
saved_arg_count = 0;
|
|
804
|
+
tmp = SLJIT_R0;
|
|
805
|
+
|
|
806
|
+
while (arg_types > 0) {
|
|
807
|
+
if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
|
|
808
|
+
if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
|
|
809
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_S0 - saved_arg_count) | RS1(tmp) | IMM_I(0)));
|
|
810
|
+
saved_arg_count++;
|
|
811
|
+
}
|
|
812
|
+
tmp++;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
arg_types >>= SLJIT_ARG_SHIFT;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
return SLJIT_SUCCESS;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
#undef STACK_MAX_DISTANCE
|
|
822
|
+
|
|
823
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
|
|
824
|
+
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
|
|
825
|
+
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
|
826
|
+
{
|
|
827
|
+
CHECK_ERROR();
|
|
828
|
+
CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
|
|
829
|
+
set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
|
|
830
|
+
|
|
831
|
+
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1);
|
|
832
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
833
|
+
if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
|
|
834
|
+
if ((local_size & SSIZE_OF(sw)) != 0)
|
|
835
|
+
local_size += SSIZE_OF(sw);
|
|
836
|
+
local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
|
|
837
|
+
}
|
|
838
|
+
#else
|
|
839
|
+
local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
|
|
840
|
+
#endif
|
|
841
|
+
compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
|
|
842
|
+
|
|
843
|
+
return SLJIT_SUCCESS;
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
#define STACK_MAX_DISTANCE (-SIMM_MIN - 16)
|
|
847
|
+
|
|
848
|
+
static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to)
|
|
849
|
+
{
|
|
850
|
+
sljit_s32 i, tmp, offset;
|
|
851
|
+
sljit_s32 local_size = compiler->local_size;
|
|
852
|
+
|
|
853
|
+
if (local_size > STACK_MAX_DISTANCE) {
|
|
854
|
+
local_size -= STACK_MAX_DISTANCE;
|
|
855
|
+
|
|
856
|
+
if (local_size > STACK_MAX_DISTANCE) {
|
|
857
|
+
FAIL_IF(load_immediate(compiler, TMP_REG2, local_size, TMP_REG3));
|
|
858
|
+
FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RS1(SLJIT_SP) | RS2(TMP_REG2)));
|
|
859
|
+
} else
|
|
860
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(local_size)));
|
|
861
|
+
|
|
862
|
+
local_size = STACK_MAX_DISTANCE;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
SLJIT_ASSERT(local_size > 0);
|
|
866
|
+
|
|
867
|
+
offset = local_size - SSIZE_OF(sw);
|
|
868
|
+
if (!is_return_to)
|
|
869
|
+
FAIL_IF(push_inst(compiler, STACK_LOAD | RD(RETURN_ADDR_REG) | RS1(SLJIT_SP) | IMM_I(offset)));
|
|
870
|
+
|
|
871
|
+
tmp = SLJIT_S0 - compiler->saveds;
|
|
872
|
+
for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) {
|
|
873
|
+
offset -= SSIZE_OF(sw);
|
|
874
|
+
FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RS1(SLJIT_SP) | IMM_I(offset)));
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
|
|
878
|
+
offset -= SSIZE_OF(sw);
|
|
879
|
+
FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RS1(SLJIT_SP) | IMM_I(offset)));
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
883
|
+
/* This alignment is valid because offset is not used after storing FPU regs. */
|
|
884
|
+
if ((offset & SSIZE_OF(sw)) != 0)
|
|
885
|
+
offset -= SSIZE_OF(sw);
|
|
886
|
+
#endif
|
|
887
|
+
|
|
888
|
+
tmp = SLJIT_FS0 - compiler->fsaveds;
|
|
889
|
+
for (i = SLJIT_FS0; i > tmp; i--) {
|
|
890
|
+
offset -= SSIZE_OF(f64);
|
|
891
|
+
FAIL_IF(push_inst(compiler, FLD | FRD(i) | RS1(SLJIT_SP) | IMM_I(offset)));
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
|
|
895
|
+
offset -= SSIZE_OF(f64);
|
|
896
|
+
FAIL_IF(push_inst(compiler, FLD | FRD(i) | RS1(SLJIT_SP) | IMM_I(offset)));
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
return push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(local_size));
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
#undef STACK_MAX_DISTANCE
|
|
903
|
+
|
|
904
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
|
|
905
|
+
{
|
|
906
|
+
CHECK_ERROR();
|
|
907
|
+
CHECK(check_sljit_emit_return_void(compiler));
|
|
908
|
+
|
|
909
|
+
FAIL_IF(emit_stack_frame_release(compiler, 0));
|
|
910
|
+
return push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(RETURN_ADDR_REG) | IMM_I(0));
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,
|
|
914
|
+
sljit_s32 src, sljit_sw srcw)
|
|
915
|
+
{
|
|
916
|
+
CHECK_ERROR();
|
|
917
|
+
CHECK(check_sljit_emit_return_to(compiler, src, srcw));
|
|
918
|
+
|
|
919
|
+
if (src & SLJIT_MEM) {
|
|
920
|
+
ADJUST_LOCAL_OFFSET(src, srcw);
|
|
921
|
+
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));
|
|
922
|
+
src = TMP_REG1;
|
|
923
|
+
srcw = 0;
|
|
924
|
+
} else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
|
|
925
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src) | IMM_I(0)));
|
|
926
|
+
src = TMP_REG1;
|
|
927
|
+
srcw = 0;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
FAIL_IF(emit_stack_frame_release(compiler, 1));
|
|
931
|
+
|
|
932
|
+
SLJIT_SKIP_CHECKS(compiler);
|
|
933
|
+
return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
/* --------------------------------------------------------------------- */
|
|
937
|
+
/* Operators */
|
|
938
|
+
/* --------------------------------------------------------------------- */
|
|
939
|
+
|
|
940
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
941
|
+
#define ARCH_32_64(a, b) a
|
|
942
|
+
#else
|
|
943
|
+
#define ARCH_32_64(a, b) b
|
|
944
|
+
#endif
|
|
945
|
+
|
|
946
|
+
static const sljit_ins data_transfer_insts[16 + 4] = {
|
|
947
|
+
/* u w s */ ARCH_32_64(F3(0x2) | OPC(0x23) /* sw */, F3(0x3) | OPC(0x23) /* sd */),
|
|
948
|
+
/* u w l */ ARCH_32_64(F3(0x2) | OPC(0x3) /* lw */, F3(0x3) | OPC(0x3) /* ld */),
|
|
949
|
+
/* u b s */ F3(0x0) | OPC(0x23) /* sb */,
|
|
950
|
+
/* u b l */ F3(0x4) | OPC(0x3) /* lbu */,
|
|
951
|
+
/* u h s */ F3(0x1) | OPC(0x23) /* sh */,
|
|
952
|
+
/* u h l */ F3(0x5) | OPC(0x3) /* lhu */,
|
|
953
|
+
/* u i s */ F3(0x2) | OPC(0x23) /* sw */,
|
|
954
|
+
/* u i l */ ARCH_32_64(F3(0x2) | OPC(0x3) /* lw */, F3(0x6) | OPC(0x3) /* lwu */),
|
|
955
|
+
|
|
956
|
+
/* s w s */ ARCH_32_64(F3(0x2) | OPC(0x23) /* sw */, F3(0x3) | OPC(0x23) /* sd */),
|
|
957
|
+
/* s w l */ ARCH_32_64(F3(0x2) | OPC(0x3) /* lw */, F3(0x3) | OPC(0x3) /* ld */),
|
|
958
|
+
/* s b s */ F3(0x0) | OPC(0x23) /* sb */,
|
|
959
|
+
/* s b l */ F3(0x0) | OPC(0x3) /* lb */,
|
|
960
|
+
/* s h s */ F3(0x1) | OPC(0x23) /* sh */,
|
|
961
|
+
/* s h l */ F3(0x1) | OPC(0x3) /* lh */,
|
|
962
|
+
/* s i s */ F3(0x2) | OPC(0x23) /* sw */,
|
|
963
|
+
/* s i l */ F3(0x2) | OPC(0x3) /* lw */,
|
|
964
|
+
|
|
965
|
+
/* d s */ F3(0x3) | OPC(0x27) /* fsd */,
|
|
966
|
+
/* d l */ F3(0x3) | OPC(0x7) /* fld */,
|
|
967
|
+
/* s s */ F3(0x2) | OPC(0x27) /* fsw */,
|
|
968
|
+
/* s l */ F3(0x2) | OPC(0x7) /* flw */,
|
|
969
|
+
};
|
|
970
|
+
|
|
971
|
+
#undef ARCH_32_64
|
|
972
|
+
|
|
973
|
+
static sljit_s32 push_mem_inst(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 base, sljit_sw offset)
|
|
974
|
+
{
|
|
975
|
+
sljit_ins ins;
|
|
976
|
+
|
|
977
|
+
SLJIT_ASSERT(FAST_IS_REG(base) && offset <= 0xfff && offset >= SIMM_MIN);
|
|
978
|
+
|
|
979
|
+
ins = data_transfer_insts[flags & MEM_MASK] | RS1(base);
|
|
980
|
+
if (flags & LOAD_DATA)
|
|
981
|
+
ins |= ((flags & MEM_MASK) <= GPR_REG ? RD(reg) : FRD(reg)) | IMM_I(offset);
|
|
982
|
+
else
|
|
983
|
+
ins |= ((flags & MEM_MASK) <= GPR_REG ? RS2(reg) : FRS2(reg)) | IMM_S(offset);
|
|
984
|
+
|
|
985
|
+
return push_inst(compiler, ins);
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
/* Can perform an operation using at most 1 instruction. */
|
|
989
|
+
static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
|
|
990
|
+
{
|
|
991
|
+
SLJIT_ASSERT(arg & SLJIT_MEM);
|
|
992
|
+
|
|
993
|
+
if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {
|
|
994
|
+
/* Works for both absoulte and relative addresses. */
|
|
995
|
+
if (SLJIT_UNLIKELY(flags & ARG_TEST))
|
|
996
|
+
return 1;
|
|
997
|
+
|
|
998
|
+
FAIL_IF(push_mem_inst(compiler, flags, reg, arg & REG_MASK, argw));
|
|
999
|
+
return -1;
|
|
1000
|
+
}
|
|
1001
|
+
return 0;
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
#define TO_ARGW_HI(argw) (((argw) & ~0xfff) + (((argw) & 0x800) ? 0x1000 : 0))
|
|
1005
|
+
|
|
1006
|
+
/* See getput_arg below.
|
|
1007
|
+
Note: can_cache is called only for binary operators. */
|
|
1008
|
+
static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
|
|
1009
|
+
{
|
|
1010
|
+
SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
|
|
1011
|
+
|
|
1012
|
+
/* Simple operation except for updates. */
|
|
1013
|
+
if (arg & OFFS_REG_MASK) {
|
|
1014
|
+
argw &= 0x3;
|
|
1015
|
+
next_argw &= 0x3;
|
|
1016
|
+
if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))
|
|
1017
|
+
return 1;
|
|
1018
|
+
return 0;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
if (arg == next_arg) {
|
|
1022
|
+
if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN)
|
|
1023
|
+
|| TO_ARGW_HI(argw) == TO_ARGW_HI(next_argw))
|
|
1024
|
+
return 1;
|
|
1025
|
+
return 0;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
return 0;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
/* Emit the necessary instructions. See can_cache above. */
|
|
1032
|
+
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)
|
|
1033
|
+
{
|
|
1034
|
+
sljit_s32 base = arg & REG_MASK;
|
|
1035
|
+
sljit_s32 tmp_r = (flags & MEM_USE_TMP2) ? TMP_REG2 : TMP_REG1;
|
|
1036
|
+
sljit_sw offset, argw_hi;
|
|
1037
|
+
|
|
1038
|
+
SLJIT_ASSERT(arg & SLJIT_MEM);
|
|
1039
|
+
if (!(next_arg & SLJIT_MEM)) {
|
|
1040
|
+
next_arg = 0;
|
|
1041
|
+
next_argw = 0;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
|
|
1045
|
+
argw &= 0x3;
|
|
1046
|
+
|
|
1047
|
+
/* Using the cache. */
|
|
1048
|
+
if (argw == compiler->cache_argw) {
|
|
1049
|
+
if (arg == compiler->cache_arg)
|
|
1050
|
+
return push_mem_inst(compiler, flags, reg, TMP_REG3, 0);
|
|
1051
|
+
|
|
1052
|
+
if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
|
|
1053
|
+
if (arg == next_arg && argw == (next_argw & 0x3)) {
|
|
1054
|
+
compiler->cache_arg = arg;
|
|
1055
|
+
compiler->cache_argw = argw;
|
|
1056
|
+
FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG3) | RS1(TMP_REG3) | RS2(base)));
|
|
1057
|
+
return push_mem_inst(compiler, flags, reg, TMP_REG3, 0);
|
|
1058
|
+
}
|
|
1059
|
+
FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(TMP_REG3)));
|
|
1060
|
+
return push_mem_inst(compiler, flags, reg, tmp_r, 0);
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
if (SLJIT_UNLIKELY(argw)) {
|
|
1065
|
+
compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);
|
|
1066
|
+
compiler->cache_argw = argw;
|
|
1067
|
+
FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG3) | RS1(OFFS_REG(arg)) | IMM_I(argw)));
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
if (arg == next_arg && argw == (next_argw & 0x3)) {
|
|
1071
|
+
compiler->cache_arg = arg;
|
|
1072
|
+
compiler->cache_argw = argw;
|
|
1073
|
+
FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG3) | RS1(base) | RS2(!argw ? OFFS_REG(arg) : TMP_REG3)));
|
|
1074
|
+
tmp_r = TMP_REG3;
|
|
1075
|
+
}
|
|
1076
|
+
else
|
|
1077
|
+
FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(!argw ? OFFS_REG(arg) : TMP_REG3)));
|
|
1078
|
+
return push_mem_inst(compiler, flags, reg, tmp_r, 0);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN)
|
|
1082
|
+
return push_mem_inst(compiler, flags, reg, TMP_REG3, argw - compiler->cache_argw);
|
|
1083
|
+
|
|
1084
|
+
if (compiler->cache_arg == SLJIT_MEM && (argw - compiler->cache_argw <= SIMM_MAX) && (argw - compiler->cache_argw >= SIMM_MIN)) {
|
|
1085
|
+
offset = argw - compiler->cache_argw;
|
|
1086
|
+
} else {
|
|
1087
|
+
compiler->cache_arg = SLJIT_MEM;
|
|
1088
|
+
|
|
1089
|
+
argw_hi = TO_ARGW_HI(argw);
|
|
1090
|
+
|
|
1091
|
+
if (next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN && argw_hi != TO_ARGW_HI(next_argw)) {
|
|
1092
|
+
FAIL_IF(load_immediate(compiler, TMP_REG3, argw, tmp_r));
|
|
1093
|
+
compiler->cache_argw = argw;
|
|
1094
|
+
offset = 0;
|
|
1095
|
+
} else {
|
|
1096
|
+
FAIL_IF(load_immediate(compiler, TMP_REG3, argw_hi, tmp_r));
|
|
1097
|
+
compiler->cache_argw = argw_hi;
|
|
1098
|
+
offset = argw & 0xfff;
|
|
1099
|
+
argw = argw_hi;
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
if (!base)
|
|
1104
|
+
return push_mem_inst(compiler, flags, reg, TMP_REG3, offset);
|
|
1105
|
+
|
|
1106
|
+
if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) {
|
|
1107
|
+
compiler->cache_arg = arg;
|
|
1108
|
+
FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG3) | RS1(TMP_REG3) | RS2(base)));
|
|
1109
|
+
return push_mem_inst(compiler, flags, reg, TMP_REG3, offset);
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(TMP_REG3) | RS2(base)));
|
|
1113
|
+
return push_mem_inst(compiler, flags, reg, tmp_r, offset);
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
|
|
1117
|
+
{
|
|
1118
|
+
sljit_s32 base = arg & REG_MASK;
|
|
1119
|
+
sljit_s32 tmp_r = TMP_REG1;
|
|
1120
|
+
|
|
1121
|
+
if (getput_arg_fast(compiler, flags, reg, arg, argw))
|
|
1122
|
+
return compiler->error;
|
|
1123
|
+
|
|
1124
|
+
if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA))
|
|
1125
|
+
tmp_r = reg;
|
|
1126
|
+
|
|
1127
|
+
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
|
|
1128
|
+
argw &= 0x3;
|
|
1129
|
+
|
|
1130
|
+
if (SLJIT_UNLIKELY(argw)) {
|
|
1131
|
+
FAIL_IF(push_inst(compiler, SLLI | RD(tmp_r) | RS1(OFFS_REG(arg)) | IMM_I(argw)));
|
|
1132
|
+
FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(tmp_r) | RS2(base)));
|
|
1133
|
+
}
|
|
1134
|
+
else
|
|
1135
|
+
FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(OFFS_REG(arg))));
|
|
1136
|
+
|
|
1137
|
+
argw = 0;
|
|
1138
|
+
} else {
|
|
1139
|
+
FAIL_IF(load_immediate(compiler, tmp_r, TO_ARGW_HI(argw), TMP_REG3));
|
|
1140
|
+
|
|
1141
|
+
if (base != 0)
|
|
1142
|
+
FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(tmp_r) | RS2(base)));
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
return push_mem_inst(compiler, flags, reg, tmp_r, argw & 0xfff);
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
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)
|
|
1149
|
+
{
|
|
1150
|
+
if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
|
|
1151
|
+
return compiler->error;
|
|
1152
|
+
return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
1156
|
+
#define WORD 0
|
|
1157
|
+
#define WORD_32 0
|
|
1158
|
+
#define IMM_EXTEND(v) (IMM_I(v))
|
|
1159
|
+
#else /* !SLJIT_CONFIG_RISCV_32 */
|
|
1160
|
+
#define WORD word
|
|
1161
|
+
#define WORD_32 0x08
|
|
1162
|
+
#define IMM_EXTEND(v) (IMM_I((op & SLJIT_32) ? (v) : (32 + (v))))
|
|
1163
|
+
#endif /* SLJIT_CONFIG_RISCV_32 */
|
|
1164
|
+
|
|
1165
|
+
static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)
|
|
1166
|
+
{
|
|
1167
|
+
sljit_s32 is_clz = (GET_OPCODE(op) == SLJIT_CLZ);
|
|
1168
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
1169
|
+
sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;
|
|
1170
|
+
sljit_ins word_size = (op & SLJIT_32) ? 32 : 64;
|
|
1171
|
+
#else /* !SLJIT_CONFIG_RISCV_64 */
|
|
1172
|
+
sljit_ins word_size = 32;
|
|
1173
|
+
#endif /* SLJIT_CONFIG_RISCV_64 */
|
|
1174
|
+
|
|
1175
|
+
SLJIT_ASSERT(WORD == 0 || WORD == 0x8);
|
|
1176
|
+
|
|
1177
|
+
/* The OTHER_FLAG is the counter. */
|
|
1178
|
+
FAIL_IF(push_inst(compiler, ADDI | WORD | RD(OTHER_FLAG) | RS1(TMP_ZERO) | IMM_I(word_size)));
|
|
1179
|
+
|
|
1180
|
+
/* The TMP_REG2 is the next value. */
|
|
1181
|
+
if (src != TMP_REG2)
|
|
1182
|
+
FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG2) | RS1(src) | IMM_I(0)));
|
|
1183
|
+
|
|
1184
|
+
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)));
|
|
1185
|
+
|
|
1186
|
+
FAIL_IF(push_inst(compiler, ADDI | WORD | RD(OTHER_FLAG) | RS1(TMP_ZERO) | IMM_I(0)));
|
|
1187
|
+
if (!is_clz) {
|
|
1188
|
+
FAIL_IF(push_inst(compiler, ANDI | RD(TMP_REG1) | RS1(TMP_REG2) | IMM_I(1)));
|
|
1189
|
+
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)));
|
|
1190
|
+
} else
|
|
1191
|
+
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)));
|
|
1192
|
+
|
|
1193
|
+
/* The TMP_REG1 is the next shift. */
|
|
1194
|
+
FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG1) | RS1(TMP_ZERO) | IMM_I(word_size)));
|
|
1195
|
+
|
|
1196
|
+
FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(TMP_REG2) | IMM_I(0)));
|
|
1197
|
+
FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_I(1)));
|
|
1198
|
+
|
|
1199
|
+
FAIL_IF(push_inst(compiler, (is_clz ? SRL : SLL) | WORD | RD(TMP_REG2) | RS1(EQUAL_FLAG) | RS2(TMP_REG1)));
|
|
1200
|
+
FAIL_IF(push_inst(compiler, BNE | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)0xfe000e80 - ((2 * SSIZE_OF(ins)) << 7))));
|
|
1201
|
+
FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG2) | RS1(TMP_REG1) | IMM_I(-1)));
|
|
1202
|
+
FAIL_IF(push_inst(compiler, (is_clz ? SRL : SLL) | WORD | RD(TMP_REG2) | RS1(EQUAL_FLAG) | RS2(TMP_REG2)));
|
|
1203
|
+
FAIL_IF(push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(TMP_REG1)));
|
|
1204
|
+
FAIL_IF(push_inst(compiler, BEQ | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)0xfe000e80 - ((5 * SSIZE_OF(ins)) << 7))));
|
|
1205
|
+
|
|
1206
|
+
return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(OTHER_FLAG) | IMM_I(0));
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)
|
|
1210
|
+
{
|
|
1211
|
+
SLJIT_UNUSED_ARG(op);
|
|
1212
|
+
|
|
1213
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
1214
|
+
if (!(op & SLJIT_32)) {
|
|
1215
|
+
FAIL_IF(push_inst(compiler, LUI | RD(OTHER_FLAG) | 0x10000));
|
|
1216
|
+
FAIL_IF(push_inst(compiler, SRLI | RD(TMP_REG1) | RS1(src) | IMM_I(32)));
|
|
1217
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | IMM_I(0xfff)));
|
|
1218
|
+
FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(src) | IMM_I(32)));
|
|
1219
|
+
FAIL_IF(push_inst(compiler, SLLI | RD(EQUAL_FLAG) | RS1(OTHER_FLAG) | IMM_I(32)));
|
|
1220
|
+
FAIL_IF(push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1)));
|
|
1221
|
+
FAIL_IF(push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(EQUAL_FLAG)));
|
|
1222
|
+
|
|
1223
|
+
FAIL_IF(push_inst(compiler, SRLI | RD(TMP_REG1) | RS1(dst) | IMM_I(16)));
|
|
1224
|
+
FAIL_IF(push_inst(compiler, AND | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));
|
|
1225
|
+
FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(OTHER_FLAG)));
|
|
1226
|
+
FAIL_IF(push_inst(compiler, SLLI | RD(EQUAL_FLAG) | RS1(OTHER_FLAG) | IMM_I(8)));
|
|
1227
|
+
FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(16)));
|
|
1228
|
+
FAIL_IF(push_inst(compiler, XOR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(EQUAL_FLAG)));
|
|
1229
|
+
FAIL_IF(push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1)));
|
|
1230
|
+
|
|
1231
|
+
FAIL_IF(push_inst(compiler, SRLI | RD(TMP_REG1) | RS1(dst) | IMM_I(8)));
|
|
1232
|
+
FAIL_IF(push_inst(compiler, AND | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));
|
|
1233
|
+
FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(OTHER_FLAG)));
|
|
1234
|
+
FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(8)));
|
|
1235
|
+
return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1));
|
|
1236
|
+
}
|
|
1237
|
+
#endif /* SLJIT_CONFIG_RISCV_64 */
|
|
1238
|
+
|
|
1239
|
+
FAIL_IF(push_inst(compiler, SRLI | WORD_32 | RD(TMP_REG1) | RS1(src) | IMM_I(16)));
|
|
1240
|
+
FAIL_IF(push_inst(compiler, LUI | RD(OTHER_FLAG) | 0xff0000));
|
|
1241
|
+
FAIL_IF(push_inst(compiler, SLLI | WORD_32 | RD(dst) | RS1(src) | IMM_I(16)));
|
|
1242
|
+
FAIL_IF(push_inst(compiler, ORI | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | IMM_I(0xff)));
|
|
1243
|
+
FAIL_IF(push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1)));
|
|
1244
|
+
|
|
1245
|
+
FAIL_IF(push_inst(compiler, SRLI | WORD_32 | RD(TMP_REG1) | RS1(dst) | IMM_I(8)));
|
|
1246
|
+
FAIL_IF(push_inst(compiler, AND | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));
|
|
1247
|
+
FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(OTHER_FLAG)));
|
|
1248
|
+
FAIL_IF(push_inst(compiler, SLLI | WORD_32 | RD(dst) | RS1(dst) | IMM_I(8)));
|
|
1249
|
+
return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1));
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
static sljit_s32 emit_rev16(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)
|
|
1253
|
+
{
|
|
1254
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
1255
|
+
sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;
|
|
1256
|
+
sljit_ins word_size = (op & SLJIT_32) ? 32 : 64;
|
|
1257
|
+
#else /* !SLJIT_CONFIG_RISCV_64 */
|
|
1258
|
+
sljit_ins word_size = 32;
|
|
1259
|
+
#endif /* SLJIT_CONFIG_RISCV_64 */
|
|
1260
|
+
|
|
1261
|
+
FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(src) | IMM_I(8)));
|
|
1262
|
+
FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src) | IMM_I(word_size - 8)));
|
|
1263
|
+
FAIL_IF(push_inst(compiler, ANDI | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_I(0xff)));
|
|
1264
|
+
FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SRLI : SRAI) | WORD | RD(dst) | RS1(dst) | IMM_I(word_size - 16)));
|
|
1265
|
+
return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1));
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
#define EMIT_LOGICAL(op_imm, op_reg) \
|
|
1269
|
+
if (flags & SRC2_IMM) { \
|
|
1270
|
+
if (op & SLJIT_SET_Z) \
|
|
1271
|
+
FAIL_IF(push_inst(compiler, op_imm | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2))); \
|
|
1272
|
+
if (!(flags & UNUSED_DEST)) \
|
|
1273
|
+
FAIL_IF(push_inst(compiler, op_imm | RD(dst) | RS1(src1) | IMM_I(src2))); \
|
|
1274
|
+
} \
|
|
1275
|
+
else { \
|
|
1276
|
+
if (op & SLJIT_SET_Z) \
|
|
1277
|
+
FAIL_IF(push_inst(compiler, op_reg | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2))); \
|
|
1278
|
+
if (!(flags & UNUSED_DEST)) \
|
|
1279
|
+
FAIL_IF(push_inst(compiler, op_reg | RD(dst) | RS1(src1) | RS2(src2))); \
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
#define EMIT_SHIFT(imm, reg) \
|
|
1283
|
+
op_imm = (imm); \
|
|
1284
|
+
op_reg = (reg);
|
|
1285
|
+
|
|
1286
|
+
static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
|
|
1287
|
+
sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
|
|
1288
|
+
{
|
|
1289
|
+
sljit_s32 is_overflow, is_carry, carry_src_r, is_handled, reg;
|
|
1290
|
+
sljit_ins op_imm, op_reg;
|
|
1291
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
1292
|
+
sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;
|
|
1293
|
+
#endif /* SLJIT_CONFIG_RISCV_64 */
|
|
1294
|
+
|
|
1295
|
+
SLJIT_ASSERT(WORD == 0 || WORD == 0x8);
|
|
1296
|
+
|
|
1297
|
+
switch (GET_OPCODE(op)) {
|
|
1298
|
+
case SLJIT_MOV:
|
|
1299
|
+
SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
|
|
1300
|
+
if (dst != src2)
|
|
1301
|
+
return push_inst(compiler, ADDI | RD(dst) | RS1(src2) | IMM_I(0));
|
|
1302
|
+
return SLJIT_SUCCESS;
|
|
1303
|
+
|
|
1304
|
+
case SLJIT_MOV_U8:
|
|
1305
|
+
SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
|
|
1306
|
+
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
|
|
1307
|
+
return push_inst(compiler, ANDI | RD(dst) | RS1(src2) | IMM_I(0xff));
|
|
1308
|
+
SLJIT_ASSERT(dst == src2);
|
|
1309
|
+
return SLJIT_SUCCESS;
|
|
1310
|
+
|
|
1311
|
+
case SLJIT_MOV_S8:
|
|
1312
|
+
SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
|
|
1313
|
+
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
|
1314
|
+
FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(24)));
|
|
1315
|
+
return push_inst(compiler, SRAI | WORD | RD(dst) | RS1(dst) | IMM_EXTEND(24));
|
|
1316
|
+
}
|
|
1317
|
+
SLJIT_ASSERT(dst == src2);
|
|
1318
|
+
return SLJIT_SUCCESS;
|
|
1319
|
+
|
|
1320
|
+
case SLJIT_MOV_U16:
|
|
1321
|
+
SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
|
|
1322
|
+
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
|
1323
|
+
FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(16)));
|
|
1324
|
+
return push_inst(compiler, SRLI | WORD | RD(dst) | RS1(dst) | IMM_EXTEND(16));
|
|
1325
|
+
}
|
|
1326
|
+
SLJIT_ASSERT(dst == src2);
|
|
1327
|
+
return SLJIT_SUCCESS;
|
|
1328
|
+
|
|
1329
|
+
case SLJIT_MOV_S16:
|
|
1330
|
+
SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
|
|
1331
|
+
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
|
1332
|
+
FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(16)));
|
|
1333
|
+
return push_inst(compiler, SRAI | WORD | RD(dst) | RS1(dst) | IMM_EXTEND(16));
|
|
1334
|
+
}
|
|
1335
|
+
SLJIT_ASSERT(dst == src2);
|
|
1336
|
+
return SLJIT_SUCCESS;
|
|
1337
|
+
|
|
1338
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
1339
|
+
case SLJIT_MOV_U32:
|
|
1340
|
+
SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
|
|
1341
|
+
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
|
1342
|
+
FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(src2) | IMM_I(32)));
|
|
1343
|
+
return push_inst(compiler, SRLI | RD(dst) | RS1(dst) | IMM_I(32));
|
|
1344
|
+
}
|
|
1345
|
+
SLJIT_ASSERT(dst == src2);
|
|
1346
|
+
return SLJIT_SUCCESS;
|
|
1347
|
+
|
|
1348
|
+
case SLJIT_MOV_S32:
|
|
1349
|
+
SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
|
|
1350
|
+
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
|
|
1351
|
+
return push_inst(compiler, ADDI | 0x8 | RD(dst) | RS1(src2) | IMM_I(0));
|
|
1352
|
+
SLJIT_ASSERT(dst == src2);
|
|
1353
|
+
return SLJIT_SUCCESS;
|
|
1354
|
+
#endif /* SLJIT_CONFIG_RISCV_64 */
|
|
1355
|
+
|
|
1356
|
+
case SLJIT_CLZ:
|
|
1357
|
+
case SLJIT_CTZ:
|
|
1358
|
+
SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
|
|
1359
|
+
return emit_clz_ctz(compiler, op, dst, src2);
|
|
1360
|
+
|
|
1361
|
+
case SLJIT_REV:
|
|
1362
|
+
case SLJIT_REV_S32:
|
|
1363
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
1364
|
+
case SLJIT_REV_U32:
|
|
1365
|
+
#endif /* SLJIT_CONFIG_RISCV_32 */
|
|
1366
|
+
SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
|
|
1367
|
+
return emit_rev(compiler, op, dst, src2);
|
|
1368
|
+
|
|
1369
|
+
case SLJIT_REV_U16:
|
|
1370
|
+
case SLJIT_REV_S16:
|
|
1371
|
+
SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
|
|
1372
|
+
return emit_rev16(compiler, op, dst, src2);
|
|
1373
|
+
|
|
1374
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
1375
|
+
case SLJIT_REV_U32:
|
|
1376
|
+
SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM) && dst != TMP_REG1);
|
|
1377
|
+
FAIL_IF(emit_rev(compiler, op, dst, src2));
|
|
1378
|
+
if (dst == TMP_REG2)
|
|
1379
|
+
return SLJIT_SUCCESS;
|
|
1380
|
+
FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(32)));
|
|
1381
|
+
return push_inst(compiler, SRLI | RD(dst) | RS1(dst) | IMM_I(32));
|
|
1382
|
+
#endif /* SLJIT_CONFIG_RISCV_32 */
|
|
1383
|
+
|
|
1384
|
+
case SLJIT_ADD:
|
|
1385
|
+
/* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */
|
|
1386
|
+
is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
|
|
1387
|
+
carry_src_r = GET_FLAG_TYPE(op) == SLJIT_CARRY;
|
|
1388
|
+
|
|
1389
|
+
if (flags & SRC2_IMM) {
|
|
1390
|
+
if (is_overflow) {
|
|
1391
|
+
if (src2 >= 0)
|
|
1392
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));
|
|
1393
|
+
else
|
|
1394
|
+
FAIL_IF(push_inst(compiler, XORI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-1)));
|
|
1395
|
+
}
|
|
1396
|
+
else if (op & SLJIT_SET_Z)
|
|
1397
|
+
FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2)));
|
|
1398
|
+
|
|
1399
|
+
/* Only the zero flag is needed. */
|
|
1400
|
+
if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
|
|
1401
|
+
FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));
|
|
1402
|
+
}
|
|
1403
|
+
else {
|
|
1404
|
+
if (is_overflow)
|
|
1405
|
+
FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
|
|
1406
|
+
else if (op & SLJIT_SET_Z)
|
|
1407
|
+
FAIL_IF(push_inst(compiler, ADD | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
|
|
1408
|
+
|
|
1409
|
+
if (is_overflow || carry_src_r != 0) {
|
|
1410
|
+
if (src1 != dst)
|
|
1411
|
+
carry_src_r = (sljit_s32)src1;
|
|
1412
|
+
else if (src2 != dst)
|
|
1413
|
+
carry_src_r = (sljit_s32)src2;
|
|
1414
|
+
else {
|
|
1415
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(0)));
|
|
1416
|
+
carry_src_r = OTHER_FLAG;
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
/* Only the zero flag is needed. */
|
|
1421
|
+
if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
|
|
1422
|
+
FAIL_IF(push_inst(compiler, ADD | WORD | RD(dst) | RS1(src1) | RS2(src2)));
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
/* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */
|
|
1426
|
+
if (is_overflow || carry_src_r != 0) {
|
|
1427
|
+
if (flags & SRC2_IMM)
|
|
1428
|
+
FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RS1(dst) | IMM_I(src2)));
|
|
1429
|
+
else
|
|
1430
|
+
FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(dst) | RS2(carry_src_r)));
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
if (!is_overflow)
|
|
1434
|
+
return SLJIT_SUCCESS;
|
|
1435
|
+
|
|
1436
|
+
FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RS1(dst) | RS2(EQUAL_FLAG)));
|
|
1437
|
+
if (op & SLJIT_SET_Z)
|
|
1438
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(0)));
|
|
1439
|
+
FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_EXTEND(31)));
|
|
1440
|
+
return push_inst(compiler, XOR | RD(OTHER_FLAG) | RS1(TMP_REG1) | RS2(OTHER_FLAG));
|
|
1441
|
+
|
|
1442
|
+
case SLJIT_ADDC:
|
|
1443
|
+
carry_src_r = GET_FLAG_TYPE(op) == SLJIT_CARRY;
|
|
1444
|
+
|
|
1445
|
+
if (flags & SRC2_IMM) {
|
|
1446
|
+
FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));
|
|
1447
|
+
} else {
|
|
1448
|
+
if (carry_src_r != 0) {
|
|
1449
|
+
if (src1 != dst)
|
|
1450
|
+
carry_src_r = (sljit_s32)src1;
|
|
1451
|
+
else if (src2 != dst)
|
|
1452
|
+
carry_src_r = (sljit_s32)src2;
|
|
1453
|
+
else {
|
|
1454
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));
|
|
1455
|
+
carry_src_r = EQUAL_FLAG;
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
FAIL_IF(push_inst(compiler, ADD | WORD | RD(dst) | RS1(src1) | RS2(src2)));
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
/* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */
|
|
1463
|
+
if (carry_src_r != 0) {
|
|
1464
|
+
if (flags & SRC2_IMM)
|
|
1465
|
+
FAIL_IF(push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(src2)));
|
|
1466
|
+
else
|
|
1467
|
+
FAIL_IF(push_inst(compiler, SLTU | RD(EQUAL_FLAG) | RS1(dst) | RS2(carry_src_r)));
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
FAIL_IF(push_inst(compiler, ADD | WORD | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));
|
|
1471
|
+
|
|
1472
|
+
if (carry_src_r == 0)
|
|
1473
|
+
return SLJIT_SUCCESS;
|
|
1474
|
+
|
|
1475
|
+
/* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */
|
|
1476
|
+
FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(dst) | RS2(OTHER_FLAG)));
|
|
1477
|
+
/* Set carry flag. */
|
|
1478
|
+
return push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(EQUAL_FLAG));
|
|
1479
|
+
|
|
1480
|
+
case SLJIT_SUB:
|
|
1481
|
+
if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
|
|
1482
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG2) | RS1(TMP_ZERO) | IMM_I(src2)));
|
|
1483
|
+
src2 = TMP_REG2;
|
|
1484
|
+
flags &= ~SRC2_IMM;
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
is_handled = 0;
|
|
1488
|
+
|
|
1489
|
+
if (flags & SRC2_IMM) {
|
|
1490
|
+
if (GET_FLAG_TYPE(op) == SLJIT_LESS) {
|
|
1491
|
+
FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));
|
|
1492
|
+
is_handled = 1;
|
|
1493
|
+
}
|
|
1494
|
+
else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS) {
|
|
1495
|
+
FAIL_IF(push_inst(compiler, SLTI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));
|
|
1496
|
+
is_handled = 1;
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
|
|
1501
|
+
is_handled = 1;
|
|
1502
|
+
|
|
1503
|
+
if (flags & SRC2_IMM) {
|
|
1504
|
+
reg = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
|
|
1505
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(reg) | RS1(TMP_ZERO) | IMM_I(src2)));
|
|
1506
|
+
src2 = reg;
|
|
1507
|
+
flags &= ~SRC2_IMM;
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
switch (GET_FLAG_TYPE(op)) {
|
|
1511
|
+
case SLJIT_LESS:
|
|
1512
|
+
FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));
|
|
1513
|
+
break;
|
|
1514
|
+
case SLJIT_GREATER:
|
|
1515
|
+
FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src2) | RS2(src1)));
|
|
1516
|
+
break;
|
|
1517
|
+
case SLJIT_SIG_LESS:
|
|
1518
|
+
FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));
|
|
1519
|
+
break;
|
|
1520
|
+
case SLJIT_SIG_GREATER:
|
|
1521
|
+
FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RS1(src2) | RS2(src1)));
|
|
1522
|
+
break;
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
if (is_handled) {
|
|
1527
|
+
if (flags & SRC2_IMM) {
|
|
1528
|
+
if (op & SLJIT_SET_Z)
|
|
1529
|
+
FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-src2)));
|
|
1530
|
+
if (!(flags & UNUSED_DEST))
|
|
1531
|
+
return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(-src2));
|
|
1532
|
+
}
|
|
1533
|
+
else {
|
|
1534
|
+
if (op & SLJIT_SET_Z)
|
|
1535
|
+
FAIL_IF(push_inst(compiler, SUB | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
|
|
1536
|
+
if (!(flags & UNUSED_DEST))
|
|
1537
|
+
return push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2));
|
|
1538
|
+
}
|
|
1539
|
+
return SLJIT_SUCCESS;
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
|
|
1543
|
+
is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;
|
|
1544
|
+
|
|
1545
|
+
if (flags & SRC2_IMM) {
|
|
1546
|
+
if (is_overflow) {
|
|
1547
|
+
if (src2 >= 0)
|
|
1548
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));
|
|
1549
|
+
else
|
|
1550
|
+
FAIL_IF(push_inst(compiler, XORI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-1)));
|
|
1551
|
+
}
|
|
1552
|
+
else if (op & SLJIT_SET_Z)
|
|
1553
|
+
FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-src2)));
|
|
1554
|
+
|
|
1555
|
+
if (is_overflow || is_carry)
|
|
1556
|
+
FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));
|
|
1557
|
+
|
|
1558
|
+
/* Only the zero flag is needed. */
|
|
1559
|
+
if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
|
|
1560
|
+
FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(-src2)));
|
|
1561
|
+
}
|
|
1562
|
+
else {
|
|
1563
|
+
if (is_overflow)
|
|
1564
|
+
FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
|
|
1565
|
+
else if (op & SLJIT_SET_Z)
|
|
1566
|
+
FAIL_IF(push_inst(compiler, SUB | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
|
|
1567
|
+
|
|
1568
|
+
if (is_overflow || is_carry)
|
|
1569
|
+
FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));
|
|
1570
|
+
|
|
1571
|
+
/* Only the zero flag is needed. */
|
|
1572
|
+
if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
|
|
1573
|
+
FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2)));
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
if (!is_overflow)
|
|
1577
|
+
return SLJIT_SUCCESS;
|
|
1578
|
+
|
|
1579
|
+
FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RS1(dst) | RS2(EQUAL_FLAG)));
|
|
1580
|
+
if (op & SLJIT_SET_Z)
|
|
1581
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(0)));
|
|
1582
|
+
FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_EXTEND(31)));
|
|
1583
|
+
return push_inst(compiler, XOR | RD(OTHER_FLAG) | RS1(TMP_REG1) | RS2(OTHER_FLAG));
|
|
1584
|
+
|
|
1585
|
+
case SLJIT_SUBC:
|
|
1586
|
+
if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
|
|
1587
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG2) | RS1(TMP_ZERO) | IMM_I(src2)));
|
|
1588
|
+
src2 = TMP_REG2;
|
|
1589
|
+
flags &= ~SRC2_IMM;
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;
|
|
1593
|
+
|
|
1594
|
+
if (flags & SRC2_IMM) {
|
|
1595
|
+
if (is_carry)
|
|
1596
|
+
FAIL_IF(push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2)));
|
|
1597
|
+
|
|
1598
|
+
FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(-src2)));
|
|
1599
|
+
}
|
|
1600
|
+
else {
|
|
1601
|
+
if (is_carry)
|
|
1602
|
+
FAIL_IF(push_inst(compiler, SLTU | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
|
|
1603
|
+
|
|
1604
|
+
FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2)));
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
if (is_carry)
|
|
1608
|
+
FAIL_IF(push_inst(compiler, SLTU | RD(TMP_REG1) | RS1(dst) | RS2(OTHER_FLAG)));
|
|
1609
|
+
|
|
1610
|
+
FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));
|
|
1611
|
+
|
|
1612
|
+
if (!is_carry)
|
|
1613
|
+
return SLJIT_SUCCESS;
|
|
1614
|
+
|
|
1615
|
+
return push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(EQUAL_FLAG) | RS2(TMP_REG1));
|
|
1616
|
+
|
|
1617
|
+
case SLJIT_MUL:
|
|
1618
|
+
SLJIT_ASSERT(!(flags & SRC2_IMM));
|
|
1619
|
+
|
|
1620
|
+
if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW)
|
|
1621
|
+
return push_inst(compiler, MUL | WORD | RD(dst) | RS1(src1) | RS2(src2));
|
|
1622
|
+
|
|
1623
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
1624
|
+
if (word) {
|
|
1625
|
+
FAIL_IF(push_inst(compiler, MUL | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));
|
|
1626
|
+
FAIL_IF(push_inst(compiler, MUL | 0x8 | RD(dst) | RS1(src1) | RS2(src2)));
|
|
1627
|
+
return push_inst(compiler, SUB | RD(OTHER_FLAG) | RS1(dst) | RS2(OTHER_FLAG));
|
|
1628
|
+
}
|
|
1629
|
+
#endif /* SLJIT_CONFIG_RISCV_64 */
|
|
1630
|
+
|
|
1631
|
+
FAIL_IF(push_inst(compiler, MULH | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
|
|
1632
|
+
FAIL_IF(push_inst(compiler, MUL | RD(dst) | RS1(src1) | RS2(src2)));
|
|
1633
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
1634
|
+
FAIL_IF(push_inst(compiler, SRAI | RD(OTHER_FLAG) | RS1(dst) | IMM_I(31)));
|
|
1635
|
+
#else /* !SLJIT_CONFIG_RISCV_32 */
|
|
1636
|
+
FAIL_IF(push_inst(compiler, SRAI | RD(OTHER_FLAG) | RS1(dst) | IMM_I(63)));
|
|
1637
|
+
#endif /* SLJIT_CONFIG_RISCV_32 */
|
|
1638
|
+
return push_inst(compiler, SUB | RD(OTHER_FLAG) | RS1(EQUAL_FLAG) | RS2(OTHER_FLAG));
|
|
1639
|
+
|
|
1640
|
+
case SLJIT_AND:
|
|
1641
|
+
EMIT_LOGICAL(ANDI, AND);
|
|
1642
|
+
return SLJIT_SUCCESS;
|
|
1643
|
+
|
|
1644
|
+
case SLJIT_OR:
|
|
1645
|
+
EMIT_LOGICAL(ORI, OR);
|
|
1646
|
+
return SLJIT_SUCCESS;
|
|
1647
|
+
|
|
1648
|
+
case SLJIT_XOR:
|
|
1649
|
+
EMIT_LOGICAL(XORI, XOR);
|
|
1650
|
+
return SLJIT_SUCCESS;
|
|
1651
|
+
|
|
1652
|
+
case SLJIT_SHL:
|
|
1653
|
+
case SLJIT_MSHL:
|
|
1654
|
+
EMIT_SHIFT(SLLI, SLL);
|
|
1655
|
+
break;
|
|
1656
|
+
|
|
1657
|
+
case SLJIT_LSHR:
|
|
1658
|
+
case SLJIT_MLSHR:
|
|
1659
|
+
EMIT_SHIFT(SRLI, SRL);
|
|
1660
|
+
break;
|
|
1661
|
+
|
|
1662
|
+
case SLJIT_ASHR:
|
|
1663
|
+
case SLJIT_MASHR:
|
|
1664
|
+
EMIT_SHIFT(SRAI, SRA);
|
|
1665
|
+
break;
|
|
1666
|
+
|
|
1667
|
+
case SLJIT_ROTL:
|
|
1668
|
+
case SLJIT_ROTR:
|
|
1669
|
+
if (flags & SRC2_IMM) {
|
|
1670
|
+
SLJIT_ASSERT(src2 != 0);
|
|
1671
|
+
|
|
1672
|
+
op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SLLI : SRLI;
|
|
1673
|
+
FAIL_IF(push_inst(compiler, op_imm | WORD | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));
|
|
1674
|
+
|
|
1675
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
1676
|
+
src2 = ((op & SLJIT_32) ? 32 : 64) - src2;
|
|
1677
|
+
#else /* !SLJIT_CONFIG_RISCV_64 */
|
|
1678
|
+
src2 = 32 - src2;
|
|
1679
|
+
#endif /* SLJIT_CONFIG_RISCV_64 */
|
|
1680
|
+
op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SRLI : SLLI;
|
|
1681
|
+
FAIL_IF(push_inst(compiler, op_imm | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));
|
|
1682
|
+
return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(OTHER_FLAG));
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
if (src2 == TMP_ZERO) {
|
|
1686
|
+
if (dst != src1)
|
|
1687
|
+
return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(0));
|
|
1688
|
+
return SLJIT_SUCCESS;
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
FAIL_IF(push_inst(compiler, SUB | WORD | RD(EQUAL_FLAG) | RS1(TMP_ZERO) | RS2(src2)));
|
|
1692
|
+
op_reg = (GET_OPCODE(op) == SLJIT_ROTL) ? SLL : SRL;
|
|
1693
|
+
FAIL_IF(push_inst(compiler, op_reg | WORD | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));
|
|
1694
|
+
op_reg = (GET_OPCODE(op) == SLJIT_ROTL) ? SRL : SLL;
|
|
1695
|
+
FAIL_IF(push_inst(compiler, op_reg | WORD | RD(dst) | RS1(src1) | RS2(EQUAL_FLAG)));
|
|
1696
|
+
return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(OTHER_FLAG));
|
|
1697
|
+
|
|
1698
|
+
default:
|
|
1699
|
+
SLJIT_UNREACHABLE();
|
|
1700
|
+
return SLJIT_SUCCESS;
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1703
|
+
if (flags & SRC2_IMM) {
|
|
1704
|
+
if (op & SLJIT_SET_Z)
|
|
1705
|
+
FAIL_IF(push_inst(compiler, op_imm | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2)));
|
|
1706
|
+
|
|
1707
|
+
if (flags & UNUSED_DEST)
|
|
1708
|
+
return SLJIT_SUCCESS;
|
|
1709
|
+
return push_inst(compiler, op_imm | WORD | RD(dst) | RS1(src1) | IMM_I(src2));
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
if (op & SLJIT_SET_Z)
|
|
1713
|
+
FAIL_IF(push_inst(compiler, op_reg | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
|
|
1714
|
+
|
|
1715
|
+
if (flags & UNUSED_DEST)
|
|
1716
|
+
return SLJIT_SUCCESS;
|
|
1717
|
+
return push_inst(compiler, op_reg | WORD | RD(dst) | RS1(src1) | RS2(src2));
|
|
1718
|
+
}
|
|
1719
|
+
|
|
1720
|
+
#undef IMM_EXTEND
|
|
1721
|
+
|
|
1722
|
+
static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
|
|
1723
|
+
sljit_s32 dst, sljit_sw dstw,
|
|
1724
|
+
sljit_s32 src1, sljit_sw src1w,
|
|
1725
|
+
sljit_s32 src2, sljit_sw src2w)
|
|
1726
|
+
{
|
|
1727
|
+
/* arg1 goes to TMP_REG1 or src reg
|
|
1728
|
+
arg2 goes to TMP_REG2, imm or src reg
|
|
1729
|
+
TMP_REG3 can be used for caching
|
|
1730
|
+
result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
|
|
1731
|
+
sljit_s32 dst_r = TMP_REG2;
|
|
1732
|
+
sljit_s32 src1_r;
|
|
1733
|
+
sljit_sw src2_r = 0;
|
|
1734
|
+
sljit_s32 src2_tmp_reg = (GET_OPCODE(op) >= SLJIT_OP2_BASE && FAST_IS_REG(src1)) ? TMP_REG1 : TMP_REG2;
|
|
1735
|
+
|
|
1736
|
+
if (!(flags & ALT_KEEP_CACHE)) {
|
|
1737
|
+
compiler->cache_arg = 0;
|
|
1738
|
+
compiler->cache_argw = 0;
|
|
1739
|
+
}
|
|
1740
|
+
|
|
1741
|
+
if (dst == 0) {
|
|
1742
|
+
SLJIT_ASSERT(HAS_FLAGS(op));
|
|
1743
|
+
flags |= UNUSED_DEST;
|
|
1744
|
+
dst = TMP_REG2;
|
|
1745
|
+
}
|
|
1746
|
+
else if (FAST_IS_REG(dst)) {
|
|
1747
|
+
dst_r = dst;
|
|
1748
|
+
flags |= REG_DEST;
|
|
1749
|
+
if (flags & MOVE_OP)
|
|
1750
|
+
src2_tmp_reg = dst_r;
|
|
1751
|
+
}
|
|
1752
|
+
else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1, dst, dstw))
|
|
1753
|
+
flags |= SLOW_DEST;
|
|
1754
|
+
|
|
1755
|
+
if (flags & IMM_OP) {
|
|
1756
|
+
if (src2 == SLJIT_IMM && src2w != 0 && src2w <= SIMM_MAX && src2w >= SIMM_MIN) {
|
|
1757
|
+
flags |= SRC2_IMM;
|
|
1758
|
+
src2_r = src2w;
|
|
1759
|
+
}
|
|
1760
|
+
else if ((flags & CUMULATIVE_OP) && src1 == SLJIT_IMM && src1w != 0 && src1w <= SIMM_MAX && src1w >= SIMM_MIN) {
|
|
1761
|
+
flags |= SRC2_IMM;
|
|
1762
|
+
src2_r = src1w;
|
|
1763
|
+
|
|
1764
|
+
/* And swap arguments. */
|
|
1765
|
+
src1 = src2;
|
|
1766
|
+
src1w = src2w;
|
|
1767
|
+
src2 = SLJIT_IMM;
|
|
1768
|
+
/* src2w = src2_r unneeded. */
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
/* Source 1. */
|
|
1773
|
+
if (FAST_IS_REG(src1)) {
|
|
1774
|
+
src1_r = src1;
|
|
1775
|
+
flags |= REG1_SOURCE;
|
|
1776
|
+
} else if (src1 == SLJIT_IMM) {
|
|
1777
|
+
if (src1w) {
|
|
1778
|
+
FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3));
|
|
1779
|
+
src1_r = TMP_REG1;
|
|
1780
|
+
}
|
|
1781
|
+
else
|
|
1782
|
+
src1_r = TMP_ZERO;
|
|
1783
|
+
} else {
|
|
1784
|
+
if (getput_arg_fast(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w))
|
|
1785
|
+
FAIL_IF(compiler->error);
|
|
1786
|
+
else
|
|
1787
|
+
flags |= SLOW_SRC1;
|
|
1788
|
+
src1_r = TMP_REG1;
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
/* Source 2. */
|
|
1792
|
+
if (FAST_IS_REG(src2)) {
|
|
1793
|
+
src2_r = src2;
|
|
1794
|
+
flags |= REG2_SOURCE;
|
|
1795
|
+
if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP)
|
|
1796
|
+
dst_r = (sljit_s32)src2_r;
|
|
1797
|
+
} else if (src2 == SLJIT_IMM) {
|
|
1798
|
+
if (!(flags & SRC2_IMM)) {
|
|
1799
|
+
if (src2w) {
|
|
1800
|
+
FAIL_IF(load_immediate(compiler, src2_tmp_reg, src2w, TMP_REG3));
|
|
1801
|
+
src2_r = src2_tmp_reg;
|
|
1802
|
+
} else {
|
|
1803
|
+
src2_r = TMP_ZERO;
|
|
1804
|
+
if (flags & MOVE_OP) {
|
|
1805
|
+
if (dst & SLJIT_MEM)
|
|
1806
|
+
dst_r = 0;
|
|
1807
|
+
else
|
|
1808
|
+
op = SLJIT_MOV;
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
} else {
|
|
1813
|
+
if (getput_arg_fast(compiler, flags | LOAD_DATA, src2_tmp_reg, src2, src2w))
|
|
1814
|
+
FAIL_IF(compiler->error);
|
|
1815
|
+
else
|
|
1816
|
+
flags |= SLOW_SRC2;
|
|
1817
|
+
src2_r = src2_tmp_reg;
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
|
|
1821
|
+
SLJIT_ASSERT(src2_r == TMP_REG2);
|
|
1822
|
+
if ((flags & SLOW_DEST) && !can_cache(src2, src2w, src1, src1w) && can_cache(src2, src2w, dst, dstw)) {
|
|
1823
|
+
FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
|
|
1824
|
+
FAIL_IF(getput_arg(compiler, flags | LOAD_DATA | MEM_USE_TMP2, TMP_REG2, src2, src2w, dst, dstw));
|
|
1825
|
+
} else {
|
|
1826
|
+
FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));
|
|
1827
|
+
FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
else if (flags & SLOW_SRC1)
|
|
1831
|
+
FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
|
|
1832
|
+
else if (flags & SLOW_SRC2)
|
|
1833
|
+
FAIL_IF(getput_arg(compiler, flags | LOAD_DATA | ((src1_r == TMP_REG1) ? MEM_USE_TMP2 : 0), src2_tmp_reg, src2, src2w, dst, dstw));
|
|
1834
|
+
|
|
1835
|
+
FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
|
|
1836
|
+
|
|
1837
|
+
if (dst & SLJIT_MEM) {
|
|
1838
|
+
if (!(flags & SLOW_DEST)) {
|
|
1839
|
+
getput_arg_fast(compiler, flags, dst_r, dst, dstw);
|
|
1840
|
+
return compiler->error;
|
|
1841
|
+
}
|
|
1842
|
+
return getput_arg(compiler, flags, dst_r, dst, dstw, 0, 0);
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
return SLJIT_SUCCESS;
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
|
|
1849
|
+
{
|
|
1850
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
1851
|
+
sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;
|
|
1852
|
+
|
|
1853
|
+
SLJIT_ASSERT(word == 0 || word == 0x8);
|
|
1854
|
+
#endif /* SLJIT_CONFIG_RISCV_64 */
|
|
1855
|
+
|
|
1856
|
+
CHECK_ERROR();
|
|
1857
|
+
CHECK(check_sljit_emit_op0(compiler, op));
|
|
1858
|
+
|
|
1859
|
+
switch (GET_OPCODE(op)) {
|
|
1860
|
+
case SLJIT_BREAKPOINT:
|
|
1861
|
+
return push_inst(compiler, EBREAK);
|
|
1862
|
+
case SLJIT_NOP:
|
|
1863
|
+
return push_inst(compiler, ADDI | RD(TMP_ZERO) | RS1(TMP_ZERO) | IMM_I(0));
|
|
1864
|
+
case SLJIT_LMUL_UW:
|
|
1865
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R1) | IMM_I(0)));
|
|
1866
|
+
FAIL_IF(push_inst(compiler, MULHU | RD(SLJIT_R1) | RS1(SLJIT_R0) | RS2(SLJIT_R1)));
|
|
1867
|
+
return push_inst(compiler, MUL | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(TMP_REG1));
|
|
1868
|
+
case SLJIT_LMUL_SW:
|
|
1869
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R1) | IMM_I(0)));
|
|
1870
|
+
FAIL_IF(push_inst(compiler, MULH | RD(SLJIT_R1) | RS1(SLJIT_R0) | RS2(SLJIT_R1)));
|
|
1871
|
+
return push_inst(compiler, MUL | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(TMP_REG1));
|
|
1872
|
+
case SLJIT_DIVMOD_UW:
|
|
1873
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R0) | IMM_I(0)));
|
|
1874
|
+
FAIL_IF(push_inst(compiler, DIVU | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1)));
|
|
1875
|
+
return push_inst(compiler, REMU | WORD | RD(SLJIT_R1) | RS1(TMP_REG1) | RS2(SLJIT_R1));
|
|
1876
|
+
case SLJIT_DIVMOD_SW:
|
|
1877
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R0) | IMM_I(0)));
|
|
1878
|
+
FAIL_IF(push_inst(compiler, DIV | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1)));
|
|
1879
|
+
return push_inst(compiler, REM | WORD | RD(SLJIT_R1) | RS1(TMP_REG1) | RS2(SLJIT_R1));
|
|
1880
|
+
case SLJIT_DIV_UW:
|
|
1881
|
+
return push_inst(compiler, DIVU | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1));
|
|
1882
|
+
case SLJIT_DIV_SW:
|
|
1883
|
+
return push_inst(compiler, DIV | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1));
|
|
1884
|
+
case SLJIT_ENDBR:
|
|
1885
|
+
case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
|
|
1886
|
+
return SLJIT_SUCCESS;
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1889
|
+
return SLJIT_SUCCESS;
|
|
1890
|
+
}
|
|
1891
|
+
|
|
1892
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
|
|
1893
|
+
sljit_s32 dst, sljit_sw dstw,
|
|
1894
|
+
sljit_s32 src, sljit_sw srcw)
|
|
1895
|
+
{
|
|
1896
|
+
sljit_s32 flags = 0;
|
|
1897
|
+
|
|
1898
|
+
CHECK_ERROR();
|
|
1899
|
+
CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
|
|
1900
|
+
ADJUST_LOCAL_OFFSET(dst, dstw);
|
|
1901
|
+
ADJUST_LOCAL_OFFSET(src, srcw);
|
|
1902
|
+
|
|
1903
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
1904
|
+
if (op & SLJIT_32)
|
|
1905
|
+
flags = INT_DATA | SIGNED_DATA;
|
|
1906
|
+
#endif
|
|
1907
|
+
|
|
1908
|
+
switch (GET_OPCODE(op)) {
|
|
1909
|
+
case SLJIT_MOV:
|
|
1910
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
1911
|
+
case SLJIT_MOV_U32:
|
|
1912
|
+
case SLJIT_MOV_S32:
|
|
1913
|
+
case SLJIT_MOV32:
|
|
1914
|
+
#endif
|
|
1915
|
+
case SLJIT_MOV_P:
|
|
1916
|
+
return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, srcw);
|
|
1917
|
+
|
|
1918
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
1919
|
+
case SLJIT_MOV_U32:
|
|
1920
|
+
return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u32)srcw : srcw);
|
|
1921
|
+
|
|
1922
|
+
case SLJIT_MOV_S32:
|
|
1923
|
+
/* Logical operators have no W variant, so sign extended input is necessary for them. */
|
|
1924
|
+
case SLJIT_MOV32:
|
|
1925
|
+
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);
|
|
1926
|
+
#endif
|
|
1927
|
+
|
|
1928
|
+
case SLJIT_MOV_U8:
|
|
1929
|
+
return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u8)srcw : srcw);
|
|
1930
|
+
|
|
1931
|
+
case SLJIT_MOV_S8:
|
|
1932
|
+
return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_s8)srcw : srcw);
|
|
1933
|
+
|
|
1934
|
+
case SLJIT_MOV_U16:
|
|
1935
|
+
return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u16)srcw : srcw);
|
|
1936
|
+
|
|
1937
|
+
case SLJIT_MOV_S16:
|
|
1938
|
+
return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_s16)srcw : srcw);
|
|
1939
|
+
|
|
1940
|
+
case SLJIT_CLZ:
|
|
1941
|
+
case SLJIT_CTZ:
|
|
1942
|
+
case SLJIT_REV:
|
|
1943
|
+
return emit_op(compiler, op, flags, dst, dstw, TMP_ZERO, 0, src, srcw);
|
|
1944
|
+
|
|
1945
|
+
case SLJIT_REV_U16:
|
|
1946
|
+
case SLJIT_REV_S16:
|
|
1947
|
+
return emit_op(compiler, op, HALF_DATA, dst, dstw, TMP_ZERO, 0, src, srcw);
|
|
1948
|
+
|
|
1949
|
+
case SLJIT_REV_U32:
|
|
1950
|
+
case SLJIT_REV_S32:
|
|
1951
|
+
return emit_op(compiler, op | SLJIT_32, INT_DATA, dst, dstw, TMP_ZERO, 0, src, srcw);
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1954
|
+
SLJIT_UNREACHABLE();
|
|
1955
|
+
return SLJIT_SUCCESS;
|
|
1956
|
+
}
|
|
1957
|
+
|
|
1958
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
|
|
1959
|
+
sljit_s32 dst, sljit_sw dstw,
|
|
1960
|
+
sljit_s32 src1, sljit_sw src1w,
|
|
1961
|
+
sljit_s32 src2, sljit_sw src2w)
|
|
1962
|
+
{
|
|
1963
|
+
sljit_s32 flags = 0;
|
|
1964
|
+
|
|
1965
|
+
CHECK_ERROR();
|
|
1966
|
+
CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
|
|
1967
|
+
ADJUST_LOCAL_OFFSET(dst, dstw);
|
|
1968
|
+
ADJUST_LOCAL_OFFSET(src1, src1w);
|
|
1969
|
+
ADJUST_LOCAL_OFFSET(src2, src2w);
|
|
1970
|
+
|
|
1971
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
1972
|
+
if (op & SLJIT_32) {
|
|
1973
|
+
flags |= INT_DATA | SIGNED_DATA;
|
|
1974
|
+
if (src1 == SLJIT_IMM)
|
|
1975
|
+
src1w = (sljit_s32)src1w;
|
|
1976
|
+
if (src2 == SLJIT_IMM)
|
|
1977
|
+
src2w = (sljit_s32)src2w;
|
|
1978
|
+
}
|
|
1979
|
+
#endif
|
|
1980
|
+
|
|
1981
|
+
switch (GET_OPCODE(op)) {
|
|
1982
|
+
case SLJIT_ADD:
|
|
1983
|
+
case SLJIT_ADDC:
|
|
1984
|
+
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
|
|
1985
|
+
return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
|
|
1986
|
+
|
|
1987
|
+
case SLJIT_SUB:
|
|
1988
|
+
case SLJIT_SUBC:
|
|
1989
|
+
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
|
|
1990
|
+
return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
|
|
1991
|
+
|
|
1992
|
+
case SLJIT_MUL:
|
|
1993
|
+
compiler->status_flags_state = 0;
|
|
1994
|
+
return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);
|
|
1995
|
+
|
|
1996
|
+
case SLJIT_AND:
|
|
1997
|
+
case SLJIT_OR:
|
|
1998
|
+
case SLJIT_XOR:
|
|
1999
|
+
return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
|
|
2000
|
+
|
|
2001
|
+
case SLJIT_SHL:
|
|
2002
|
+
case SLJIT_MSHL:
|
|
2003
|
+
case SLJIT_LSHR:
|
|
2004
|
+
case SLJIT_MLSHR:
|
|
2005
|
+
case SLJIT_ASHR:
|
|
2006
|
+
case SLJIT_MASHR:
|
|
2007
|
+
case SLJIT_ROTL:
|
|
2008
|
+
case SLJIT_ROTR:
|
|
2009
|
+
if (src2 == SLJIT_IMM) {
|
|
2010
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
2011
|
+
src2w &= 0x1f;
|
|
2012
|
+
#else /* !SLJIT_CONFIG_RISCV_32 */
|
|
2013
|
+
if (op & SLJIT_32)
|
|
2014
|
+
src2w &= 0x1f;
|
|
2015
|
+
else
|
|
2016
|
+
src2w &= 0x3f;
|
|
2017
|
+
#endif /* SLJIT_CONFIG_RISCV_32 */
|
|
2018
|
+
}
|
|
2019
|
+
|
|
2020
|
+
return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
|
|
2021
|
+
}
|
|
2022
|
+
|
|
2023
|
+
SLJIT_UNREACHABLE();
|
|
2024
|
+
return SLJIT_SUCCESS;
|
|
2025
|
+
}
|
|
2026
|
+
|
|
2027
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
|
|
2028
|
+
sljit_s32 src1, sljit_sw src1w,
|
|
2029
|
+
sljit_s32 src2, sljit_sw src2w)
|
|
2030
|
+
{
|
|
2031
|
+
CHECK_ERROR();
|
|
2032
|
+
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
|
2033
|
+
|
|
2034
|
+
SLJIT_SKIP_CHECKS(compiler);
|
|
2035
|
+
return sljit_emit_op2(compiler, op, 0, 0, src1, src1w, src2, src2w);
|
|
2036
|
+
}
|
|
2037
|
+
|
|
2038
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,
|
|
2039
|
+
sljit_s32 dst_reg,
|
|
2040
|
+
sljit_s32 src1, sljit_sw src1w,
|
|
2041
|
+
sljit_s32 src2, sljit_sw src2w)
|
|
2042
|
+
{
|
|
2043
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
2044
|
+
sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;
|
|
2045
|
+
#endif /* SLJIT_CONFIG_RISCV_64 */
|
|
2046
|
+
|
|
2047
|
+
CHECK_ERROR();
|
|
2048
|
+
CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));
|
|
2049
|
+
|
|
2050
|
+
SLJIT_ASSERT(WORD == 0 || WORD == 0x8);
|
|
2051
|
+
|
|
2052
|
+
switch (GET_OPCODE(op)) {
|
|
2053
|
+
case SLJIT_MULADD:
|
|
2054
|
+
SLJIT_SKIP_CHECKS(compiler);
|
|
2055
|
+
FAIL_IF(sljit_emit_op2(compiler, SLJIT_MUL | (op & SLJIT_32), TMP_REG2, 0, src1, src1w, src2, src2w));
|
|
2056
|
+
return push_inst(compiler, ADD | WORD | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG2));
|
|
2057
|
+
}
|
|
2058
|
+
|
|
2059
|
+
return SLJIT_SUCCESS;
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,
|
|
2063
|
+
sljit_s32 dst_reg,
|
|
2064
|
+
sljit_s32 src1_reg,
|
|
2065
|
+
sljit_s32 src2_reg,
|
|
2066
|
+
sljit_s32 src3, sljit_sw src3w)
|
|
2067
|
+
{
|
|
2068
|
+
sljit_s32 is_left;
|
|
2069
|
+
sljit_ins ins1, ins2, ins3;
|
|
2070
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
2071
|
+
sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;
|
|
2072
|
+
sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
|
|
2073
|
+
sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64;
|
|
2074
|
+
#else /* !SLJIT_CONFIG_RISCV_64 */
|
|
2075
|
+
sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;
|
|
2076
|
+
sljit_sw bit_length = 32;
|
|
2077
|
+
#endif /* SLJIT_CONFIG_RISCV_64 */
|
|
2078
|
+
|
|
2079
|
+
SLJIT_ASSERT(WORD == 0 || WORD == 0x8);
|
|
2080
|
+
|
|
2081
|
+
CHECK_ERROR();
|
|
2082
|
+
CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));
|
|
2083
|
+
|
|
2084
|
+
is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL);
|
|
2085
|
+
|
|
2086
|
+
if (src1_reg == src2_reg) {
|
|
2087
|
+
SLJIT_SKIP_CHECKS(compiler);
|
|
2088
|
+
return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);
|
|
2089
|
+
}
|
|
2090
|
+
|
|
2091
|
+
ADJUST_LOCAL_OFFSET(src3, src3w);
|
|
2092
|
+
|
|
2093
|
+
if (src3 == SLJIT_IMM) {
|
|
2094
|
+
src3w &= bit_length - 1;
|
|
2095
|
+
|
|
2096
|
+
if (src3w == 0)
|
|
2097
|
+
return SLJIT_SUCCESS;
|
|
2098
|
+
|
|
2099
|
+
if (is_left) {
|
|
2100
|
+
ins1 = SLLI | WORD | IMM_I(src3w);
|
|
2101
|
+
src3w = bit_length - src3w;
|
|
2102
|
+
ins2 = SRLI | WORD | IMM_I(src3w);
|
|
2103
|
+
} else {
|
|
2104
|
+
ins1 = SRLI | WORD | IMM_I(src3w);
|
|
2105
|
+
src3w = bit_length - src3w;
|
|
2106
|
+
ins2 = SLLI | WORD | IMM_I(src3w);
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
FAIL_IF(push_inst(compiler, ins1 | RD(dst_reg) | RS1(src1_reg)));
|
|
2110
|
+
FAIL_IF(push_inst(compiler, ins2 | RD(TMP_REG1) | RS1(src2_reg)));
|
|
2111
|
+
return push_inst(compiler, OR | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1));
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
if (src3 & SLJIT_MEM) {
|
|
2115
|
+
FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG2, src3, src3w));
|
|
2116
|
+
src3 = TMP_REG2;
|
|
2117
|
+
} else if (dst_reg == src3) {
|
|
2118
|
+
push_inst(compiler, ADDI | WORD | RD(TMP_REG2) | RS1(src3) | IMM_I(0));
|
|
2119
|
+
src3 = TMP_REG2;
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2122
|
+
if (is_left) {
|
|
2123
|
+
ins1 = SLL;
|
|
2124
|
+
ins2 = SRLI;
|
|
2125
|
+
ins3 = SRL;
|
|
2126
|
+
} else {
|
|
2127
|
+
ins1 = SRL;
|
|
2128
|
+
ins2 = SLLI;
|
|
2129
|
+
ins3 = SLL;
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
FAIL_IF(push_inst(compiler, ins1 | WORD | RD(dst_reg) | RS1(src1_reg) | RS2(src3)));
|
|
2133
|
+
|
|
2134
|
+
if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) {
|
|
2135
|
+
FAIL_IF(push_inst(compiler, ins2 | WORD | RD(TMP_REG1) | RS1(src2_reg) | IMM_I(1)));
|
|
2136
|
+
FAIL_IF(push_inst(compiler, XORI | RD(TMP_REG2) | RS1(src3) | IMM_I((sljit_ins)bit_length - 1)));
|
|
2137
|
+
src2_reg = TMP_REG1;
|
|
2138
|
+
} else
|
|
2139
|
+
FAIL_IF(push_inst(compiler, SUB | WORD | RD(TMP_REG2) | RS1(TMP_ZERO) | RS2(src3)));
|
|
2140
|
+
|
|
2141
|
+
FAIL_IF(push_inst(compiler, ins3 | WORD | RD(TMP_REG1) | RS1(src2_reg) | RS2(TMP_REG2)));
|
|
2142
|
+
return push_inst(compiler, OR | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1));
|
|
2143
|
+
}
|
|
2144
|
+
|
|
2145
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
|
|
2146
|
+
sljit_s32 src, sljit_sw srcw)
|
|
2147
|
+
{
|
|
2148
|
+
CHECK_ERROR();
|
|
2149
|
+
CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
|
|
2150
|
+
ADJUST_LOCAL_OFFSET(src, srcw);
|
|
2151
|
+
|
|
2152
|
+
switch (op) {
|
|
2153
|
+
case SLJIT_FAST_RETURN:
|
|
2154
|
+
if (FAST_IS_REG(src))
|
|
2155
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(RETURN_ADDR_REG) | RS1(src) | IMM_I(0)));
|
|
2156
|
+
else
|
|
2157
|
+
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
|
|
2158
|
+
|
|
2159
|
+
return push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(RETURN_ADDR_REG) | IMM_I(0));
|
|
2160
|
+
case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
|
|
2161
|
+
return SLJIT_SUCCESS;
|
|
2162
|
+
case SLJIT_PREFETCH_L1:
|
|
2163
|
+
case SLJIT_PREFETCH_L2:
|
|
2164
|
+
case SLJIT_PREFETCH_L3:
|
|
2165
|
+
case SLJIT_PREFETCH_ONCE:
|
|
2166
|
+
return SLJIT_SUCCESS;
|
|
2167
|
+
}
|
|
2168
|
+
|
|
2169
|
+
return SLJIT_SUCCESS;
|
|
2170
|
+
}
|
|
2171
|
+
|
|
2172
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,
|
|
2173
|
+
sljit_s32 dst, sljit_sw dstw)
|
|
2174
|
+
{
|
|
2175
|
+
sljit_s32 dst_r;
|
|
2176
|
+
|
|
2177
|
+
CHECK_ERROR();
|
|
2178
|
+
CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));
|
|
2179
|
+
ADJUST_LOCAL_OFFSET(dst, dstw);
|
|
2180
|
+
|
|
2181
|
+
switch (op) {
|
|
2182
|
+
case SLJIT_FAST_ENTER:
|
|
2183
|
+
if (FAST_IS_REG(dst))
|
|
2184
|
+
return push_inst(compiler, ADDI | RD(dst) | RS1(RETURN_ADDR_REG) | IMM_I(0));
|
|
2185
|
+
|
|
2186
|
+
SLJIT_ASSERT(RETURN_ADDR_REG == TMP_REG2);
|
|
2187
|
+
break;
|
|
2188
|
+
case SLJIT_GET_RETURN_ADDRESS:
|
|
2189
|
+
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
|
2190
|
+
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size - SSIZE_OF(sw)));
|
|
2191
|
+
break;
|
|
2192
|
+
}
|
|
2193
|
+
|
|
2194
|
+
if (dst & SLJIT_MEM)
|
|
2195
|
+
return emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw);
|
|
2196
|
+
|
|
2197
|
+
return SLJIT_SUCCESS;
|
|
2198
|
+
}
|
|
2199
|
+
|
|
2200
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)
|
|
2201
|
+
{
|
|
2202
|
+
CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));
|
|
2203
|
+
|
|
2204
|
+
if (type == SLJIT_GP_REGISTER)
|
|
2205
|
+
return reg_map[reg];
|
|
2206
|
+
|
|
2207
|
+
if (type != SLJIT_FLOAT_REGISTER)
|
|
2208
|
+
return -1;
|
|
2209
|
+
|
|
2210
|
+
return freg_map[reg];
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
|
|
2214
|
+
void *instruction, sljit_u32 size)
|
|
2215
|
+
{
|
|
2216
|
+
SLJIT_UNUSED_ARG(size);
|
|
2217
|
+
|
|
2218
|
+
CHECK_ERROR();
|
|
2219
|
+
CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
|
|
2220
|
+
|
|
2221
|
+
return push_inst(compiler, *(sljit_ins*)instruction);
|
|
2222
|
+
}
|
|
2223
|
+
|
|
2224
|
+
/* --------------------------------------------------------------------- */
|
|
2225
|
+
/* Floating point operators */
|
|
2226
|
+
/* --------------------------------------------------------------------- */
|
|
2227
|
+
|
|
2228
|
+
#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7))
|
|
2229
|
+
#define FMT(op) ((sljit_ins)((op & SLJIT_32) ^ SLJIT_32) << 17)
|
|
2230
|
+
|
|
2231
|
+
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
|
|
2232
|
+
sljit_s32 dst, sljit_sw dstw,
|
|
2233
|
+
sljit_s32 src, sljit_sw srcw)
|
|
2234
|
+
{
|
|
2235
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
2236
|
+
# define flags (sljit_u32)0
|
|
2237
|
+
#else
|
|
2238
|
+
sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)) << 21;
|
|
2239
|
+
#endif
|
|
2240
|
+
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
|
2241
|
+
|
|
2242
|
+
if (src & SLJIT_MEM) {
|
|
2243
|
+
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));
|
|
2244
|
+
src = TMP_FREG1;
|
|
2245
|
+
}
|
|
2246
|
+
|
|
2247
|
+
FAIL_IF(push_inst(compiler, FCVT_W_S | FMT(op) | flags | RD(dst_r) | FRS1(src)));
|
|
2248
|
+
|
|
2249
|
+
/* Store the integer value from a VFP register. */
|
|
2250
|
+
if (dst & SLJIT_MEM) {
|
|
2251
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
2252
|
+
return emit_op_mem2(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0);
|
|
2253
|
+
#else
|
|
2254
|
+
return emit_op_mem2(compiler, flags ? WORD_DATA : INT_DATA, TMP_REG2, dst, dstw, 0, 0);
|
|
2255
|
+
#endif
|
|
2256
|
+
}
|
|
2257
|
+
return SLJIT_SUCCESS;
|
|
2258
|
+
|
|
2259
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
2260
|
+
# undef flags
|
|
2261
|
+
#endif
|
|
2262
|
+
}
|
|
2263
|
+
|
|
2264
|
+
static sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_ins ins,
|
|
2265
|
+
sljit_s32 dst, sljit_sw dstw,
|
|
2266
|
+
sljit_s32 src, sljit_sw srcw)
|
|
2267
|
+
{
|
|
2268
|
+
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
|
2269
|
+
|
|
2270
|
+
if (src & SLJIT_MEM) {
|
|
2271
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
2272
|
+
FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));
|
|
2273
|
+
#else /* SLJIT_CONFIG_RISCV_32 */
|
|
2274
|
+
FAIL_IF(emit_op_mem2(compiler, ((ins & (1 << 21)) ? WORD_DATA : INT_DATA) | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));
|
|
2275
|
+
#endif /* !SLJIT_CONFIG_RISCV_32 */
|
|
2276
|
+
src = TMP_REG1;
|
|
2277
|
+
} else if (src == SLJIT_IMM) {
|
|
2278
|
+
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw, TMP_REG3));
|
|
2279
|
+
src = TMP_REG1;
|
|
2280
|
+
}
|
|
2281
|
+
|
|
2282
|
+
FAIL_IF(push_inst(compiler, ins | FRD(dst_r) | RS1(src)));
|
|
2283
|
+
|
|
2284
|
+
if (dst & SLJIT_MEM)
|
|
2285
|
+
return emit_op_mem2(compiler, DOUBLE_DATA | ((sljit_s32)(~ins >> 24) & 0x2), TMP_FREG1, dst, dstw, 0, 0);
|
|
2286
|
+
return SLJIT_SUCCESS;
|
|
2287
|
+
}
|
|
2288
|
+
|
|
2289
|
+
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
|
|
2290
|
+
sljit_s32 dst, sljit_sw dstw,
|
|
2291
|
+
sljit_s32 src, sljit_sw srcw)
|
|
2292
|
+
{
|
|
2293
|
+
sljit_ins ins = FCVT_S_W | FMT(op);
|
|
2294
|
+
|
|
2295
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
2296
|
+
if (op & SLJIT_32)
|
|
2297
|
+
ins |= F3(0x7);
|
|
2298
|
+
#else /* !SLJIT_CONFIG_RISCV_32 */
|
|
2299
|
+
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)
|
|
2300
|
+
ins |= (1 << 21);
|
|
2301
|
+
else if (src == SLJIT_IMM)
|
|
2302
|
+
srcw = (sljit_s32)srcw;
|
|
2303
|
+
|
|
2304
|
+
if (op != SLJIT_CONV_F64_FROM_S32)
|
|
2305
|
+
ins |= F3(0x7);
|
|
2306
|
+
#endif /* SLJIT_CONFIG_RISCV_32 */
|
|
2307
|
+
|
|
2308
|
+
return sljit_emit_fop1_conv_f64_from_w(compiler, ins, dst, dstw, src, srcw);
|
|
2309
|
+
}
|
|
2310
|
+
|
|
2311
|
+
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
|
|
2312
|
+
sljit_s32 dst, sljit_sw dstw,
|
|
2313
|
+
sljit_s32 src, sljit_sw srcw)
|
|
2314
|
+
{
|
|
2315
|
+
sljit_ins ins = FCVT_S_WU | FMT(op);
|
|
2316
|
+
|
|
2317
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
2318
|
+
if (op & SLJIT_32)
|
|
2319
|
+
ins |= F3(0x7);
|
|
2320
|
+
#else /* !SLJIT_CONFIG_RISCV_32 */
|
|
2321
|
+
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_UW)
|
|
2322
|
+
ins |= (1 << 21);
|
|
2323
|
+
else if (src == SLJIT_IMM)
|
|
2324
|
+
srcw = (sljit_u32)srcw;
|
|
2325
|
+
|
|
2326
|
+
if (op != SLJIT_CONV_F64_FROM_S32)
|
|
2327
|
+
ins |= F3(0x7);
|
|
2328
|
+
#endif /* SLJIT_CONFIG_RISCV_32 */
|
|
2329
|
+
|
|
2330
|
+
return sljit_emit_fop1_conv_f64_from_w(compiler, ins, dst, dstw, src, srcw);
|
|
2331
|
+
}
|
|
2332
|
+
|
|
2333
|
+
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
|
|
2334
|
+
sljit_s32 src1, sljit_sw src1w,
|
|
2335
|
+
sljit_s32 src2, sljit_sw src2w)
|
|
2336
|
+
{
|
|
2337
|
+
sljit_ins inst;
|
|
2338
|
+
|
|
2339
|
+
if (src1 & SLJIT_MEM) {
|
|
2340
|
+
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
|
|
2341
|
+
src1 = TMP_FREG1;
|
|
2342
|
+
}
|
|
2343
|
+
|
|
2344
|
+
if (src2 & SLJIT_MEM) {
|
|
2345
|
+
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));
|
|
2346
|
+
src2 = TMP_FREG2;
|
|
2347
|
+
}
|
|
2348
|
+
|
|
2349
|
+
switch (GET_FLAG_TYPE(op)) {
|
|
2350
|
+
case SLJIT_F_EQUAL:
|
|
2351
|
+
case SLJIT_ORDERED_EQUAL:
|
|
2352
|
+
inst = FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2);
|
|
2353
|
+
break;
|
|
2354
|
+
case SLJIT_F_LESS:
|
|
2355
|
+
case SLJIT_ORDERED_LESS:
|
|
2356
|
+
inst = FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2);
|
|
2357
|
+
break;
|
|
2358
|
+
case SLJIT_ORDERED_GREATER:
|
|
2359
|
+
inst = FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src2) | FRS2(src1);
|
|
2360
|
+
break;
|
|
2361
|
+
case SLJIT_F_GREATER:
|
|
2362
|
+
case SLJIT_UNORDERED_OR_GREATER:
|
|
2363
|
+
inst = FLE_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2);
|
|
2364
|
+
break;
|
|
2365
|
+
case SLJIT_UNORDERED_OR_LESS:
|
|
2366
|
+
inst = FLE_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src2) | FRS2(src1);
|
|
2367
|
+
break;
|
|
2368
|
+
case SLJIT_UNORDERED_OR_EQUAL:
|
|
2369
|
+
FAIL_IF(push_inst(compiler, FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2)));
|
|
2370
|
+
FAIL_IF(push_inst(compiler, FLT_S | FMT(op) | RD(TMP_REG1) | FRS1(src2) | FRS2(src1)));
|
|
2371
|
+
inst = OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(TMP_REG1);
|
|
2372
|
+
break;
|
|
2373
|
+
default: /* SLJIT_UNORDERED */
|
|
2374
|
+
if (src1 == src2) {
|
|
2375
|
+
inst = FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src1);
|
|
2376
|
+
break;
|
|
2377
|
+
}
|
|
2378
|
+
FAIL_IF(push_inst(compiler, FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src1)));
|
|
2379
|
+
FAIL_IF(push_inst(compiler, FEQ_S | FMT(op) | RD(TMP_REG1) | FRS1(src2) | FRS2(src2)));
|
|
2380
|
+
inst = AND | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(TMP_REG1);
|
|
2381
|
+
break;
|
|
2382
|
+
}
|
|
2383
|
+
|
|
2384
|
+
return push_inst(compiler, inst);
|
|
2385
|
+
}
|
|
2386
|
+
|
|
2387
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
|
|
2388
|
+
sljit_s32 dst, sljit_sw dstw,
|
|
2389
|
+
sljit_s32 src, sljit_sw srcw)
|
|
2390
|
+
{
|
|
2391
|
+
sljit_s32 dst_r;
|
|
2392
|
+
|
|
2393
|
+
CHECK_ERROR();
|
|
2394
|
+
compiler->cache_arg = 0;
|
|
2395
|
+
compiler->cache_argw = 0;
|
|
2396
|
+
|
|
2397
|
+
SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
|
|
2398
|
+
SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
|
|
2399
|
+
|
|
2400
|
+
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
|
|
2401
|
+
op ^= SLJIT_32;
|
|
2402
|
+
|
|
2403
|
+
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
|
2404
|
+
|
|
2405
|
+
if (src & SLJIT_MEM) {
|
|
2406
|
+
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw));
|
|
2407
|
+
src = dst_r;
|
|
2408
|
+
}
|
|
2409
|
+
|
|
2410
|
+
switch (GET_OPCODE(op)) {
|
|
2411
|
+
case SLJIT_MOV_F64:
|
|
2412
|
+
if (src != dst_r) {
|
|
2413
|
+
if (!(dst & SLJIT_MEM))
|
|
2414
|
+
FAIL_IF(push_inst(compiler, FSGNJ_S | FMT(op) | FRD(dst_r) | FRS1(src) | FRS2(src)));
|
|
2415
|
+
else
|
|
2416
|
+
dst_r = src;
|
|
2417
|
+
}
|
|
2418
|
+
break;
|
|
2419
|
+
case SLJIT_NEG_F64:
|
|
2420
|
+
FAIL_IF(push_inst(compiler, FSGNJN_S | FMT(op) | FRD(dst_r) | FRS1(src) | FRS2(src)));
|
|
2421
|
+
break;
|
|
2422
|
+
case SLJIT_ABS_F64:
|
|
2423
|
+
FAIL_IF(push_inst(compiler, FSGNJX_S | FMT(op) | FRD(dst_r) | FRS1(src) | FRS2(src)));
|
|
2424
|
+
break;
|
|
2425
|
+
case SLJIT_CONV_F64_FROM_F32:
|
|
2426
|
+
/* The SLJIT_32 bit is inverted because sljit_f32 needs to be loaded from the memory. */
|
|
2427
|
+
FAIL_IF(push_inst(compiler, FCVT_S_D | ((op & SLJIT_32) ? (1 << 25) : ((1 << 20) | F3(7))) | FRD(dst_r) | FRS1(src)));
|
|
2428
|
+
op ^= SLJIT_32;
|
|
2429
|
+
break;
|
|
2430
|
+
}
|
|
2431
|
+
|
|
2432
|
+
if (dst & SLJIT_MEM)
|
|
2433
|
+
return emit_op_mem2(compiler, FLOAT_DATA(op), dst_r, dst, dstw, 0, 0);
|
|
2434
|
+
return SLJIT_SUCCESS;
|
|
2435
|
+
}
|
|
2436
|
+
|
|
2437
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
|
|
2438
|
+
sljit_s32 dst, sljit_sw dstw,
|
|
2439
|
+
sljit_s32 src1, sljit_sw src1w,
|
|
2440
|
+
sljit_s32 src2, sljit_sw src2w)
|
|
2441
|
+
{
|
|
2442
|
+
sljit_s32 dst_r, flags = 0;
|
|
2443
|
+
|
|
2444
|
+
CHECK_ERROR();
|
|
2445
|
+
CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
|
|
2446
|
+
ADJUST_LOCAL_OFFSET(dst, dstw);
|
|
2447
|
+
ADJUST_LOCAL_OFFSET(src1, src1w);
|
|
2448
|
+
ADJUST_LOCAL_OFFSET(src2, src2w);
|
|
2449
|
+
|
|
2450
|
+
compiler->cache_arg = 0;
|
|
2451
|
+
compiler->cache_argw = 0;
|
|
2452
|
+
|
|
2453
|
+
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
|
|
2454
|
+
|
|
2455
|
+
if (src1 & SLJIT_MEM) {
|
|
2456
|
+
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {
|
|
2457
|
+
FAIL_IF(compiler->error);
|
|
2458
|
+
src1 = TMP_FREG1;
|
|
2459
|
+
} else
|
|
2460
|
+
flags |= SLOW_SRC1;
|
|
2461
|
+
}
|
|
2462
|
+
|
|
2463
|
+
if (src2 & SLJIT_MEM) {
|
|
2464
|
+
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {
|
|
2465
|
+
FAIL_IF(compiler->error);
|
|
2466
|
+
src2 = TMP_FREG2;
|
|
2467
|
+
} else
|
|
2468
|
+
flags |= SLOW_SRC2;
|
|
2469
|
+
}
|
|
2470
|
+
|
|
2471
|
+
if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
|
|
2472
|
+
if ((dst & SLJIT_MEM) && !can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
|
|
2473
|
+
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, src1, src1w));
|
|
2474
|
+
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
|
|
2475
|
+
} else {
|
|
2476
|
+
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
|
|
2477
|
+
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
|
|
2478
|
+
}
|
|
2479
|
+
}
|
|
2480
|
+
else if (flags & SLOW_SRC1)
|
|
2481
|
+
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
|
|
2482
|
+
else if (flags & SLOW_SRC2)
|
|
2483
|
+
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
|
|
2484
|
+
|
|
2485
|
+
if (flags & SLOW_SRC1)
|
|
2486
|
+
src1 = TMP_FREG1;
|
|
2487
|
+
if (flags & SLOW_SRC2)
|
|
2488
|
+
src2 = TMP_FREG2;
|
|
2489
|
+
|
|
2490
|
+
switch (GET_OPCODE(op)) {
|
|
2491
|
+
case SLJIT_ADD_F64:
|
|
2492
|
+
FAIL_IF(push_inst(compiler, FADD_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));
|
|
2493
|
+
break;
|
|
2494
|
+
|
|
2495
|
+
case SLJIT_SUB_F64:
|
|
2496
|
+
FAIL_IF(push_inst(compiler, FSUB_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));
|
|
2497
|
+
break;
|
|
2498
|
+
|
|
2499
|
+
case SLJIT_MUL_F64:
|
|
2500
|
+
FAIL_IF(push_inst(compiler, FMUL_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));
|
|
2501
|
+
break;
|
|
2502
|
+
|
|
2503
|
+
case SLJIT_DIV_F64:
|
|
2504
|
+
FAIL_IF(push_inst(compiler, FDIV_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));
|
|
2505
|
+
break;
|
|
2506
|
+
|
|
2507
|
+
case SLJIT_COPYSIGN_F64:
|
|
2508
|
+
return push_inst(compiler, FSGNJ_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2));
|
|
2509
|
+
}
|
|
2510
|
+
|
|
2511
|
+
if (dst_r != dst)
|
|
2512
|
+
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0));
|
|
2513
|
+
|
|
2514
|
+
return SLJIT_SUCCESS;
|
|
2515
|
+
}
|
|
2516
|
+
|
|
2517
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,
|
|
2518
|
+
sljit_s32 freg, sljit_f32 value)
|
|
2519
|
+
{
|
|
2520
|
+
union {
|
|
2521
|
+
sljit_s32 imm;
|
|
2522
|
+
sljit_f32 value;
|
|
2523
|
+
} u;
|
|
2524
|
+
|
|
2525
|
+
CHECK_ERROR();
|
|
2526
|
+
CHECK(check_sljit_emit_fset32(compiler, freg, value));
|
|
2527
|
+
|
|
2528
|
+
u.value = value;
|
|
2529
|
+
|
|
2530
|
+
if (u.imm == 0)
|
|
2531
|
+
return push_inst(compiler, FMV_W_X | RS1(TMP_ZERO) | FRD(freg));
|
|
2532
|
+
|
|
2533
|
+
FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm, TMP_REG3));
|
|
2534
|
+
return push_inst(compiler, FMV_W_X | RS1(TMP_REG1) | FRD(freg));
|
|
2535
|
+
}
|
|
2536
|
+
|
|
2537
|
+
/* --------------------------------------------------------------------- */
|
|
2538
|
+
/* Conditional instructions */
|
|
2539
|
+
/* --------------------------------------------------------------------- */
|
|
2540
|
+
|
|
2541
|
+
SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
|
|
2542
|
+
{
|
|
2543
|
+
struct sljit_label *label;
|
|
2544
|
+
|
|
2545
|
+
CHECK_ERROR_PTR();
|
|
2546
|
+
CHECK_PTR(check_sljit_emit_label(compiler));
|
|
2547
|
+
|
|
2548
|
+
if (compiler->last_label && compiler->last_label->size == compiler->size)
|
|
2549
|
+
return compiler->last_label;
|
|
2550
|
+
|
|
2551
|
+
label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
|
|
2552
|
+
PTR_FAIL_IF(!label);
|
|
2553
|
+
set_label(label, compiler);
|
|
2554
|
+
return label;
|
|
2555
|
+
}
|
|
2556
|
+
|
|
2557
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
2558
|
+
#define BRANCH_LENGTH ((sljit_ins)(3 * sizeof(sljit_ins)) << 7)
|
|
2559
|
+
#else
|
|
2560
|
+
#define BRANCH_LENGTH ((sljit_ins)(7 * sizeof(sljit_ins)) << 7)
|
|
2561
|
+
#endif
|
|
2562
|
+
|
|
2563
|
+
static sljit_ins get_jump_instruction(sljit_s32 type)
|
|
2564
|
+
{
|
|
2565
|
+
switch (type) {
|
|
2566
|
+
case SLJIT_EQUAL:
|
|
2567
|
+
return BNE | RS1(EQUAL_FLAG) | RS2(TMP_ZERO);
|
|
2568
|
+
case SLJIT_NOT_EQUAL:
|
|
2569
|
+
return BEQ | RS1(EQUAL_FLAG) | RS2(TMP_ZERO);
|
|
2570
|
+
case SLJIT_LESS:
|
|
2571
|
+
case SLJIT_GREATER:
|
|
2572
|
+
case SLJIT_SIG_LESS:
|
|
2573
|
+
case SLJIT_SIG_GREATER:
|
|
2574
|
+
case SLJIT_OVERFLOW:
|
|
2575
|
+
case SLJIT_CARRY:
|
|
2576
|
+
case SLJIT_F_EQUAL:
|
|
2577
|
+
case SLJIT_ORDERED_EQUAL:
|
|
2578
|
+
case SLJIT_ORDERED_NOT_EQUAL:
|
|
2579
|
+
case SLJIT_F_LESS:
|
|
2580
|
+
case SLJIT_ORDERED_LESS:
|
|
2581
|
+
case SLJIT_ORDERED_GREATER:
|
|
2582
|
+
case SLJIT_F_LESS_EQUAL:
|
|
2583
|
+
case SLJIT_ORDERED_LESS_EQUAL:
|
|
2584
|
+
case SLJIT_ORDERED_GREATER_EQUAL:
|
|
2585
|
+
case SLJIT_ORDERED:
|
|
2586
|
+
return BEQ | RS1(OTHER_FLAG) | RS2(TMP_ZERO);
|
|
2587
|
+
break;
|
|
2588
|
+
case SLJIT_GREATER_EQUAL:
|
|
2589
|
+
case SLJIT_LESS_EQUAL:
|
|
2590
|
+
case SLJIT_SIG_GREATER_EQUAL:
|
|
2591
|
+
case SLJIT_SIG_LESS_EQUAL:
|
|
2592
|
+
case SLJIT_NOT_OVERFLOW:
|
|
2593
|
+
case SLJIT_NOT_CARRY:
|
|
2594
|
+
case SLJIT_F_NOT_EQUAL:
|
|
2595
|
+
case SLJIT_UNORDERED_OR_NOT_EQUAL:
|
|
2596
|
+
case SLJIT_UNORDERED_OR_EQUAL:
|
|
2597
|
+
case SLJIT_F_GREATER_EQUAL:
|
|
2598
|
+
case SLJIT_UNORDERED_OR_GREATER_EQUAL:
|
|
2599
|
+
case SLJIT_UNORDERED_OR_LESS_EQUAL:
|
|
2600
|
+
case SLJIT_F_GREATER:
|
|
2601
|
+
case SLJIT_UNORDERED_OR_GREATER:
|
|
2602
|
+
case SLJIT_UNORDERED_OR_LESS:
|
|
2603
|
+
case SLJIT_UNORDERED:
|
|
2604
|
+
return BNE | RS1(OTHER_FLAG) | RS2(TMP_ZERO);
|
|
2605
|
+
default:
|
|
2606
|
+
/* Not conditional branch. */
|
|
2607
|
+
return 0;
|
|
2608
|
+
}
|
|
2609
|
+
}
|
|
2610
|
+
|
|
2611
|
+
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
|
|
2612
|
+
{
|
|
2613
|
+
struct sljit_jump *jump;
|
|
2614
|
+
sljit_ins inst;
|
|
2615
|
+
|
|
2616
|
+
CHECK_ERROR_PTR();
|
|
2617
|
+
CHECK_PTR(check_sljit_emit_jump(compiler, type));
|
|
2618
|
+
|
|
2619
|
+
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
|
2620
|
+
PTR_FAIL_IF(!jump);
|
|
2621
|
+
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
|
|
2622
|
+
type &= 0xff;
|
|
2623
|
+
|
|
2624
|
+
inst = get_jump_instruction(type);
|
|
2625
|
+
|
|
2626
|
+
if (inst != 0) {
|
|
2627
|
+
PTR_FAIL_IF(push_inst(compiler, inst | BRANCH_LENGTH));
|
|
2628
|
+
jump->flags |= IS_COND;
|
|
2629
|
+
}
|
|
2630
|
+
|
|
2631
|
+
jump->addr = compiler->size;
|
|
2632
|
+
inst = JALR | RS1(TMP_REG1) | IMM_I(0);
|
|
2633
|
+
|
|
2634
|
+
if (type >= SLJIT_FAST_CALL) {
|
|
2635
|
+
jump->flags |= IS_CALL;
|
|
2636
|
+
inst |= RD(RETURN_ADDR_REG);
|
|
2637
|
+
}
|
|
2638
|
+
|
|
2639
|
+
PTR_FAIL_IF(push_inst(compiler, inst));
|
|
2640
|
+
|
|
2641
|
+
/* Maximum number of instructions required for generating a constant. */
|
|
2642
|
+
compiler->size += JUMP_MAX_SIZE - 1;
|
|
2643
|
+
return jump;
|
|
2644
|
+
}
|
|
2645
|
+
|
|
2646
|
+
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
|
|
2647
|
+
sljit_s32 arg_types)
|
|
2648
|
+
{
|
|
2649
|
+
SLJIT_UNUSED_ARG(arg_types);
|
|
2650
|
+
CHECK_ERROR_PTR();
|
|
2651
|
+
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
|
|
2652
|
+
|
|
2653
|
+
if (type & SLJIT_CALL_RETURN) {
|
|
2654
|
+
PTR_FAIL_IF(emit_stack_frame_release(compiler, 0));
|
|
2655
|
+
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
|
2656
|
+
}
|
|
2657
|
+
|
|
2658
|
+
SLJIT_SKIP_CHECKS(compiler);
|
|
2659
|
+
return sljit_emit_jump(compiler, type);
|
|
2660
|
+
}
|
|
2661
|
+
|
|
2662
|
+
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
|
|
2663
|
+
sljit_s32 src1, sljit_sw src1w,
|
|
2664
|
+
sljit_s32 src2, sljit_sw src2w)
|
|
2665
|
+
{
|
|
2666
|
+
struct sljit_jump *jump;
|
|
2667
|
+
sljit_s32 flags;
|
|
2668
|
+
sljit_ins inst;
|
|
2669
|
+
sljit_s32 src2_tmp_reg = FAST_IS_REG(src1) ? TMP_REG1 : TMP_REG2;
|
|
2670
|
+
|
|
2671
|
+
CHECK_ERROR_PTR();
|
|
2672
|
+
CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));
|
|
2673
|
+
ADJUST_LOCAL_OFFSET(src1, src1w);
|
|
2674
|
+
ADJUST_LOCAL_OFFSET(src2, src2w);
|
|
2675
|
+
|
|
2676
|
+
compiler->cache_arg = 0;
|
|
2677
|
+
compiler->cache_argw = 0;
|
|
2678
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
2679
|
+
flags = WORD_DATA | LOAD_DATA;
|
|
2680
|
+
#else /* !SLJIT_CONFIG_RISCV_32 */
|
|
2681
|
+
flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
|
|
2682
|
+
#endif /* SLJIT_CONFIG_RISCV_32 */
|
|
2683
|
+
|
|
2684
|
+
if (src1 & SLJIT_MEM) {
|
|
2685
|
+
PTR_FAIL_IF(emit_op_mem2(compiler, flags, TMP_REG1, src1, src1w, src2, src2w));
|
|
2686
|
+
src1 = TMP_REG1;
|
|
2687
|
+
}
|
|
2688
|
+
|
|
2689
|
+
if (src2 & SLJIT_MEM) {
|
|
2690
|
+
PTR_FAIL_IF(emit_op_mem2(compiler, flags, src2_tmp_reg, src2, src2w, 0, 0));
|
|
2691
|
+
src2 = src2_tmp_reg;
|
|
2692
|
+
}
|
|
2693
|
+
|
|
2694
|
+
if (src1 == SLJIT_IMM) {
|
|
2695
|
+
if (src1w != 0) {
|
|
2696
|
+
PTR_FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3));
|
|
2697
|
+
src1 = TMP_REG1;
|
|
2698
|
+
}
|
|
2699
|
+
else
|
|
2700
|
+
src1 = TMP_ZERO;
|
|
2701
|
+
}
|
|
2702
|
+
|
|
2703
|
+
if (src2 == SLJIT_IMM) {
|
|
2704
|
+
if (src2w != 0) {
|
|
2705
|
+
PTR_FAIL_IF(load_immediate(compiler, src2_tmp_reg, src2w, TMP_REG3));
|
|
2706
|
+
src2 = src2_tmp_reg;
|
|
2707
|
+
}
|
|
2708
|
+
else
|
|
2709
|
+
src2 = TMP_ZERO;
|
|
2710
|
+
}
|
|
2711
|
+
|
|
2712
|
+
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
|
2713
|
+
PTR_FAIL_IF(!jump);
|
|
2714
|
+
set_jump(jump, compiler, (sljit_u32)((type & SLJIT_REWRITABLE_JUMP) | IS_COND));
|
|
2715
|
+
type &= 0xff;
|
|
2716
|
+
|
|
2717
|
+
switch (type) {
|
|
2718
|
+
case SLJIT_EQUAL:
|
|
2719
|
+
inst = BNE | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
|
|
2720
|
+
break;
|
|
2721
|
+
case SLJIT_NOT_EQUAL:
|
|
2722
|
+
inst = BEQ | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
|
|
2723
|
+
break;
|
|
2724
|
+
case SLJIT_LESS:
|
|
2725
|
+
inst = BGEU | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
|
|
2726
|
+
break;
|
|
2727
|
+
case SLJIT_GREATER_EQUAL:
|
|
2728
|
+
inst = BLTU | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
|
|
2729
|
+
break;
|
|
2730
|
+
case SLJIT_GREATER:
|
|
2731
|
+
inst = BGEU | RS1(src2) | RS2(src1) | BRANCH_LENGTH;
|
|
2732
|
+
break;
|
|
2733
|
+
case SLJIT_LESS_EQUAL:
|
|
2734
|
+
inst = BLTU | RS1(src2) | RS2(src1) | BRANCH_LENGTH;
|
|
2735
|
+
break;
|
|
2736
|
+
case SLJIT_SIG_LESS:
|
|
2737
|
+
inst = BGE | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
|
|
2738
|
+
break;
|
|
2739
|
+
case SLJIT_SIG_GREATER_EQUAL:
|
|
2740
|
+
inst = BLT | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
|
|
2741
|
+
break;
|
|
2742
|
+
case SLJIT_SIG_GREATER:
|
|
2743
|
+
inst = BGE | RS1(src2) | RS2(src1) | BRANCH_LENGTH;
|
|
2744
|
+
break;
|
|
2745
|
+
case SLJIT_SIG_LESS_EQUAL:
|
|
2746
|
+
inst = BLT | RS1(src2) | RS2(src1) | BRANCH_LENGTH;
|
|
2747
|
+
break;
|
|
2748
|
+
}
|
|
2749
|
+
|
|
2750
|
+
PTR_FAIL_IF(push_inst(compiler, inst));
|
|
2751
|
+
|
|
2752
|
+
jump->addr = compiler->size;
|
|
2753
|
+
PTR_FAIL_IF(push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(TMP_REG1) | IMM_I(0)));
|
|
2754
|
+
|
|
2755
|
+
/* Maximum number of instructions required for generating a constant. */
|
|
2756
|
+
compiler->size += JUMP_MAX_SIZE - 1;
|
|
2757
|
+
return jump;
|
|
2758
|
+
}
|
|
2759
|
+
|
|
2760
|
+
#undef BRANCH_LENGTH
|
|
2761
|
+
|
|
2762
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
|
|
2763
|
+
{
|
|
2764
|
+
struct sljit_jump *jump;
|
|
2765
|
+
|
|
2766
|
+
CHECK_ERROR();
|
|
2767
|
+
CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
|
|
2768
|
+
|
|
2769
|
+
if (src != SLJIT_IMM) {
|
|
2770
|
+
if (src & SLJIT_MEM) {
|
|
2771
|
+
ADJUST_LOCAL_OFFSET(src, srcw);
|
|
2772
|
+
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));
|
|
2773
|
+
src = TMP_REG1;
|
|
2774
|
+
}
|
|
2775
|
+
return push_inst(compiler, JALR | RD((type >= SLJIT_FAST_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | RS1(src) | IMM_I(0));
|
|
2776
|
+
}
|
|
2777
|
+
|
|
2778
|
+
/* These jumps are converted to jump/call instructions when possible. */
|
|
2779
|
+
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
|
2780
|
+
FAIL_IF(!jump);
|
|
2781
|
+
set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_CALL : 0));
|
|
2782
|
+
jump->u.target = (sljit_uw)srcw;
|
|
2783
|
+
|
|
2784
|
+
jump->addr = compiler->size;
|
|
2785
|
+
FAIL_IF(push_inst(compiler, JALR | RD((type >= SLJIT_FAST_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | RS1(TMP_REG1) | IMM_I(0)));
|
|
2786
|
+
|
|
2787
|
+
/* Maximum number of instructions required for generating a constant. */
|
|
2788
|
+
compiler->size += JUMP_MAX_SIZE - 1;
|
|
2789
|
+
return SLJIT_SUCCESS;
|
|
2790
|
+
}
|
|
2791
|
+
|
|
2792
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
|
|
2793
|
+
sljit_s32 arg_types,
|
|
2794
|
+
sljit_s32 src, sljit_sw srcw)
|
|
2795
|
+
{
|
|
2796
|
+
SLJIT_UNUSED_ARG(arg_types);
|
|
2797
|
+
CHECK_ERROR();
|
|
2798
|
+
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
|
|
2799
|
+
|
|
2800
|
+
if (src & SLJIT_MEM) {
|
|
2801
|
+
ADJUST_LOCAL_OFFSET(src, srcw);
|
|
2802
|
+
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));
|
|
2803
|
+
src = TMP_REG1;
|
|
2804
|
+
}
|
|
2805
|
+
|
|
2806
|
+
if (type & SLJIT_CALL_RETURN) {
|
|
2807
|
+
if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
|
|
2808
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src) | IMM_I(0)));
|
|
2809
|
+
src = TMP_REG1;
|
|
2810
|
+
}
|
|
2811
|
+
|
|
2812
|
+
FAIL_IF(emit_stack_frame_release(compiler, 0));
|
|
2813
|
+
type = SLJIT_JUMP;
|
|
2814
|
+
}
|
|
2815
|
+
|
|
2816
|
+
SLJIT_SKIP_CHECKS(compiler);
|
|
2817
|
+
return sljit_emit_ijump(compiler, type, src, srcw);
|
|
2818
|
+
}
|
|
2819
|
+
|
|
2820
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
|
|
2821
|
+
sljit_s32 dst, sljit_sw dstw,
|
|
2822
|
+
sljit_s32 type)
|
|
2823
|
+
{
|
|
2824
|
+
sljit_s32 src_r, dst_r, invert;
|
|
2825
|
+
sljit_s32 saved_op = op;
|
|
2826
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
2827
|
+
sljit_s32 mem_type = WORD_DATA;
|
|
2828
|
+
#else
|
|
2829
|
+
sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
|
|
2830
|
+
#endif
|
|
2831
|
+
|
|
2832
|
+
CHECK_ERROR();
|
|
2833
|
+
CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
|
|
2834
|
+
ADJUST_LOCAL_OFFSET(dst, dstw);
|
|
2835
|
+
|
|
2836
|
+
op = GET_OPCODE(op);
|
|
2837
|
+
dst_r = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
|
|
2838
|
+
|
|
2839
|
+
compiler->cache_arg = 0;
|
|
2840
|
+
compiler->cache_argw = 0;
|
|
2841
|
+
|
|
2842
|
+
if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
|
|
2843
|
+
FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, TMP_REG1, dst, dstw, dst, dstw));
|
|
2844
|
+
|
|
2845
|
+
if (type < SLJIT_F_EQUAL) {
|
|
2846
|
+
src_r = OTHER_FLAG;
|
|
2847
|
+
invert = type & 0x1;
|
|
2848
|
+
|
|
2849
|
+
switch (type) {
|
|
2850
|
+
case SLJIT_EQUAL:
|
|
2851
|
+
case SLJIT_NOT_EQUAL:
|
|
2852
|
+
FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RS1(EQUAL_FLAG) | IMM_I(1)));
|
|
2853
|
+
src_r = dst_r;
|
|
2854
|
+
break;
|
|
2855
|
+
case SLJIT_OVERFLOW:
|
|
2856
|
+
case SLJIT_NOT_OVERFLOW:
|
|
2857
|
+
if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) {
|
|
2858
|
+
src_r = OTHER_FLAG;
|
|
2859
|
+
break;
|
|
2860
|
+
}
|
|
2861
|
+
FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RS1(OTHER_FLAG) | IMM_I(1)));
|
|
2862
|
+
src_r = dst_r;
|
|
2863
|
+
invert ^= 0x1;
|
|
2864
|
+
break;
|
|
2865
|
+
}
|
|
2866
|
+
} else {
|
|
2867
|
+
invert = 0;
|
|
2868
|
+
src_r = OTHER_FLAG;
|
|
2869
|
+
|
|
2870
|
+
switch (type) {
|
|
2871
|
+
case SLJIT_F_NOT_EQUAL:
|
|
2872
|
+
case SLJIT_UNORDERED_OR_NOT_EQUAL:
|
|
2873
|
+
case SLJIT_UNORDERED_OR_EQUAL: /* Not supported. */
|
|
2874
|
+
case SLJIT_F_GREATER_EQUAL:
|
|
2875
|
+
case SLJIT_UNORDERED_OR_GREATER_EQUAL:
|
|
2876
|
+
case SLJIT_UNORDERED_OR_LESS_EQUAL:
|
|
2877
|
+
case SLJIT_F_GREATER:
|
|
2878
|
+
case SLJIT_UNORDERED_OR_GREATER:
|
|
2879
|
+
case SLJIT_UNORDERED_OR_LESS:
|
|
2880
|
+
case SLJIT_UNORDERED:
|
|
2881
|
+
invert = 1;
|
|
2882
|
+
break;
|
|
2883
|
+
}
|
|
2884
|
+
}
|
|
2885
|
+
|
|
2886
|
+
if (invert) {
|
|
2887
|
+
FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(src_r) | IMM_I(1)));
|
|
2888
|
+
src_r = dst_r;
|
|
2889
|
+
}
|
|
2890
|
+
|
|
2891
|
+
if (op < SLJIT_ADD) {
|
|
2892
|
+
if (dst & SLJIT_MEM)
|
|
2893
|
+
return emit_op_mem(compiler, mem_type, src_r, dst, dstw);
|
|
2894
|
+
|
|
2895
|
+
if (src_r != dst_r)
|
|
2896
|
+
return push_inst(compiler, ADDI | RD(dst_r) | RS1(src_r) | IMM_I(0));
|
|
2897
|
+
return SLJIT_SUCCESS;
|
|
2898
|
+
}
|
|
2899
|
+
|
|
2900
|
+
mem_type |= CUMULATIVE_OP | IMM_OP | ALT_KEEP_CACHE;
|
|
2901
|
+
|
|
2902
|
+
if (dst & SLJIT_MEM)
|
|
2903
|
+
return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, src_r, 0);
|
|
2904
|
+
return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, src_r, 0);
|
|
2905
|
+
}
|
|
2906
|
+
|
|
2907
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,
|
|
2908
|
+
sljit_s32 dst_reg,
|
|
2909
|
+
sljit_s32 src1, sljit_sw src1w,
|
|
2910
|
+
sljit_s32 src2_reg)
|
|
2911
|
+
{
|
|
2912
|
+
sljit_ins *ptr;
|
|
2913
|
+
sljit_uw size;
|
|
2914
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
2915
|
+
sljit_ins word = (sljit_ins)(type & SLJIT_32) >> 5;
|
|
2916
|
+
sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
|
|
2917
|
+
#else /* !SLJIT_CONFIG_RISCV_64 */
|
|
2918
|
+
sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;
|
|
2919
|
+
#endif /* SLJIT_CONFIG_RISCV_64 */
|
|
2920
|
+
|
|
2921
|
+
SLJIT_ASSERT(WORD == 0 || WORD == 0x8);
|
|
2922
|
+
|
|
2923
|
+
CHECK_ERROR();
|
|
2924
|
+
CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
|
|
2925
|
+
|
|
2926
|
+
ADJUST_LOCAL_OFFSET(src1, src1w);
|
|
2927
|
+
|
|
2928
|
+
if (dst_reg != src2_reg) {
|
|
2929
|
+
if (dst_reg == src1) {
|
|
2930
|
+
src1 = src2_reg;
|
|
2931
|
+
src1w = 0;
|
|
2932
|
+
type ^= 0x1;
|
|
2933
|
+
} else {
|
|
2934
|
+
if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {
|
|
2935
|
+
FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(dst_reg) | IMM_I(0)));
|
|
2936
|
+
|
|
2937
|
+
if ((src1 & REG_MASK) == dst_reg)
|
|
2938
|
+
src1 = (src1 & ~REG_MASK) | TMP_REG1;
|
|
2939
|
+
|
|
2940
|
+
if (OFFS_REG(src1) == dst_reg)
|
|
2941
|
+
src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);
|
|
2942
|
+
}
|
|
2943
|
+
|
|
2944
|
+
FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst_reg) | RS1(src2_reg) | IMM_I(0)));
|
|
2945
|
+
}
|
|
2946
|
+
}
|
|
2947
|
+
|
|
2948
|
+
size = compiler->size;
|
|
2949
|
+
|
|
2950
|
+
ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
|
|
2951
|
+
FAIL_IF(!ptr);
|
|
2952
|
+
compiler->size++;
|
|
2953
|
+
|
|
2954
|
+
if (src1 & SLJIT_MEM) {
|
|
2955
|
+
FAIL_IF(emit_op_mem(compiler, inp_flags, dst_reg, src1, src1w));
|
|
2956
|
+
} else if (src1 == SLJIT_IMM) {
|
|
2957
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
2958
|
+
if (word)
|
|
2959
|
+
src1w = (sljit_s32)src1w;
|
|
2960
|
+
#endif /* SLJIT_CONFIG_RISCV_64 */
|
|
2961
|
+
FAIL_IF(load_immediate(compiler, dst_reg, src1w, TMP_REG1));
|
|
2962
|
+
} else
|
|
2963
|
+
FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst_reg) | RS1(src1) | IMM_I(0)));
|
|
2964
|
+
|
|
2965
|
+
size = compiler->size - size;
|
|
2966
|
+
*ptr = get_jump_instruction(type & ~SLJIT_32) | (sljit_ins)((size & 0x7) << 9) | (sljit_ins)((size >> 3) << 25);
|
|
2967
|
+
return SLJIT_SUCCESS;
|
|
2968
|
+
}
|
|
2969
|
+
|
|
2970
|
+
#undef WORD
|
|
2971
|
+
|
|
2972
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,
|
|
2973
|
+
sljit_s32 dst_freg,
|
|
2974
|
+
sljit_s32 src1, sljit_sw src1w,
|
|
2975
|
+
sljit_s32 src2_freg)
|
|
2976
|
+
{
|
|
2977
|
+
sljit_ins *ptr;
|
|
2978
|
+
sljit_uw size;
|
|
2979
|
+
|
|
2980
|
+
CHECK_ERROR();
|
|
2981
|
+
CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));
|
|
2982
|
+
|
|
2983
|
+
ADJUST_LOCAL_OFFSET(src1, src1w);
|
|
2984
|
+
|
|
2985
|
+
if (dst_freg != src2_freg) {
|
|
2986
|
+
if (dst_freg == src1) {
|
|
2987
|
+
src1 = src2_freg;
|
|
2988
|
+
src1w = 0;
|
|
2989
|
+
type ^= 0x1;
|
|
2990
|
+
} else
|
|
2991
|
+
FAIL_IF(push_inst(compiler, FSGNJ_S | FMT(type) | FRD(dst_freg) | FRS1(src2_freg) | FRS2(src2_freg)));
|
|
2992
|
+
}
|
|
2993
|
+
|
|
2994
|
+
size = compiler->size;
|
|
2995
|
+
|
|
2996
|
+
ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
|
|
2997
|
+
FAIL_IF(!ptr);
|
|
2998
|
+
compiler->size++;
|
|
2999
|
+
|
|
3000
|
+
if (src1 & SLJIT_MEM)
|
|
3001
|
+
FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, dst_freg, src1, src1w));
|
|
3002
|
+
else
|
|
3003
|
+
FAIL_IF(push_inst(compiler, FSGNJ_S | FMT(type) | FRD(dst_freg) | FRS1(src1) | FRS2(src1)));
|
|
3004
|
+
|
|
3005
|
+
size = compiler->size - size;
|
|
3006
|
+
*ptr = get_jump_instruction(type & ~SLJIT_32) | (sljit_ins)((size & 0x7) << 9) | (sljit_ins)((size >> 3) << 25);
|
|
3007
|
+
return SLJIT_SUCCESS;
|
|
3008
|
+
}
|
|
3009
|
+
|
|
3010
|
+
#undef FLOAT_DATA
|
|
3011
|
+
#undef FMT
|
|
3012
|
+
|
|
3013
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
|
|
3014
|
+
sljit_s32 reg,
|
|
3015
|
+
sljit_s32 mem, sljit_sw memw)
|
|
3016
|
+
{
|
|
3017
|
+
sljit_s32 flags;
|
|
3018
|
+
|
|
3019
|
+
CHECK_ERROR();
|
|
3020
|
+
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
|
|
3021
|
+
|
|
3022
|
+
if (!(reg & REG_PAIR_MASK))
|
|
3023
|
+
return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
|
|
3024
|
+
|
|
3025
|
+
if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
|
|
3026
|
+
memw &= 0x3;
|
|
3027
|
+
|
|
3028
|
+
if (SLJIT_UNLIKELY(memw != 0)) {
|
|
3029
|
+
FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG1) | RS1(OFFS_REG(mem)) | IMM_I(memw)));
|
|
3030
|
+
FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(mem & REG_MASK)));
|
|
3031
|
+
} else
|
|
3032
|
+
FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(mem & REG_MASK) | RS2(OFFS_REG(mem))));
|
|
3033
|
+
|
|
3034
|
+
mem = TMP_REG1;
|
|
3035
|
+
memw = 0;
|
|
3036
|
+
} else if (memw > SIMM_MAX - SSIZE_OF(sw) || memw < SIMM_MIN) {
|
|
3037
|
+
if (((memw + 0x800) & 0xfff) <= 0xfff - SSIZE_OF(sw)) {
|
|
3038
|
+
FAIL_IF(load_immediate(compiler, TMP_REG1, TO_ARGW_HI(memw), TMP_REG3));
|
|
3039
|
+
memw &= 0xfff;
|
|
3040
|
+
} else {
|
|
3041
|
+
FAIL_IF(load_immediate(compiler, TMP_REG1, memw, TMP_REG3));
|
|
3042
|
+
memw = 0;
|
|
3043
|
+
}
|
|
3044
|
+
|
|
3045
|
+
if (mem & REG_MASK)
|
|
3046
|
+
FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(mem & REG_MASK)));
|
|
3047
|
+
|
|
3048
|
+
mem = TMP_REG1;
|
|
3049
|
+
} else {
|
|
3050
|
+
mem &= REG_MASK;
|
|
3051
|
+
memw &= 0xfff;
|
|
3052
|
+
}
|
|
3053
|
+
|
|
3054
|
+
SLJIT_ASSERT((memw >= 0 && memw <= SIMM_MAX - SSIZE_OF(sw)) || (memw > SIMM_MAX && memw <= 0xfff));
|
|
3055
|
+
|
|
3056
|
+
if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) {
|
|
3057
|
+
FAIL_IF(push_mem_inst(compiler, WORD_DATA | LOAD_DATA, REG_PAIR_SECOND(reg), mem, (memw + SSIZE_OF(sw)) & 0xfff));
|
|
3058
|
+
return push_mem_inst(compiler, WORD_DATA | LOAD_DATA, REG_PAIR_FIRST(reg), mem, memw);
|
|
3059
|
+
}
|
|
3060
|
+
|
|
3061
|
+
flags = WORD_DATA | (!(type & SLJIT_MEM_STORE) ? LOAD_DATA : 0);
|
|
3062
|
+
|
|
3063
|
+
FAIL_IF(push_mem_inst(compiler, flags, REG_PAIR_FIRST(reg), mem, memw));
|
|
3064
|
+
return push_mem_inst(compiler, flags, REG_PAIR_SECOND(reg), mem, (memw + SSIZE_OF(sw)) & 0xfff);
|
|
3065
|
+
}
|
|
3066
|
+
|
|
3067
|
+
#undef TO_ARGW_HI
|
|
3068
|
+
|
|
3069
|
+
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
|
3070
|
+
{
|
|
3071
|
+
struct sljit_const *const_;
|
|
3072
|
+
sljit_s32 dst_r;
|
|
3073
|
+
|
|
3074
|
+
CHECK_ERROR_PTR();
|
|
3075
|
+
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
|
|
3076
|
+
ADJUST_LOCAL_OFFSET(dst, dstw);
|
|
3077
|
+
|
|
3078
|
+
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
|
|
3079
|
+
PTR_FAIL_IF(!const_);
|
|
3080
|
+
set_const(const_, compiler);
|
|
3081
|
+
|
|
3082
|
+
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
|
3083
|
+
PTR_FAIL_IF(emit_const(compiler, dst_r, init_value, ADDI | RD(dst_r)));
|
|
3084
|
+
|
|
3085
|
+
if (dst & SLJIT_MEM)
|
|
3086
|
+
PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
|
|
3087
|
+
|
|
3088
|
+
return const_;
|
|
3089
|
+
}
|
|
3090
|
+
|
|
3091
|
+
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
|
|
3092
|
+
{
|
|
3093
|
+
struct sljit_jump *jump;
|
|
3094
|
+
sljit_s32 dst_r;
|
|
3095
|
+
|
|
3096
|
+
CHECK_ERROR_PTR();
|
|
3097
|
+
CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));
|
|
3098
|
+
ADJUST_LOCAL_OFFSET(dst, dstw);
|
|
3099
|
+
|
|
3100
|
+
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
|
3101
|
+
PTR_FAIL_IF(!jump);
|
|
3102
|
+
set_mov_addr(jump, compiler, 0);
|
|
3103
|
+
|
|
3104
|
+
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
|
3105
|
+
PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r));
|
|
3106
|
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
|
|
3107
|
+
compiler->size += 1;
|
|
3108
|
+
#else /* !SLJIT_CONFIG_RISCV_32 */
|
|
3109
|
+
compiler->size += 5;
|
|
3110
|
+
#endif /* SLJIT_CONFIG_RISCV_32 */
|
|
3111
|
+
|
|
3112
|
+
if (dst & SLJIT_MEM)
|
|
3113
|
+
PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
|
|
3114
|
+
|
|
3115
|
+
return jump;
|
|
3116
|
+
}
|
|
3117
|
+
|
|
3118
|
+
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
|
|
3119
|
+
{
|
|
3120
|
+
sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
|
|
3121
|
+
}
|