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,3161 @@
|
|
|
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
|
+
return "PowerPC" SLJIT_CPUINFO;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Length of an instruction word.
|
|
33
|
+
Both for ppc-32 and ppc-64. */
|
|
34
|
+
typedef sljit_u32 sljit_ins;
|
|
35
|
+
|
|
36
|
+
#if ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && (defined _AIX)) \
|
|
37
|
+
|| (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
38
|
+
#define SLJIT_PPC_STACK_FRAME_V2 1
|
|
39
|
+
#endif
|
|
40
|
+
|
|
41
|
+
#ifdef _AIX
|
|
42
|
+
#include <sys/cache.h>
|
|
43
|
+
#endif
|
|
44
|
+
|
|
45
|
+
#if (defined _CALL_ELF && _CALL_ELF == 2)
|
|
46
|
+
#define SLJIT_PASS_ENTRY_ADDR_TO_CALL 1
|
|
47
|
+
#endif
|
|
48
|
+
|
|
49
|
+
#if (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL)
|
|
50
|
+
|
|
51
|
+
static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)
|
|
52
|
+
{
|
|
53
|
+
#ifdef _AIX
|
|
54
|
+
_sync_cache_range((caddr_t)from, (int)((size_t)to - (size_t)from));
|
|
55
|
+
#elif defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM)
|
|
56
|
+
# if defined(_ARCH_PWR) || defined(_ARCH_PWR2)
|
|
57
|
+
/* Cache flush for POWER architecture. */
|
|
58
|
+
while (from < to) {
|
|
59
|
+
__asm__ volatile (
|
|
60
|
+
"clf 0, %0\n"
|
|
61
|
+
"dcs\n"
|
|
62
|
+
: : "r"(from)
|
|
63
|
+
);
|
|
64
|
+
from++;
|
|
65
|
+
}
|
|
66
|
+
__asm__ volatile ( "ics" );
|
|
67
|
+
# elif defined(_ARCH_COM) && !defined(_ARCH_PPC)
|
|
68
|
+
# error "Cache flush is not implemented for PowerPC/POWER common mode."
|
|
69
|
+
# else
|
|
70
|
+
/* Cache flush for PowerPC architecture. */
|
|
71
|
+
while (from < to) {
|
|
72
|
+
__asm__ volatile (
|
|
73
|
+
"dcbf 0, %0\n"
|
|
74
|
+
"sync\n"
|
|
75
|
+
"icbi 0, %0\n"
|
|
76
|
+
: : "r"(from)
|
|
77
|
+
);
|
|
78
|
+
from++;
|
|
79
|
+
}
|
|
80
|
+
__asm__ volatile ( "isync" );
|
|
81
|
+
# endif
|
|
82
|
+
# ifdef __xlc__
|
|
83
|
+
# warning "This file may fail to compile if -qfuncsect is used"
|
|
84
|
+
# endif
|
|
85
|
+
#elif defined(__xlc__)
|
|
86
|
+
#error "Please enable GCC syntax for inline assembly statements with -qasm=gcc"
|
|
87
|
+
#else
|
|
88
|
+
#error "This platform requires a cache flush implementation."
|
|
89
|
+
#endif /* _AIX */
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
#endif /* (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL) */
|
|
93
|
+
|
|
94
|
+
#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
|
|
95
|
+
#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
|
|
96
|
+
#define TMP_ZERO (SLJIT_NUMBER_OF_REGISTERS + 4)
|
|
97
|
+
|
|
98
|
+
#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
|
|
99
|
+
#define TMP_CALL_REG (SLJIT_NUMBER_OF_REGISTERS + 5)
|
|
100
|
+
#else
|
|
101
|
+
#define TMP_CALL_REG TMP_REG1
|
|
102
|
+
#endif
|
|
103
|
+
|
|
104
|
+
#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
|
|
105
|
+
#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
|
|
106
|
+
|
|
107
|
+
static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
|
|
108
|
+
0, 3, 4, 5, 6, 7, 8, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 9, 10, 31, 12
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
|
|
112
|
+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 0, 13
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/* --------------------------------------------------------------------- */
|
|
116
|
+
/* Instrucion forms */
|
|
117
|
+
/* --------------------------------------------------------------------- */
|
|
118
|
+
#define D(d) ((sljit_ins)reg_map[d] << 21)
|
|
119
|
+
#define S(s) ((sljit_ins)reg_map[s] << 21)
|
|
120
|
+
#define A(a) ((sljit_ins)reg_map[a] << 16)
|
|
121
|
+
#define B(b) ((sljit_ins)reg_map[b] << 11)
|
|
122
|
+
#define C(c) ((sljit_ins)reg_map[c] << 6)
|
|
123
|
+
#define FD(fd) ((sljit_ins)freg_map[fd] << 21)
|
|
124
|
+
#define FS(fs) ((sljit_ins)freg_map[fs] << 21)
|
|
125
|
+
#define FA(fa) ((sljit_ins)freg_map[fa] << 16)
|
|
126
|
+
#define FB(fb) ((sljit_ins)freg_map[fb] << 11)
|
|
127
|
+
#define FC(fc) ((sljit_ins)freg_map[fc] << 6)
|
|
128
|
+
#define IMM(imm) ((sljit_ins)(imm) & 0xffff)
|
|
129
|
+
#define CRD(d) ((sljit_ins)(d) << 21)
|
|
130
|
+
|
|
131
|
+
/* Instruction bit sections.
|
|
132
|
+
OE and Rc flag (see ALT_SET_FLAGS). */
|
|
133
|
+
#define OE(flags) ((flags) & ALT_SET_FLAGS)
|
|
134
|
+
/* Rc flag (see ALT_SET_FLAGS). */
|
|
135
|
+
#define RC(flags) ((sljit_ins)((flags) & ALT_SET_FLAGS) >> 10)
|
|
136
|
+
#define HI(opcode) ((sljit_ins)(opcode) << 26)
|
|
137
|
+
#define LO(opcode) ((sljit_ins)(opcode) << 1)
|
|
138
|
+
|
|
139
|
+
#define ADD (HI(31) | LO(266))
|
|
140
|
+
#define ADDC (HI(31) | LO(10))
|
|
141
|
+
#define ADDE (HI(31) | LO(138))
|
|
142
|
+
#define ADDI (HI(14))
|
|
143
|
+
#define ADDIC (HI(13))
|
|
144
|
+
#define ADDIS (HI(15))
|
|
145
|
+
#define ADDME (HI(31) | LO(234))
|
|
146
|
+
#define AND (HI(31) | LO(28))
|
|
147
|
+
#define ANDI (HI(28))
|
|
148
|
+
#define ANDIS (HI(29))
|
|
149
|
+
#define Bx (HI(18))
|
|
150
|
+
#define BCx (HI(16))
|
|
151
|
+
#define BCCTR (HI(19) | LO(528) | (3 << 11))
|
|
152
|
+
#define BLR (HI(19) | LO(16) | (0x14 << 21))
|
|
153
|
+
#if defined(_ARCH_PWR10) && _ARCH_PWR10
|
|
154
|
+
#define BRD (HI(31) | LO(187))
|
|
155
|
+
#endif /* POWER10 */
|
|
156
|
+
#define CNTLZD (HI(31) | LO(58))
|
|
157
|
+
#define CNTLZW (HI(31) | LO(26))
|
|
158
|
+
#define CMP (HI(31) | LO(0))
|
|
159
|
+
#define CMPI (HI(11))
|
|
160
|
+
#define CMPL (HI(31) | LO(32))
|
|
161
|
+
#define CMPLI (HI(10))
|
|
162
|
+
#define CROR (HI(19) | LO(449))
|
|
163
|
+
#define DCBT (HI(31) | LO(278))
|
|
164
|
+
#define DIVD (HI(31) | LO(489))
|
|
165
|
+
#define DIVDU (HI(31) | LO(457))
|
|
166
|
+
#define DIVW (HI(31) | LO(491))
|
|
167
|
+
#define DIVWU (HI(31) | LO(459))
|
|
168
|
+
#define EXTSB (HI(31) | LO(954))
|
|
169
|
+
#define EXTSH (HI(31) | LO(922))
|
|
170
|
+
#define EXTSW (HI(31) | LO(986))
|
|
171
|
+
#define FABS (HI(63) | LO(264))
|
|
172
|
+
#define FADD (HI(63) | LO(21))
|
|
173
|
+
#define FADDS (HI(59) | LO(21))
|
|
174
|
+
#define FCFID (HI(63) | LO(846))
|
|
175
|
+
#define FCMPU (HI(63) | LO(0))
|
|
176
|
+
#define FCTIDZ (HI(63) | LO(815))
|
|
177
|
+
#define FCTIWZ (HI(63) | LO(15))
|
|
178
|
+
#define FDIV (HI(63) | LO(18))
|
|
179
|
+
#define FDIVS (HI(59) | LO(18))
|
|
180
|
+
#define FMR (HI(63) | LO(72))
|
|
181
|
+
#define FMUL (HI(63) | LO(25))
|
|
182
|
+
#define FMULS (HI(59) | LO(25))
|
|
183
|
+
#define FNEG (HI(63) | LO(40))
|
|
184
|
+
#define FRSP (HI(63) | LO(12))
|
|
185
|
+
#define FSUB (HI(63) | LO(20))
|
|
186
|
+
#define FSUBS (HI(59) | LO(20))
|
|
187
|
+
#define LD (HI(58) | 0)
|
|
188
|
+
#define LFD (HI(50))
|
|
189
|
+
#define LFS (HI(48))
|
|
190
|
+
#if defined(_ARCH_PWR7) && _ARCH_PWR7
|
|
191
|
+
#define LDBRX (HI(31) | LO(532))
|
|
192
|
+
#endif /* POWER7 */
|
|
193
|
+
#define LHBRX (HI(31) | LO(790))
|
|
194
|
+
#define LWBRX (HI(31) | LO(534))
|
|
195
|
+
#define LWZ (HI(32))
|
|
196
|
+
#define MFCR (HI(31) | LO(19))
|
|
197
|
+
#define MFLR (HI(31) | LO(339) | 0x80000)
|
|
198
|
+
#define MFXER (HI(31) | LO(339) | 0x10000)
|
|
199
|
+
#define MTCTR (HI(31) | LO(467) | 0x90000)
|
|
200
|
+
#define MTLR (HI(31) | LO(467) | 0x80000)
|
|
201
|
+
#define MTXER (HI(31) | LO(467) | 0x10000)
|
|
202
|
+
#define MULHD (HI(31) | LO(73))
|
|
203
|
+
#define MULHDU (HI(31) | LO(9))
|
|
204
|
+
#define MULHW (HI(31) | LO(75))
|
|
205
|
+
#define MULHWU (HI(31) | LO(11))
|
|
206
|
+
#define MULLD (HI(31) | LO(233))
|
|
207
|
+
#define MULLI (HI(7))
|
|
208
|
+
#define MULLW (HI(31) | LO(235))
|
|
209
|
+
#define NEG (HI(31) | LO(104))
|
|
210
|
+
#define NOP (HI(24))
|
|
211
|
+
#define NOR (HI(31) | LO(124))
|
|
212
|
+
#define OR (HI(31) | LO(444))
|
|
213
|
+
#define ORI (HI(24))
|
|
214
|
+
#define ORIS (HI(25))
|
|
215
|
+
#define RLDCL (HI(30) | LO(8))
|
|
216
|
+
#define RLDICL (HI(30) | LO(0 << 1))
|
|
217
|
+
#define RLDICR (HI(30) | LO(1 << 1))
|
|
218
|
+
#define RLDIMI (HI(30) | LO(3 << 1))
|
|
219
|
+
#define RLWIMI (HI(20))
|
|
220
|
+
#define RLWINM (HI(21))
|
|
221
|
+
#define RLWNM (HI(23))
|
|
222
|
+
#define SLD (HI(31) | LO(27))
|
|
223
|
+
#define SLW (HI(31) | LO(24))
|
|
224
|
+
#define SRAD (HI(31) | LO(794))
|
|
225
|
+
#define SRADI (HI(31) | LO(413 << 1))
|
|
226
|
+
#define SRAW (HI(31) | LO(792))
|
|
227
|
+
#define SRAWI (HI(31) | LO(824))
|
|
228
|
+
#define SRD (HI(31) | LO(539))
|
|
229
|
+
#define SRW (HI(31) | LO(536))
|
|
230
|
+
#define STD (HI(62) | 0)
|
|
231
|
+
#if defined(_ARCH_PWR7) && _ARCH_PWR7
|
|
232
|
+
#define STDBRX (HI(31) | LO(660))
|
|
233
|
+
#endif /* POWER7 */
|
|
234
|
+
#define STDU (HI(62) | 1)
|
|
235
|
+
#define STDUX (HI(31) | LO(181))
|
|
236
|
+
#define STFD (HI(54))
|
|
237
|
+
#define STFIWX (HI(31) | LO(983))
|
|
238
|
+
#define STFS (HI(52))
|
|
239
|
+
#define STHBRX (HI(31) | LO(918))
|
|
240
|
+
#define STW (HI(36))
|
|
241
|
+
#define STWBRX (HI(31) | LO(662))
|
|
242
|
+
#define STWU (HI(37))
|
|
243
|
+
#define STWUX (HI(31) | LO(183))
|
|
244
|
+
#define SUBF (HI(31) | LO(40))
|
|
245
|
+
#define SUBFC (HI(31) | LO(8))
|
|
246
|
+
#define SUBFE (HI(31) | LO(136))
|
|
247
|
+
#define SUBFIC (HI(8))
|
|
248
|
+
#define XOR (HI(31) | LO(316))
|
|
249
|
+
#define XORI (HI(26))
|
|
250
|
+
#define XORIS (HI(27))
|
|
251
|
+
|
|
252
|
+
#define SIMM_MAX (0x7fff)
|
|
253
|
+
#define SIMM_MIN (-0x8000)
|
|
254
|
+
#define UIMM_MAX (0xffff)
|
|
255
|
+
|
|
256
|
+
/* Shift helpers. */
|
|
257
|
+
#define RLWI_SH(sh) ((sljit_ins)(sh) << 11)
|
|
258
|
+
#define RLWI_MBE(mb, me) (((sljit_ins)(mb) << 6) | ((sljit_ins)(me) << 1))
|
|
259
|
+
#define RLDI_SH(sh) ((((sljit_ins)(sh) & 0x1f) << 11) | (((sljit_ins)(sh) & 0x20) >> 4))
|
|
260
|
+
#define RLDI_MB(mb) ((((sljit_ins)(mb) & 0x1f) << 6) | ((sljit_ins)(mb) & 0x20))
|
|
261
|
+
#define RLDI_ME(me) RLDI_MB(me)
|
|
262
|
+
|
|
263
|
+
#define SLWI(shift) (RLWINM | RLWI_SH(shift) | RLWI_MBE(0, 31 - (shift)))
|
|
264
|
+
#define SLDI(shift) (RLDICR | RLDI_SH(shift) | RLDI_ME(63 - (shift)))
|
|
265
|
+
/* shift > 0 */
|
|
266
|
+
#define SRWI(shift) (RLWINM | RLWI_SH(32 - (shift)) | RLWI_MBE((shift), 31))
|
|
267
|
+
#define SRDI(shift) (RLDICL | RLDI_SH(64 - (shift)) | RLDI_MB(shift))
|
|
268
|
+
|
|
269
|
+
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
|
270
|
+
#define SLWI_W(shift) SLWI(shift)
|
|
271
|
+
#define TMP_MEM_OFFSET (2 * sizeof(sljit_sw))
|
|
272
|
+
#else /* !SLJIT_CONFIG_PPC_32 */
|
|
273
|
+
#define SLWI_W(shift) SLDI(shift)
|
|
274
|
+
#define TMP_MEM_OFFSET (6 * sizeof(sljit_sw))
|
|
275
|
+
#endif /* SLJIT_CONFIG_PPC_32 */
|
|
276
|
+
|
|
277
|
+
#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
|
|
278
|
+
#define TMP_MEM_OFFSET_LO (TMP_MEM_OFFSET)
|
|
279
|
+
#define TMP_MEM_OFFSET_HI (TMP_MEM_OFFSET + sizeof(sljit_s32))
|
|
280
|
+
#define LWBRX_FIRST_REG S(TMP_REG1)
|
|
281
|
+
#define LWBRX_SECOND_REG S(dst)
|
|
282
|
+
#else /* !SLJIT_LITTLE_ENDIAN */
|
|
283
|
+
#define TMP_MEM_OFFSET_LO (TMP_MEM_OFFSET + sizeof(sljit_s32))
|
|
284
|
+
#define TMP_MEM_OFFSET_HI (TMP_MEM_OFFSET)
|
|
285
|
+
#define LWBRX_FIRST_REG S(dst)
|
|
286
|
+
#define LWBRX_SECOND_REG S(TMP_REG1)
|
|
287
|
+
#endif /* SLJIT_LITTLE_ENDIAN */
|
|
288
|
+
|
|
289
|
+
#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
|
|
290
|
+
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_uw addr, void* func)
|
|
291
|
+
{
|
|
292
|
+
sljit_uw* ptrs;
|
|
293
|
+
|
|
294
|
+
if (func_ptr)
|
|
295
|
+
*func_ptr = (void*)context;
|
|
296
|
+
|
|
297
|
+
ptrs = (sljit_uw*)func;
|
|
298
|
+
context->addr = addr ? addr : ptrs[0];
|
|
299
|
+
context->r2 = ptrs[1];
|
|
300
|
+
context->r11 = ptrs[2];
|
|
301
|
+
}
|
|
302
|
+
#endif
|
|
303
|
+
|
|
304
|
+
static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
|
|
305
|
+
{
|
|
306
|
+
sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
|
|
307
|
+
FAIL_IF(!ptr);
|
|
308
|
+
*ptr = ins;
|
|
309
|
+
compiler->size++;
|
|
310
|
+
return SLJIT_SUCCESS;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
|
|
314
|
+
{
|
|
315
|
+
sljit_sw diff;
|
|
316
|
+
sljit_uw target_addr;
|
|
317
|
+
|
|
318
|
+
#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
|
319
|
+
if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))
|
|
320
|
+
goto exit;
|
|
321
|
+
#else
|
|
322
|
+
if (jump->flags & SLJIT_REWRITABLE_JUMP)
|
|
323
|
+
goto exit;
|
|
324
|
+
#endif
|
|
325
|
+
|
|
326
|
+
if (jump->flags & JUMP_ADDR)
|
|
327
|
+
target_addr = jump->u.target;
|
|
328
|
+
else {
|
|
329
|
+
SLJIT_ASSERT(jump->u.label != NULL);
|
|
330
|
+
target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
334
|
+
if (jump->flags & IS_CALL)
|
|
335
|
+
goto keep_address;
|
|
336
|
+
#endif
|
|
337
|
+
|
|
338
|
+
diff = (sljit_sw)target_addr - (sljit_sw)code_ptr - executable_offset;
|
|
339
|
+
|
|
340
|
+
if (jump->flags & IS_COND) {
|
|
341
|
+
if (diff <= 0x7fff && diff >= -0x8000) {
|
|
342
|
+
jump->flags |= PATCH_B;
|
|
343
|
+
return code_ptr;
|
|
344
|
+
}
|
|
345
|
+
if (target_addr <= 0xffff) {
|
|
346
|
+
jump->flags |= PATCH_B | PATCH_ABS_B;
|
|
347
|
+
return code_ptr;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
diff -= SSIZE_OF(ins);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
if (diff <= 0x01ffffff && diff >= -0x02000000) {
|
|
354
|
+
jump->flags |= PATCH_B;
|
|
355
|
+
} else if (target_addr <= 0x01ffffff) {
|
|
356
|
+
jump->flags |= PATCH_B | PATCH_ABS_B;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (jump->flags & PATCH_B) {
|
|
360
|
+
if (!(jump->flags & IS_COND))
|
|
361
|
+
return code_ptr;
|
|
362
|
+
|
|
363
|
+
code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001);
|
|
364
|
+
code_ptr[1] = Bx;
|
|
365
|
+
jump->addr += sizeof(sljit_ins);
|
|
366
|
+
jump->flags -= IS_COND;
|
|
367
|
+
return code_ptr + 1;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
371
|
+
#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
|
|
372
|
+
keep_address:
|
|
373
|
+
#endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */
|
|
374
|
+
if (target_addr < 0x80000000l) {
|
|
375
|
+
jump->flags |= PATCH_ABS32;
|
|
376
|
+
code_ptr[2] = MTCTR | S(TMP_CALL_REG);
|
|
377
|
+
code_ptr[3] = code_ptr[0];
|
|
378
|
+
return code_ptr + 3;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
if (target_addr < 0x800000000000l) {
|
|
382
|
+
jump->flags |= PATCH_ABS48;
|
|
383
|
+
code_ptr[4] = MTCTR | S(TMP_CALL_REG);
|
|
384
|
+
code_ptr[5] = code_ptr[0];
|
|
385
|
+
return code_ptr + 5;
|
|
386
|
+
}
|
|
387
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
388
|
+
|
|
389
|
+
exit:
|
|
390
|
+
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
|
391
|
+
code_ptr[2] = MTCTR | S(TMP_CALL_REG);
|
|
392
|
+
code_ptr[3] = code_ptr[0];
|
|
393
|
+
#else /* !SLJIT_CONFIG_PPC_32 */
|
|
394
|
+
code_ptr[5] = MTCTR | S(TMP_CALL_REG);
|
|
395
|
+
code_ptr[6] = code_ptr[0];
|
|
396
|
+
#endif /* SLJIT_CONFIG_PPC_32 */
|
|
397
|
+
return code_ptr + JUMP_MAX_SIZE - 1;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
401
|
+
|
|
402
|
+
static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)
|
|
403
|
+
{
|
|
404
|
+
sljit_uw addr;
|
|
405
|
+
SLJIT_UNUSED_ARG(executable_offset);
|
|
406
|
+
|
|
407
|
+
SLJIT_ASSERT(jump->flags < ((sljit_uw)5 << JUMP_SIZE_SHIFT));
|
|
408
|
+
if (jump->flags & JUMP_ADDR)
|
|
409
|
+
addr = jump->u.target;
|
|
410
|
+
else
|
|
411
|
+
addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);
|
|
412
|
+
|
|
413
|
+
if (addr < 0x80000000l) {
|
|
414
|
+
SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));
|
|
415
|
+
jump->flags |= PATCH_ABS32;
|
|
416
|
+
return 1;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
if (addr < 0x800000000000l) {
|
|
420
|
+
SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));
|
|
421
|
+
jump->flags |= PATCH_ABS48;
|
|
422
|
+
return 3;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
SLJIT_ASSERT(jump->flags >= ((sljit_uw)4 << JUMP_SIZE_SHIFT));
|
|
426
|
+
return 4;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
430
|
+
|
|
431
|
+
static void generate_jump_or_mov_addr(struct sljit_jump *jump, sljit_sw executable_offset)
|
|
432
|
+
{
|
|
433
|
+
sljit_uw flags = jump->flags;
|
|
434
|
+
sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
|
|
435
|
+
sljit_ins *ins = (sljit_ins*)jump->addr;
|
|
436
|
+
sljit_s32 reg;
|
|
437
|
+
SLJIT_UNUSED_ARG(executable_offset);
|
|
438
|
+
|
|
439
|
+
if (flags & PATCH_B) {
|
|
440
|
+
if (flags & IS_COND) {
|
|
441
|
+
if (!(flags & PATCH_ABS_B)) {
|
|
442
|
+
addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(ins, executable_offset);
|
|
443
|
+
SLJIT_ASSERT((sljit_sw)addr <= 0x7fff && (sljit_sw)addr >= -0x8000);
|
|
444
|
+
ins[0] = BCx | ((sljit_ins)addr & 0xfffc) | (ins[0] & 0x03ff0001);
|
|
445
|
+
} else {
|
|
446
|
+
SLJIT_ASSERT(addr <= 0xffff);
|
|
447
|
+
ins[0] = BCx | ((sljit_ins)addr & 0xfffc) | 0x2 | ((*ins) & 0x03ff0001);
|
|
448
|
+
}
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
if (!(flags & PATCH_ABS_B)) {
|
|
453
|
+
addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(ins, executable_offset);
|
|
454
|
+
SLJIT_ASSERT((sljit_sw)addr <= 0x01ffffff && (sljit_sw)addr >= -0x02000000);
|
|
455
|
+
ins[0] = Bx | ((sljit_ins)addr & 0x03fffffc) | (ins[0] & 0x1);
|
|
456
|
+
} else {
|
|
457
|
+
SLJIT_ASSERT(addr <= 0x03ffffff);
|
|
458
|
+
ins[0] = Bx | ((sljit_ins)addr & 0x03fffffc) | 0x2 | (ins[0] & 0x1);
|
|
459
|
+
}
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
reg = (flags & JUMP_MOV_ADDR) ? (sljit_s32)ins[0] : TMP_CALL_REG;
|
|
464
|
+
|
|
465
|
+
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
|
466
|
+
ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 16);
|
|
467
|
+
ins[1] = ORI | S(reg) | A(reg) | IMM(addr);
|
|
468
|
+
#else /* !SLJIT_CONFIG_PPC_32 */
|
|
469
|
+
|
|
470
|
+
/* The TMP_ZERO cannot be used because it is restored for tail calls. */
|
|
471
|
+
if (flags & PATCH_ABS32) {
|
|
472
|
+
SLJIT_ASSERT(addr < 0x80000000l);
|
|
473
|
+
ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 16);
|
|
474
|
+
ins[1] = ORI | S(reg) | A(reg) | IMM(addr);
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
if (flags & PATCH_ABS48) {
|
|
479
|
+
SLJIT_ASSERT(addr < 0x800000000000l);
|
|
480
|
+
ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 32);
|
|
481
|
+
ins[1] = ORI | S(reg) | A(reg) | IMM(addr >> 16);
|
|
482
|
+
ins[2] = SLDI(16) | S(reg) | A(reg);
|
|
483
|
+
ins[3] = ORI | S(reg) | A(reg) | IMM(addr);
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 48);
|
|
488
|
+
ins[1] = ORI | S(reg) | A(reg) | IMM(addr >> 32);
|
|
489
|
+
ins[2] = SLDI(32) | S(reg) | A(reg);
|
|
490
|
+
ins[3] = ORIS | S(reg) | A(reg) | IMM(addr >> 16);
|
|
491
|
+
ins[4] = ORI | S(reg) | A(reg) | IMM(addr);
|
|
492
|
+
#endif /* SLJIT_CONFIG_PPC_32 */
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
static void reduce_code_size(struct sljit_compiler *compiler)
|
|
496
|
+
{
|
|
497
|
+
struct sljit_label *label;
|
|
498
|
+
struct sljit_jump *jump;
|
|
499
|
+
struct sljit_const *const_;
|
|
500
|
+
SLJIT_NEXT_DEFINE_TYPES;
|
|
501
|
+
sljit_uw total_size;
|
|
502
|
+
sljit_uw size_reduce = 0;
|
|
503
|
+
sljit_sw diff;
|
|
504
|
+
|
|
505
|
+
label = compiler->labels;
|
|
506
|
+
jump = compiler->jumps;
|
|
507
|
+
const_ = compiler->consts;
|
|
508
|
+
SLJIT_NEXT_INIT_TYPES();
|
|
509
|
+
|
|
510
|
+
while (1) {
|
|
511
|
+
SLJIT_GET_NEXT_MIN();
|
|
512
|
+
|
|
513
|
+
if (next_min_addr == SLJIT_MAX_ADDRESS)
|
|
514
|
+
break;
|
|
515
|
+
|
|
516
|
+
if (next_min_addr == next_label_size) {
|
|
517
|
+
label->size -= size_reduce;
|
|
518
|
+
|
|
519
|
+
label = label->next;
|
|
520
|
+
next_label_size = SLJIT_GET_NEXT_SIZE(label);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
if (next_min_addr == next_const_addr) {
|
|
524
|
+
const_->addr -= size_reduce;
|
|
525
|
+
const_ = const_->next;
|
|
526
|
+
next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
if (next_min_addr != next_jump_addr)
|
|
531
|
+
continue;
|
|
532
|
+
|
|
533
|
+
jump->addr -= size_reduce;
|
|
534
|
+
if (!(jump->flags & JUMP_MOV_ADDR)) {
|
|
535
|
+
total_size = JUMP_MAX_SIZE - 1;
|
|
536
|
+
|
|
537
|
+
if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) {
|
|
538
|
+
if (jump->flags & JUMP_ADDR) {
|
|
539
|
+
if (jump->u.target <= 0x01ffffff)
|
|
540
|
+
total_size = 1 - 1;
|
|
541
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
542
|
+
else if (jump->u.target < 0x80000000l)
|
|
543
|
+
total_size = 4 - 1;
|
|
544
|
+
else if (jump->u.target < 0x800000000000l)
|
|
545
|
+
total_size = 6 - 1;
|
|
546
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
547
|
+
} else {
|
|
548
|
+
/* Unit size: instruction. */
|
|
549
|
+
diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;
|
|
550
|
+
|
|
551
|
+
if (jump->flags & IS_COND) {
|
|
552
|
+
if (diff <= (0x7fff / SSIZE_OF(ins)) && diff >= (-0x8000 / SSIZE_OF(ins)))
|
|
553
|
+
total_size = 1 - 1;
|
|
554
|
+
else if ((diff - 1) <= (0x01ffffff / SSIZE_OF(ins)) && (diff - 1) >= (-0x02000000 / SSIZE_OF(ins)))
|
|
555
|
+
total_size = 2 - 1;
|
|
556
|
+
} else if (diff <= (0x01ffffff / SSIZE_OF(ins)) && diff >= (-0x02000000 / SSIZE_OF(ins)))
|
|
557
|
+
total_size = 1 - 1;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
size_reduce += (JUMP_MAX_SIZE - 1) - total_size;
|
|
562
|
+
jump->flags |= total_size << JUMP_SIZE_SHIFT;
|
|
563
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
564
|
+
} else {
|
|
565
|
+
total_size = (sljit_uw)4 << JUMP_SIZE_SHIFT;
|
|
566
|
+
|
|
567
|
+
if (jump->flags & JUMP_ADDR) {
|
|
568
|
+
if (jump->u.target < 0x80000000l) {
|
|
569
|
+
total_size = (sljit_uw)1 << JUMP_SIZE_SHIFT;
|
|
570
|
+
size_reduce += 3;
|
|
571
|
+
} else if (jump->u.target < 0x800000000000l) {
|
|
572
|
+
total_size = (sljit_uw)3 << JUMP_SIZE_SHIFT;
|
|
573
|
+
size_reduce += 1;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
jump->flags |= total_size;
|
|
577
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
jump = jump->next;
|
|
581
|
+
next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
compiler->size -= size_reduce;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
|
|
588
|
+
{
|
|
589
|
+
struct sljit_memory_fragment *buf;
|
|
590
|
+
sljit_ins *code;
|
|
591
|
+
sljit_ins *code_ptr;
|
|
592
|
+
sljit_ins *buf_ptr;
|
|
593
|
+
sljit_ins *buf_end;
|
|
594
|
+
sljit_uw word_count;
|
|
595
|
+
SLJIT_NEXT_DEFINE_TYPES;
|
|
596
|
+
sljit_sw executable_offset;
|
|
597
|
+
|
|
598
|
+
struct sljit_label *label;
|
|
599
|
+
struct sljit_jump *jump;
|
|
600
|
+
struct sljit_const *const_;
|
|
601
|
+
|
|
602
|
+
CHECK_ERROR_PTR();
|
|
603
|
+
CHECK_PTR(check_sljit_generate_code(compiler));
|
|
604
|
+
|
|
605
|
+
reduce_code_size(compiler);
|
|
606
|
+
|
|
607
|
+
#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
|
|
608
|
+
/* add to compiler->size additional instruction space to hold the trampoline and padding */
|
|
609
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
610
|
+
compiler->size += (compiler->size & 0x1) + (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
|
|
611
|
+
#else
|
|
612
|
+
compiler->size += (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
|
|
613
|
+
#endif
|
|
614
|
+
#endif
|
|
615
|
+
code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);
|
|
616
|
+
PTR_FAIL_WITH_EXEC_IF(code);
|
|
617
|
+
|
|
618
|
+
reverse_buf(compiler);
|
|
619
|
+
buf = compiler->buf;
|
|
620
|
+
|
|
621
|
+
code_ptr = code;
|
|
622
|
+
word_count = 0;
|
|
623
|
+
label = compiler->labels;
|
|
624
|
+
jump = compiler->jumps;
|
|
625
|
+
const_ = compiler->consts;
|
|
626
|
+
SLJIT_NEXT_INIT_TYPES();
|
|
627
|
+
SLJIT_GET_NEXT_MIN();
|
|
628
|
+
|
|
629
|
+
do {
|
|
630
|
+
buf_ptr = (sljit_ins*)buf->memory;
|
|
631
|
+
buf_end = buf_ptr + (buf->used_size >> 2);
|
|
632
|
+
do {
|
|
633
|
+
*code_ptr = *buf_ptr++;
|
|
634
|
+
if (next_min_addr == word_count) {
|
|
635
|
+
SLJIT_ASSERT(!label || label->size >= word_count);
|
|
636
|
+
SLJIT_ASSERT(!jump || jump->addr >= word_count);
|
|
637
|
+
SLJIT_ASSERT(!const_ || const_->addr >= word_count);
|
|
638
|
+
|
|
639
|
+
/* These structures are ordered by their address. */
|
|
640
|
+
if (next_min_addr == next_label_size) {
|
|
641
|
+
/* Just recording the address. */
|
|
642
|
+
label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
|
|
643
|
+
label->size = (sljit_uw)(code_ptr - code);
|
|
644
|
+
label = label->next;
|
|
645
|
+
next_label_size = SLJIT_GET_NEXT_SIZE(label);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
if (next_min_addr == next_jump_addr) {
|
|
649
|
+
if (!(jump->flags & JUMP_MOV_ADDR)) {
|
|
650
|
+
word_count += jump->flags >> JUMP_SIZE_SHIFT;
|
|
651
|
+
jump->addr = (sljit_uw)code_ptr;
|
|
652
|
+
code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
|
|
653
|
+
SLJIT_ASSERT(((sljit_uw)code_ptr - jump->addr <= (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins)));
|
|
654
|
+
} else {
|
|
655
|
+
jump->addr = (sljit_uw)code_ptr;
|
|
656
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
657
|
+
word_count += jump->flags >> JUMP_SIZE_SHIFT;
|
|
658
|
+
code_ptr += mov_addr_get_length(jump, code, executable_offset);
|
|
659
|
+
#else /* !SLJIT_CONFIG_PPC_64 */
|
|
660
|
+
word_count++;
|
|
661
|
+
code_ptr++;
|
|
662
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
663
|
+
}
|
|
664
|
+
jump = jump->next;
|
|
665
|
+
next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
|
|
666
|
+
} else if (next_min_addr == next_const_addr) {
|
|
667
|
+
const_->addr = (sljit_uw)code_ptr;
|
|
668
|
+
const_ = const_->next;
|
|
669
|
+
next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
SLJIT_GET_NEXT_MIN();
|
|
673
|
+
}
|
|
674
|
+
code_ptr++;
|
|
675
|
+
word_count++;
|
|
676
|
+
} while (buf_ptr < buf_end);
|
|
677
|
+
|
|
678
|
+
buf = buf->next;
|
|
679
|
+
} while (buf);
|
|
680
|
+
|
|
681
|
+
if (label && label->size == word_count) {
|
|
682
|
+
label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
|
|
683
|
+
label->size = (sljit_uw)(code_ptr - code);
|
|
684
|
+
label = label->next;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
SLJIT_ASSERT(!label);
|
|
688
|
+
SLJIT_ASSERT(!jump);
|
|
689
|
+
SLJIT_ASSERT(!const_);
|
|
690
|
+
|
|
691
|
+
#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
|
|
692
|
+
SLJIT_ASSERT(code_ptr - code <= (sljit_sw)(compiler->size - (sizeof(struct sljit_function_context) / sizeof(sljit_ins))));
|
|
693
|
+
#else
|
|
694
|
+
SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
|
|
695
|
+
#endif
|
|
696
|
+
|
|
697
|
+
jump = compiler->jumps;
|
|
698
|
+
while (jump) {
|
|
699
|
+
generate_jump_or_mov_addr(jump, executable_offset);
|
|
700
|
+
jump = jump->next;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
compiler->error = SLJIT_ERR_COMPILED;
|
|
704
|
+
compiler->executable_offset = executable_offset;
|
|
705
|
+
|
|
706
|
+
code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
|
|
707
|
+
|
|
708
|
+
#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
|
|
709
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
710
|
+
if (((sljit_sw)code_ptr) & 0x4)
|
|
711
|
+
code_ptr++;
|
|
712
|
+
#endif
|
|
713
|
+
sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_uw)code, (void*)sljit_generate_code);
|
|
714
|
+
#endif
|
|
715
|
+
|
|
716
|
+
code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
|
|
717
|
+
|
|
718
|
+
SLJIT_CACHE_FLUSH(code, code_ptr);
|
|
719
|
+
SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
|
|
720
|
+
|
|
721
|
+
#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
|
|
722
|
+
compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins) + sizeof(struct sljit_function_context);
|
|
723
|
+
return code_ptr;
|
|
724
|
+
#else
|
|
725
|
+
compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);
|
|
726
|
+
return code;
|
|
727
|
+
#endif
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
|
731
|
+
{
|
|
732
|
+
switch (feature_type) {
|
|
733
|
+
case SLJIT_HAS_FPU:
|
|
734
|
+
#ifdef SLJIT_IS_FPU_AVAILABLE
|
|
735
|
+
return (SLJIT_IS_FPU_AVAILABLE) != 0;
|
|
736
|
+
#else
|
|
737
|
+
/* Available by default. */
|
|
738
|
+
return 1;
|
|
739
|
+
#endif
|
|
740
|
+
case SLJIT_HAS_REV:
|
|
741
|
+
#if defined(_ARCH_PWR10) && _ARCH_PWR10
|
|
742
|
+
return 1;
|
|
743
|
+
#else /* !POWER10 */
|
|
744
|
+
return 2;
|
|
745
|
+
#endif /* POWER10 */
|
|
746
|
+
/* A saved register is set to a zero value. */
|
|
747
|
+
case SLJIT_HAS_ZERO_REGISTER:
|
|
748
|
+
case SLJIT_HAS_CLZ:
|
|
749
|
+
case SLJIT_HAS_ROT:
|
|
750
|
+
case SLJIT_HAS_PREFETCH:
|
|
751
|
+
return 1;
|
|
752
|
+
|
|
753
|
+
case SLJIT_HAS_CTZ:
|
|
754
|
+
return 2;
|
|
755
|
+
|
|
756
|
+
default:
|
|
757
|
+
return 0;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)
|
|
762
|
+
{
|
|
763
|
+
switch (type) {
|
|
764
|
+
case SLJIT_UNORDERED_OR_EQUAL:
|
|
765
|
+
case SLJIT_ORDERED_NOT_EQUAL:
|
|
766
|
+
case SLJIT_UNORDERED_OR_LESS:
|
|
767
|
+
case SLJIT_ORDERED_GREATER_EQUAL:
|
|
768
|
+
case SLJIT_UNORDERED_OR_GREATER:
|
|
769
|
+
case SLJIT_ORDERED_LESS_EQUAL:
|
|
770
|
+
return 1;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
return 0;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
/* --------------------------------------------------------------------- */
|
|
777
|
+
/* Entry, exit */
|
|
778
|
+
/* --------------------------------------------------------------------- */
|
|
779
|
+
|
|
780
|
+
/* inp_flags: */
|
|
781
|
+
|
|
782
|
+
/* Creates an index in data_transfer_insts array. */
|
|
783
|
+
#define LOAD_DATA 0x01
|
|
784
|
+
#define INDEXED 0x02
|
|
785
|
+
#define SIGNED_DATA 0x04
|
|
786
|
+
|
|
787
|
+
#define WORD_DATA 0x00
|
|
788
|
+
#define BYTE_DATA 0x08
|
|
789
|
+
#define HALF_DATA 0x10
|
|
790
|
+
#define INT_DATA 0x18
|
|
791
|
+
/* Separates integer and floating point registers */
|
|
792
|
+
#define GPR_REG 0x1f
|
|
793
|
+
#define DOUBLE_DATA 0x20
|
|
794
|
+
|
|
795
|
+
#define MEM_MASK 0x7f
|
|
796
|
+
|
|
797
|
+
#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 6))
|
|
798
|
+
|
|
799
|
+
/* Other inp_flags. */
|
|
800
|
+
|
|
801
|
+
/* Integer opertion and set flags -> requires exts on 64 bit systems. */
|
|
802
|
+
#define ALT_SIGN_EXT 0x000100
|
|
803
|
+
/* This flag affects the RC() and OERC() macros. */
|
|
804
|
+
#define ALT_SET_FLAGS 0x000400
|
|
805
|
+
#define ALT_FORM1 0x001000
|
|
806
|
+
#define ALT_FORM2 0x002000
|
|
807
|
+
#define ALT_FORM3 0x004000
|
|
808
|
+
#define ALT_FORM4 0x008000
|
|
809
|
+
#define ALT_FORM5 0x010000
|
|
810
|
+
|
|
811
|
+
/* Source and destination is register. */
|
|
812
|
+
#define REG_DEST 0x000001
|
|
813
|
+
#define REG1_SOURCE 0x000002
|
|
814
|
+
#define REG2_SOURCE 0x000004
|
|
815
|
+
/*
|
|
816
|
+
ALT_SIGN_EXT 0x000100
|
|
817
|
+
ALT_SET_FLAGS 0x000200
|
|
818
|
+
ALT_FORM1 0x001000
|
|
819
|
+
...
|
|
820
|
+
ALT_FORM5 0x010000 */
|
|
821
|
+
|
|
822
|
+
static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg,
|
|
823
|
+
sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg);
|
|
824
|
+
|
|
825
|
+
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
|
826
|
+
#include "sljitNativePPC_32.c"
|
|
827
|
+
#else
|
|
828
|
+
#include "sljitNativePPC_64.c"
|
|
829
|
+
#endif
|
|
830
|
+
|
|
831
|
+
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
|
832
|
+
#define STACK_STORE STW
|
|
833
|
+
#define STACK_LOAD LWZ
|
|
834
|
+
#else
|
|
835
|
+
#define STACK_STORE STD
|
|
836
|
+
#define STACK_LOAD LD
|
|
837
|
+
#endif
|
|
838
|
+
|
|
839
|
+
#if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
|
|
840
|
+
#define LR_SAVE_OFFSET (2 * SSIZE_OF(sw))
|
|
841
|
+
#else
|
|
842
|
+
#define LR_SAVE_OFFSET SSIZE_OF(sw)
|
|
843
|
+
#endif
|
|
844
|
+
|
|
845
|
+
#define STACK_MAX_DISTANCE (0x8000 - SSIZE_OF(sw) - LR_SAVE_OFFSET)
|
|
846
|
+
|
|
847
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
|
|
848
|
+
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
|
|
849
|
+
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
|
850
|
+
{
|
|
851
|
+
sljit_s32 i, tmp, base, offset;
|
|
852
|
+
sljit_s32 word_arg_count = 0;
|
|
853
|
+
sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);
|
|
854
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
855
|
+
sljit_s32 arg_count = 0;
|
|
856
|
+
#endif
|
|
857
|
+
|
|
858
|
+
CHECK_ERROR();
|
|
859
|
+
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
|
|
860
|
+
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
|
|
861
|
+
|
|
862
|
+
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 0)
|
|
863
|
+
+ GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
|
|
864
|
+
|
|
865
|
+
if (!(options & SLJIT_ENTER_REG_ARG))
|
|
866
|
+
local_size += SSIZE_OF(sw);
|
|
867
|
+
|
|
868
|
+
local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
|
|
869
|
+
compiler->local_size = local_size;
|
|
870
|
+
|
|
871
|
+
FAIL_IF(push_inst(compiler, MFLR | D(0)));
|
|
872
|
+
|
|
873
|
+
base = SLJIT_SP;
|
|
874
|
+
offset = local_size;
|
|
875
|
+
|
|
876
|
+
if (local_size <= STACK_MAX_DISTANCE) {
|
|
877
|
+
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
|
878
|
+
FAIL_IF(push_inst(compiler, STWU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
|
|
879
|
+
#else
|
|
880
|
+
FAIL_IF(push_inst(compiler, STDU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
|
|
881
|
+
#endif
|
|
882
|
+
} else {
|
|
883
|
+
base = TMP_REG1;
|
|
884
|
+
FAIL_IF(push_inst(compiler, OR | S(SLJIT_SP) | A(TMP_REG1) | B(SLJIT_SP)));
|
|
885
|
+
FAIL_IF(load_immediate(compiler, TMP_REG2, -local_size));
|
|
886
|
+
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
|
887
|
+
FAIL_IF(push_inst(compiler, STWUX | S(SLJIT_SP) | A(SLJIT_SP) | B(TMP_REG2)));
|
|
888
|
+
#else
|
|
889
|
+
FAIL_IF(push_inst(compiler, STDUX | S(SLJIT_SP) | A(SLJIT_SP) | B(TMP_REG2)));
|
|
890
|
+
#endif
|
|
891
|
+
local_size = 0;
|
|
892
|
+
offset = 0;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
tmp = SLJIT_FS0 - fsaveds;
|
|
896
|
+
for (i = SLJIT_FS0; i > tmp; i--) {
|
|
897
|
+
offset -= SSIZE_OF(f64);
|
|
898
|
+
FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset)));
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
|
|
902
|
+
offset -= SSIZE_OF(f64);
|
|
903
|
+
FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset)));
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
if (!(options & SLJIT_ENTER_REG_ARG)) {
|
|
907
|
+
offset -= SSIZE_OF(sw);
|
|
908
|
+
FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(base) | IMM(offset)));
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
tmp = SLJIT_S0 - saveds;
|
|
912
|
+
for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {
|
|
913
|
+
offset -= SSIZE_OF(sw);
|
|
914
|
+
FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(base) | IMM(offset)));
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
|
|
918
|
+
offset -= SSIZE_OF(sw);
|
|
919
|
+
FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(base) | IMM(offset)));
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(base) | IMM(local_size + LR_SAVE_OFFSET)));
|
|
923
|
+
|
|
924
|
+
if (options & SLJIT_ENTER_REG_ARG)
|
|
925
|
+
return SLJIT_SUCCESS;
|
|
926
|
+
|
|
927
|
+
FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0));
|
|
928
|
+
|
|
929
|
+
arg_types >>= SLJIT_ARG_SHIFT;
|
|
930
|
+
saved_arg_count = 0;
|
|
931
|
+
|
|
932
|
+
while (arg_types > 0) {
|
|
933
|
+
if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
|
|
934
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
935
|
+
do {
|
|
936
|
+
if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
|
|
937
|
+
tmp = SLJIT_S0 - saved_arg_count;
|
|
938
|
+
saved_arg_count++;
|
|
939
|
+
} else if (arg_count != word_arg_count)
|
|
940
|
+
tmp = SLJIT_R0 + word_arg_count;
|
|
941
|
+
else
|
|
942
|
+
break;
|
|
943
|
+
|
|
944
|
+
FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0 + arg_count) | A(tmp) | B(SLJIT_R0 + arg_count)));
|
|
945
|
+
} while (0);
|
|
946
|
+
#else
|
|
947
|
+
if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
|
|
948
|
+
FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0 + word_arg_count) | A(SLJIT_S0 - saved_arg_count) | B(SLJIT_R0 + word_arg_count)));
|
|
949
|
+
saved_arg_count++;
|
|
950
|
+
}
|
|
951
|
+
#endif
|
|
952
|
+
word_arg_count++;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
956
|
+
arg_count++;
|
|
957
|
+
#endif
|
|
958
|
+
arg_types >>= SLJIT_ARG_SHIFT;
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
return SLJIT_SUCCESS;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
|
|
965
|
+
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
|
|
966
|
+
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
|
|
967
|
+
{
|
|
968
|
+
CHECK_ERROR();
|
|
969
|
+
CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
|
|
970
|
+
set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
|
|
971
|
+
|
|
972
|
+
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 0)
|
|
973
|
+
+ GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
|
|
974
|
+
|
|
975
|
+
if (!(options & SLJIT_ENTER_REG_ARG))
|
|
976
|
+
local_size += SSIZE_OF(sw);
|
|
977
|
+
|
|
978
|
+
compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
|
|
979
|
+
return SLJIT_SUCCESS;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to)
|
|
983
|
+
{
|
|
984
|
+
sljit_s32 i, tmp, base, offset;
|
|
985
|
+
sljit_s32 local_size = compiler->local_size;
|
|
986
|
+
|
|
987
|
+
SLJIT_ASSERT(TMP_CALL_REG != TMP_REG2);
|
|
988
|
+
|
|
989
|
+
base = SLJIT_SP;
|
|
990
|
+
if (local_size > STACK_MAX_DISTANCE) {
|
|
991
|
+
base = TMP_REG2;
|
|
992
|
+
if (local_size > 2 * STACK_MAX_DISTANCE + LR_SAVE_OFFSET) {
|
|
993
|
+
FAIL_IF(push_inst(compiler, STACK_LOAD | D(base) | A(SLJIT_SP) | IMM(0)));
|
|
994
|
+
local_size = 0;
|
|
995
|
+
} else {
|
|
996
|
+
FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(SLJIT_SP) | IMM(local_size - STACK_MAX_DISTANCE)));
|
|
997
|
+
local_size = STACK_MAX_DISTANCE;
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
offset = local_size;
|
|
1002
|
+
if (!is_return_to)
|
|
1003
|
+
FAIL_IF(push_inst(compiler, STACK_LOAD | S(0) | A(base) | IMM(offset + LR_SAVE_OFFSET)));
|
|
1004
|
+
|
|
1005
|
+
tmp = SLJIT_FS0 - compiler->fsaveds;
|
|
1006
|
+
for (i = SLJIT_FS0; i > tmp; i--) {
|
|
1007
|
+
offset -= SSIZE_OF(f64);
|
|
1008
|
+
FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset)));
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
|
|
1012
|
+
offset -= SSIZE_OF(f64);
|
|
1013
|
+
FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset)));
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
if (!(compiler->options & SLJIT_ENTER_REG_ARG)) {
|
|
1017
|
+
offset -= SSIZE_OF(sw);
|
|
1018
|
+
FAIL_IF(push_inst(compiler, STACK_LOAD | S(TMP_ZERO) | A(base) | IMM(offset)));
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
tmp = SLJIT_S0 - compiler->saveds;
|
|
1022
|
+
for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) {
|
|
1023
|
+
offset -= SSIZE_OF(sw);
|
|
1024
|
+
FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset)));
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
|
|
1028
|
+
offset -= SSIZE_OF(sw);
|
|
1029
|
+
FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset)));
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
if (!is_return_to)
|
|
1033
|
+
push_inst(compiler, MTLR | S(0));
|
|
1034
|
+
|
|
1035
|
+
if (local_size > 0)
|
|
1036
|
+
return push_inst(compiler, ADDI | D(SLJIT_SP) | A(base) | IMM(local_size));
|
|
1037
|
+
|
|
1038
|
+
SLJIT_ASSERT(base == TMP_REG2);
|
|
1039
|
+
return push_inst(compiler, OR | S(base) | A(SLJIT_SP) | B(base));
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
#undef STACK_STORE
|
|
1043
|
+
#undef STACK_LOAD
|
|
1044
|
+
|
|
1045
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
|
|
1046
|
+
{
|
|
1047
|
+
CHECK_ERROR();
|
|
1048
|
+
CHECK(check_sljit_emit_return_void(compiler));
|
|
1049
|
+
|
|
1050
|
+
FAIL_IF(emit_stack_frame_release(compiler, 0));
|
|
1051
|
+
return push_inst(compiler, BLR);
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,
|
|
1055
|
+
sljit_s32 src, sljit_sw srcw)
|
|
1056
|
+
{
|
|
1057
|
+
CHECK_ERROR();
|
|
1058
|
+
CHECK(check_sljit_emit_return_to(compiler, src, srcw));
|
|
1059
|
+
|
|
1060
|
+
if (src & SLJIT_MEM) {
|
|
1061
|
+
ADJUST_LOCAL_OFFSET(src, srcw);
|
|
1062
|
+
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG));
|
|
1063
|
+
src = TMP_CALL_REG;
|
|
1064
|
+
srcw = 0;
|
|
1065
|
+
} else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
|
|
1066
|
+
FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));
|
|
1067
|
+
src = TMP_CALL_REG;
|
|
1068
|
+
srcw = 0;
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
FAIL_IF(emit_stack_frame_release(compiler, 1));
|
|
1072
|
+
|
|
1073
|
+
SLJIT_SKIP_CHECKS(compiler);
|
|
1074
|
+
return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
/* --------------------------------------------------------------------- */
|
|
1078
|
+
/* Operators */
|
|
1079
|
+
/* --------------------------------------------------------------------- */
|
|
1080
|
+
|
|
1081
|
+
/* s/l - store/load (1 bit)
|
|
1082
|
+
i/x - immediate/indexed form
|
|
1083
|
+
u/s - signed/unsigned (1 bit)
|
|
1084
|
+
w/b/h/i - word/byte/half/int allowed (2 bit)
|
|
1085
|
+
|
|
1086
|
+
Some opcodes are repeated (e.g. store signed / unsigned byte is the same instruction). */
|
|
1087
|
+
|
|
1088
|
+
/* 64 bit only: [reg+imm] must be aligned to 4 bytes. */
|
|
1089
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1090
|
+
#define INT_ALIGNED 0x10000
|
|
1091
|
+
#endif
|
|
1092
|
+
|
|
1093
|
+
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
|
1094
|
+
#define ARCH_32_64(a, b) a
|
|
1095
|
+
#define INST_CODE_AND_DST(inst, flags, reg) \
|
|
1096
|
+
((sljit_ins)(inst) | (sljit_ins)(((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
|
|
1097
|
+
#else
|
|
1098
|
+
#define ARCH_32_64(a, b) b
|
|
1099
|
+
#define INST_CODE_AND_DST(inst, flags, reg) \
|
|
1100
|
+
(((sljit_ins)(inst) & ~(sljit_ins)INT_ALIGNED) | (sljit_ins)(((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
|
|
1101
|
+
#endif
|
|
1102
|
+
|
|
1103
|
+
static const sljit_ins data_transfer_insts[64 + 16] = {
|
|
1104
|
+
|
|
1105
|
+
/* -------- Integer -------- */
|
|
1106
|
+
|
|
1107
|
+
/* Word. */
|
|
1108
|
+
|
|
1109
|
+
/* w u i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),
|
|
1110
|
+
/* w u i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),
|
|
1111
|
+
/* w u x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
|
|
1112
|
+
/* w u x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
|
|
1113
|
+
|
|
1114
|
+
/* w s i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),
|
|
1115
|
+
/* w s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),
|
|
1116
|
+
/* w s x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
|
|
1117
|
+
/* w s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
|
|
1118
|
+
|
|
1119
|
+
/* Byte. */
|
|
1120
|
+
|
|
1121
|
+
/* b u i s */ HI(38) /* stb */,
|
|
1122
|
+
/* b u i l */ HI(34) /* lbz */,
|
|
1123
|
+
/* b u x s */ HI(31) | LO(215) /* stbx */,
|
|
1124
|
+
/* b u x l */ HI(31) | LO(87) /* lbzx */,
|
|
1125
|
+
|
|
1126
|
+
/* b s i s */ HI(38) /* stb */,
|
|
1127
|
+
/* b s i l */ HI(34) /* lbz */ /* EXTS_REQ */,
|
|
1128
|
+
/* b s x s */ HI(31) | LO(215) /* stbx */,
|
|
1129
|
+
/* b s x l */ HI(31) | LO(87) /* lbzx */ /* EXTS_REQ */,
|
|
1130
|
+
|
|
1131
|
+
/* Half. */
|
|
1132
|
+
|
|
1133
|
+
/* h u i s */ HI(44) /* sth */,
|
|
1134
|
+
/* h u i l */ HI(40) /* lhz */,
|
|
1135
|
+
/* h u x s */ HI(31) | LO(407) /* sthx */,
|
|
1136
|
+
/* h u x l */ HI(31) | LO(279) /* lhzx */,
|
|
1137
|
+
|
|
1138
|
+
/* h s i s */ HI(44) /* sth */,
|
|
1139
|
+
/* h s i l */ HI(42) /* lha */,
|
|
1140
|
+
/* h s x s */ HI(31) | LO(407) /* sthx */,
|
|
1141
|
+
/* h s x l */ HI(31) | LO(343) /* lhax */,
|
|
1142
|
+
|
|
1143
|
+
/* Int. */
|
|
1144
|
+
|
|
1145
|
+
/* i u i s */ HI(36) /* stw */,
|
|
1146
|
+
/* i u i l */ HI(32) /* lwz */,
|
|
1147
|
+
/* i u x s */ HI(31) | LO(151) /* stwx */,
|
|
1148
|
+
/* i u x l */ HI(31) | LO(23) /* lwzx */,
|
|
1149
|
+
|
|
1150
|
+
/* i s i s */ HI(36) /* stw */,
|
|
1151
|
+
/* i s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x2 /* lwa */),
|
|
1152
|
+
/* i s x s */ HI(31) | LO(151) /* stwx */,
|
|
1153
|
+
/* i s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(341) /* lwax */),
|
|
1154
|
+
|
|
1155
|
+
/* -------- Floating point -------- */
|
|
1156
|
+
|
|
1157
|
+
/* d i s */ HI(54) /* stfd */,
|
|
1158
|
+
/* d i l */ HI(50) /* lfd */,
|
|
1159
|
+
/* d x s */ HI(31) | LO(727) /* stfdx */,
|
|
1160
|
+
/* d x l */ HI(31) | LO(599) /* lfdx */,
|
|
1161
|
+
|
|
1162
|
+
/* s i s */ HI(52) /* stfs */,
|
|
1163
|
+
/* s i l */ HI(48) /* lfs */,
|
|
1164
|
+
/* s x s */ HI(31) | LO(663) /* stfsx */,
|
|
1165
|
+
/* s x l */ HI(31) | LO(535) /* lfsx */,
|
|
1166
|
+
};
|
|
1167
|
+
|
|
1168
|
+
static const sljit_ins updated_data_transfer_insts[64] = {
|
|
1169
|
+
|
|
1170
|
+
/* -------- Integer -------- */
|
|
1171
|
+
|
|
1172
|
+
/* Word. */
|
|
1173
|
+
|
|
1174
|
+
/* w u i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),
|
|
1175
|
+
/* w u i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),
|
|
1176
|
+
/* w u x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
|
|
1177
|
+
/* w u x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
|
|
1178
|
+
|
|
1179
|
+
/* w s i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),
|
|
1180
|
+
/* w s i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),
|
|
1181
|
+
/* w s x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
|
|
1182
|
+
/* w s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
|
|
1183
|
+
|
|
1184
|
+
/* Byte. */
|
|
1185
|
+
|
|
1186
|
+
/* b u i s */ HI(39) /* stbu */,
|
|
1187
|
+
/* b u i l */ HI(35) /* lbzu */,
|
|
1188
|
+
/* b u x s */ HI(31) | LO(247) /* stbux */,
|
|
1189
|
+
/* b u x l */ HI(31) | LO(119) /* lbzux */,
|
|
1190
|
+
|
|
1191
|
+
/* b s i s */ HI(39) /* stbu */,
|
|
1192
|
+
/* b s i l */ 0 /* no such instruction */,
|
|
1193
|
+
/* b s x s */ HI(31) | LO(247) /* stbux */,
|
|
1194
|
+
/* b s x l */ 0 /* no such instruction */,
|
|
1195
|
+
|
|
1196
|
+
/* Half. */
|
|
1197
|
+
|
|
1198
|
+
/* h u i s */ HI(45) /* sthu */,
|
|
1199
|
+
/* h u i l */ HI(41) /* lhzu */,
|
|
1200
|
+
/* h u x s */ HI(31) | LO(439) /* sthux */,
|
|
1201
|
+
/* h u x l */ HI(31) | LO(311) /* lhzux */,
|
|
1202
|
+
|
|
1203
|
+
/* h s i s */ HI(45) /* sthu */,
|
|
1204
|
+
/* h s i l */ HI(43) /* lhau */,
|
|
1205
|
+
/* h s x s */ HI(31) | LO(439) /* sthux */,
|
|
1206
|
+
/* h s x l */ HI(31) | LO(375) /* lhaux */,
|
|
1207
|
+
|
|
1208
|
+
/* Int. */
|
|
1209
|
+
|
|
1210
|
+
/* i u i s */ HI(37) /* stwu */,
|
|
1211
|
+
/* i u i l */ HI(33) /* lwzu */,
|
|
1212
|
+
/* i u x s */ HI(31) | LO(183) /* stwux */,
|
|
1213
|
+
/* i u x l */ HI(31) | LO(55) /* lwzux */,
|
|
1214
|
+
|
|
1215
|
+
/* i s i s */ HI(37) /* stwu */,
|
|
1216
|
+
/* i s i l */ ARCH_32_64(HI(33) /* lwzu */, 0 /* no such instruction */),
|
|
1217
|
+
/* i s x s */ HI(31) | LO(183) /* stwux */,
|
|
1218
|
+
/* i s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(373) /* lwaux */),
|
|
1219
|
+
|
|
1220
|
+
/* -------- Floating point -------- */
|
|
1221
|
+
|
|
1222
|
+
/* d i s */ HI(55) /* stfdu */,
|
|
1223
|
+
/* d i l */ HI(51) /* lfdu */,
|
|
1224
|
+
/* d x s */ HI(31) | LO(759) /* stfdux */,
|
|
1225
|
+
/* d x l */ HI(31) | LO(631) /* lfdux */,
|
|
1226
|
+
|
|
1227
|
+
/* s i s */ HI(53) /* stfsu */,
|
|
1228
|
+
/* s i l */ HI(49) /* lfsu */,
|
|
1229
|
+
/* s x s */ HI(31) | LO(695) /* stfsux */,
|
|
1230
|
+
/* s x l */ HI(31) | LO(567) /* lfsux */,
|
|
1231
|
+
};
|
|
1232
|
+
|
|
1233
|
+
#undef ARCH_32_64
|
|
1234
|
+
|
|
1235
|
+
/* Simple cases, (no caching is required). */
|
|
1236
|
+
static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg,
|
|
1237
|
+
sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
|
|
1238
|
+
{
|
|
1239
|
+
sljit_ins inst;
|
|
1240
|
+
sljit_s32 offs_reg;
|
|
1241
|
+
|
|
1242
|
+
/* Should work when (arg & REG_MASK) == 0. */
|
|
1243
|
+
SLJIT_ASSERT(A(0) == 0);
|
|
1244
|
+
SLJIT_ASSERT(arg & SLJIT_MEM);
|
|
1245
|
+
|
|
1246
|
+
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
|
|
1247
|
+
argw &= 0x3;
|
|
1248
|
+
offs_reg = OFFS_REG(arg);
|
|
1249
|
+
|
|
1250
|
+
if (argw != 0) {
|
|
1251
|
+
FAIL_IF(push_inst(compiler, SLWI_W(argw) | S(OFFS_REG(arg)) | A(tmp_reg)));
|
|
1252
|
+
offs_reg = tmp_reg;
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
|
|
1256
|
+
|
|
1257
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1258
|
+
SLJIT_ASSERT(!(inst & INT_ALIGNED));
|
|
1259
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
1260
|
+
|
|
1261
|
+
return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(offs_reg));
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
inst = data_transfer_insts[inp_flags & MEM_MASK];
|
|
1265
|
+
arg &= REG_MASK;
|
|
1266
|
+
|
|
1267
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1268
|
+
if ((inst & INT_ALIGNED) && (argw & 0x3) != 0) {
|
|
1269
|
+
FAIL_IF(load_immediate(compiler, tmp_reg, argw));
|
|
1270
|
+
|
|
1271
|
+
inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
|
|
1272
|
+
return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));
|
|
1273
|
+
}
|
|
1274
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
1275
|
+
|
|
1276
|
+
if (argw <= SIMM_MAX && argw >= SIMM_MIN)
|
|
1277
|
+
return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | IMM(argw));
|
|
1278
|
+
|
|
1279
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1280
|
+
if (argw <= 0x7fff7fffl && argw >= -0x80000000l) {
|
|
1281
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
1282
|
+
FAIL_IF(push_inst(compiler, ADDIS | D(tmp_reg) | A(arg) | IMM((argw + 0x8000) >> 16)));
|
|
1283
|
+
return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_reg) | IMM(argw));
|
|
1284
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
FAIL_IF(load_immediate(compiler, tmp_reg, argw));
|
|
1288
|
+
|
|
1289
|
+
inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
|
|
1290
|
+
return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));
|
|
1291
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 input_flags,
|
|
1295
|
+
sljit_s32 dst, sljit_sw dstw,
|
|
1296
|
+
sljit_s32 src1, sljit_sw src1w,
|
|
1297
|
+
sljit_s32 src2, sljit_sw src2w)
|
|
1298
|
+
{
|
|
1299
|
+
/* arg1 goes to TMP_REG1 or src reg
|
|
1300
|
+
arg2 goes to TMP_REG2, imm or src reg
|
|
1301
|
+
result goes to TMP_REG2, so put result can use TMP_REG1. */
|
|
1302
|
+
sljit_s32 dst_r = TMP_REG2;
|
|
1303
|
+
sljit_s32 src1_r;
|
|
1304
|
+
sljit_s32 src2_r;
|
|
1305
|
+
sljit_s32 src2_tmp_reg = (!(input_flags & ALT_SIGN_EXT) && GET_OPCODE(op) >= SLJIT_OP2_BASE && FAST_IS_REG(src1)) ? TMP_REG1 : TMP_REG2;
|
|
1306
|
+
sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_SIGN_EXT | ALT_SET_FLAGS);
|
|
1307
|
+
|
|
1308
|
+
/* Destination check. */
|
|
1309
|
+
if (FAST_IS_REG(dst)) {
|
|
1310
|
+
dst_r = dst;
|
|
1311
|
+
/* The REG_DEST is only used by SLJIT_MOV operations, although
|
|
1312
|
+
* it is set for op2 operations with unset destination. */
|
|
1313
|
+
flags |= REG_DEST;
|
|
1314
|
+
|
|
1315
|
+
if (op >= SLJIT_MOV && op <= SLJIT_MOV_P)
|
|
1316
|
+
src2_tmp_reg = dst_r;
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
/* Source 2. */
|
|
1320
|
+
if (FAST_IS_REG(src2)) {
|
|
1321
|
+
src2_r = src2;
|
|
1322
|
+
flags |= REG2_SOURCE;
|
|
1323
|
+
|
|
1324
|
+
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P)
|
|
1325
|
+
dst_r = src2_r;
|
|
1326
|
+
} else if (src2 == SLJIT_IMM) {
|
|
1327
|
+
src2_r = TMP_ZERO;
|
|
1328
|
+
if (src2w != 0) {
|
|
1329
|
+
FAIL_IF(load_immediate(compiler, src2_tmp_reg, src2w));
|
|
1330
|
+
src2_r = src2_tmp_reg;
|
|
1331
|
+
}
|
|
1332
|
+
} else {
|
|
1333
|
+
FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, src2_tmp_reg, src2, src2w, TMP_REG1));
|
|
1334
|
+
src2_r = src2_tmp_reg;
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
/* Source 1. */
|
|
1338
|
+
if (FAST_IS_REG(src1)) {
|
|
1339
|
+
src1_r = src1;
|
|
1340
|
+
flags |= REG1_SOURCE;
|
|
1341
|
+
} else if (src1 == SLJIT_IMM) {
|
|
1342
|
+
src1_r = TMP_ZERO;
|
|
1343
|
+
if (src1w != 0) {
|
|
1344
|
+
FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
|
|
1345
|
+
src1_r = TMP_REG1;
|
|
1346
|
+
}
|
|
1347
|
+
} else {
|
|
1348
|
+
FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));
|
|
1349
|
+
src1_r = TMP_REG1;
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
|
|
1353
|
+
|
|
1354
|
+
if (!(dst & SLJIT_MEM))
|
|
1355
|
+
return SLJIT_SUCCESS;
|
|
1356
|
+
|
|
1357
|
+
return emit_op_mem(compiler, input_flags, dst_r, dst, dstw, TMP_REG1);
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
|
|
1361
|
+
{
|
|
1362
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1363
|
+
sljit_s32 int_op = op & SLJIT_32;
|
|
1364
|
+
#endif
|
|
1365
|
+
|
|
1366
|
+
CHECK_ERROR();
|
|
1367
|
+
CHECK(check_sljit_emit_op0(compiler, op));
|
|
1368
|
+
|
|
1369
|
+
op = GET_OPCODE(op);
|
|
1370
|
+
switch (op) {
|
|
1371
|
+
case SLJIT_BREAKPOINT:
|
|
1372
|
+
case SLJIT_NOP:
|
|
1373
|
+
return push_inst(compiler, NOP);
|
|
1374
|
+
case SLJIT_LMUL_UW:
|
|
1375
|
+
case SLJIT_LMUL_SW:
|
|
1376
|
+
FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
|
|
1377
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1378
|
+
FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
|
|
1379
|
+
return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHDU : MULHD) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
|
|
1380
|
+
#else
|
|
1381
|
+
FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
|
|
1382
|
+
return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
|
|
1383
|
+
#endif
|
|
1384
|
+
case SLJIT_DIVMOD_UW:
|
|
1385
|
+
case SLJIT_DIVMOD_SW:
|
|
1386
|
+
FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
|
|
1387
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1388
|
+
FAIL_IF(push_inst(compiler, (int_op ? (op == SLJIT_DIVMOD_UW ? DIVWU : DIVW) : (op == SLJIT_DIVMOD_UW ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));
|
|
1389
|
+
FAIL_IF(push_inst(compiler, (int_op ? MULLW : MULLD) | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
|
|
1390
|
+
#else
|
|
1391
|
+
FAIL_IF(push_inst(compiler, (op == SLJIT_DIVMOD_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));
|
|
1392
|
+
FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
|
|
1393
|
+
#endif
|
|
1394
|
+
return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1));
|
|
1395
|
+
case SLJIT_DIV_UW:
|
|
1396
|
+
case SLJIT_DIV_SW:
|
|
1397
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1398
|
+
return push_inst(compiler, (int_op ? (op == SLJIT_DIV_UW ? DIVWU : DIVW) : (op == SLJIT_DIV_UW ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));
|
|
1399
|
+
#else
|
|
1400
|
+
return push_inst(compiler, (op == SLJIT_DIV_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));
|
|
1401
|
+
#endif
|
|
1402
|
+
case SLJIT_ENDBR:
|
|
1403
|
+
case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
|
|
1404
|
+
return SLJIT_SUCCESS;
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
return SLJIT_SUCCESS;
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op,
|
|
1411
|
+
sljit_s32 dst, sljit_sw dstw,
|
|
1412
|
+
sljit_s32 src, sljit_sw srcw)
|
|
1413
|
+
{
|
|
1414
|
+
sljit_s32 mem, offs_reg, inp_flags;
|
|
1415
|
+
sljit_sw memw;
|
|
1416
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1417
|
+
sljit_s32 is_32 = op & SLJIT_32;
|
|
1418
|
+
|
|
1419
|
+
op = GET_OPCODE(op);
|
|
1420
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
1421
|
+
|
|
1422
|
+
if (!((dst | src) & SLJIT_MEM)) {
|
|
1423
|
+
/* Both are registers. */
|
|
1424
|
+
if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) {
|
|
1425
|
+
if (src == dst) {
|
|
1426
|
+
FAIL_IF(push_inst(compiler, RLWIMI | S(dst) | A(dst) | RLWI_SH(16) | RLWI_MBE(8, 15)));
|
|
1427
|
+
FAIL_IF(push_inst(compiler, RLWINM | S(dst) | A(dst) | RLWI_SH(24) | RLWI_MBE(16, 31)));
|
|
1428
|
+
} else {
|
|
1429
|
+
FAIL_IF(push_inst(compiler, RLWINM | S(src) | A(dst) | RLWI_SH(8) | RLWI_MBE(16, 23)));
|
|
1430
|
+
FAIL_IF(push_inst(compiler, RLWIMI | S(src) | A(dst) | RLWI_SH(24) | RLWI_MBE(24, 31)));
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
if (op == SLJIT_REV_U16)
|
|
1434
|
+
return SLJIT_SUCCESS;
|
|
1435
|
+
return push_inst(compiler, EXTSH | S(dst) | A(dst));
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1439
|
+
if (!is_32) {
|
|
1440
|
+
#if defined(_ARCH_PWR10) && _ARCH_PWR10
|
|
1441
|
+
return push_inst(compiler, BRD | S(src) | A(dst));
|
|
1442
|
+
#else /* !POWER10 */
|
|
1443
|
+
FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET_HI)));
|
|
1444
|
+
FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(32) | RLDI_MB(32)));
|
|
1445
|
+
FAIL_IF(push_inst(compiler, STWBRX | S(src) | A(SLJIT_SP) | B(TMP_REG2)));
|
|
1446
|
+
FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET_LO)));
|
|
1447
|
+
FAIL_IF(push_inst(compiler, STWBRX | S(TMP_REG1) | A(SLJIT_SP) | B(TMP_REG2)));
|
|
1448
|
+
return push_inst(compiler, LD | D(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET);
|
|
1449
|
+
#endif /* POWER10 */
|
|
1450
|
+
}
|
|
1451
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
1452
|
+
|
|
1453
|
+
FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET)));
|
|
1454
|
+
FAIL_IF(push_inst(compiler, STWBRX | S(src) | A(SLJIT_SP) | B(TMP_REG2)));
|
|
1455
|
+
FAIL_IF(push_inst(compiler, LWZ | D(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
|
1456
|
+
|
|
1457
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1458
|
+
if (op == SLJIT_REV_S32)
|
|
1459
|
+
return push_inst(compiler, EXTSW | S(dst) | A(dst));
|
|
1460
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
1461
|
+
return SLJIT_SUCCESS;
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
mem = src;
|
|
1465
|
+
memw = srcw;
|
|
1466
|
+
|
|
1467
|
+
if (dst & SLJIT_MEM) {
|
|
1468
|
+
mem = dst;
|
|
1469
|
+
memw = dstw;
|
|
1470
|
+
|
|
1471
|
+
if (src & SLJIT_MEM) {
|
|
1472
|
+
inp_flags = HALF_DATA | LOAD_DATA;
|
|
1473
|
+
|
|
1474
|
+
if (op != SLJIT_REV_U16 && op != SLJIT_REV_S16) {
|
|
1475
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1476
|
+
inp_flags = (is_32 ? INT_DATA : WORD_DATA) | LOAD_DATA;
|
|
1477
|
+
#else /* !SLJIT_CONFIG_PPC_64 */
|
|
1478
|
+
inp_flags = WORD_DATA | LOAD_DATA;
|
|
1479
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG1, src, srcw, TMP_REG2));
|
|
1483
|
+
src = TMP_REG1;
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
|
|
1488
|
+
offs_reg = OFFS_REG(mem);
|
|
1489
|
+
mem &= REG_MASK;
|
|
1490
|
+
memw &= 0x3;
|
|
1491
|
+
|
|
1492
|
+
if (memw != 0) {
|
|
1493
|
+
FAIL_IF(push_inst(compiler, SLWI_W(memw) | S(offs_reg) | A(TMP_REG2)));
|
|
1494
|
+
offs_reg = TMP_REG2;
|
|
1495
|
+
}
|
|
1496
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1497
|
+
} else if (memw > 0x7fff7fffl || memw < -0x80000000l) {
|
|
1498
|
+
FAIL_IF(load_immediate(compiler, TMP_REG2, memw));
|
|
1499
|
+
offs_reg = TMP_REG2;
|
|
1500
|
+
mem &= REG_MASK;
|
|
1501
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
1502
|
+
} else {
|
|
1503
|
+
FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(mem & REG_MASK) | IMM(memw)));
|
|
1504
|
+
if (memw > SIMM_MAX || memw < SIMM_MIN)
|
|
1505
|
+
FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(TMP_REG2) | IMM((memw + 0x8000) >> 16)));
|
|
1506
|
+
|
|
1507
|
+
mem = 0;
|
|
1508
|
+
offs_reg = TMP_REG2;
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) {
|
|
1512
|
+
if (dst & SLJIT_MEM)
|
|
1513
|
+
return push_inst(compiler, STHBRX | S(src) | A(mem) | B(offs_reg));
|
|
1514
|
+
|
|
1515
|
+
FAIL_IF(push_inst(compiler, LHBRX | S(dst) | A(mem) | B(offs_reg)));
|
|
1516
|
+
|
|
1517
|
+
if (op == SLJIT_REV_U16)
|
|
1518
|
+
return SLJIT_SUCCESS;
|
|
1519
|
+
return push_inst(compiler, EXTSH | S(dst) | A(dst));
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1523
|
+
if (!is_32) {
|
|
1524
|
+
if (dst & SLJIT_MEM) {
|
|
1525
|
+
#if defined(_ARCH_PWR7) && _ARCH_PWR7
|
|
1526
|
+
return push_inst(compiler, STDBRX | S(src) | A(mem) | B(offs_reg));
|
|
1527
|
+
#else /* !POWER7 */
|
|
1528
|
+
#if defined(SLJIT_LITTLE_ENDIAN) && SLJIT_LITTLE_ENDIAN
|
|
1529
|
+
FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(32) | RLDI_MB(32)));
|
|
1530
|
+
FAIL_IF(push_inst(compiler, STWBRX | S(TMP_REG1) | A(mem) | B(offs_reg)));
|
|
1531
|
+
FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(offs_reg) | IMM(SSIZE_OF(s32))));
|
|
1532
|
+
return push_inst(compiler, STWBRX | S(src) | A(mem) | B(TMP_REG2));
|
|
1533
|
+
#else /* !SLJIT_LITTLE_ENDIAN */
|
|
1534
|
+
FAIL_IF(push_inst(compiler, STWBRX | S(src) | A(mem) | B(offs_reg)));
|
|
1535
|
+
FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(32) | RLDI_MB(32)));
|
|
1536
|
+
FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(offs_reg) | IMM(SSIZE_OF(s32))));
|
|
1537
|
+
return push_inst(compiler, STWBRX | S(TMP_REG1) | A(mem) | B(TMP_REG2));
|
|
1538
|
+
#endif /* SLJIT_LITTLE_ENDIAN */
|
|
1539
|
+
#endif /* POWER7 */
|
|
1540
|
+
}
|
|
1541
|
+
#if defined(_ARCH_PWR7) && _ARCH_PWR7
|
|
1542
|
+
return push_inst(compiler, LDBRX | S(dst) | A(mem) | B(offs_reg));
|
|
1543
|
+
#else /* !POWER7 */
|
|
1544
|
+
FAIL_IF(push_inst(compiler, LWBRX | LWBRX_FIRST_REG | A(mem) | B(offs_reg)));
|
|
1545
|
+
FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(offs_reg) | IMM(SSIZE_OF(s32))));
|
|
1546
|
+
FAIL_IF(push_inst(compiler, LWBRX | LWBRX_SECOND_REG | A(mem) | B(TMP_REG2)));
|
|
1547
|
+
return push_inst(compiler, RLDIMI | S(TMP_REG1) | A(dst) | RLDI_SH(32) | RLDI_MB(0));
|
|
1548
|
+
#endif /* POWER7 */
|
|
1549
|
+
}
|
|
1550
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
1551
|
+
|
|
1552
|
+
if (dst & SLJIT_MEM)
|
|
1553
|
+
return push_inst(compiler, STWBRX | S(src) | A(mem) | B(offs_reg));
|
|
1554
|
+
|
|
1555
|
+
FAIL_IF(push_inst(compiler, LWBRX | S(dst) | A(mem) | B(offs_reg)));
|
|
1556
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1557
|
+
if (op == SLJIT_REV_S32)
|
|
1558
|
+
return push_inst(compiler, EXTSW | S(dst) | A(dst));
|
|
1559
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
1560
|
+
return SLJIT_SUCCESS;
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
#define EMIT_MOV(type, type_flags, type_cast) \
|
|
1564
|
+
emit_op(compiler, (src == SLJIT_IMM) ? SLJIT_MOV : type, flags | (type_flags), dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? type_cast srcw : srcw)
|
|
1565
|
+
|
|
1566
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
|
|
1567
|
+
sljit_s32 dst, sljit_sw dstw,
|
|
1568
|
+
sljit_s32 src, sljit_sw srcw)
|
|
1569
|
+
{
|
|
1570
|
+
sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
|
|
1571
|
+
sljit_s32 op_flags = GET_ALL_FLAGS(op);
|
|
1572
|
+
|
|
1573
|
+
CHECK_ERROR();
|
|
1574
|
+
CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
|
|
1575
|
+
ADJUST_LOCAL_OFFSET(dst, dstw);
|
|
1576
|
+
ADJUST_LOCAL_OFFSET(src, srcw);
|
|
1577
|
+
|
|
1578
|
+
op = GET_OPCODE(op);
|
|
1579
|
+
|
|
1580
|
+
if (GET_FLAG_TYPE(op_flags) == SLJIT_OVERFLOW)
|
|
1581
|
+
FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
|
|
1582
|
+
|
|
1583
|
+
if (op <= SLJIT_MOV_P && FAST_IS_REG(src) && src == dst) {
|
|
1584
|
+
if (!TYPE_CAST_NEEDED(op))
|
|
1585
|
+
return SLJIT_SUCCESS;
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1589
|
+
if (op_flags & SLJIT_32) {
|
|
1590
|
+
if (op <= SLJIT_MOV_P) {
|
|
1591
|
+
if (src & SLJIT_MEM) {
|
|
1592
|
+
if (op == SLJIT_MOV_S32)
|
|
1593
|
+
op = SLJIT_MOV_U32;
|
|
1594
|
+
}
|
|
1595
|
+
else if (src == SLJIT_IMM) {
|
|
1596
|
+
if (op == SLJIT_MOV_U32)
|
|
1597
|
+
op = SLJIT_MOV_S32;
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
else {
|
|
1601
|
+
/* Most operations expect sign extended arguments. */
|
|
1602
|
+
flags |= INT_DATA | SIGNED_DATA;
|
|
1603
|
+
if (HAS_FLAGS(op_flags))
|
|
1604
|
+
flags |= ALT_SIGN_EXT;
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
#endif
|
|
1608
|
+
|
|
1609
|
+
switch (op) {
|
|
1610
|
+
case SLJIT_MOV:
|
|
1611
|
+
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
|
1612
|
+
case SLJIT_MOV_U32:
|
|
1613
|
+
case SLJIT_MOV_S32:
|
|
1614
|
+
case SLJIT_MOV32:
|
|
1615
|
+
#endif
|
|
1616
|
+
case SLJIT_MOV_P:
|
|
1617
|
+
return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
|
|
1618
|
+
|
|
1619
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1620
|
+
case SLJIT_MOV_U32:
|
|
1621
|
+
return EMIT_MOV(SLJIT_MOV_U32, INT_DATA, (sljit_u32));
|
|
1622
|
+
|
|
1623
|
+
case SLJIT_MOV_S32:
|
|
1624
|
+
case SLJIT_MOV32:
|
|
1625
|
+
return EMIT_MOV(SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, (sljit_s32));
|
|
1626
|
+
#endif
|
|
1627
|
+
|
|
1628
|
+
case SLJIT_MOV_U8:
|
|
1629
|
+
return EMIT_MOV(SLJIT_MOV_U8, BYTE_DATA, (sljit_u8));
|
|
1630
|
+
|
|
1631
|
+
case SLJIT_MOV_S8:
|
|
1632
|
+
return EMIT_MOV(SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, (sljit_s8));
|
|
1633
|
+
|
|
1634
|
+
case SLJIT_MOV_U16:
|
|
1635
|
+
return EMIT_MOV(SLJIT_MOV_U16, HALF_DATA, (sljit_u16));
|
|
1636
|
+
|
|
1637
|
+
case SLJIT_MOV_S16:
|
|
1638
|
+
return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, (sljit_s16));
|
|
1639
|
+
|
|
1640
|
+
case SLJIT_CLZ:
|
|
1641
|
+
case SLJIT_CTZ:
|
|
1642
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1643
|
+
if (op_flags & SLJIT_32)
|
|
1644
|
+
flags |= ALT_FORM1;
|
|
1645
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
1646
|
+
return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
|
|
1647
|
+
case SLJIT_REV_U32:
|
|
1648
|
+
case SLJIT_REV_S32:
|
|
1649
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1650
|
+
op |= SLJIT_32;
|
|
1651
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
1652
|
+
/* fallthrough */
|
|
1653
|
+
case SLJIT_REV:
|
|
1654
|
+
case SLJIT_REV_U16:
|
|
1655
|
+
case SLJIT_REV_S16:
|
|
1656
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1657
|
+
op |= (op_flags & SLJIT_32);
|
|
1658
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
1659
|
+
return emit_rev(compiler, op, dst, dstw, src, srcw);
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
return SLJIT_SUCCESS;
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
#undef EMIT_MOV
|
|
1666
|
+
|
|
1667
|
+
/* Macros for checking different operand types / values. */
|
|
1668
|
+
#define TEST_SL_IMM(src, srcw) \
|
|
1669
|
+
((src) == SLJIT_IMM && (srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)
|
|
1670
|
+
#define TEST_UL_IMM(src, srcw) \
|
|
1671
|
+
((src) == SLJIT_IMM && !((srcw) & ~0xffff))
|
|
1672
|
+
#define TEST_UH_IMM(src, srcw) \
|
|
1673
|
+
((src) == SLJIT_IMM && !((srcw) & ~(sljit_sw)0xffff0000))
|
|
1674
|
+
|
|
1675
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1676
|
+
#define TEST_SH_IMM(src, srcw) \
|
|
1677
|
+
((src) == SLJIT_IMM && !((srcw) & 0xffff) && (srcw) <= 0x7fffffffl && (srcw) >= -0x80000000l)
|
|
1678
|
+
#define TEST_ADD_IMM(src, srcw) \
|
|
1679
|
+
((src) == SLJIT_IMM && (srcw) <= 0x7fff7fffl && (srcw) >= -0x80000000l)
|
|
1680
|
+
#define TEST_UI_IMM(src, srcw) \
|
|
1681
|
+
((src) == SLJIT_IMM && !((srcw) & ~0xffffffff))
|
|
1682
|
+
|
|
1683
|
+
#define TEST_ADD_FORM1(op) \
|
|
1684
|
+
(GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \
|
|
1685
|
+
|| (op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_32 | SLJIT_SET_Z | SLJIT_SET_CARRY))
|
|
1686
|
+
#define TEST_SUB_FORM2(op) \
|
|
1687
|
+
((GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) \
|
|
1688
|
+
|| (op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_32 | SLJIT_SET_Z))
|
|
1689
|
+
#define TEST_SUB_FORM3(op) \
|
|
1690
|
+
(GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \
|
|
1691
|
+
|| (op & (SLJIT_32 | SLJIT_SET_Z)) == (SLJIT_32 | SLJIT_SET_Z))
|
|
1692
|
+
|
|
1693
|
+
#else /* !SLJIT_CONFIG_PPC_64 */
|
|
1694
|
+
#define TEST_SH_IMM(src, srcw) \
|
|
1695
|
+
((src) == SLJIT_IMM && !((srcw) & 0xffff))
|
|
1696
|
+
#define TEST_ADD_IMM(src, srcw) \
|
|
1697
|
+
((src) == SLJIT_IMM)
|
|
1698
|
+
#define TEST_UI_IMM(src, srcw) \
|
|
1699
|
+
((src) == SLJIT_IMM)
|
|
1700
|
+
|
|
1701
|
+
#define TEST_ADD_FORM1(op) \
|
|
1702
|
+
(GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
|
|
1703
|
+
#define TEST_SUB_FORM2(op) \
|
|
1704
|
+
(GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL)
|
|
1705
|
+
#define TEST_SUB_FORM3(op) \
|
|
1706
|
+
(GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
|
|
1707
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
1708
|
+
|
|
1709
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
|
|
1710
|
+
sljit_s32 dst, sljit_sw dstw,
|
|
1711
|
+
sljit_s32 src1, sljit_sw src1w,
|
|
1712
|
+
sljit_s32 src2, sljit_sw src2w)
|
|
1713
|
+
{
|
|
1714
|
+
sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
|
|
1715
|
+
|
|
1716
|
+
CHECK_ERROR();
|
|
1717
|
+
CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
|
|
1718
|
+
ADJUST_LOCAL_OFFSET(dst, dstw);
|
|
1719
|
+
ADJUST_LOCAL_OFFSET(src1, src1w);
|
|
1720
|
+
ADJUST_LOCAL_OFFSET(src2, src2w);
|
|
1721
|
+
|
|
1722
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1723
|
+
if (op & SLJIT_32) {
|
|
1724
|
+
/* Most operations expect sign extended arguments. */
|
|
1725
|
+
flags |= INT_DATA | SIGNED_DATA;
|
|
1726
|
+
if (src1 == SLJIT_IMM)
|
|
1727
|
+
src1w = (sljit_s32)(src1w);
|
|
1728
|
+
if (src2 == SLJIT_IMM)
|
|
1729
|
+
src2w = (sljit_s32)(src2w);
|
|
1730
|
+
if (HAS_FLAGS(op))
|
|
1731
|
+
flags |= ALT_SIGN_EXT;
|
|
1732
|
+
}
|
|
1733
|
+
#endif
|
|
1734
|
+
if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
|
|
1735
|
+
FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
|
|
1736
|
+
|
|
1737
|
+
switch (GET_OPCODE(op)) {
|
|
1738
|
+
case SLJIT_ADD:
|
|
1739
|
+
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
|
|
1740
|
+
|
|
1741
|
+
if (TEST_ADD_FORM1(op))
|
|
1742
|
+
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
|
|
1743
|
+
|
|
1744
|
+
if (!HAS_FLAGS(op) && (src1 == SLJIT_IMM || src2 == SLJIT_IMM)) {
|
|
1745
|
+
if (TEST_SL_IMM(src2, src2w)) {
|
|
1746
|
+
compiler->imm = (sljit_ins)src2w & 0xffff;
|
|
1747
|
+
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
|
|
1748
|
+
}
|
|
1749
|
+
if (TEST_SL_IMM(src1, src1w)) {
|
|
1750
|
+
compiler->imm = (sljit_ins)src1w & 0xffff;
|
|
1751
|
+
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
|
|
1752
|
+
}
|
|
1753
|
+
if (TEST_SH_IMM(src2, src2w)) {
|
|
1754
|
+
compiler->imm = (sljit_ins)(src2w >> 16) & 0xffff;
|
|
1755
|
+
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
|
|
1756
|
+
}
|
|
1757
|
+
if (TEST_SH_IMM(src1, src1w)) {
|
|
1758
|
+
compiler->imm = (sljit_ins)(src1w >> 16) & 0xffff;
|
|
1759
|
+
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
|
|
1760
|
+
}
|
|
1761
|
+
/* Range between -1 and -32768 is covered above. */
|
|
1762
|
+
if (TEST_ADD_IMM(src2, src2w)) {
|
|
1763
|
+
compiler->imm = (sljit_ins)src2w & 0xffffffff;
|
|
1764
|
+
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
|
|
1765
|
+
}
|
|
1766
|
+
if (TEST_ADD_IMM(src1, src1w)) {
|
|
1767
|
+
compiler->imm = (sljit_ins)src1w & 0xffffffff;
|
|
1768
|
+
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1773
|
+
if ((op & (SLJIT_32 | SLJIT_SET_Z)) == (SLJIT_32 | SLJIT_SET_Z)) {
|
|
1774
|
+
if (TEST_SL_IMM(src2, src2w)) {
|
|
1775
|
+
compiler->imm = (sljit_ins)src2w & 0xffff;
|
|
1776
|
+
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src1, src1w, TMP_REG2, 0);
|
|
1777
|
+
}
|
|
1778
|
+
if (TEST_SL_IMM(src1, src1w)) {
|
|
1779
|
+
compiler->imm = (sljit_ins)src1w & 0xffff;
|
|
1780
|
+
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src2, src2w, TMP_REG2, 0);
|
|
1781
|
+
}
|
|
1782
|
+
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
|
|
1783
|
+
}
|
|
1784
|
+
#endif
|
|
1785
|
+
if (HAS_FLAGS(op)) {
|
|
1786
|
+
if (TEST_SL_IMM(src2, src2w)) {
|
|
1787
|
+
compiler->imm = (sljit_ins)src2w & 0xffff;
|
|
1788
|
+
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
|
|
1789
|
+
}
|
|
1790
|
+
if (TEST_SL_IMM(src1, src1w)) {
|
|
1791
|
+
compiler->imm = (sljit_ins)src1w & 0xffff;
|
|
1792
|
+
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
return emit_op(compiler, SLJIT_ADD, flags | ((GET_FLAG_TYPE(op) == SLJIT_CARRY) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
|
|
1796
|
+
|
|
1797
|
+
case SLJIT_ADDC:
|
|
1798
|
+
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
|
|
1799
|
+
return emit_op(compiler, SLJIT_ADDC, flags, dst, dstw, src1, src1w, src2, src2w);
|
|
1800
|
+
|
|
1801
|
+
case SLJIT_SUB:
|
|
1802
|
+
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
|
|
1803
|
+
|
|
1804
|
+
if (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_LESS_EQUAL) {
|
|
1805
|
+
if (dst == TMP_REG1) {
|
|
1806
|
+
if (TEST_UL_IMM(src2, src2w)) {
|
|
1807
|
+
compiler->imm = (sljit_ins)src2w & 0xffff;
|
|
1808
|
+
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
|
|
1809
|
+
}
|
|
1810
|
+
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1813
|
+
if (src2 == SLJIT_IMM && src2w >= 0 && src2w <= (SIMM_MAX + 1)) {
|
|
1814
|
+
compiler->imm = (sljit_ins)src2w;
|
|
1815
|
+
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
|
|
1816
|
+
}
|
|
1817
|
+
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
if (dst == TMP_REG1 && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
|
|
1821
|
+
if (TEST_SL_IMM(src2, src2w)) {
|
|
1822
|
+
compiler->imm = (sljit_ins)src2w & 0xffff;
|
|
1823
|
+
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
|
|
1824
|
+
}
|
|
1825
|
+
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, src2, src2w);
|
|
1826
|
+
}
|
|
1827
|
+
|
|
1828
|
+
if (TEST_SUB_FORM2(op)) {
|
|
1829
|
+
if (src2 == SLJIT_IMM && src2w >= -SIMM_MAX && src2w <= SIMM_MAX) {
|
|
1830
|
+
compiler->imm = (sljit_ins)src2w & 0xffff;
|
|
1831
|
+
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
|
|
1832
|
+
}
|
|
1833
|
+
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1836
|
+
if (TEST_SUB_FORM3(op))
|
|
1837
|
+
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
|
|
1838
|
+
|
|
1839
|
+
if (TEST_SL_IMM(src2, -src2w)) {
|
|
1840
|
+
compiler->imm = (sljit_ins)(-src2w) & 0xffff;
|
|
1841
|
+
return emit_op(compiler, SLJIT_ADD, flags | (!HAS_FLAGS(op) ? ALT_FORM2 : ALT_FORM3), dst, dstw, src1, src1w, TMP_REG2, 0);
|
|
1842
|
+
}
|
|
1843
|
+
|
|
1844
|
+
if (TEST_SL_IMM(src1, src1w) && !(op & SLJIT_SET_Z)) {
|
|
1845
|
+
compiler->imm = (sljit_ins)src1w & 0xffff;
|
|
1846
|
+
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
if (!HAS_FLAGS(op)) {
|
|
1850
|
+
if (TEST_SH_IMM(src2, -src2w)) {
|
|
1851
|
+
compiler->imm = (sljit_ins)((-src2w) >> 16) & 0xffff;
|
|
1852
|
+
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
|
|
1853
|
+
}
|
|
1854
|
+
/* Range between -1 and -32768 is covered above. */
|
|
1855
|
+
if (TEST_ADD_IMM(src2, -src2w)) {
|
|
1856
|
+
compiler->imm = (sljit_ins)-src2w;
|
|
1857
|
+
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
/* We know ALT_SIGN_EXT is set if it is an SLJIT_32 on 64 bit systems. */
|
|
1862
|
+
return emit_op(compiler, SLJIT_SUB, flags | ((GET_FLAG_TYPE(op) == SLJIT_CARRY) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
|
|
1863
|
+
|
|
1864
|
+
case SLJIT_SUBC:
|
|
1865
|
+
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
|
|
1866
|
+
return emit_op(compiler, SLJIT_SUBC, flags, dst, dstw, src1, src1w, src2, src2w);
|
|
1867
|
+
|
|
1868
|
+
case SLJIT_MUL:
|
|
1869
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1870
|
+
if (op & SLJIT_32)
|
|
1871
|
+
flags |= ALT_FORM2;
|
|
1872
|
+
#endif
|
|
1873
|
+
if (!HAS_FLAGS(op)) {
|
|
1874
|
+
if (TEST_SL_IMM(src2, src2w)) {
|
|
1875
|
+
compiler->imm = (sljit_ins)src2w & 0xffff;
|
|
1876
|
+
return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
|
|
1877
|
+
}
|
|
1878
|
+
if (TEST_SL_IMM(src1, src1w)) {
|
|
1879
|
+
compiler->imm = (sljit_ins)src1w & 0xffff;
|
|
1880
|
+
return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
else
|
|
1884
|
+
FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
|
|
1885
|
+
return emit_op(compiler, SLJIT_MUL, flags, dst, dstw, src1, src1w, src2, src2w);
|
|
1886
|
+
|
|
1887
|
+
case SLJIT_XOR:
|
|
1888
|
+
if (src2 == SLJIT_IMM && src2w == -1) {
|
|
1889
|
+
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM4, dst, dstw, TMP_REG1, 0, src1, src1w);
|
|
1890
|
+
}
|
|
1891
|
+
if (src1 == SLJIT_IMM && src1w == -1) {
|
|
1892
|
+
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM4, dst, dstw, TMP_REG1, 0, src2, src2w);
|
|
1893
|
+
}
|
|
1894
|
+
/* fallthrough */
|
|
1895
|
+
case SLJIT_AND:
|
|
1896
|
+
case SLJIT_OR:
|
|
1897
|
+
/* Commutative unsigned operations. */
|
|
1898
|
+
if (!HAS_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) {
|
|
1899
|
+
if (TEST_UL_IMM(src2, src2w)) {
|
|
1900
|
+
compiler->imm = (sljit_ins)src2w;
|
|
1901
|
+
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
|
|
1902
|
+
}
|
|
1903
|
+
if (TEST_UL_IMM(src1, src1w)) {
|
|
1904
|
+
compiler->imm = (sljit_ins)src1w;
|
|
1905
|
+
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
|
|
1906
|
+
}
|
|
1907
|
+
if (TEST_UH_IMM(src2, src2w)) {
|
|
1908
|
+
compiler->imm = (sljit_ins)(src2w >> 16) & 0xffff;
|
|
1909
|
+
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
|
|
1910
|
+
}
|
|
1911
|
+
if (TEST_UH_IMM(src1, src1w)) {
|
|
1912
|
+
compiler->imm = (sljit_ins)(src1w >> 16) & 0xffff;
|
|
1913
|
+
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
if (!HAS_FLAGS(op) && GET_OPCODE(op) != SLJIT_AND) {
|
|
1917
|
+
/* Unlike or and xor, the and resets unwanted bits as well. */
|
|
1918
|
+
if (TEST_UI_IMM(src2, src2w)) {
|
|
1919
|
+
compiler->imm = (sljit_ins)src2w;
|
|
1920
|
+
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
|
|
1921
|
+
}
|
|
1922
|
+
if (TEST_UI_IMM(src1, src1w)) {
|
|
1923
|
+
compiler->imm = (sljit_ins)src1w;
|
|
1924
|
+
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1927
|
+
return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
|
|
1928
|
+
|
|
1929
|
+
case SLJIT_SHL:
|
|
1930
|
+
case SLJIT_MSHL:
|
|
1931
|
+
case SLJIT_LSHR:
|
|
1932
|
+
case SLJIT_MLSHR:
|
|
1933
|
+
case SLJIT_ASHR:
|
|
1934
|
+
case SLJIT_MASHR:
|
|
1935
|
+
case SLJIT_ROTL:
|
|
1936
|
+
case SLJIT_ROTR:
|
|
1937
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1938
|
+
if (op & SLJIT_32)
|
|
1939
|
+
flags |= ALT_FORM2;
|
|
1940
|
+
#endif
|
|
1941
|
+
if (src2 == SLJIT_IMM) {
|
|
1942
|
+
compiler->imm = (sljit_ins)src2w;
|
|
1943
|
+
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
|
|
1944
|
+
}
|
|
1945
|
+
return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
return SLJIT_SUCCESS;
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1951
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
|
|
1952
|
+
sljit_s32 src1, sljit_sw src1w,
|
|
1953
|
+
sljit_s32 src2, sljit_sw src2w)
|
|
1954
|
+
{
|
|
1955
|
+
CHECK_ERROR();
|
|
1956
|
+
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
|
1957
|
+
|
|
1958
|
+
SLJIT_SKIP_CHECKS(compiler);
|
|
1959
|
+
return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);
|
|
1960
|
+
}
|
|
1961
|
+
|
|
1962
|
+
#undef TEST_ADD_FORM1
|
|
1963
|
+
#undef TEST_SUB_FORM2
|
|
1964
|
+
#undef TEST_SUB_FORM3
|
|
1965
|
+
|
|
1966
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,
|
|
1967
|
+
sljit_s32 dst_reg,
|
|
1968
|
+
sljit_s32 src1, sljit_sw src1w,
|
|
1969
|
+
sljit_s32 src2, sljit_sw src2w)
|
|
1970
|
+
{
|
|
1971
|
+
CHECK_ERROR();
|
|
1972
|
+
CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));
|
|
1973
|
+
|
|
1974
|
+
switch (GET_OPCODE(op)) {
|
|
1975
|
+
case SLJIT_MULADD:
|
|
1976
|
+
SLJIT_SKIP_CHECKS(compiler);
|
|
1977
|
+
FAIL_IF(sljit_emit_op2(compiler, SLJIT_MUL | (op & SLJIT_32), TMP_REG2, 0, src1, src1w, src2, src2w));
|
|
1978
|
+
return push_inst(compiler, ADD | D(dst_reg) | A(dst_reg) | B(TMP_REG2));
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
return SLJIT_SUCCESS;
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1984
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,
|
|
1985
|
+
sljit_s32 dst_reg,
|
|
1986
|
+
sljit_s32 src1_reg,
|
|
1987
|
+
sljit_s32 src2_reg,
|
|
1988
|
+
sljit_s32 src3, sljit_sw src3w)
|
|
1989
|
+
{
|
|
1990
|
+
sljit_s32 is_right;
|
|
1991
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
1992
|
+
sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
|
|
1993
|
+
sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64;
|
|
1994
|
+
#else /* !SLJIT_CONFIG_PPC_64 */
|
|
1995
|
+
sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;
|
|
1996
|
+
sljit_sw bit_length = 32;
|
|
1997
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
1998
|
+
|
|
1999
|
+
CHECK_ERROR();
|
|
2000
|
+
CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));
|
|
2001
|
+
|
|
2002
|
+
is_right = (GET_OPCODE(op) == SLJIT_LSHR || GET_OPCODE(op) == SLJIT_MLSHR);
|
|
2003
|
+
|
|
2004
|
+
if (src1_reg == src2_reg) {
|
|
2005
|
+
SLJIT_SKIP_CHECKS(compiler);
|
|
2006
|
+
return sljit_emit_op2(compiler, (is_right ? SLJIT_ROTR : SLJIT_ROTL) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2009
|
+
ADJUST_LOCAL_OFFSET(src3, src3w);
|
|
2010
|
+
|
|
2011
|
+
if (src3 == SLJIT_IMM) {
|
|
2012
|
+
src3w &= bit_length - 1;
|
|
2013
|
+
|
|
2014
|
+
if (src3w == 0)
|
|
2015
|
+
return SLJIT_SUCCESS;
|
|
2016
|
+
|
|
2017
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
2018
|
+
if (!(op & SLJIT_32)) {
|
|
2019
|
+
if (is_right) {
|
|
2020
|
+
FAIL_IF(push_inst(compiler, SRDI(src3w) | S(src1_reg) | A(dst_reg)));
|
|
2021
|
+
return push_inst(compiler, RLDIMI | S(src2_reg) | A(dst_reg) | RLDI_SH(64 - src3w) | RLDI_MB(0));
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
FAIL_IF(push_inst(compiler, SLDI(src3w) | S(src1_reg) | A(dst_reg)));
|
|
2025
|
+
/* Computes SRDI(64 - src2w). */
|
|
2026
|
+
FAIL_IF(push_inst(compiler, RLDICL | S(src2_reg) | A(TMP_REG1) | RLDI_SH(src3w) | RLDI_MB(64 - src3w)));
|
|
2027
|
+
return push_inst(compiler, OR | S(dst_reg) | A(dst_reg) | B(TMP_REG1));
|
|
2028
|
+
}
|
|
2029
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
2030
|
+
|
|
2031
|
+
if (is_right) {
|
|
2032
|
+
FAIL_IF(push_inst(compiler, SRWI(src3w) | S(src1_reg) | A(dst_reg)));
|
|
2033
|
+
return push_inst(compiler, RLWIMI | S(src2_reg) | A(dst_reg) | RLWI_SH(32 - src3w) | RLWI_MBE(0, src3w - 1));
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
FAIL_IF(push_inst(compiler, SLWI(src3w) | S(src1_reg) | A(dst_reg)));
|
|
2037
|
+
return push_inst(compiler, RLWIMI | S(src2_reg) | A(dst_reg) | RLWI_SH(src3w) | RLWI_MBE(32 - src3w, 31));
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
if (src3 & SLJIT_MEM) {
|
|
2041
|
+
FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG2, src3, src3w, TMP_REG2));
|
|
2042
|
+
src3 = TMP_REG2;
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2045
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
2046
|
+
if (!(op & SLJIT_32)) {
|
|
2047
|
+
if (GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR || dst_reg == src3) {
|
|
2048
|
+
FAIL_IF(push_inst(compiler, ANDI | S(src3) | A(TMP_REG2) | 0x3f));
|
|
2049
|
+
src3 = TMP_REG2;
|
|
2050
|
+
}
|
|
2051
|
+
|
|
2052
|
+
FAIL_IF(push_inst(compiler, (is_right ? SRD : SLD) | S(src1_reg) | A(dst_reg) | B(src3)));
|
|
2053
|
+
FAIL_IF(push_inst(compiler, (is_right ? SLDI(1) : SRDI(1)) | S(src2_reg) | A(TMP_REG1)));
|
|
2054
|
+
FAIL_IF(push_inst(compiler, XORI | S(src3) | A(TMP_REG2) | 0x3f));
|
|
2055
|
+
FAIL_IF(push_inst(compiler, (is_right ? SLD : SRD) | S(TMP_REG1) | A(TMP_REG1) | B(TMP_REG2)));
|
|
2056
|
+
return push_inst(compiler, OR | S(dst_reg) | A(dst_reg) | B(TMP_REG1));
|
|
2057
|
+
}
|
|
2058
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
2059
|
+
|
|
2060
|
+
if (GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR || dst_reg == src3) {
|
|
2061
|
+
FAIL_IF(push_inst(compiler, ANDI | S(src3) | A(TMP_REG2) | 0x1f));
|
|
2062
|
+
src3 = TMP_REG2;
|
|
2063
|
+
}
|
|
2064
|
+
|
|
2065
|
+
FAIL_IF(push_inst(compiler, (is_right ? SRW : SLW) | S(src1_reg) | A(dst_reg) | B(src3)));
|
|
2066
|
+
FAIL_IF(push_inst(compiler, (is_right ? SLWI(1) : SRWI(1)) | S(src2_reg) | A(TMP_REG1)));
|
|
2067
|
+
FAIL_IF(push_inst(compiler, XORI | S(src3) | A(TMP_REG2) | 0x1f));
|
|
2068
|
+
FAIL_IF(push_inst(compiler, (is_right ? SLW : SRW) | S(TMP_REG1) | A(TMP_REG1) | B(TMP_REG2)));
|
|
2069
|
+
return push_inst(compiler, OR | S(dst_reg) | A(dst_reg) | B(TMP_REG1));
|
|
2070
|
+
}
|
|
2071
|
+
|
|
2072
|
+
static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
|
|
2073
|
+
sljit_s32 src, sljit_sw srcw)
|
|
2074
|
+
{
|
|
2075
|
+
if (!(src & OFFS_REG_MASK)) {
|
|
2076
|
+
if (srcw == 0 && (src & REG_MASK))
|
|
2077
|
+
return push_inst(compiler, DCBT | A(0) | B(src & REG_MASK));
|
|
2078
|
+
|
|
2079
|
+
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
|
|
2080
|
+
/* Works with SLJIT_MEM0() case as well. */
|
|
2081
|
+
return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));
|
|
2082
|
+
}
|
|
2083
|
+
|
|
2084
|
+
srcw &= 0x3;
|
|
2085
|
+
|
|
2086
|
+
if (srcw == 0)
|
|
2087
|
+
return push_inst(compiler, DCBT | A(src & REG_MASK) | B(OFFS_REG(src)));
|
|
2088
|
+
|
|
2089
|
+
FAIL_IF(push_inst(compiler, SLWI_W(srcw) | S(OFFS_REG(src)) | A(TMP_REG1)));
|
|
2090
|
+
return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));
|
|
2091
|
+
}
|
|
2092
|
+
|
|
2093
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
|
|
2094
|
+
sljit_s32 src, sljit_sw srcw)
|
|
2095
|
+
{
|
|
2096
|
+
CHECK_ERROR();
|
|
2097
|
+
CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
|
|
2098
|
+
ADJUST_LOCAL_OFFSET(src, srcw);
|
|
2099
|
+
|
|
2100
|
+
switch (op) {
|
|
2101
|
+
case SLJIT_FAST_RETURN:
|
|
2102
|
+
if (FAST_IS_REG(src))
|
|
2103
|
+
FAIL_IF(push_inst(compiler, MTLR | S(src)));
|
|
2104
|
+
else {
|
|
2105
|
+
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG2));
|
|
2106
|
+
FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2)));
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
return push_inst(compiler, BLR);
|
|
2110
|
+
case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
|
|
2111
|
+
return SLJIT_SUCCESS;
|
|
2112
|
+
case SLJIT_PREFETCH_L1:
|
|
2113
|
+
case SLJIT_PREFETCH_L2:
|
|
2114
|
+
case SLJIT_PREFETCH_L3:
|
|
2115
|
+
case SLJIT_PREFETCH_ONCE:
|
|
2116
|
+
return emit_prefetch(compiler, src, srcw);
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2119
|
+
return SLJIT_SUCCESS;
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2122
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,
|
|
2123
|
+
sljit_s32 dst, sljit_sw dstw)
|
|
2124
|
+
{
|
|
2125
|
+
sljit_s32 dst_r;
|
|
2126
|
+
|
|
2127
|
+
CHECK_ERROR();
|
|
2128
|
+
CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));
|
|
2129
|
+
ADJUST_LOCAL_OFFSET(dst, dstw);
|
|
2130
|
+
|
|
2131
|
+
switch (op) {
|
|
2132
|
+
case SLJIT_FAST_ENTER:
|
|
2133
|
+
if (FAST_IS_REG(dst))
|
|
2134
|
+
return push_inst(compiler, MFLR | D(dst));
|
|
2135
|
+
|
|
2136
|
+
FAIL_IF(push_inst(compiler, MFLR | D(TMP_REG1)));
|
|
2137
|
+
break;
|
|
2138
|
+
case SLJIT_GET_RETURN_ADDRESS:
|
|
2139
|
+
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
|
|
2140
|
+
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size + LR_SAVE_OFFSET, TMP_REG2));
|
|
2141
|
+
break;
|
|
2142
|
+
}
|
|
2143
|
+
|
|
2144
|
+
if (dst & SLJIT_MEM)
|
|
2145
|
+
return emit_op_mem(compiler, WORD_DATA, TMP_REG1, dst, dstw, TMP_REG2);
|
|
2146
|
+
|
|
2147
|
+
return SLJIT_SUCCESS;
|
|
2148
|
+
}
|
|
2149
|
+
|
|
2150
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)
|
|
2151
|
+
{
|
|
2152
|
+
CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));
|
|
2153
|
+
|
|
2154
|
+
if (type == SLJIT_GP_REGISTER)
|
|
2155
|
+
return reg_map[reg];
|
|
2156
|
+
|
|
2157
|
+
if (type != SLJIT_FLOAT_REGISTER)
|
|
2158
|
+
return -1;
|
|
2159
|
+
|
|
2160
|
+
return freg_map[reg];
|
|
2161
|
+
}
|
|
2162
|
+
|
|
2163
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
|
|
2164
|
+
void *instruction, sljit_u32 size)
|
|
2165
|
+
{
|
|
2166
|
+
SLJIT_UNUSED_ARG(size);
|
|
2167
|
+
|
|
2168
|
+
CHECK_ERROR();
|
|
2169
|
+
CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
|
|
2170
|
+
|
|
2171
|
+
return push_inst(compiler, *(sljit_ins*)instruction);
|
|
2172
|
+
}
|
|
2173
|
+
|
|
2174
|
+
/* --------------------------------------------------------------------- */
|
|
2175
|
+
/* Floating point operators */
|
|
2176
|
+
/* --------------------------------------------------------------------- */
|
|
2177
|
+
|
|
2178
|
+
#define SELECT_FOP(op, single, double) ((sljit_ins)((op & SLJIT_32) ? single : double))
|
|
2179
|
+
|
|
2180
|
+
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
|
|
2181
|
+
sljit_s32 dst, sljit_sw dstw,
|
|
2182
|
+
sljit_s32 src, sljit_sw srcw)
|
|
2183
|
+
{
|
|
2184
|
+
if (src & SLJIT_MEM) {
|
|
2185
|
+
/* We can ignore the temporary data store on the stack from caching point of view. */
|
|
2186
|
+
FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));
|
|
2187
|
+
src = TMP_FREG1;
|
|
2188
|
+
}
|
|
2189
|
+
|
|
2190
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
2191
|
+
op = GET_OPCODE(op);
|
|
2192
|
+
FAIL_IF(push_inst(compiler, (op == SLJIT_CONV_S32_FROM_F64 ? FCTIWZ : FCTIDZ) | FD(TMP_FREG1) | FB(src)));
|
|
2193
|
+
|
|
2194
|
+
if (op == SLJIT_CONV_SW_FROM_F64) {
|
|
2195
|
+
if (FAST_IS_REG(dst)) {
|
|
2196
|
+
FAIL_IF(push_inst(compiler, STFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
|
2197
|
+
return push_inst(compiler, LD | S(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET);
|
|
2198
|
+
}
|
|
2199
|
+
return emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, dst, dstw, TMP_REG1);
|
|
2200
|
+
}
|
|
2201
|
+
#else /* !SLJIT_CONFIG_PPC_64 */
|
|
2202
|
+
FAIL_IF(push_inst(compiler, FCTIWZ | FD(TMP_FREG1) | FB(src)));
|
|
2203
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
2204
|
+
|
|
2205
|
+
if (FAST_IS_REG(dst)) {
|
|
2206
|
+
FAIL_IF(load_immediate(compiler, TMP_REG1, TMP_MEM_OFFSET));
|
|
2207
|
+
FAIL_IF(push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(SLJIT_SP) | B(TMP_REG1)));
|
|
2208
|
+
return push_inst(compiler, LWZ | S(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET);
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2211
|
+
SLJIT_ASSERT(dst & SLJIT_MEM);
|
|
2212
|
+
|
|
2213
|
+
if (dst & OFFS_REG_MASK) {
|
|
2214
|
+
dstw &= 0x3;
|
|
2215
|
+
if (dstw) {
|
|
2216
|
+
FAIL_IF(push_inst(compiler, SLWI_W(dstw) | S(OFFS_REG(dst)) | A(TMP_REG1)));
|
|
2217
|
+
dstw = TMP_REG1;
|
|
2218
|
+
} else
|
|
2219
|
+
dstw = OFFS_REG(dst);
|
|
2220
|
+
}
|
|
2221
|
+
else {
|
|
2222
|
+
if ((dst & REG_MASK) && !dstw) {
|
|
2223
|
+
dstw = dst & REG_MASK;
|
|
2224
|
+
dst = 0;
|
|
2225
|
+
} else {
|
|
2226
|
+
/* This works regardless we have SLJIT_MEM1 or SLJIT_MEM0. */
|
|
2227
|
+
FAIL_IF(load_immediate(compiler, TMP_REG1, dstw));
|
|
2228
|
+
dstw = TMP_REG1;
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
return push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(dst & REG_MASK) | B(dstw));
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2235
|
+
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
|
|
2236
|
+
sljit_s32 src1, sljit_sw src1w,
|
|
2237
|
+
sljit_s32 src2, sljit_sw src2w)
|
|
2238
|
+
{
|
|
2239
|
+
if (src1 & SLJIT_MEM) {
|
|
2240
|
+
FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));
|
|
2241
|
+
src1 = TMP_FREG1;
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
if (src2 & SLJIT_MEM) {
|
|
2245
|
+
FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG2));
|
|
2246
|
+
src2 = TMP_FREG2;
|
|
2247
|
+
}
|
|
2248
|
+
|
|
2249
|
+
FAIL_IF(push_inst(compiler, FCMPU | CRD(4) | FA(src1) | FB(src2)));
|
|
2250
|
+
|
|
2251
|
+
switch (GET_FLAG_TYPE(op)) {
|
|
2252
|
+
case SLJIT_UNORDERED_OR_EQUAL:
|
|
2253
|
+
return push_inst(compiler, CROR | ((4 + 2) << 21) | ((4 + 2) << 16) | ((4 + 3) << 11));
|
|
2254
|
+
case SLJIT_UNORDERED_OR_LESS:
|
|
2255
|
+
return push_inst(compiler, CROR | ((4 + 0) << 21) | ((4 + 0) << 16) | ((4 + 3) << 11));
|
|
2256
|
+
case SLJIT_UNORDERED_OR_GREATER:
|
|
2257
|
+
return push_inst(compiler, CROR | ((4 + 1) << 21) | ((4 + 1) << 16) | ((4 + 3) << 11));
|
|
2258
|
+
}
|
|
2259
|
+
|
|
2260
|
+
return SLJIT_SUCCESS;
|
|
2261
|
+
}
|
|
2262
|
+
|
|
2263
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
|
|
2264
|
+
sljit_s32 dst, sljit_sw dstw,
|
|
2265
|
+
sljit_s32 src, sljit_sw srcw)
|
|
2266
|
+
{
|
|
2267
|
+
sljit_s32 dst_r;
|
|
2268
|
+
|
|
2269
|
+
CHECK_ERROR();
|
|
2270
|
+
|
|
2271
|
+
SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error);
|
|
2272
|
+
SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
|
|
2273
|
+
|
|
2274
|
+
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
|
|
2275
|
+
op ^= SLJIT_32;
|
|
2276
|
+
|
|
2277
|
+
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
|
2278
|
+
|
|
2279
|
+
if (src & SLJIT_MEM) {
|
|
2280
|
+
FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, TMP_REG1));
|
|
2281
|
+
src = dst_r;
|
|
2282
|
+
}
|
|
2283
|
+
|
|
2284
|
+
switch (GET_OPCODE(op)) {
|
|
2285
|
+
case SLJIT_CONV_F64_FROM_F32:
|
|
2286
|
+
op ^= SLJIT_32;
|
|
2287
|
+
if (op & SLJIT_32) {
|
|
2288
|
+
FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(src)));
|
|
2289
|
+
break;
|
|
2290
|
+
}
|
|
2291
|
+
/* Fall through. */
|
|
2292
|
+
case SLJIT_MOV_F64:
|
|
2293
|
+
if (src != dst_r) {
|
|
2294
|
+
if (!(dst & SLJIT_MEM))
|
|
2295
|
+
FAIL_IF(push_inst(compiler, FMR | FD(dst_r) | FB(src)));
|
|
2296
|
+
else
|
|
2297
|
+
dst_r = src;
|
|
2298
|
+
}
|
|
2299
|
+
break;
|
|
2300
|
+
case SLJIT_NEG_F64:
|
|
2301
|
+
FAIL_IF(push_inst(compiler, FNEG | FD(dst_r) | FB(src)));
|
|
2302
|
+
break;
|
|
2303
|
+
case SLJIT_ABS_F64:
|
|
2304
|
+
FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src)));
|
|
2305
|
+
break;
|
|
2306
|
+
}
|
|
2307
|
+
|
|
2308
|
+
if (dst & SLJIT_MEM)
|
|
2309
|
+
FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), dst_r, dst, dstw, TMP_REG1));
|
|
2310
|
+
return SLJIT_SUCCESS;
|
|
2311
|
+
}
|
|
2312
|
+
|
|
2313
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
|
|
2314
|
+
sljit_s32 dst, sljit_sw dstw,
|
|
2315
|
+
sljit_s32 src1, sljit_sw src1w,
|
|
2316
|
+
sljit_s32 src2, sljit_sw src2w)
|
|
2317
|
+
{
|
|
2318
|
+
sljit_s32 dst_r;
|
|
2319
|
+
|
|
2320
|
+
CHECK_ERROR();
|
|
2321
|
+
CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
|
|
2322
|
+
ADJUST_LOCAL_OFFSET(dst, dstw);
|
|
2323
|
+
ADJUST_LOCAL_OFFSET(src1, src1w);
|
|
2324
|
+
ADJUST_LOCAL_OFFSET(src2, src2w);
|
|
2325
|
+
|
|
2326
|
+
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
|
|
2327
|
+
|
|
2328
|
+
if (src1 & SLJIT_MEM) {
|
|
2329
|
+
FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));
|
|
2330
|
+
src1 = TMP_FREG1;
|
|
2331
|
+
}
|
|
2332
|
+
|
|
2333
|
+
if (src2 & SLJIT_MEM) {
|
|
2334
|
+
FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG1));
|
|
2335
|
+
src2 = TMP_FREG2;
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2338
|
+
switch (GET_OPCODE(op)) {
|
|
2339
|
+
case SLJIT_ADD_F64:
|
|
2340
|
+
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADD) | FD(dst_r) | FA(src1) | FB(src2)));
|
|
2341
|
+
break;
|
|
2342
|
+
case SLJIT_SUB_F64:
|
|
2343
|
+
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUB) | FD(dst_r) | FA(src1) | FB(src2)));
|
|
2344
|
+
break;
|
|
2345
|
+
case SLJIT_MUL_F64:
|
|
2346
|
+
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMUL) | FD(dst_r) | FA(src1) | FC(src2) /* FMUL use FC as src2 */));
|
|
2347
|
+
break;
|
|
2348
|
+
case SLJIT_DIV_F64:
|
|
2349
|
+
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIV) | FD(dst_r) | FA(src1) | FB(src2)));
|
|
2350
|
+
break;
|
|
2351
|
+
case SLJIT_COPYSIGN_F64:
|
|
2352
|
+
FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? STFS : STFD) | FS(src2) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
|
2353
|
+
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
|
2354
|
+
FAIL_IF(push_inst(compiler, LWZ | S(TMP_REG1) | A(SLJIT_SP) | ((op & SLJIT_32) ? TMP_MEM_OFFSET : TMP_MEM_OFFSET_HI)));
|
|
2355
|
+
#else /* !SLJIT_CONFIG_PPC_32 */
|
|
2356
|
+
FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? LWZ : LD) | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
|
2357
|
+
#endif /* SLJIT_CONFIG_PPC_32 */
|
|
2358
|
+
FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src1)));
|
|
2359
|
+
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
|
2360
|
+
FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(TMP_REG1) | 0));
|
|
2361
|
+
#else /* !SLJIT_CONFIG_PPC_32 */
|
|
2362
|
+
FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((op & SLJIT_32) ? 0 : 1)) | A(TMP_REG1) | 0));
|
|
2363
|
+
#endif /* SLJIT_CONFIG_PPC_32 */
|
|
2364
|
+
FAIL_IF(push_inst(compiler, BCx | (4 << 21) | (0 << 16) | 8));
|
|
2365
|
+
return push_inst(compiler, FNEG | FD(dst_r) | FB(dst_r));
|
|
2366
|
+
}
|
|
2367
|
+
|
|
2368
|
+
if (dst & SLJIT_MEM)
|
|
2369
|
+
FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, TMP_REG1));
|
|
2370
|
+
|
|
2371
|
+
return SLJIT_SUCCESS;
|
|
2372
|
+
}
|
|
2373
|
+
|
|
2374
|
+
#undef SELECT_FOP
|
|
2375
|
+
|
|
2376
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,
|
|
2377
|
+
sljit_s32 freg, sljit_f32 value)
|
|
2378
|
+
{
|
|
2379
|
+
union {
|
|
2380
|
+
sljit_s32 imm;
|
|
2381
|
+
sljit_f32 value;
|
|
2382
|
+
} u;
|
|
2383
|
+
|
|
2384
|
+
CHECK_ERROR();
|
|
2385
|
+
CHECK(check_sljit_emit_fset32(compiler, freg, value));
|
|
2386
|
+
|
|
2387
|
+
u.value = value;
|
|
2388
|
+
|
|
2389
|
+
if (u.imm != 0)
|
|
2390
|
+
FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm));
|
|
2391
|
+
|
|
2392
|
+
FAIL_IF(push_inst(compiler, STW | S(u.imm != 0 ? TMP_REG1 : TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET));
|
|
2393
|
+
return push_inst(compiler, LFS | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
|
|
2394
|
+
}
|
|
2395
|
+
|
|
2396
|
+
/* --------------------------------------------------------------------- */
|
|
2397
|
+
/* Conditional instructions */
|
|
2398
|
+
/* --------------------------------------------------------------------- */
|
|
2399
|
+
|
|
2400
|
+
SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
|
|
2401
|
+
{
|
|
2402
|
+
struct sljit_label *label;
|
|
2403
|
+
|
|
2404
|
+
CHECK_ERROR_PTR();
|
|
2405
|
+
CHECK_PTR(check_sljit_emit_label(compiler));
|
|
2406
|
+
|
|
2407
|
+
if (compiler->last_label && compiler->last_label->size == compiler->size)
|
|
2408
|
+
return compiler->last_label;
|
|
2409
|
+
|
|
2410
|
+
label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
|
|
2411
|
+
PTR_FAIL_IF(!label);
|
|
2412
|
+
set_label(label, compiler);
|
|
2413
|
+
return label;
|
|
2414
|
+
}
|
|
2415
|
+
|
|
2416
|
+
static sljit_ins get_bo_bi_flags(struct sljit_compiler *compiler, sljit_s32 type)
|
|
2417
|
+
{
|
|
2418
|
+
switch (type) {
|
|
2419
|
+
case SLJIT_NOT_CARRY:
|
|
2420
|
+
if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)
|
|
2421
|
+
return (4 << 21) | (2 << 16);
|
|
2422
|
+
/* fallthrough */
|
|
2423
|
+
|
|
2424
|
+
case SLJIT_EQUAL:
|
|
2425
|
+
return (12 << 21) | (2 << 16);
|
|
2426
|
+
|
|
2427
|
+
case SLJIT_CARRY:
|
|
2428
|
+
if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)
|
|
2429
|
+
return (12 << 21) | (2 << 16);
|
|
2430
|
+
/* fallthrough */
|
|
2431
|
+
|
|
2432
|
+
case SLJIT_NOT_EQUAL:
|
|
2433
|
+
return (4 << 21) | (2 << 16);
|
|
2434
|
+
|
|
2435
|
+
case SLJIT_LESS:
|
|
2436
|
+
case SLJIT_SIG_LESS:
|
|
2437
|
+
return (12 << 21) | (0 << 16);
|
|
2438
|
+
|
|
2439
|
+
case SLJIT_GREATER_EQUAL:
|
|
2440
|
+
case SLJIT_SIG_GREATER_EQUAL:
|
|
2441
|
+
return (4 << 21) | (0 << 16);
|
|
2442
|
+
|
|
2443
|
+
case SLJIT_GREATER:
|
|
2444
|
+
case SLJIT_SIG_GREATER:
|
|
2445
|
+
return (12 << 21) | (1 << 16);
|
|
2446
|
+
|
|
2447
|
+
case SLJIT_LESS_EQUAL:
|
|
2448
|
+
case SLJIT_SIG_LESS_EQUAL:
|
|
2449
|
+
return (4 << 21) | (1 << 16);
|
|
2450
|
+
|
|
2451
|
+
case SLJIT_OVERFLOW:
|
|
2452
|
+
return (12 << 21) | (3 << 16);
|
|
2453
|
+
|
|
2454
|
+
case SLJIT_NOT_OVERFLOW:
|
|
2455
|
+
return (4 << 21) | (3 << 16);
|
|
2456
|
+
|
|
2457
|
+
case SLJIT_F_LESS:
|
|
2458
|
+
case SLJIT_ORDERED_LESS:
|
|
2459
|
+
case SLJIT_UNORDERED_OR_LESS:
|
|
2460
|
+
return (12 << 21) | ((4 + 0) << 16);
|
|
2461
|
+
|
|
2462
|
+
case SLJIT_F_GREATER_EQUAL:
|
|
2463
|
+
case SLJIT_ORDERED_GREATER_EQUAL:
|
|
2464
|
+
case SLJIT_UNORDERED_OR_GREATER_EQUAL:
|
|
2465
|
+
return (4 << 21) | ((4 + 0) << 16);
|
|
2466
|
+
|
|
2467
|
+
case SLJIT_F_GREATER:
|
|
2468
|
+
case SLJIT_ORDERED_GREATER:
|
|
2469
|
+
case SLJIT_UNORDERED_OR_GREATER:
|
|
2470
|
+
return (12 << 21) | ((4 + 1) << 16);
|
|
2471
|
+
|
|
2472
|
+
case SLJIT_F_LESS_EQUAL:
|
|
2473
|
+
case SLJIT_ORDERED_LESS_EQUAL:
|
|
2474
|
+
case SLJIT_UNORDERED_OR_LESS_EQUAL:
|
|
2475
|
+
return (4 << 21) | ((4 + 1) << 16);
|
|
2476
|
+
|
|
2477
|
+
case SLJIT_F_EQUAL:
|
|
2478
|
+
case SLJIT_ORDERED_EQUAL:
|
|
2479
|
+
case SLJIT_UNORDERED_OR_EQUAL:
|
|
2480
|
+
return (12 << 21) | ((4 + 2) << 16);
|
|
2481
|
+
|
|
2482
|
+
case SLJIT_F_NOT_EQUAL:
|
|
2483
|
+
case SLJIT_ORDERED_NOT_EQUAL:
|
|
2484
|
+
case SLJIT_UNORDERED_OR_NOT_EQUAL:
|
|
2485
|
+
return (4 << 21) | ((4 + 2) << 16);
|
|
2486
|
+
|
|
2487
|
+
case SLJIT_UNORDERED:
|
|
2488
|
+
return (12 << 21) | ((4 + 3) << 16);
|
|
2489
|
+
|
|
2490
|
+
case SLJIT_ORDERED:
|
|
2491
|
+
return (4 << 21) | ((4 + 3) << 16);
|
|
2492
|
+
|
|
2493
|
+
default:
|
|
2494
|
+
SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_REG_ARG);
|
|
2495
|
+
return (20 << 21);
|
|
2496
|
+
}
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2499
|
+
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
|
|
2500
|
+
{
|
|
2501
|
+
struct sljit_jump *jump;
|
|
2502
|
+
sljit_ins bo_bi_flags;
|
|
2503
|
+
|
|
2504
|
+
CHECK_ERROR_PTR();
|
|
2505
|
+
CHECK_PTR(check_sljit_emit_jump(compiler, type));
|
|
2506
|
+
|
|
2507
|
+
bo_bi_flags = get_bo_bi_flags(compiler, type & 0xff);
|
|
2508
|
+
if (!bo_bi_flags)
|
|
2509
|
+
return NULL;
|
|
2510
|
+
|
|
2511
|
+
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
|
2512
|
+
PTR_FAIL_IF(!jump);
|
|
2513
|
+
set_jump(jump, compiler, (sljit_u32)type & SLJIT_REWRITABLE_JUMP);
|
|
2514
|
+
type &= 0xff;
|
|
2515
|
+
|
|
2516
|
+
if ((type | 0x1) == SLJIT_NOT_CARRY)
|
|
2517
|
+
PTR_FAIL_IF(push_inst(compiler, ADDE | RC(ALT_SET_FLAGS) | D(TMP_REG2) | A(TMP_ZERO) | B(TMP_ZERO)));
|
|
2518
|
+
|
|
2519
|
+
/* In PPC, we don't need to touch the arguments. */
|
|
2520
|
+
if (type < SLJIT_JUMP)
|
|
2521
|
+
jump->flags |= IS_COND;
|
|
2522
|
+
#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
|
|
2523
|
+
if (type >= SLJIT_CALL)
|
|
2524
|
+
jump->flags |= IS_CALL;
|
|
2525
|
+
#endif
|
|
2526
|
+
|
|
2527
|
+
jump->addr = compiler->size;
|
|
2528
|
+
PTR_FAIL_IF(push_inst(compiler, BCCTR | bo_bi_flags | (type >= SLJIT_FAST_CALL ? 1 : 0)));
|
|
2529
|
+
|
|
2530
|
+
/* Maximum number of instructions required for generating a constant. */
|
|
2531
|
+
compiler->size += JUMP_MAX_SIZE - 1;
|
|
2532
|
+
return jump;
|
|
2533
|
+
}
|
|
2534
|
+
|
|
2535
|
+
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
|
|
2536
|
+
sljit_s32 arg_types)
|
|
2537
|
+
{
|
|
2538
|
+
SLJIT_UNUSED_ARG(arg_types);
|
|
2539
|
+
|
|
2540
|
+
CHECK_ERROR_PTR();
|
|
2541
|
+
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
|
|
2542
|
+
|
|
2543
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
2544
|
+
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
|
2545
|
+
PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
|
|
2546
|
+
#endif
|
|
2547
|
+
|
|
2548
|
+
if (type & SLJIT_CALL_RETURN) {
|
|
2549
|
+
PTR_FAIL_IF(emit_stack_frame_release(compiler, 0));
|
|
2550
|
+
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
|
2551
|
+
}
|
|
2552
|
+
|
|
2553
|
+
SLJIT_SKIP_CHECKS(compiler);
|
|
2554
|
+
return sljit_emit_jump(compiler, type);
|
|
2555
|
+
}
|
|
2556
|
+
|
|
2557
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
|
|
2558
|
+
{
|
|
2559
|
+
struct sljit_jump *jump = NULL;
|
|
2560
|
+
sljit_s32 src_r;
|
|
2561
|
+
|
|
2562
|
+
CHECK_ERROR();
|
|
2563
|
+
CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
|
|
2564
|
+
|
|
2565
|
+
if (src == SLJIT_IMM) {
|
|
2566
|
+
/* These jumps are converted to jump/call instructions when possible. */
|
|
2567
|
+
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
|
2568
|
+
FAIL_IF(!jump);
|
|
2569
|
+
set_jump(jump, compiler, JUMP_ADDR);
|
|
2570
|
+
jump->u.target = (sljit_uw)srcw;
|
|
2571
|
+
|
|
2572
|
+
#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
|
|
2573
|
+
if (type >= SLJIT_CALL)
|
|
2574
|
+
jump->flags |= IS_CALL;
|
|
2575
|
+
#endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */
|
|
2576
|
+
|
|
2577
|
+
jump->addr = compiler->size;
|
|
2578
|
+
FAIL_IF(push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0)));
|
|
2579
|
+
|
|
2580
|
+
/* Maximum number of instructions required for generating a constant. */
|
|
2581
|
+
compiler->size += JUMP_MAX_SIZE - 1;
|
|
2582
|
+
return SLJIT_SUCCESS;
|
|
2583
|
+
}
|
|
2584
|
+
|
|
2585
|
+
if (FAST_IS_REG(src)) {
|
|
2586
|
+
#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
|
|
2587
|
+
if (type >= SLJIT_CALL && src != TMP_CALL_REG) {
|
|
2588
|
+
FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));
|
|
2589
|
+
src_r = TMP_CALL_REG;
|
|
2590
|
+
} else
|
|
2591
|
+
src_r = src;
|
|
2592
|
+
#else /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */
|
|
2593
|
+
src_r = src;
|
|
2594
|
+
#endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */
|
|
2595
|
+
} else {
|
|
2596
|
+
ADJUST_LOCAL_OFFSET(src, srcw);
|
|
2597
|
+
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG));
|
|
2598
|
+
src_r = TMP_CALL_REG;
|
|
2599
|
+
}
|
|
2600
|
+
|
|
2601
|
+
FAIL_IF(push_inst(compiler, MTCTR | S(src_r)));
|
|
2602
|
+
return push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0));
|
|
2603
|
+
}
|
|
2604
|
+
|
|
2605
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
|
|
2606
|
+
sljit_s32 arg_types,
|
|
2607
|
+
sljit_s32 src, sljit_sw srcw)
|
|
2608
|
+
{
|
|
2609
|
+
SLJIT_UNUSED_ARG(arg_types);
|
|
2610
|
+
|
|
2611
|
+
CHECK_ERROR();
|
|
2612
|
+
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
|
|
2613
|
+
|
|
2614
|
+
if (src & SLJIT_MEM) {
|
|
2615
|
+
ADJUST_LOCAL_OFFSET(src, srcw);
|
|
2616
|
+
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG));
|
|
2617
|
+
src = TMP_CALL_REG;
|
|
2618
|
+
}
|
|
2619
|
+
|
|
2620
|
+
if (type & SLJIT_CALL_RETURN) {
|
|
2621
|
+
if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
|
|
2622
|
+
FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));
|
|
2623
|
+
src = TMP_CALL_REG;
|
|
2624
|
+
}
|
|
2625
|
+
|
|
2626
|
+
FAIL_IF(emit_stack_frame_release(compiler, 0));
|
|
2627
|
+
type = SLJIT_JUMP;
|
|
2628
|
+
}
|
|
2629
|
+
|
|
2630
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
2631
|
+
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
|
2632
|
+
FAIL_IF(call_with_args(compiler, arg_types, &src));
|
|
2633
|
+
#endif
|
|
2634
|
+
|
|
2635
|
+
SLJIT_SKIP_CHECKS(compiler);
|
|
2636
|
+
return sljit_emit_ijump(compiler, type, src, srcw);
|
|
2637
|
+
}
|
|
2638
|
+
|
|
2639
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
|
|
2640
|
+
sljit_s32 dst, sljit_sw dstw,
|
|
2641
|
+
sljit_s32 type)
|
|
2642
|
+
{
|
|
2643
|
+
sljit_s32 reg, invert;
|
|
2644
|
+
sljit_u32 bit, from_xer;
|
|
2645
|
+
sljit_s32 saved_op = op;
|
|
2646
|
+
sljit_sw saved_dstw = dstw;
|
|
2647
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
2648
|
+
sljit_s32 input_flags = ((op & SLJIT_32) || op == SLJIT_MOV32) ? INT_DATA : WORD_DATA;
|
|
2649
|
+
#else
|
|
2650
|
+
sljit_s32 input_flags = WORD_DATA;
|
|
2651
|
+
#endif
|
|
2652
|
+
|
|
2653
|
+
CHECK_ERROR();
|
|
2654
|
+
CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
|
|
2655
|
+
ADJUST_LOCAL_OFFSET(dst, dstw);
|
|
2656
|
+
|
|
2657
|
+
op = GET_OPCODE(op);
|
|
2658
|
+
reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
|
|
2659
|
+
|
|
2660
|
+
if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
|
|
2661
|
+
FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG1));
|
|
2662
|
+
|
|
2663
|
+
invert = 0;
|
|
2664
|
+
bit = 0;
|
|
2665
|
+
from_xer = 0;
|
|
2666
|
+
|
|
2667
|
+
switch (type) {
|
|
2668
|
+
case SLJIT_LESS:
|
|
2669
|
+
case SLJIT_SIG_LESS:
|
|
2670
|
+
break;
|
|
2671
|
+
|
|
2672
|
+
case SLJIT_GREATER_EQUAL:
|
|
2673
|
+
case SLJIT_SIG_GREATER_EQUAL:
|
|
2674
|
+
invert = 1;
|
|
2675
|
+
break;
|
|
2676
|
+
|
|
2677
|
+
case SLJIT_GREATER:
|
|
2678
|
+
case SLJIT_SIG_GREATER:
|
|
2679
|
+
bit = 1;
|
|
2680
|
+
break;
|
|
2681
|
+
|
|
2682
|
+
case SLJIT_LESS_EQUAL:
|
|
2683
|
+
case SLJIT_SIG_LESS_EQUAL:
|
|
2684
|
+
bit = 1;
|
|
2685
|
+
invert = 1;
|
|
2686
|
+
break;
|
|
2687
|
+
|
|
2688
|
+
case SLJIT_EQUAL:
|
|
2689
|
+
bit = 2;
|
|
2690
|
+
break;
|
|
2691
|
+
|
|
2692
|
+
case SLJIT_NOT_EQUAL:
|
|
2693
|
+
bit = 2;
|
|
2694
|
+
invert = 1;
|
|
2695
|
+
break;
|
|
2696
|
+
|
|
2697
|
+
case SLJIT_OVERFLOW:
|
|
2698
|
+
from_xer = 1;
|
|
2699
|
+
bit = 1;
|
|
2700
|
+
break;
|
|
2701
|
+
|
|
2702
|
+
case SLJIT_NOT_OVERFLOW:
|
|
2703
|
+
from_xer = 1;
|
|
2704
|
+
bit = 1;
|
|
2705
|
+
invert = 1;
|
|
2706
|
+
break;
|
|
2707
|
+
|
|
2708
|
+
case SLJIT_CARRY:
|
|
2709
|
+
from_xer = 1;
|
|
2710
|
+
bit = 2;
|
|
2711
|
+
invert = (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB) != 0;
|
|
2712
|
+
break;
|
|
2713
|
+
|
|
2714
|
+
case SLJIT_NOT_CARRY:
|
|
2715
|
+
from_xer = 1;
|
|
2716
|
+
bit = 2;
|
|
2717
|
+
invert = (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD) != 0;
|
|
2718
|
+
break;
|
|
2719
|
+
|
|
2720
|
+
case SLJIT_F_LESS:
|
|
2721
|
+
case SLJIT_ORDERED_LESS:
|
|
2722
|
+
case SLJIT_UNORDERED_OR_LESS:
|
|
2723
|
+
bit = 4 + 0;
|
|
2724
|
+
break;
|
|
2725
|
+
|
|
2726
|
+
case SLJIT_F_GREATER_EQUAL:
|
|
2727
|
+
case SLJIT_ORDERED_GREATER_EQUAL:
|
|
2728
|
+
case SLJIT_UNORDERED_OR_GREATER_EQUAL:
|
|
2729
|
+
bit = 4 + 0;
|
|
2730
|
+
invert = 1;
|
|
2731
|
+
break;
|
|
2732
|
+
|
|
2733
|
+
case SLJIT_F_GREATER:
|
|
2734
|
+
case SLJIT_ORDERED_GREATER:
|
|
2735
|
+
case SLJIT_UNORDERED_OR_GREATER:
|
|
2736
|
+
bit = 4 + 1;
|
|
2737
|
+
break;
|
|
2738
|
+
|
|
2739
|
+
case SLJIT_F_LESS_EQUAL:
|
|
2740
|
+
case SLJIT_ORDERED_LESS_EQUAL:
|
|
2741
|
+
case SLJIT_UNORDERED_OR_LESS_EQUAL:
|
|
2742
|
+
bit = 4 + 1;
|
|
2743
|
+
invert = 1;
|
|
2744
|
+
break;
|
|
2745
|
+
|
|
2746
|
+
case SLJIT_F_EQUAL:
|
|
2747
|
+
case SLJIT_ORDERED_EQUAL:
|
|
2748
|
+
case SLJIT_UNORDERED_OR_EQUAL:
|
|
2749
|
+
bit = 4 + 2;
|
|
2750
|
+
break;
|
|
2751
|
+
|
|
2752
|
+
case SLJIT_F_NOT_EQUAL:
|
|
2753
|
+
case SLJIT_ORDERED_NOT_EQUAL:
|
|
2754
|
+
case SLJIT_UNORDERED_OR_NOT_EQUAL:
|
|
2755
|
+
bit = 4 + 2;
|
|
2756
|
+
invert = 1;
|
|
2757
|
+
break;
|
|
2758
|
+
|
|
2759
|
+
case SLJIT_UNORDERED:
|
|
2760
|
+
bit = 4 + 3;
|
|
2761
|
+
break;
|
|
2762
|
+
|
|
2763
|
+
case SLJIT_ORDERED:
|
|
2764
|
+
bit = 4 + 3;
|
|
2765
|
+
invert = 1;
|
|
2766
|
+
break;
|
|
2767
|
+
|
|
2768
|
+
default:
|
|
2769
|
+
SLJIT_UNREACHABLE();
|
|
2770
|
+
break;
|
|
2771
|
+
}
|
|
2772
|
+
|
|
2773
|
+
FAIL_IF(push_inst(compiler, (from_xer ? MFXER : MFCR) | D(reg)));
|
|
2774
|
+
/* Simplified mnemonics: extrwi. */
|
|
2775
|
+
FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | RLWI_SH(1 + bit) | RLWI_MBE(31, 31)));
|
|
2776
|
+
|
|
2777
|
+
if (invert)
|
|
2778
|
+
FAIL_IF(push_inst(compiler, XORI | S(reg) | A(reg) | 0x1));
|
|
2779
|
+
|
|
2780
|
+
if (op < SLJIT_ADD) {
|
|
2781
|
+
if (!(dst & SLJIT_MEM))
|
|
2782
|
+
return SLJIT_SUCCESS;
|
|
2783
|
+
return emit_op_mem(compiler, input_flags, reg, dst, dstw, TMP_REG1);
|
|
2784
|
+
}
|
|
2785
|
+
|
|
2786
|
+
SLJIT_SKIP_CHECKS(compiler);
|
|
2787
|
+
|
|
2788
|
+
if (dst & SLJIT_MEM)
|
|
2789
|
+
return sljit_emit_op2(compiler, saved_op, dst, saved_dstw, TMP_REG1, 0, TMP_REG2, 0);
|
|
2790
|
+
return sljit_emit_op2(compiler, saved_op, dst, 0, dst, 0, TMP_REG2, 0);
|
|
2791
|
+
}
|
|
2792
|
+
|
|
2793
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,
|
|
2794
|
+
sljit_s32 dst_reg,
|
|
2795
|
+
sljit_s32 src1, sljit_sw src1w,
|
|
2796
|
+
sljit_s32 src2_reg)
|
|
2797
|
+
{
|
|
2798
|
+
sljit_ins *ptr;
|
|
2799
|
+
sljit_uw size;
|
|
2800
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
2801
|
+
sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
|
|
2802
|
+
#else /* !SLJIT_CONFIG_PPC_64 */
|
|
2803
|
+
sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;
|
|
2804
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
2805
|
+
|
|
2806
|
+
CHECK_ERROR();
|
|
2807
|
+
CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
|
|
2808
|
+
|
|
2809
|
+
ADJUST_LOCAL_OFFSET(src1, src1w);
|
|
2810
|
+
|
|
2811
|
+
if (dst_reg != src2_reg) {
|
|
2812
|
+
if (dst_reg == src1) {
|
|
2813
|
+
src1 = src2_reg;
|
|
2814
|
+
src1w = 0;
|
|
2815
|
+
type ^= 0x1;
|
|
2816
|
+
} else {
|
|
2817
|
+
if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {
|
|
2818
|
+
FAIL_IF(push_inst(compiler, OR | S(dst_reg) | A(TMP_REG1) | B(dst_reg)));
|
|
2819
|
+
|
|
2820
|
+
if ((src1 & REG_MASK) == dst_reg)
|
|
2821
|
+
src1 = (src1 & ~REG_MASK) | TMP_REG1;
|
|
2822
|
+
|
|
2823
|
+
if (OFFS_REG(src1) == dst_reg)
|
|
2824
|
+
src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);
|
|
2825
|
+
}
|
|
2826
|
+
|
|
2827
|
+
FAIL_IF(push_inst(compiler, OR | S(src2_reg) | A(dst_reg) | B(src2_reg)));
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
|
|
2831
|
+
if (((type & ~SLJIT_32) | 0x1) == SLJIT_NOT_CARRY)
|
|
2832
|
+
FAIL_IF(push_inst(compiler, ADDE | RC(ALT_SET_FLAGS) | D(TMP_REG1) | A(TMP_ZERO) | B(TMP_ZERO)));
|
|
2833
|
+
|
|
2834
|
+
size = compiler->size;
|
|
2835
|
+
|
|
2836
|
+
ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
|
|
2837
|
+
FAIL_IF(!ptr);
|
|
2838
|
+
compiler->size++;
|
|
2839
|
+
|
|
2840
|
+
if (src1 & SLJIT_MEM) {
|
|
2841
|
+
FAIL_IF(emit_op_mem(compiler, inp_flags, dst_reg, src1, src1w, TMP_REG1));
|
|
2842
|
+
} else if (src1 == SLJIT_IMM) {
|
|
2843
|
+
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
|
2844
|
+
if (type & SLJIT_32)
|
|
2845
|
+
src1w = (sljit_s32)src1w;
|
|
2846
|
+
#endif /* SLJIT_CONFIG_RISCV_64 */
|
|
2847
|
+
FAIL_IF(load_immediate(compiler, dst_reg, src1w));
|
|
2848
|
+
} else
|
|
2849
|
+
FAIL_IF(push_inst(compiler, OR | S(src1) | A(dst_reg) | B(src1)));
|
|
2850
|
+
|
|
2851
|
+
*ptr = BCx | get_bo_bi_flags(compiler, (type ^ 0x1) & ~SLJIT_32) | (sljit_ins)((compiler->size - size) << 2);
|
|
2852
|
+
return SLJIT_SUCCESS;
|
|
2853
|
+
}
|
|
2854
|
+
|
|
2855
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,
|
|
2856
|
+
sljit_s32 dst_freg,
|
|
2857
|
+
sljit_s32 src1, sljit_sw src1w,
|
|
2858
|
+
sljit_s32 src2_freg)
|
|
2859
|
+
{
|
|
2860
|
+
sljit_ins *ptr;
|
|
2861
|
+
sljit_uw size;
|
|
2862
|
+
|
|
2863
|
+
CHECK_ERROR();
|
|
2864
|
+
CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));
|
|
2865
|
+
|
|
2866
|
+
ADJUST_LOCAL_OFFSET(src1, src1w);
|
|
2867
|
+
|
|
2868
|
+
if (dst_freg != src2_freg) {
|
|
2869
|
+
if (dst_freg == src1) {
|
|
2870
|
+
src1 = src2_freg;
|
|
2871
|
+
src1w = 0;
|
|
2872
|
+
type ^= 0x1;
|
|
2873
|
+
} else
|
|
2874
|
+
FAIL_IF(push_inst(compiler, FMR | FD(dst_freg) | FB(src2_freg)));
|
|
2875
|
+
}
|
|
2876
|
+
|
|
2877
|
+
if (((type & ~SLJIT_32) | 0x1) == SLJIT_NOT_CARRY)
|
|
2878
|
+
FAIL_IF(push_inst(compiler, ADDE | RC(ALT_SET_FLAGS) | D(TMP_REG1) | A(TMP_ZERO) | B(TMP_ZERO)));
|
|
2879
|
+
|
|
2880
|
+
size = compiler->size;
|
|
2881
|
+
|
|
2882
|
+
ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
|
|
2883
|
+
FAIL_IF(!ptr);
|
|
2884
|
+
compiler->size++;
|
|
2885
|
+
|
|
2886
|
+
if (src1 & SLJIT_MEM)
|
|
2887
|
+
FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, dst_freg, src1, src1w, TMP_REG1));
|
|
2888
|
+
else
|
|
2889
|
+
FAIL_IF(push_inst(compiler, FMR | FD(dst_freg) | FB(src1)));
|
|
2890
|
+
|
|
2891
|
+
*ptr = BCx | get_bo_bi_flags(compiler, (type ^ 0x1) & ~SLJIT_32) | (sljit_ins)((compiler->size - size) << 2);
|
|
2892
|
+
return SLJIT_SUCCESS;
|
|
2893
|
+
}
|
|
2894
|
+
|
|
2895
|
+
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
|
2896
|
+
|
|
2897
|
+
#define EMIT_MEM_LOAD_IMM(inst, mem, memw) \
|
|
2898
|
+
((sljit_s16)(memw) > SIMM_MAX - SSIZE_OF(sw))
|
|
2899
|
+
|
|
2900
|
+
#else /* !SLJIT_CONFIG_PPC_32 */
|
|
2901
|
+
|
|
2902
|
+
#define EMIT_MEM_LOAD_IMM(inst, mem, memw) \
|
|
2903
|
+
((((inst) & INT_ALIGNED) && ((memw) & 0x3) != 0) \
|
|
2904
|
+
|| ((sljit_s16)(memw) > SIMM_MAX - SSIZE_OF(sw)) \
|
|
2905
|
+
|| ((memw) > 0x7fff7fffl || (memw) < -0x80000000l)) \
|
|
2906
|
+
|
|
2907
|
+
#endif /* SLJIT_CONFIG_PPC_32 */
|
|
2908
|
+
|
|
2909
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
|
|
2910
|
+
sljit_s32 reg,
|
|
2911
|
+
sljit_s32 mem, sljit_sw memw)
|
|
2912
|
+
{
|
|
2913
|
+
sljit_ins inst;
|
|
2914
|
+
|
|
2915
|
+
CHECK_ERROR();
|
|
2916
|
+
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
|
|
2917
|
+
|
|
2918
|
+
if (!(reg & REG_PAIR_MASK))
|
|
2919
|
+
return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
|
|
2920
|
+
|
|
2921
|
+
ADJUST_LOCAL_OFFSET(mem, memw);
|
|
2922
|
+
|
|
2923
|
+
inst = data_transfer_insts[WORD_DATA | ((type & SLJIT_MEM_STORE) ? 0 : LOAD_DATA)];
|
|
2924
|
+
|
|
2925
|
+
if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
|
|
2926
|
+
memw &= 0x3;
|
|
2927
|
+
|
|
2928
|
+
if (memw != 0) {
|
|
2929
|
+
FAIL_IF(push_inst(compiler, SLWI_W(memw) | S(OFFS_REG(mem)) | A(TMP_REG1)));
|
|
2930
|
+
FAIL_IF(push_inst(compiler, ADD | D(TMP_REG1) | A(TMP_REG1) | B(mem & REG_MASK)));
|
|
2931
|
+
} else
|
|
2932
|
+
FAIL_IF(push_inst(compiler, ADD | D(TMP_REG1) | A(mem & REG_MASK) | B(OFFS_REG(mem))));
|
|
2933
|
+
|
|
2934
|
+
mem = TMP_REG1;
|
|
2935
|
+
memw = 0;
|
|
2936
|
+
} else {
|
|
2937
|
+
if (EMIT_MEM_LOAD_IMM(inst, mem, memw)) {
|
|
2938
|
+
if ((mem & REG_MASK) != 0) {
|
|
2939
|
+
SLJIT_SKIP_CHECKS(compiler);
|
|
2940
|
+
FAIL_IF(sljit_emit_op2(compiler, SLJIT_ADD, TMP_REG1, 0, mem & REG_MASK, 0, SLJIT_IMM, memw));
|
|
2941
|
+
} else
|
|
2942
|
+
FAIL_IF(load_immediate(compiler, TMP_REG1, memw));
|
|
2943
|
+
|
|
2944
|
+
memw = 0;
|
|
2945
|
+
mem = TMP_REG1;
|
|
2946
|
+
} else if (memw > SIMM_MAX || memw < SIMM_MIN) {
|
|
2947
|
+
FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(mem & REG_MASK) | IMM((memw + 0x8000) >> 16)));
|
|
2948
|
+
|
|
2949
|
+
memw &= 0xffff;
|
|
2950
|
+
mem = TMP_REG1;
|
|
2951
|
+
} else {
|
|
2952
|
+
memw &= 0xffff;
|
|
2953
|
+
mem &= REG_MASK;
|
|
2954
|
+
}
|
|
2955
|
+
}
|
|
2956
|
+
|
|
2957
|
+
SLJIT_ASSERT((memw >= 0 && memw <= SIMM_MAX - SSIZE_OF(sw)) || (memw >= 0x8000 && memw <= 0xffff));
|
|
2958
|
+
|
|
2959
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
2960
|
+
inst &= (sljit_ins)~INT_ALIGNED;
|
|
2961
|
+
#endif /* SLJIT_CONFIG_PPC_64 */
|
|
2962
|
+
|
|
2963
|
+
if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) {
|
|
2964
|
+
FAIL_IF(push_inst(compiler, inst | D(REG_PAIR_SECOND(reg)) | A(mem) | IMM(memw + SSIZE_OF(sw))));
|
|
2965
|
+
return push_inst(compiler, inst | D(REG_PAIR_FIRST(reg)) | A(mem) | IMM(memw));
|
|
2966
|
+
}
|
|
2967
|
+
|
|
2968
|
+
FAIL_IF(push_inst(compiler, inst | D(REG_PAIR_FIRST(reg)) | A(mem) | IMM(memw)));
|
|
2969
|
+
return push_inst(compiler, inst | D(REG_PAIR_SECOND(reg)) | A(mem) | IMM(memw + SSIZE_OF(sw)));
|
|
2970
|
+
}
|
|
2971
|
+
|
|
2972
|
+
#undef EMIT_MEM_LOAD_IMM
|
|
2973
|
+
|
|
2974
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,
|
|
2975
|
+
sljit_s32 reg,
|
|
2976
|
+
sljit_s32 mem, sljit_sw memw)
|
|
2977
|
+
{
|
|
2978
|
+
sljit_s32 mem_flags;
|
|
2979
|
+
sljit_ins inst;
|
|
2980
|
+
|
|
2981
|
+
CHECK_ERROR();
|
|
2982
|
+
CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw));
|
|
2983
|
+
|
|
2984
|
+
if (type & SLJIT_MEM_POST)
|
|
2985
|
+
return SLJIT_ERR_UNSUPPORTED;
|
|
2986
|
+
|
|
2987
|
+
switch (type & 0xff) {
|
|
2988
|
+
case SLJIT_MOV:
|
|
2989
|
+
case SLJIT_MOV_P:
|
|
2990
|
+
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
|
2991
|
+
case SLJIT_MOV_U32:
|
|
2992
|
+
case SLJIT_MOV_S32:
|
|
2993
|
+
case SLJIT_MOV32:
|
|
2994
|
+
#endif
|
|
2995
|
+
mem_flags = WORD_DATA;
|
|
2996
|
+
break;
|
|
2997
|
+
|
|
2998
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
2999
|
+
case SLJIT_MOV_U32:
|
|
3000
|
+
case SLJIT_MOV32:
|
|
3001
|
+
mem_flags = INT_DATA;
|
|
3002
|
+
break;
|
|
3003
|
+
|
|
3004
|
+
case SLJIT_MOV_S32:
|
|
3005
|
+
mem_flags = INT_DATA;
|
|
3006
|
+
|
|
3007
|
+
if (!(type & SLJIT_MEM_STORE) && !(type & SLJIT_32)) {
|
|
3008
|
+
if (mem & OFFS_REG_MASK)
|
|
3009
|
+
mem_flags |= SIGNED_DATA;
|
|
3010
|
+
else
|
|
3011
|
+
return SLJIT_ERR_UNSUPPORTED;
|
|
3012
|
+
}
|
|
3013
|
+
break;
|
|
3014
|
+
#endif
|
|
3015
|
+
|
|
3016
|
+
case SLJIT_MOV_U8:
|
|
3017
|
+
case SLJIT_MOV_S8:
|
|
3018
|
+
mem_flags = BYTE_DATA;
|
|
3019
|
+
break;
|
|
3020
|
+
|
|
3021
|
+
case SLJIT_MOV_U16:
|
|
3022
|
+
mem_flags = HALF_DATA;
|
|
3023
|
+
break;
|
|
3024
|
+
|
|
3025
|
+
case SLJIT_MOV_S16:
|
|
3026
|
+
mem_flags = HALF_DATA | SIGNED_DATA;
|
|
3027
|
+
break;
|
|
3028
|
+
|
|
3029
|
+
default:
|
|
3030
|
+
SLJIT_UNREACHABLE();
|
|
3031
|
+
mem_flags = WORD_DATA;
|
|
3032
|
+
break;
|
|
3033
|
+
}
|
|
3034
|
+
|
|
3035
|
+
if (!(type & SLJIT_MEM_STORE))
|
|
3036
|
+
mem_flags |= LOAD_DATA;
|
|
3037
|
+
|
|
3038
|
+
if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
|
|
3039
|
+
if (memw != 0)
|
|
3040
|
+
return SLJIT_ERR_UNSUPPORTED;
|
|
3041
|
+
|
|
3042
|
+
if (type & SLJIT_MEM_SUPP)
|
|
3043
|
+
return SLJIT_SUCCESS;
|
|
3044
|
+
|
|
3045
|
+
inst = updated_data_transfer_insts[mem_flags | INDEXED];
|
|
3046
|
+
FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | B(OFFS_REG(mem))));
|
|
3047
|
+
}
|
|
3048
|
+
else {
|
|
3049
|
+
if (memw > SIMM_MAX || memw < SIMM_MIN)
|
|
3050
|
+
return SLJIT_ERR_UNSUPPORTED;
|
|
3051
|
+
|
|
3052
|
+
inst = updated_data_transfer_insts[mem_flags];
|
|
3053
|
+
|
|
3054
|
+
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
3055
|
+
if ((inst & INT_ALIGNED) && (memw & 0x3) != 0)
|
|
3056
|
+
return SLJIT_ERR_UNSUPPORTED;
|
|
3057
|
+
#endif
|
|
3058
|
+
|
|
3059
|
+
if (type & SLJIT_MEM_SUPP)
|
|
3060
|
+
return SLJIT_SUCCESS;
|
|
3061
|
+
|
|
3062
|
+
FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | IMM(memw)));
|
|
3063
|
+
}
|
|
3064
|
+
|
|
3065
|
+
if ((mem_flags & LOAD_DATA) && (type & 0xff) == SLJIT_MOV_S8)
|
|
3066
|
+
return push_inst(compiler, EXTSB | S(reg) | A(reg));
|
|
3067
|
+
return SLJIT_SUCCESS;
|
|
3068
|
+
}
|
|
3069
|
+
|
|
3070
|
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type,
|
|
3071
|
+
sljit_s32 freg,
|
|
3072
|
+
sljit_s32 mem, sljit_sw memw)
|
|
3073
|
+
{
|
|
3074
|
+
sljit_s32 mem_flags;
|
|
3075
|
+
sljit_ins inst;
|
|
3076
|
+
|
|
3077
|
+
CHECK_ERROR();
|
|
3078
|
+
CHECK(check_sljit_emit_fmem_update(compiler, type, freg, mem, memw));
|
|
3079
|
+
|
|
3080
|
+
if (type & SLJIT_MEM_POST)
|
|
3081
|
+
return SLJIT_ERR_UNSUPPORTED;
|
|
3082
|
+
|
|
3083
|
+
if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
|
|
3084
|
+
if (memw != 0)
|
|
3085
|
+
return SLJIT_ERR_UNSUPPORTED;
|
|
3086
|
+
}
|
|
3087
|
+
else {
|
|
3088
|
+
if (memw > SIMM_MAX || memw < SIMM_MIN)
|
|
3089
|
+
return SLJIT_ERR_UNSUPPORTED;
|
|
3090
|
+
}
|
|
3091
|
+
|
|
3092
|
+
if (type & SLJIT_MEM_SUPP)
|
|
3093
|
+
return SLJIT_SUCCESS;
|
|
3094
|
+
|
|
3095
|
+
mem_flags = FLOAT_DATA(type);
|
|
3096
|
+
|
|
3097
|
+
if (!(type & SLJIT_MEM_STORE))
|
|
3098
|
+
mem_flags |= LOAD_DATA;
|
|
3099
|
+
|
|
3100
|
+
if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
|
|
3101
|
+
inst = updated_data_transfer_insts[mem_flags | INDEXED];
|
|
3102
|
+
return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | B(OFFS_REG(mem)));
|
|
3103
|
+
}
|
|
3104
|
+
|
|
3105
|
+
inst = updated_data_transfer_insts[mem_flags];
|
|
3106
|
+
return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | IMM(memw));
|
|
3107
|
+
}
|
|
3108
|
+
|
|
3109
|
+
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
|
3110
|
+
{
|
|
3111
|
+
struct sljit_const *const_;
|
|
3112
|
+
sljit_s32 dst_r;
|
|
3113
|
+
|
|
3114
|
+
CHECK_ERROR_PTR();
|
|
3115
|
+
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
|
|
3116
|
+
ADJUST_LOCAL_OFFSET(dst, dstw);
|
|
3117
|
+
|
|
3118
|
+
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
|
|
3119
|
+
PTR_FAIL_IF(!const_);
|
|
3120
|
+
set_const(const_, compiler);
|
|
3121
|
+
|
|
3122
|
+
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
|
3123
|
+
PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
|
|
3124
|
+
|
|
3125
|
+
if (dst & SLJIT_MEM)
|
|
3126
|
+
PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, dst_r, dst, dstw, TMP_REG1));
|
|
3127
|
+
|
|
3128
|
+
return const_;
|
|
3129
|
+
}
|
|
3130
|
+
|
|
3131
|
+
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
|
|
3132
|
+
{
|
|
3133
|
+
struct sljit_jump *jump;
|
|
3134
|
+
sljit_s32 dst_r;
|
|
3135
|
+
|
|
3136
|
+
CHECK_ERROR_PTR();
|
|
3137
|
+
CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));
|
|
3138
|
+
ADJUST_LOCAL_OFFSET(dst, dstw);
|
|
3139
|
+
|
|
3140
|
+
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
|
3141
|
+
PTR_FAIL_IF(!jump);
|
|
3142
|
+
set_mov_addr(jump, compiler, 0);
|
|
3143
|
+
|
|
3144
|
+
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
|
3145
|
+
PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r));
|
|
3146
|
+
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
|
3147
|
+
compiler->size++;
|
|
3148
|
+
#else
|
|
3149
|
+
compiler->size += 4;
|
|
3150
|
+
#endif
|
|
3151
|
+
|
|
3152
|
+
if (dst & SLJIT_MEM)
|
|
3153
|
+
PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
|
|
3154
|
+
|
|
3155
|
+
return jump;
|
|
3156
|
+
}
|
|
3157
|
+
|
|
3158
|
+
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
|
|
3159
|
+
{
|
|
3160
|
+
sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
|
|
3161
|
+
}
|