diff --git a/deps/asmjit/.github/ISSUE_TEMPLATE/01_bug_report.yml b/deps/asmjit/.github/ISSUE_TEMPLATE/01_bug_report.yml new file mode 100644 index 00000000..ba173b42 --- /dev/null +++ b/deps/asmjit/.github/ISSUE_TEMPLATE/01_bug_report.yml @@ -0,0 +1,42 @@ +name: Bug Report +description: File a bug report +body: + - type: markdown + attributes: + value: | + Before you hit the submit button: + * Please see our [Contribution Guidelines](https://github.com/asmjit/asmjit/blob/master/CONTRIBUTING.md). + * Make sure that you use a recent AsmJit (master branch) before filing a bug report. + * Make sure that you use logging and error handling features to collect as much information as possible, if applicable. + - type: textarea + id: issue-description + attributes: + label: Issue Description + description: Please share a clear and concise description of the issue and optionally provide reproducibility information and output from AsmJit's logger. + placeholder: Description + validations: + required: true + - type: dropdown + id: operating-system + attributes: + label: Operating System + multiple: true + options: + - Not specified / possibly all + - Windows + - Linux + - Mac + - Android + - Other + - type: dropdown + id: target-architecture + attributes: + label: Architecture + multiple: true + options: + - Not specified + - X86 / X86_64 + - AArch32 + - AArch64 + - RISC-V + - Other diff --git a/deps/asmjit/.github/ISSUE_TEMPLATE/02_feature_request.yml b/deps/asmjit/.github/ISSUE_TEMPLATE/02_feature_request.yml new file mode 100644 index 00000000..f1e9f3db --- /dev/null +++ b/deps/asmjit/.github/ISSUE_TEMPLATE/02_feature_request.yml @@ -0,0 +1,18 @@ +name: Feature Request +description: Request a new feature or enhancement +labels: [enhancement] +body: + - type: markdown + attributes: + value: | + Before you hit the submit button: + * Please see our [Contribution Guidelines](https://github.com/asmjit/asmjit/blob/master/CONTRIBUTING.md). + * Make sure that you use a recent AsmJit (master branch) before filing a feature request. + - type: textarea + id: issue-description + attributes: + label: Issue Description + description: Please share a clear and concise description of a new feature or enhancement. + placeholder: Description + validations: + required: true diff --git a/deps/asmjit/.github/ISSUE_TEMPLATE/03_help_question.yml b/deps/asmjit/.github/ISSUE_TEMPLATE/03_help_question.yml new file mode 100644 index 00000000..8d829edc --- /dev/null +++ b/deps/asmjit/.github/ISSUE_TEMPLATE/03_help_question.yml @@ -0,0 +1,18 @@ +name: Help & Questions +description: Ask a question or get help +labels: [question] +body: + - type: markdown + attributes: + value: | + Before you hit the submit button: + * Please see our [Contribution Guidelines](https://github.com/asmjit/asmjit/blob/master/CONTRIBUTING.md). + * [Gitter Chat](https://app.gitter.im/#/room/#asmjit:gitter.im) is usually faster to get answers. + * If you need a help, please include as much information as possible to make it clear what the intend is. + - type: textarea + id: issue-description + attributes: + label: Details + description: The description of the problem or question. + validations: + required: true diff --git a/deps/asmjit/.github/ISSUE_TEMPLATE/99_other_issues.yml b/deps/asmjit/.github/ISSUE_TEMPLATE/99_other_issues.yml new file mode 100644 index 00000000..4f4e36e0 --- /dev/null +++ b/deps/asmjit/.github/ISSUE_TEMPLATE/99_other_issues.yml @@ -0,0 +1,11 @@ +name: Other Issues +description: Something that doesn't fit the other categories +body: + - type: textarea + id: issue-description + attributes: + label: Issue Description + description: Please share a clear and concise description of the issue. + placeholder: Description + validations: + required: true diff --git a/deps/asmjit/.github/workflows/build-config.json b/deps/asmjit/.github/workflows/build-config.json index 08022ef3..e72d8e31 100644 --- a/deps/asmjit/.github/workflows/build-config.json +++ b/deps/asmjit/.github/workflows/build-config.json @@ -1,7 +1,8 @@ { "diagnostics": { "asan": { "definitions": ["ASMJIT_SANITIZE=address"] }, - "ubsan": { "definitions": ["ASMJIT_SANITIZE=undefined"] } + "ubsan": { "definitions": ["ASMJIT_SANITIZE=undefined"] }, + "msan": { "definitions": ["ASMJIT_SANITIZE=memory"] } }, "valgrind_arguments": [ @@ -11,37 +12,14 @@ ], "tests": [ - { - "cmd": ["asmjit_test_unit", "--quick"], - "optional": true - }, - { - "cmd": ["asmjit_test_assembler"], - "optional": true - }, - { - "cmd": ["asmjit_test_assembler", "--validate"], - "optional": true - }, - { - "cmd": ["asmjit_test_emitters"], - "optional": true - }, - { - "cmd": ["asmjit_test_compiler"], - "optional": true - }, - { - "cmd": ["asmjit_test_instinfo"], - "optional": true - }, - { - "cmd": ["asmjit_test_x86_sections"], - "optional": true - }, - { - "cmd": ["asmjit_test_perf", "--quick"], - "optional": true - } + { "optional": true, "cmd": ["asmjit_test_unit", "--quick"] }, + { "optional": true, "cmd": ["asmjit_test_assembler"] }, + { "optional": true, "cmd": ["asmjit_test_assembler", "--validate"] }, + { "optional": true, "cmd": ["asmjit_test_emitters"] }, + { "optional": true, "cmd": ["asmjit_test_execute"] }, + { "optional": true, "cmd": ["asmjit_test_compiler"] }, + { "optional": true, "cmd": ["asmjit_test_instinfo"] }, + { "optional": true, "cmd": ["asmjit_test_x86_sections"] }, + { "optional": true, "cmd": ["asmjit_test_perf", "--quick"] } ] -} \ No newline at end of file +} diff --git a/deps/asmjit/.github/workflows/build.yml b/deps/asmjit/.github/workflows/build.yml index 0fea3bcf..fe5eaf1c 100644 --- a/deps/asmjit/.github/workflows/build.yml +++ b/deps/asmjit/.github/workflows/build.yml @@ -14,12 +14,12 @@ jobs: steps: - name: "Checkout" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: "Setup node.js" - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: - node-version: "16" + node-version: "*" - name: "Check Enumerations" run: | @@ -31,127 +31,163 @@ jobs: fail-fast: false matrix: include: - - { title: "linux-lib" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Debug" , problem_matcher: "cpp" } - - { title: "macos-lib" , os: "macos-latest" , cc: "clang" , arch: "x64", build_type: "Debug" , problem_matcher: "cpp" } - - { title: "windows-lib" , os: "windows-latest", cc: "vs2022" , arch: "x64", build_type: "Debug" , problem_matcher: "cpp" } + - { title: "diag-analyze" , host: "ubuntu-latest" , arch: "x64" , cc: "clang-18", conf: "Debug" , diagnostics: "analyze-build" } + - { title: "diag-asan" , host: "ubuntu-latest" , arch: "x64" , cc: "clang-18", conf: "Release", diagnostics: "asan", defs: "ASMJIT_TEST=1" } + - { title: "diag-msan" , host: "ubuntu-latest" , arch: "x64" , cc: "clang-18", conf: "Release", diagnostics: "msan", defs: "ASMJIT_TEST=1" } + - { title: "diag-ubsan" , host: "ubuntu-latest" , arch: "x64" , cc: "clang-18", conf: "Release", diagnostics: "ubsan", defs: "ASMJIT_TEST=1" } + - { title: "diag-hardened" , host: "ubuntu-latest" , arch: "x64" , cc: "clang-18", conf: "Release", diagnostics: "hardened", defs: "ASMJIT_TEST=1" } + - { title: "diag-valgrind" , host: "ubuntu-latest" , arch: "x64" , cc: "clang-18", conf: "Release", diagnostics: "valgrind", defs: "ASMJIT_TEST=1" } - - { title: "diag-asan" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", diagnostics: "address" , defs: "ASMJIT_TEST=1" } - - { title: "diag-ubsan" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", diagnostics: "undefined", defs: "ASMJIT_TEST=1" } - - { title: "diag-valgrind" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", diagnostics: "valgrind" , defs: "ASMJIT_TEST=1" } - - { title: "diag-scan-build" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Debug" , diagnostics: "scan-build" } + - { title: "no-deprecated" , host: "ubuntu-latest" , arch: "x64" , cc: "clang-18", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_DEPRECATED=1" } + - { title: "no-intrinsics" , host: "ubuntu-latest" , arch: "x64" , cc: "clang-18", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_INTRINSICS=1" } + - { title: "no-logging" , host: "ubuntu-latest" , arch: "x64" , cc: "clang-18", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_LOGGING=1" } + - { title: "no-logging-text" , host: "ubuntu-latest" , arch: "x64" , cc: "clang-18", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_LOGGING=1,ASMJIT_NO_TEXT=1" } + - { title: "no-builder" , host: "ubuntu-latest" , arch: "x64" , cc: "clang-18", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_BUILDER=1" } + - { title: "no-compiler" , host: "ubuntu-latest" , arch: "x64" , cc: "clang-18", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_COMPILER=1" } + - { title: "no-introspection", host: "ubuntu-latest" , arch: "x64" , cc: "clang-18", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_COMPILER=1,ASMJIT_NO_INTROSPECTION=1" } + - { title: "no-jit" , host: "ubuntu-latest" , arch: "x64" , cc: "clang-18", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_JIT=1" } + - { title: "no-validation" , host: "ubuntu-latest" , arch: "x64" , cc: "clang-18", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_VALIDATION=1" } + - { title: "no-x86" , host: "ubuntu-latest" , arch: "x64" , cc: "clang-18", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_X86=1" } + - { title: "no-aarch64" , host: "ubuntu-latest" , arch: "x64" , cc: "clang-18", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_AARCH64=1" } - - { title: "no-deprecated" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_DEPRECATED=1" } - - { title: "no-intrinsics" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_INTRINSICS=1" } - - { title: "no-logging" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_LOGGING=1" } - - { title: "no-logging-text" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_LOGGING=1,ASMJIT_NO_TEXT=1" } - - { title: "no-builder" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_BUILDER=1" } - - { title: "no-compiler" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_COMPILER=1" } - - { title: "no-jit" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_JIT=1" } - - { title: "no-introspection", os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_INTROSPECTION=1" } - - { title: "no-validation" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_VALIDATION=1" } - - { title: "no-x86" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_X86=1" } - - { title: "no-aarch64" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_AARCH64=1" } + - { title: "linux" , host: "ubuntu-20.04" , arch: "x86" , cc: "gcc-7" , conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-20.04" , arch: "x86" , cc: "gcc-7" , conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-20.04" , arch: "x64" , cc: "gcc-7" , conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-20.04" , arch: "x64" , cc: "gcc-7" , conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-20.04" , arch: "x86" , cc: "gcc-8" , conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-20.04" , arch: "x86" , cc: "gcc-8" , conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-20.04" , arch: "x64" , cc: "gcc-8" , conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-20.04" , arch: "x64" , cc: "gcc-8" , conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "gcc-9" , conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "gcc-9" , conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "gcc-9" , conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "gcc-9" , conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "gcc-10" , conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "gcc-10" , conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "gcc-10" , conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "gcc-10" , conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "gcc-11" , conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "gcc-11" , conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "gcc-11" , conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "gcc-11" , conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "gcc-12" , conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "gcc-12" , conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "gcc-12" , conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "gcc-12" , conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "gcc-13" , conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "gcc-13" , conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "gcc-13" , conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "gcc-13" , conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-20.04" , arch: "x86" , cc: "clang-10", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-20.04" , arch: "x86" , cc: "clang-10", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-20.04" , arch: "x64" , cc: "clang-10", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-20.04" , arch: "x64" , cc: "clang-10", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "clang-11", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "clang-11", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "clang-11", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "clang-11", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "clang-12", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "clang-12", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "clang-12", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "clang-12", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "clang-13", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "clang-13", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "clang-13", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "clang-13", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "clang-14", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "clang-14", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "clang-14", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "clang-14", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "clang-15", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "clang-15", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "clang-15", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "clang-15", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "clang-16", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "clang-16", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "clang-16", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "clang-16", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "clang-17", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "clang-17", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "clang-17", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "clang-17", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "clang-18", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x86" , cc: "clang-18", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "clang-18", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , host: "ubuntu-22.04" , arch: "x64" , cc: "clang-18", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "macos" , host: "macos-12" , arch: "x64" , cc: "gcc-11" , conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "macos" , host: "macos-12" , arch: "x64" , cc: "gcc-11" , conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "macos" , host: "macos-12" , arch: "x64" , cc: "clang" , conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "macos" , host: "macos-12" , arch: "x64" , cc: "clang" , conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "macos" , host: "macos-14" , arch: "arm64" , cc: "clang" , conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "macos" , host: "macos-14" , arch: "arm64" , cc: "clang" , conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "windows" , host: "windows-2019" , arch: "x86" , cc: "vs2019" , conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "windows" , host: "windows-2019" , arch: "x86" , cc: "vs2019" , conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "windows" , host: "windows-2019" , arch: "x64" , cc: "vs2019" , conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "windows" , host: "windows-2019" , arch: "x64" , cc: "vs2019" , conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "windows" , host: "windows-2022" , arch: "x86" , cc: "vs2022" , conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "windows" , host: "windows-2022" , arch: "x86" , cc: "vs2022" , conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "windows" , host: "windows-2022" , arch: "x64" , cc: "vs2022" , conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "windows" , host: "windows-2022" , arch: "x64" , cc: "vs2022" , conf: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-7" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-7" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-7" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-7" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-8" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-8" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-8" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-8" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-9" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-9" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-9" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-9" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-10" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-10" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-10" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-10" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-11" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-11" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-11" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-11" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-12" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-12" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-12" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-12" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-11", arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-11", arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-11", arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-11", arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-12", arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-12", arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-12", arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-12", arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-13", arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-13", arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-13", arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-13", arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-14", arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-14", arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-14", arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-14", arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "macos" , os: "macos-12" , cc: "gcc-11" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "macos" , os: "macos-12" , cc: "gcc-11" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "macos" , os: "macos-12" , cc: "clang" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "macos" , os: "macos-12" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "windows" , os: "windows-2019" , cc: "vs2019" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "windows" , os: "windows-2019" , cc: "vs2019" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "windows" , os: "windows-2019" , cc: "vs2019" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "windows" , os: "windows-2019" , cc: "vs2019" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "windows" , os: "windows-2022" , cc: "vs2022" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "windows" , os: "windows-2022" , cc: "vs2022" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "windows" , os: "windows-2022" , cc: "vs2022" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "windows" , os: "windows-2022" , cc: "vs2022" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } + - { title: "freebsd" , host: "macos-12" , arch: "x86-64" , cc: "clang" , conf: "Release", vm: "freebsd", vm_ver: "13.2", defs: "ASMJIT_TEST=1" } + - { title: "netbsd" , host: "macos-12" , arch: "x86-64" , cc: "clang" , conf: "Release", vm: "netbsd" , vm_ver: "9.3" , defs: "ASMJIT_TEST=1" } + - { title: "openbsd" , host: "macos-12" , arch: "x86-64" , cc: "clang" , conf: "Release", vm: "openbsd", vm_ver: "7.4" , defs: "ASMJIT_TEST=1" } + - { title: "openbsd" , host: "ubuntu-latest" , arch: "arm64" , cc: "clang" , conf: "Release", vm: "openbsd", vm_ver: "7.4" , defs: "ASMJIT_TEST=1" } - - { host: "macos-12" , os: "freebsd", osver: "13.2", cc: "clang", arch: "x86-64", build_type: "Release", defs: "ASMJIT_TEST=ON" } - - { host: "macos-12" , os: "netbsd" , osver: "9.3" , cc: "clang", arch: "x86-64", build_type: "Release", defs: "ASMJIT_TEST=ON" } - - { host: "macos-12" , os: "openbsd", osver: "7.3" , cc: "clang", arch: "x86-64", build_type: "Release", defs: "ASMJIT_TEST=ON" } - - { host: "ubuntu-latest" , os: "openbsd", osver: "7.3" , cc: "clang", arch: "arm64" , build_type: "Release", defs: "ASMJIT_TEST=ON" } + # arm/v7 VM image doesn't work on CI environment at the moment + # - { title: "debian" , host: "ubuntu-latest" , arch: "arm/v7" , cc: "clang" , conf: "Release", vm: "debian:unstable", defs: "ASMJIT_TEST=1" } - name: "${{matrix.title || format('{0}-{1}', matrix.os, matrix.osver)}} (${{matrix.cc}}, ${{matrix.arch}}, ${{matrix.build_type}})" - runs-on: "${{matrix.host || matrix.os}}" + - { title: "debian" , host: "ubuntu-latest" , arch: "arm64" , cc: "clang" , conf: "Release", vm: "debian:unstable", defs: "ASMJIT_TEST=1" } + - { title: "debian" , host: "ubuntu-latest" , arch: "riscv64", cc: "clang" , conf: "Release", vm: "debian:unstable", defs: "ASMJIT_TEST=1" } + - { title: "debian" , host: "ubuntu-latest" , arch: "ppc64le", cc: "clang" , conf: "Release", vm: "debian:unstable", defs: "ASMJIT_TEST=1" } + + name: "${{matrix.title}}/${{matrix.arch}}, ${{matrix.cc}} ${{matrix.conf}}" + runs-on: "${{matrix.host}}" steps: - name: "Checkout" - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: "source" - name: "Checkout Build Actions" - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: build-actions/build-actions path: "build-actions" - name: "Python" - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.x" - - name: "Build & Test" - if: ${{!matrix.host}} + - name: QEMU + if: ${{matrix.vm && !matrix.vm_ver}} + uses: docker/setup-qemu-action@v3 + with: + platforms: linux/${{matrix.arch}} + + - name: "Build & Test - Native" + if: ${{!matrix.vm}} run: python build-actions/action.py - --step=all - --compiler=${{matrix.cc}} - --architecture=${{matrix.arch}} --source-dir=source --config=source/.github/workflows/build-config.json - --build-type=${{matrix.build_type}} + --compiler=${{matrix.cc}} + --diagnostics=${{matrix.diagnostics}} + --architecture=${{matrix.arch}} + --problem-matcher=auto + --build-type=${{matrix.conf}} --build-defs=${{matrix.defs}} - - name: "Build & Test in VM" - if: ${{matrix.host}} + - name: "Build & Test - Cross Platform Actions" + if: ${{matrix.vm && matrix.vm_ver}} uses: cross-platform-actions/action@master with: - operating_system: ${{matrix.os}} + operating_system: ${{matrix.vm}} architecture: ${{matrix.arch}} - version: ${{matrix.osver}} + version: ${{matrix.vm_ver}} + sync_files: "runner-to-vm" + shutdown_vm: false shell: bash run: | set -e @@ -163,11 +199,31 @@ jobs: export CI_NETBSD_USE_PKGIN sh ./build-actions/prepare-environment.sh - python3 build-actions/action.py \ - --step=all \ - --compiler=${{matrix.cc}} \ - --architecture=${{matrix.arch}} \ - --source-dir=source \ - --config=source/.github/workflows/build-config.json \ - --build-type=${{matrix.build_type}} \ + python3 build-actions/action.py \ + --source-dir=source \ + --config=source/.github/workflows/build-config.json \ + --compiler=${{matrix.cc}} \ + --diagnostics=${{matrix.diagnostics}} \ + --architecture=${{matrix.arch}} \ + --problem-matcher=auto \ + --build-type=${{matrix.conf}} \ --build-defs=${{matrix.defs}} + + - name: "Build & Test - Docker + QEMU" + if: ${{matrix.vm && !matrix.vm_ver}} + run: | + docker run \ + --rm \ + -v $(pwd):/${{github.workspace}} \ + -w ${{github.workspace}}/build-actions \ + --platform linux/${{matrix.arch}} \ + ${{matrix.vm}} \ + bash action.sh \ + --source-dir=../source \ + --config=../source/.github/workflows/build-config.json \ + --compiler=${{matrix.cc}} \ + --diagnostics=${{matrix.diagnostics}} \ + --architecture=${{matrix.arch}} \ + --problem-matcher=auto \ + --build-type=${{matrix.conf}} \ + --build-defs=${{matrix.defs}} diff --git a/deps/asmjit/CMakeLists.txt b/deps/asmjit/CMakeLists.txt index 2d8f5be7..375350de 100644 --- a/deps/asmjit/CMakeLists.txt +++ b/deps/asmjit/CMakeLists.txt @@ -1,12 +1,12 @@ -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) +cmake_minimum_required(VERSION 3.8 FATAL_ERROR) cmake_policy(PUSH) -if(POLICY CMP0063) +if (POLICY CMP0063) cmake_policy(SET CMP0063 NEW) # Honor visibility properties. endif() -if(POLICY CMP0092) +if (POLICY CMP0092) cmake_policy(SET CMP0092 NEW) # Don't add -W3 warning level by default. endif() @@ -33,15 +33,13 @@ if (DEFINED ASMJIT_BUILD_STATIC) set(ASMJIT_STATIC "${ASMJIT_BUILD_STATIC}") endif() -# AsmJit - Configuration -# ====================== +# AsmJit - Configuration - Build +# ============================== -# AsmJit testing. if (NOT DEFINED ASMJIT_TEST) set(ASMJIT_TEST FALSE) endif() -# AsmJit build options if (NOT DEFINED ASMJIT_EMBED) set(ASMJIT_EMBED FALSE) endif() @@ -54,15 +52,22 @@ if (NOT DEFINED ASMJIT_SANITIZE) set(ASMJIT_SANITIZE FALSE) endif() -if (NOT DEFINED ASMJIT_NO_NATVIS) - set(ASMJIT_NO_NATVIS FALSE) -endif() - if (NOT DEFINED ASMJIT_NO_CUSTOM_FLAGS) set(ASMJIT_NO_CUSTOM_FLAGS FALSE) endif() -# AsmJit backends selection. +if (NOT DEFINED ASMJIT_NO_NATVIS) + set(ASMJIT_NO_NATVIS FALSE) +endif() + +# EMBED implies STATIC. +if (ASMJIT_EMBED AND NOT ASMJIT_STATIC) + set(ASMJIT_STATIC TRUE) +endif() + +# AsmJit - Configuration - Backend +# ================================ + if (NOT DEFINED ASMJIT_NO_X86) set(ASMJIT_NO_X86 FALSE) endif() @@ -75,7 +80,9 @@ if (NOT DEFINED ASMJIT_NO_FOREIGN) set(ASMJIT_NO_FOREIGN FALSE) endif() -# AsmJit features selection. +# AsmJit - Configuration - Features +# ================================= + if (NOT DEFINED ASMJIT_NO_DEPRECATED) set(ASMJIT_NO_DEPRECATED FALSE) endif() @@ -89,19 +96,19 @@ if (NOT DEFINED ASMJIT_NO_JIT) endif() if (NOT DEFINED ASMJIT_NO_TEXT) - set(ASMJIT_NO_TEXT ${ASMJIT_NO_TEXT}) + set(ASMJIT_NO_TEXT FALSE) endif() if (NOT DEFINED ASMJIT_NO_LOGGING) - set(ASMJIT_NO_LOGGING FALSE) + set(ASMJIT_NO_LOGGING ${ASMJIT_NO_TEXT}) endif() if (NOT DEFINED ASMJIT_NO_VALIDATION) - set(ASMJIT_NO_VALIDATION ${ASMJIT_NO_VALIDATION}) + set(ASMJIT_NO_VALIDATION FALSE) endif() if (NOT DEFINED ASMJIT_NO_INTROSPECTION) - set(ASMJIT_NO_INTROSPECTION ${ASMJIT_NO_INTROSPECTION}) + set(ASMJIT_NO_INTROSPECTION FALSE) endif() if (NOT DEFINED ASMJIT_NO_BUILDER) @@ -109,16 +116,17 @@ if (NOT DEFINED ASMJIT_NO_BUILDER) endif() if (NOT DEFINED ASMJIT_NO_COMPILER) - set(ASMJIT_NO_BUILDER ${ASMJIT_NO_BUILDER}) + if (ASMJIT_NO_BUILDER OR ASMJIT_NO_INTROSPECTION) + set(ASMJIT_NO_COMPILER TRUE) + else() + set(ASMJIT_NO_COMPILER FALSE) + endif() endif() -# EMBED implies STATIC. -if (ASMJIT_EMBED AND NOT ASMJIT_STATIC) - set(ASMJIT_STATIC TRUE) -endif() +# AsmJit - Configuration - CMake Introspection +# ============================================ set(ASMJIT_DIR "${CMAKE_CURRENT_LIST_DIR}" CACHE PATH "Location of 'asmjit'") - set(ASMJIT_TEST "${ASMJIT_TEST}" CACHE BOOL "Build 'asmjit' test applications") set(ASMJIT_EMBED "${ASMJIT_EMBED}" CACHE BOOL "Embed 'asmjit' library (no targets)") set(ASMJIT_STATIC "${ASMJIT_STATIC}" CACHE BOOL "Build 'asmjit' library as static") @@ -212,11 +220,7 @@ function(asmjit_add_target target target_type) set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " ${link_flag}") endforeach() - if (${CMAKE_VERSION} VERSION_LESS "3.8.0") - set_property(TARGET ${target} PROPERTY CXX_STANDARD 11) - else() - target_compile_features(${target} PUBLIC cxx_std_11) - endif() + target_compile_features(${target} PUBLIC cxx_std_11) set_property(TARGET ${target} PROPERTY CXX_EXTENSIONS NO) set_property(TARGET ${target} PROPERTY CXX_VISIBILITY_PRESET hidden) target_compile_options(${target} PRIVATE ${X_CFLAGS} ${ASMJIT_SANITIZE_CFLAGS} $<$:${X_CFLAGS_DBG}> $<$>:${X_CFLAGS_REL}>) @@ -229,17 +233,6 @@ endfunction() # AsmJit - Compiler Support # ========================= -set(ASMJIT_INCLUDE_DIRS "${ASMJIT_DIR}/src") # Include directory is the same as source dir. -set(ASMJIT_DEPS "") # AsmJit dependencies (libraries) for the linker. -set(ASMJIT_LIBS "") # Dependencies of libs/apps that want to use AsmJit. -set(ASMJIT_CFLAGS "") # Public compiler flags. -set(ASMJIT_PRIVATE_CFLAGS "") # Private compiler flags independent of build type. -set(ASMJIT_PRIVATE_CFLAGS_DBG "") # Private compiler flags used by debug builds. -set(ASMJIT_PRIVATE_CFLAGS_REL "") # Private compiler flags used by release builds. -set(ASMJIT_PRIVATE_LFLAGS "") # Private linker flags. -set(ASMJIT_SANITIZE_CFLAGS "") # Compiler flags required by currently enabled sanitizers. -set(ASMJIT_SANITIZE_LFLAGS "") # Linker flags required by currently enabled sanitizers. - # We will have to keep this most likely forever as some users may still be using it. set(ASMJIT_INCLUDE_DIR "${ASMJIT_INCLUDE_DIRS}") @@ -282,7 +275,7 @@ endif() # Support for sanitizers. if (ASMJIT_SANITIZE) - ASMJIT_detect_sanitizers(ASMJIT_SANITIZE_CFLAGS ${ASMJIT_SANITIZE}) + asmjit_detect_sanitizers(ASMJIT_SANITIZE_CFLAGS ${ASMJIT_SANITIZE}) if (ASMJIT_SANITIZE_CFLAGS) message("-- Enabling sanitizers: '${ASMJIT_SANITIZE_CFLAGS}'") @@ -363,21 +356,21 @@ else() set(ASMJIT_TARGET_TYPE "SHARED") endif() -foreach(build_option ASMJIT_STATIC +foreach(build_option # AsmJit build options. + ASMJIT_STATIC + ASMJIT_NO_DEPRECATED # AsmJit backends selection. ASMJIT_NO_X86 ASMJIT_NO_AARCH64 ASMJIT_NO_FOREIGN # AsmJit features selection. - ASMJIT_NO_DEPRECATED - ASMJIT_NO_SHM_OPEN ASMJIT_NO_JIT ASMJIT_NO_TEXT ASMJIT_NO_LOGGING - ASMJIT_NO_BUILDER - ASMJIT_NO_COMPILER + ASMJIT_NO_INTROSPECTION ASMJIT_NO_VALIDATION - ASMJIT_NO_INTROSPECTION) + ASMJIT_NO_BUILDER + ASMJIT_NO_COMPILER) if (${build_option}) List(APPEND ASMJIT_CFLAGS "-D${build_option}") List(APPEND ASMJIT_PRIVATE_CFLAGS "-D${build_option}") @@ -388,7 +381,7 @@ endforeach() # ======================= if (WIN32) - if(CMAKE_LINKER MATCHES "link\\.exe" OR CMAKE_LINKER MATCHES "lld-link\\.exe") + if (CMAKE_LINKER MATCHES "link\\.exe" OR CMAKE_LINKER MATCHES "lld-link\\.exe") set(ASMJIT_LINKER_SUPPORTS_NATVIS TRUE) endif() endif() @@ -443,6 +436,8 @@ set(ASMJIT_SRC_LIST asmjit/core/globals.h asmjit/core/inst.cpp asmjit/core/inst.h + asmjit/core/instdb.cpp + asmjit/core/instdb_p.h asmjit/core/jitallocator.cpp asmjit/core/jitallocator.h asmjit/core/jitruntime.cpp @@ -562,9 +557,7 @@ foreach(src_file ${ASMJIT_SRC_LIST}) endif() endforeach() -if (NOT ${CMAKE_VERSION} VERSION_LESS "3.8.0") - source_group(TREE "${ASMJIT_DIR}" FILES ${ASMJIT_SRC}) -endif() +source_group(TREE "${ASMJIT_DIR}" FILES ${ASMJIT_SRC}) # AsmJit - Summary # ================ @@ -597,7 +590,7 @@ if (NOT ASMJIT_EMBED) $ $) - # Add blend2d::blend2d alias. + # Add asmjit::asmjit alias. add_library(asmjit::asmjit ALIAS asmjit) # TODO: [CMAKE] Deprecated alias - we use projectname::libraryname convention now. add_library(AsmJit::AsmJit ALIAS asmjit) @@ -662,6 +655,7 @@ if (NOT ASMJIT_EMBED) CFLAGS_REL ${ASMJIT_PRIVATE_CFLAGS_REL}) foreach(_target asmjit_test_emitters + asmjit_test_execute asmjit_test_x86_sections) asmjit_add_target(${_target} TEST SOURCES test/${_target}.cpp @@ -682,11 +676,29 @@ if (NOT ASMJIT_EMBED) if (NOT (ASMJIT_NO_BUILDER OR ASMJIT_NO_COMPILER)) # Vectorcall tests and XMM tests require at least SSE2 in 32-bit mode (in 64-bit mode it's implicit). - set(sse2_flags "") - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" OR "x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC") - asmjit_detect_cflags(sse2_flags "-arch:SSE2") - else() - asmjit_detect_cflags(sse2_flags "-msse2") + # Some compilers don't like passing -msse2 for 64-bit targets, and some compilers targeting non-x86 + # would pass "-msse2" compile flag check, but with a warning not detected by CMake. Thus, verify that + # our target is really 32-bit X86 and only use -msse2 or -arch:SSE2 flags when necessary. + set(ASMJIT_SSE2_CFLAGS "") + + check_cxx_source_compiles(" + #if defined(_M_IX86) || defined(__X86__) || defined(__i386__) + int target_is_32_bit_x86() { return 1; } + #else + // Compile error... + #endif + + int main() { + return target_is_32_bit_x86(); + } + " ASMJIT_TARGET_IS_32_BIT_X86) + + if (ASMJIT_TARGET_IS_32_BIT_X86) + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" OR "x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC") + asmjit_detect_cflags(ASMJIT_SSE2_CFLAGS "-arch:SSE2") + else() + asmjit_detect_cflags(ASMJIT_SSE2_CFLAGS "-msse2") + endif() endif() asmjit_add_target(asmjit_test_compiler TEST SOURCES test/asmjit_test_compiler.cpp @@ -694,7 +706,7 @@ if (NOT ASMJIT_EMBED) test/asmjit_test_compiler_a64.cpp test/asmjit_test_compiler_x86.cpp LIBRARIES asmjit::asmjit - CFLAGS ${ASMJIT_PRIVATE_CFLAGS} ${sse2_flags} + CFLAGS ${ASMJIT_PRIVATE_CFLAGS} ${ASMJIT_SSE2_CFLAGS} CFLAGS_DBG ${ASMJIT_PRIVATE_CFLAGS_DBG} CFLAGS_REL ${ASMJIT_PRIVATE_CFLAGS_REL}) endif() diff --git a/deps/asmjit/CONTRIBUTING.md b/deps/asmjit/CONTRIBUTING.md new file mode 100644 index 00000000..54f5047b --- /dev/null +++ b/deps/asmjit/CONTRIBUTING.md @@ -0,0 +1,102 @@ +## How to Contribute to AsmJit + +### Did you find a bug or something isn't working as expected? + + * Please use [Issues](https://github.com/asmjit/asmjit/issues) page to report bugs or create a [pull request](https://github.com/asmjit/asmjit/pulls) if you have already fixed it. + + * Make sure that when a bug is reported it provides as much information as possible to make it easy to either reproduce it locally or to at least guess where the problem could be. AsmJit is a low-level tool, which makes it very easy to emit code that would crash or not work as intended when executed. Always use AsmJit's [Logging](https://asmjit.com/doc/group__asmjit__logging.html) and [Error Handling](https://asmjit.com/doc/group__asmjit__error__handling.html) features first to analyze whether there is not a simple to catch bug in your own code. + + * Don't be afraid to ask for help if you don't know how to solve a particular problem or in case it's unclear how to do it. The community would help if the problem is well described and has a solution. In general we always try to at least improve the documentation in case it doesn't provide enough information and users must ask for help. + +### Asking questions + + * We prefer GitHub issues to be used for reporting bugs or feature requests, but it's still okay to ask questions there as well. However, please consider joining our [Gitter Chat](https://app.gitter.im/#/room/#asmjit:gitter.im) to ask questions; it has an active community that can quickly respond. + +### Suggesting feature requests + + * It's very likely that when using AsmJit you have found something that AsmJit doesn't provide, which would be handy to have as a built-in. The [Issues](https://github.com/asmjit/asmjit/issues) page can be used to submit feature requests, but please keep in mind that AsmJit is a relatively small project and not all requested features will be accepted, especially if they are non-trivial, time consuming to implement, or the scope of the feature doesn't match AsmJit goals. + + * If you have already implemented the feature you are suggesting, please open a [pull request](https://github.com/asmjit/asmjit/pulls). + + * Ports (requesting new AsmJit backends) can be reported as feature requests, but only by people that are willing to work on them as creating new ports takes a lot of time. + +### Suggesting a documentation enhancement + + * [AsmJit's documentation](https://asmjit.com/doc/index.html) is auto-generated from source code, so if you would like to improve it just open a [pull request](https://github.com/asmjit/asmjit/pulls) with your changes. The documentation uses [Doxygen](https://www.doxygen.nl/) as a front-end, so you can use `\ref` keyword to create links and other Doxygen keywords to enhance the documentation. + +### Suggesting a website content enhancement + + * [AsmJit's website](https://asmjit.com) is also generated, but not from public sources at the moment. If you did find an issue on the website you can either use contact information on the [support page](https://asmjit.com/support.html) or to discuss the change on our [Gitter Chat](https://app.gitter.im/#/room/#asmjit:gitter.im). Alternatively, opening a regular issue is also okay. + + +## Coding Style & Consistency + + * If you decide to open a pull request, make sure that the code you submit uses the same convention as the rest of the code. We prefer keeping the code consistent. + + * [.editorconfig](./.editorconfig) should help with basic settings. + + * Initially, AsmJit coding style was based on Google C++ Style Guide, but it has diverged from it. + + * Include guards use `_H_INCLUDED` format. + + * `asmjit` namespace must be open by `ASMJIT_BEGIN_NAMESPACE` and closed by `ASMJIT_END_NAMESPACE` + + * `asmjit::xxx` (backend specific) nested namespace must be open by `ASMJIT_BEGIN_SUB_NAMESPACE(xxx)` and closed by `ASMJIT_END_SUB_NAMESPACE`. + + * Opening bracket is on the same line, like `struct Something {`, `if (condition) {`, etc... + + * The code uses a soft limit of 120 characters per line (including documentation), but it's not enforced and it's okay to use more when it makes sense (for example defining tables, etc...). + + * Since AsmJit doesn't use Exceptions nor RTTI the code cannot use containers provided by the C++ standard library. In general, we try to only use a bare minimum from the C++ standard library to make it viable to use AsmJit even in C code bases where JIT complier is implemented in C++ ([Erlang](https://www.erlang.org/) can be seen as a great example). + +## Testing + + * AsmJit uses a minimalist unit testing framework to write unit tests to avoid third-party dependencies. + + * At the moment tests are in the same file as the implementation and are only compiled when `ASMJIT_TEST` macro is defined. + + * Use `-DASMJIT_TEST=1` when invoking [CMake](https://cmake.org/) to compile AsmJit tests. + + * Unit tests are compiled to a single `asmjit_test_unit[.exe]` executable. + + * Other tests have their own executables based on what is tested. + + * Always add assembler tests when adding new instructions, see [asmjit_test_assembler_x64.cpp](./test/asmjit_test_assembler_x64.cpp) and [asmjit_test_assembler_a64.cpp](./test/asmjit_test_assembler_a64.cpp) for more details. + +## Pull Request Messages + + * If a change fixes a bug the message should should start with `[bug]`. + + * If a change fixes or enhances documentation it should start with `[doc]`. + + * If a change fixes or enhances our CI it should start with `[ci]`. + + * If a change breaks ABI it must start with `[abi]`. + + * Otherwise there is no suggested prefix. + +## ABI Changes + + * ABI changes happen, but they are usually accumulated and committed within a short time window to not break it often. In general we prefer to break ABI once a year, or once 6 months if there is something that has a high priority. There are no hard rules though. + + * AsmJit uses an `inline namespace`, which should make it impossible to link to AsmJit library that is ABI incompatible. When ABI break happens both AsmJit version and ABI namespace are changed, see [asmjit/core/api-config.h](./src/asmjit/core/api-config.h) for more details. + + * What is an ABI break? + + * Modifying a public struct/class in a way that its functionality is altered and/or its size is changed + + * Adding/removing virtual functions to/from classes, respectively + + * Changing a signature of a public function or a class member function (for example adding a parameter). + + * Changing the value of an enum or global constant (for example instructions are now sorted by name, so adding a new instruction breaks ABI) + + * Possibly more, but these were the most common... + + * What is not ABI break? + + * Extending the functionality by using reserved members of a struct/class + + * Adding new API including new structs and classes + + * Changing anything that is internal and that doesn't leak to public headers diff --git a/deps/asmjit/LICENSE.md b/deps/asmjit/LICENSE.md index 020a569d..d87dbf9b 100644 --- a/deps/asmjit/LICENSE.md +++ b/deps/asmjit/LICENSE.md @@ -1,4 +1,4 @@ -Copyright (c) 2008-2020 The AsmJit Authors +Copyright (c) 2008-2024 The AsmJit Authors This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/deps/asmjit/README.md b/deps/asmjit/README.md index 7bf0893b..ee0c7200 100644 --- a/deps/asmjit/README.md +++ b/deps/asmjit/README.md @@ -5,7 +5,7 @@ AsmJit is a lightweight library for machine code generation written in C++ langu * [Official Home Page (asmjit.com)](https://asmjit.com) * [Official Repository (asmjit/asmjit)](https://github.com/asmjit/asmjit) - * [Public Chat Channel](https://gitter.im/asmjit/asmjit) + * [Public Chat Channel](https://app.gitter.im/#/room/#asmjit:gitter.im) * [Zlib License](./LICENSE.md) See [asmjit.com](https://asmjit.com) page for more details, examples, and documentation. @@ -16,39 +16,42 @@ Documentation * [Documentation Index](https://asmjit.com/doc/index.html) * [Build Instructions](https://asmjit.com/doc/group__asmjit__build.html) +Contributing +------------ + + * See [CONTRIBUTING](./CONTRIBUTING.md) page for more details + Breaking Changes ---------------- Breaking the API is sometimes inevitable, what to do? - * See [Breaking Changes Guide](https://asmjit.com/doc/group__asmjit__breaking__changes.html), which is now part of AsmJit documentation. + * See [Breaking Changes Guide](https://asmjit.com/doc/group__asmjit__breaking__changes.html), which is now part of AsmJit documentation * See asmjit tests, they always compile and provide implementation of many use-cases: - * [asmjit_test_emitters.cpp](./test/asmjit_test_emitters.cpp) - Tests that demonstrate the purpose of emitters. - * [asmjit_test_assembler_x86.cpp](./test/asmjit_test_assembler_x86.cpp) - Tests targeting AsmJit's Assembler (x86/x64). - * [asmjit_test_compiler_x86.cpp](./test/asmjit_test_compiler_x86.cpp) - Tests targeting AsmJit's Compiler (x86/x64). - * [asmjit_test_instinfo.cpp](./test/asmjit_test_instinfo.cpp) - Tests that query instruction information. + * [asmjit_test_emitters.cpp](./test/asmjit_test_emitters.cpp) - Tests that demonstrate the purpose of emitters + * [asmjit_test_assembler_x86.cpp](./test/asmjit_test_assembler_x86.cpp) - Tests targeting AsmJit's Assembler (x86/x64) + * [asmjit_test_compiler_x86.cpp](./test/asmjit_test_compiler_x86.cpp) - Tests targeting AsmJit's Compiler (x86/x64) + * [asmjit_test_instinfo.cpp](./test/asmjit_test_instinfo.cpp) - Tests that query instruction information * [asmjit_test_x86_sections.cpp](./test/asmjit_test_x86_sections.cpp) - Multiple sections test. - * Visit our [Official Chat](https://gitter.im/asmjit/asmjit) if you need a quick help. + * Visit our [Gitter Chat](https://app.gitter.im/#/room/#asmjit:gitter.im) if you need a quick help Project Organization -------------------- - * **`/`** - Project root. - * **src** - Source code. - * **asmjit** - Source code and headers (always point include path in here). - * **core** - Core API, backend independent except relocations. - * **arm** - ARM specific API, used only by ARM and AArch64 backends. - * **x86** - X86 specific API, used only by X86 and X64 backends. - * **test** - Unit and integration tests (don't embed in your project). - * **tools** - Tools used for configuring, documenting, and generating files. + * **`/`** - Project root + * **src** - Source code + * **asmjit** - Source code and headers (always point include path in here) + * **core** - Core API, backend independent except relocations + * **arm** - ARM specific API, used only by ARM and AArch64 backends + * **x86** - X86 specific API, used only by X86 and X64 backends + * **test** - Unit and integration tests (don't embed in your project) + * **tools** - Tools used for configuring, documenting, and generating files -TODO ----- +Ports +----- - * [ ] Ports: - * [ ] 32-bit ARM/Thumb port. - * [ ] 64-bit ARM (AArch64) port. - * [ ] RISC-V port. + * [ ] 32-bit ARM/Thumb port (work in progress) + * [ ] RISC-V port (not in progress, help welcome) Support ------- diff --git a/deps/asmjit/db/LICENSE.md b/deps/asmjit/db/LICENSE.md new file mode 100644 index 00000000..9fc2f1a0 --- /dev/null +++ b/deps/asmjit/db/LICENSE.md @@ -0,0 +1,26 @@ +AsmJit database is dual licensed under Zlib and Unlicense (public domain) + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to \ No newline at end of file diff --git a/deps/asmjit/db/README.md b/deps/asmjit/db/README.md index 36444fba..12eaf9b0 100644 --- a/deps/asmjit/db/README.md +++ b/deps/asmjit/db/README.md @@ -1,15 +1,21 @@ AsmJit Instruction Database --------------------------- -This is a database of instructions that is used by AsmJit to generate its internal database and also assembler implementations. This project started initially as AsmDB, but was merged to AsmJit later to make the maintenance easier. The database was created in a way so that each instruction definition would only need a single line in JSON data. The data is then processed by architecture specific data readers that make the data canonical and ready for processing. +This is a database of instructions that is used by AsmJit to generate its internal database and also assembler implementations. This project started initially as AsmDB, but was merged to AsmJit later to make the maintenance easier. The database was created in a way so that each instruction definition would only need a single line in JSON data file. The data is then processed by architecture specific data readers that make the data canonical and ready for processing. AsmJit database provides the following ISAs: * `isa_x86.json` - provides X86 instruction data (both 32-bit and 64-bit) - * `isa_arm.json` - provides AArch32 instruction data (both ARM32 and THUMB) - * `isa_a64.json` - provides AArch64 instruction data + * `isa_aarch32.json` - provides AArch32 instruction data (A32/T16/T32 encoding) + * `isa_aarch64.json` - provides AArch64 instruction data (A64 encoding) + * `isa_aarch64_sme.json` - provides AArch64 SME instruction data (work-in-progress) To Be Documented ---------------- This project will be refactored and documented in the future. + +License +------- + +AsmJit database is dual licensed under Zlib (AsmJit license) or public domain. The database can be used for any purpose, not just by AsmJit. \ No newline at end of file diff --git a/deps/asmjit/db/arm.js b/deps/asmjit/db/aarch32.js similarity index 91% rename from deps/asmjit/db/arm.js rename to deps/asmjit/db/aarch32.js index 6f66b902..dac8ac92 100644 --- a/deps/asmjit/db/arm.js +++ b/deps/asmjit/db/aarch32.js @@ -1,8 +1,7 @@ // This file is part of AsmJit project // // See asmjit.h or LICENSE.md for license and copyright information -// SPDX-License-Identifier: Zlib - +// SPDX-License-Identifier: (Zlib or Unlicense) (function($scope, $as) { "use strict"; @@ -29,14 +28,14 @@ const arm = $scope[$as] = dict(); // Database // ======== -arm.dbName = "isa_arm.json"; +arm.dbName = "isa_aarch32.json"; -// asmdb.arm.Utils -// =============== +// asmdb.aarch32.Utils +// =================== // Can be used to assign the number of bits each part of the opcode occupies. // NOTE: THUMB instructions that use halfword must always specify the width -// of all registers as many instructictions accept only LO (r0..r7) registers. +// of all registers as many instructions accept only LO (r0..r7) registers. const FieldInfo = { "P" : { "bits": 1 }, "U" : { "bits": 1 }, @@ -56,6 +55,7 @@ const FieldInfo = { "cmode" : { "bits": 4 }, "Cn" : { "bits": 4 }, "Cm" : { "bits": 4 }, + "Rd" : { "bits": 4, "read": false, "write": true }, "Rd2" : { "bits": 4, "read": false, "write": true }, "RdLo" : { "bits": 4, "read": false, "write": true }, @@ -70,17 +70,22 @@ const FieldInfo = { "Rs" : { "bits": 4, "read": true , "write": false }, "Rs2" : { "bits": 4, "read": true , "write": false }, "RsList": { "bits": 4, "read": true , "write": false , "list": true }, + "Sd" : { "bits": 4, "read": false, "write": true }, "Sd2" : { "bits": 4, "read": false, "write": true }, + "SdList": { "bits": 4, "read": false, "write": true , "list": true }, "Sx" : { "bits": 4, "read": true , "write": true }, "Sn" : { "bits": 4, "read": true , "write": false }, "Sm" : { "bits": 4, "read": true , "write": false }, "Ss" : { "bits": 4, "read": true , "write": false }, "Ss2" : { "bits": 4, "read": true , "write": false }, + "SsList": { "bits": 4, "read": true , "write": false , "list": true }, + "Dd" : { "bits": 4, "read": false, "write": true }, "Dd2" : { "bits": 4, "read": false, "write": true }, "Dd3" : { "bits": 4, "read": false, "write": true }, "Dd4" : { "bits": 4, "read": false, "write": true }, + "DdList": { "bits": 4, "read": false, "write": true , "list": true }, "Dx" : { "bits": 4, "read": true , "write": true }, "Dx2" : { "bits": 4, "read": true , "write": true }, "Dn" : { "bits": 4, "read": true , "write": false }, @@ -92,18 +97,18 @@ const FieldInfo = { "Ds2" : { "bits": 4, "read": true , "write": false }, "Ds3" : { "bits": 4, "read": true , "write": false }, "Ds4" : { "bits": 4, "read": true , "write": false }, + "DsList": { "bits": 4, "read": true , "write": false , "list": true }, + "Vd" : { "bits": 4, "read": false, "write": true }, "Vd2" : { "bits": 4, "read": false, "write": true }, "Vd3" : { "bits": 4, "read": false, "write": true }, "Vd4" : { "bits": 4, "read": false, "write": true }, - "VdList": { "bits": 4, "read": false, "write": true , "list": true }, "Vx" : { "bits": 4, "read": true , "write": true }, "Vx2" : { "bits": 4, "read": true , "write": true }, "Vn" : { "bits": 4, "read": true , "write": false }, "Vm" : { "bits": 4, "read": true , "write": false }, "Vs" : { "bits": 4, "read": true , "write": false }, "Vs2" : { "bits": 4, "read": true , "write": false }, - "VsList": { "bits": 4, "read": true , "write": false , "list": true } }; arm.FieldInfo = FieldInfo; @@ -192,10 +197,16 @@ function decomposeOperand(s) { const elementSuffix = "[#i]"; let element = null; let consecutive = 0; + let userRegList = false; + + if (s.endsWith("^")) { + userRegList = true; + s = s.substring(0, s.length - 1); + } if (s.endsWith(elementSuffix)) { element = "#i"; - s = s.substr(0, s.length - elementSuffix.length); + s = s.substring(0, s.length - elementSuffix.length); } if (s.endsWith("++")) { @@ -219,7 +230,8 @@ function decomposeOperand(s) { data : s, element : element, restrict: restrict, - consecutive: consecutive + consecutive: consecutive, + userRegList: true }; } @@ -238,8 +250,8 @@ function splitOpcodeFields(s) { return out.map((field) => { return field.trim(); }); } -// asmdb.arm.Operand -// ================= +// asmdb.aarch32.Operand +// ===================== // ARM operand. class Operand extends base.Operand { @@ -267,17 +279,44 @@ class Operand extends base.Operand { else return 0; } + + isRelative() { + if (this.type === "imm") + return this.name === "relA" || this.name === "relS" || this.name === "relZ"; + else + return false; + } } arm.Operand = Operand; -// asmdb.arm.Instruction -// ===================== +// asmdb.aarch32.Instruction +// ========================= function patternFromOperand(key) { return key; // return key.replace(/\b(?:[RVDS](?:d|s|n|m|x|x2))\b/, "R"); } +// Rewrite a memory operand expression (either base or index) to a simplified one, which is okay +// to be generated as C++ expression. In general, we want to simplify != to a more favorable code. +function simplifyMemoryExpression(e) { + if (e.type === "binary" && e.op === "!=" && e.right.type === "var") { + // Rewrite A != PC to A < PC + if (e.right.name === "PC") { e.op = "<"; } + + // Rewrite A != HI to A < 8 + if (e.right.name === "HI") { e.op = "<"; e.right = exp.Imm(8); } + + // Rewrite A != XX to A < SP || A == LR + if (e.right.name === "XX") { + return exp.Or(exp.Lt(e.left, exp.Var("SP")), + exp.Eq(e.left.clone(), exp.Var("LR"))); + } + } + + return e; +} + // ARM instruction. class Instruction extends base.Instruction { constructor(db, data) { @@ -482,13 +521,14 @@ class Instruction extends base.Instruction { const m = part.match(/^([A-Za-z]\w*)/); if (m.length < part.length) { - op.base.exp = exp.parse(part); + op.base.exp = simplifyMemoryExpression(exp.parse(part)); op.base.field = m[1]; } } else if (part.startsWith("#")) { let p = part.substring(1); let u = "1"; + let alwaysNegative = false; let offExp = null; let offMul = 1; @@ -498,6 +538,11 @@ class Instruction extends base.Instruction { p = p.substring(3); } + if (p.startsWith("-")) { + alwaysNegative = false; + p = p.substring(1); + } + const expMatch = p.match(/^([A-Za-z]\w*)==/); if (expMatch) { offExp = exp.parse(p); @@ -515,6 +560,7 @@ class Instruction extends base.Instruction { op.offset.u = u; op.offset.exp = offExp; op.offset.mul = offMul; + op.offset.negative = alwaysNegative; } else { let p = part; @@ -531,7 +577,7 @@ class Instruction extends base.Instruction { const m = p.match(/^([A-Za-z]\w*)/); if (m.length < p.length) { - op.index.exp = exp.parse(p); + op.index.exp = simplifyMemoryExpression(exp.parse(p)); op.index.field = m[1]; } } @@ -858,8 +904,8 @@ class Instruction extends base.Instruction { } arm.Instruction = Instruction; -// asmdb.arm.ISA -// ============= +// asmdb.aarch32.ISA +// ================= function mergeGroupData(data, group) { for (let k in group) { @@ -921,7 +967,7 @@ class ISA extends base.ISA { hasOwn.call(obj, "t16") ? "t16" : ""; if (!encoding) - FAIL(`Instrution ${names.join("/")} doesn't encoding, it must provide either a32, t32, or t16 field`); + FAIL(`Instruction ${names.join("/")} doesn't encoding, it must provide either a32, t32, or t16 field`); for (let j = 0; j < names.length; j++) { const inst = new Instruction(this, names[j], operands, encoding.toUpperCase(), obj[encoding], obj); @@ -938,4 +984,4 @@ class ISA extends base.ISA { arm.ISA = ISA; }).apply(this, typeof module === "object" && module && module.exports - ? [module, "exports"] : [this.asmdb || (this.asmdb = {}), "arm"]); + ? [module, "exports"] : [this.asmdb || (this.asmdb = {}), "aarch32"]); diff --git a/deps/asmjit/db/aarch64.js b/deps/asmjit/db/aarch64.js index ddea8d93..70932f70 100644 --- a/deps/asmjit/db/aarch64.js +++ b/deps/asmjit/db/aarch64.js @@ -1,8 +1,7 @@ // This file is part of AsmJit project // // See asmjit.h or LICENSE.md for license and copyright information -// SPDX-License-Identifier: Zlib - +// SPDX-License-Identifier: (Zlib or Unlicense) (function($scope, $as) { "use strict"; @@ -36,7 +35,7 @@ arm.dbName = "isa_aarch64.json"; // Can be used to assign the number of bits each part of the opcode occupies. // NOTE: THUMB instructions that use halfword must always specify the width -// of all registers as many instructictions accept only LO (r0..r7) registers. +// of all registers as many instructions accept only LO (r0..r7) registers. const FieldInfo = { "P" : { "bits": 1 }, "U" : { "bits": 1 }, diff --git a/deps/asmjit/db/base.js b/deps/asmjit/db/base.js index 06cf74f5..11ef2b1e 100644 --- a/deps/asmjit/db/base.js +++ b/deps/asmjit/db/base.js @@ -1,7 +1,7 @@ // This file is part of AsmJit project // // See asmjit.h or LICENSE.md for license and copyright information -// SPDX-License-Identifier: Zlib +// SPDX-License-Identifier: (Zlib or Unlicense) (function($scope, $as) { "use strict"; @@ -205,7 +205,7 @@ class Operand { toString() { return this.data; } - isReg() { return !!this.reg; } + isReg() { return !!this.reg && this.type !== "reg-list"; } isMem() { return !!this.mem; } isImm() { return !!this.imm; } isRel() { return !!this.rel; } @@ -259,6 +259,20 @@ class Instruction { return out; } + get operandCount() { + return this.operands.length; + } + + get minimumOperandCount() { + const count = this.operands.length; + for (let i = 0; i < count; i++) { + if (this.operands[i].optional) { + return i; + } + } + return count + } + _assignAttribute(key, value) { switch (key) { case "ext": diff --git a/deps/asmjit/db/exp.js b/deps/asmjit/db/exp.js index df69c84a..ac5b325c 100644 --- a/deps/asmjit/db/exp.js +++ b/deps/asmjit/db/exp.js @@ -1,7 +1,7 @@ // This file is part of AsmJit project // // See asmjit.h or LICENSE.md for license and copyright information -// SPDX-License-Identifier: Zlib +// SPDX-License-Identifier: (Zlib or Unlicense) (function($scope, $as) { "use strict"; @@ -87,6 +87,7 @@ class ExpNode { info() { return null; } clone() { throw new Error("ExpNode.clone() must be overridden"); } + evaluate(ctx) { throw new Error("ExpNode.evaluate() must be overridden"); } toString(ctx) { throw new Error("ExpNode.toString() must be overridden"); } } @@ -97,6 +98,7 @@ class ImmNode extends ExpNode { } clone() { return new ImmNode(this.imm); } + evaluate(ctx) { return this.imm; } toString(ctx) { return ctx ? ctx.stringifyImmediate(this.imm) : String(this.imm); } } @@ -106,7 +108,8 @@ class VarNode extends ExpNode { this.name = name || ""; } - clone() { return new VarNode(this.var); } + clone() { return new VarNode(this.name); } + evaluate(ctx) { return ctx.variable(this.name); } toString(ctx) { return ctx ? ctx.stringifyVariable(this.name) : String(this.name); } } @@ -117,7 +120,14 @@ class CallNode extends ExpNode { this.args = args || []; } - clone() { return new CallNode(this.name, this.args.map(function(arg) { return arg.clone(); })); } + clone() { + return new CallNode(this.name, this.args.map(function(arg) { return arg.clone(); })); + } + + evaluate(ctx) { + const evaluatedArgs = this.args.map(function(arg) { return arg.evaluate(ctx); }); + return ctx.function(this.name, evaluatedArgs); + } toString(ctx) { if (this.name === "$bit") { @@ -143,8 +153,23 @@ class UnaryNode extends ExpNode { this.child = child || null; } - info() { return kUnaryOperators[this.op]; } - clone() { return new UnaryNode(this.op, this.left ? this.left.clone() : null); } + info() { + return kUnaryOperators[this.op]; + } + + clone() { + return new UnaryNode(this.op, this.left ? this.left.clone() : null); + } + + evaluate(ctx) { + const val = this.child.evaluate(ctx); + switch (this.op) { + case "-": return (-val); + case "~": return (~val); + case "!": return (val ? 0 : 1); + default : return ctx.unary(this.op, val); + } + } toString(ctx) { return this.info().emit.replace(/@1/g, () => { @@ -166,8 +191,40 @@ class BinaryNode extends ExpNode { this.right = right || null; } - info() { return kBinaryOperators[this.op]; } - clone() { return new BinaryNode(this.op, this.left ? this.left.clone() : null, this.right ? this.right.clone() : null); } + info() { + return kBinaryOperators[this.op]; + } + + clone() { + return new BinaryNode(this.op, this.left ? this.left.clone() : null, this.right ? this.right.clone() : null); + } + + evaluate(ctx) { + const left = this.left.evaluate(ctx); + const right = this.right.evaluate(ctx); + + switch (this.op) { + case "-" : return left - right; + case "+" : return left + right; + case "*" : return left * right; + case "/" : return (left / right)|0; + case "%" : return (left % right)|0; + case "&" : return left & right; + case "|" : return left | right; + case "^" : return left ^ right; + case "<<": return left << right; + case ">>": return left >> right; + case "==": return left == right ? 1 : 0; + case "!=": return left != right ? 1 : 0; + case "<" : return left < right ? 1 : 0; + case "<=": return left <= right ? 1 : 0; + case ">" : return left > right ? 1 : 0; + case ">=": return left >= right ? 1 : 0; + case "&&": return left && right ? 1 : 0; + case "||": return left || right ? 1 : 0; + default : return ctx.binary(this.op, left, right); + } + } toString(ctx) { return this.info().emit.replace(/@[1-2]/g, (p) => { @@ -184,8 +241,6 @@ function Call(name, args) { return new CallNode(name, args); } function Unary(op, child) { return new UnaryNode(op, child); } function Binary(op, left, right) { return new BinaryNode(op, left, right); } -/* -// TODO: Unused, remove? function Negate(child) { return Unary("-", child); } function BitNot(child) { return Unary("~", child); } @@ -207,7 +262,8 @@ function Gt(left, right) { return Binary(">", left, right); } function Ge(left, right) { return Binary(">=", left, right); } function And(left, right) { return Binary("&&", left, right); } function Or(left, right) { return Binary("||", left, right); } -*/ + + // Expression Tokenizer // -------------------- @@ -256,7 +312,44 @@ function newToken(type, position, data, value) { const NoToken = newToken(kTokenNone, -1, "", null); // Must be reset before it can be used, use `RegExp.lastIndex`. -const reValue = /(?:(?:\d*\.\d+|\d+)(?:[E|e][+|-]?\d+)?)/g; +const reNumValue = /(?:(?:\d*\.\d+|\d+)(?:[E|e][+|-]?\d+)?)/g; + +function parseHex(source, from) { + let i = from; + let number = 0; + + while (i < source.length) { + let c = source.charCodeAt(i); + let n = 0; + + if (c >= '0'.charCodeAt(0) && c <= '9'.charCodeAt(0)) { + n = c - '0'.charCodeAt(0); + } + else if (c >= 'a'.charCodeAt(0) && c <= 'f'.charCodeAt(0)) { + n = c - 'a'.charCodeAt(0) + 10; + } + else if (c >= 'A'.charCodeAt(0) && c <= 'F'.charCodeAt(0)) { + n = c - 'A'.charCodeAt(0) + 10; + } + else if (c >= 'g'.charCodeAt(0) && c <= 'z'.charCodeAt(0) || c >= 'g'.charCodeAt(0) && c <= 'Z'.charCodeAt(0)) { + throwExpressionError(`Invalid hex number 0x${source.substring(from, i + 1)}`); + } + else { + break; + } + + number = (number << 4) | n; + i++; + } + + if (i === from) + throwExpressionError(`Invalid number starting with 0x`); + + return { + number: number, + end: i + }; +} function tokenize(source) { const len = source.length; @@ -268,22 +361,33 @@ function tokenize(source) { let c, cat; // Current character code and category. while (i < len) { - cat = Category(c = source.charCodeAt(i)); + c = source.charCodeAt(i); + cat = Category(c); if (cat === kCharSpace) { i++; } else if (cat === kCharDigit) { const n = tokens.length - 1; - if (n >= 0 && tokens[n].data === "." && source[i - 1] === ".") { - tokens.length = n; - i--; - } - reValue.lastIndex = i; - data = reValue.exec(source)[0]; - tokens.push(newToken(kTokenValue, i, data, parseFloat(data))); - i += data.length; + // Hex number. + if (c === '0'.charCodeAt(0) && i + 1 < len && source.charCodeAt(i + 1) === 'x'.charCodeAt(0)) { + const status = parseHex(source, i + 2); + tokens.push(newToken(kTokenValue, i, source.substring(i, status.end), status.number)); + i = status.end; + } + else { + if (n >= 0 && tokens[n].data === "." && source[i - 1] === ".") { + tokens.length = n; + i--; + } + + reNumValue.lastIndex = i; + data = reNumValue.exec(source)[0]; + + tokens.push(newToken(kTokenValue, i, data, parseFloat(data))); + i += data.length; + } } else if (cat === kCharAlpha) { start = i; @@ -623,6 +727,29 @@ $scope[$as] = { Call: Call, Unary: Unary, Binary: Binary, + + Negate: Negate, + BitNot: BitNot, + + Add: Add, + Sub: Sub, + Mul: Mul, + Div: Div, + Mod: Mod, + Shl: Shl, + Shr: Shr, + BitAnd: BitAnd, + BitOr: BitOr, + BitXor: BitXor, + Eq: Eq, + Ne: Ne, + Lt: Lt, + Le: Le, + Gt: Gt, + Ge: Ge, + And: And, + Or: Or, + Visitor: Visitor, ExpressionError: ExpressionError, diff --git a/deps/asmjit/db/index.js b/deps/asmjit/db/index.js index 75449dad..9c32d300 100644 --- a/deps/asmjit/db/index.js +++ b/deps/asmjit/db/index.js @@ -1,11 +1,11 @@ // This file is part of AsmJit project // // See asmjit.h or LICENSE.md for license and copyright information -// SPDX-License-Identifier: Zlib +// SPDX-License-Identifier: (Zlib or Unlicense) "use strict"; exports.base = require("./base.js"); -exports.arm = require("./arm.js"); +exports.aarch32 = require("./aarch32.js"); exports.aarch64 = require("./aarch64.js"); exports.x86 = require("./x86.js"); diff --git a/deps/asmjit/db/isa_arm.json b/deps/asmjit/db/isa_aarch32.json similarity index 61% rename from deps/asmjit/db/isa_arm.json rename to deps/asmjit/db/isa_aarch32.json index 914b99ed..2e530100 100644 --- a/deps/asmjit/db/isa_arm.json +++ b/deps/asmjit/db/isa_aarch32.json @@ -1,39 +1,38 @@ { "instructions": [ {"category": "GP", "data": [ - {"inst": "adc Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0101|0|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "C=R"}, - {"inst": "adc Rd, Rn, Rm, {sop #n}" , "a32": "cond|000|0101|0|Rn|Rd|n:5|sop:2|0|Rm" , "io": "C=R"}, - {"inst": "adc Rd, Rn, #immA" , "a32": "cond|001|0101|0|Rn|Rd|imm:12" , "io": "C=R"}, - {"inst": "adcS Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0101|1|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=X V=W"}, - {"inst": "adcS Rd!=PC, Rn, Rm, {sop #n}" , "a32": "cond|000|0101|1|Rn|Rd|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=X V=W"}, - {"inst": "adcS Rd!=PC, Rn, #immA" , "a32": "cond|001|0101|1|Rn|Rd|imm:12" , "io": "N=W Z=W C=X V=W"}, + {"inst": "adc Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0101|0|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "C=R"}, + {"inst": "adc Rd, Rn, Rm, {sop #n}" , "a32": "cond|000|0101|0|Rn|Rd|n:5|sop:2|0|Rm" , "io": "C=R"}, + {"inst": "adc Rd, Rn, #immA" , "a32": "cond|001|0101|0|Rn|Rd|imm:12" , "io": "C=R"}, + {"inst": "adcS Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0101|1|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=X V=W"}, + {"inst": "adcS Rd!=PC, Rn, Rm, {sop #n}" , "a32": "cond|000|0101|1|Rn|Rd|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=X V=W"}, + {"inst": "adcS Rd!=PC, Rn, #immA" , "a32": "cond|001|0101|1|Rn|Rd|imm:12" , "io": "N=W Z=W C=X V=W"}, {"inst": "add Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0100|0|Rn|Rd|Rs|0|sop:2|1|Rm"}, {"inst": "add Rd, Rn, Rm, {sop #n}" , "a32": "cond|000|0100|0|Rn|Rd|n:5|sop:2|0|Rm"}, {"inst": "add Rd, Rn!=PC, #immA" , "a32": "cond|001|0100|0|Rn|Rd|imm:12"}, - {"inst": "addS Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0100|1|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W V=W"}, - {"inst": "addS Rd!=PC, Rn, Rm, {sop #n}" , "a32": "cond|000|0100|1|Rn|Rd|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W V=W"}, - {"inst": "addS Rd!=PC, Rn, #immA" , "a32": "cond|001|0100|1|Rn|Rd|imm:12" , "io": "N=W Z=W C=W V=W"}, - {"inst": "adr Rd, #RelA" , "a32": "cond|001|0100|0|1111|Rd|RelA:12" , "mode": "add"}, - {"inst": "adr Rd, #RelA" , "a32": "cond|001|0010|0|1111|Rd|RelA:12" , "mode": "sub"}, + {"inst": "addS Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0100|1|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W V=W"}, + {"inst": "addS Rd!=PC, Rn, Rm, {sop #n}" , "a32": "cond|000|0100|1|Rn|Rd|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W V=W"}, + {"inst": "addS Rd!=PC, Rn, #immA" , "a32": "cond|001|0100|1|Rn|Rd|imm:12" , "io": "N=W Z=W C=W V=W"}, + {"inst": "adr Rd, #relA" , "a32": "cond|001|0PN0|0|1111|Rd|relA:12"}, {"inst": "and Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0000|0|Rn|Rd|Rs|0|sop:2|1|Rm"}, {"inst": "and Rd, Rn, Rm, {sop #n}" , "a32": "cond|000|0000|0|Rn|Rd|n:5|sop:2|0|Rm"}, {"inst": "and Rd, Rn, #immA" , "a32": "cond|001|0000|0|Rn|Rd|imm:12"}, - {"inst": "andS Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0000|1|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W"}, - {"inst": "andS Rd!=PC, Rn, Rm, {sop #n}" , "a32": "cond|000|0000|1|Rn|Rd|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W"}, - {"inst": "andS Rd!=PC, Rn, #immA" , "a32": "cond|001|0000|1|Rn|Rd|imm:12" , "io": "N=W Z=W C=W"}, + {"inst": "andS Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0000|1|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W"}, + {"inst": "andS Rd!=PC, Rn, Rm, {sop #n}" , "a32": "cond|000|0000|1|Rn|Rd|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W"}, + {"inst": "andS Rd!=PC, Rn, #immA" , "a32": "cond|001|0000|1|Rn|Rd|imm:12" , "io": "N=W Z=W C=W"}, {"inst": "asr Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1101|0|0000|Rd|Rm|0101|Rn"}, {"inst": "asr Rd, Rn, #n" , "a32": "cond|000|1101|0|0000|Rd|n:5|100|Rn"}, - {"inst": "asrS Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1101|1|0000|Rd|Rm|0101|Rn" , "io": "N=W Z=W C=W"}, - {"inst": "asrS Rd, Rn, #n" , "a32": "cond|000|1101|1|0000|Rd|n:5|100|Rn" , "io": "N=W Z=W C=W"}, + {"inst": "asrS Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1101|1|0000|Rd|Rm|0101|Rn" , "io": "N=W Z=W C=W"}, + {"inst": "asrS Rd, Rn, #n" , "a32": "cond|000|1101|1|0000|Rd|n:5|100|Rn" , "io": "N=W Z=W C=W"}, {"inst": "b #relS*4" , "a32": "cond|101|0|relS:24"}, - {"inst": "bfc Rd!=PC, #lsb, #width" , "a32": "cond|011|1110|msb:5|Rd|lsb:5|001|1111" , "imm": "BfcBfiImm(lsb, width)"}, - {"inst": "bfi Rd!=PC, Rn!=PC, #lsb, #width" , "a32": "cond|011|1110|msb:5|Rd|lsb:5|001|Rn" , "imm": "BfcBfiImm(lsb, width)"}, + {"inst": "bfc Rd!=PC, #lsb, #width" , "a32": "cond|011|1110|msb:5|Rd|lsb:5|001|1111" , "imm": "BfcBfiImm(lsb, width)"}, + {"inst": "bfi Rd!=PC, Rn!=PC, #lsb, #width" , "a32": "cond|011|1110|msb:5|Rd|lsb:5|001|Rn" , "imm": "BfcBfiImm(lsb, width)"}, {"inst": "bic Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|1110|0|Rn|Rd|Rs|0|sop:2|1|Rm"}, {"inst": "bic Rd, Rn, Rm, {sop #n}" , "a32": "cond|000|1110|0|Rn|Rd|n:5|sop:2|0|Rm"}, {"inst": "bic Rd, Rn, #immA" , "a32": "cond|001|1110|0|Rn|Rd|imm:12"}, - {"inst": "bicS Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|1110|1|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W"}, - {"inst": "bicS Rd!=PC, Rn, Rm, {sop #n}" , "a32": "cond|000|1110|1|Rn|Rd|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W"}, - {"inst": "bicS Rd!=PC, Rn, #immA" , "a32": "cond|001|1110|1|Rn|Rd|imm:12" , "io": "N=W Z=W C=W"}, + {"inst": "bicS Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|1110|1|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W"}, + {"inst": "bicS Rd!=PC, Rn, Rm, {sop #n}" , "a32": "cond|000|1110|1|Rn|Rd|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W"}, + {"inst": "bicS Rd!=PC, Rn, #immA" , "a32": "cond|001|1110|1|Rn|Rd|imm:12" , "io": "N=W Z=W C=W"}, {"inst": "bkpt #immZ" , "a32": "cond|000|1001|0|immZ:12|0111|immZ:4"}, {"inst": "bl #relS*4" , "a32": "cond|101|1|relS:24"}, {"inst": "blx Rm!=PC" , "a32": "cond|000|1001|0|1111|1111|1111|0011|Rm"}, @@ -41,12 +40,12 @@ {"inst": "bx Rm" , "a32": "cond|000|1001|0|1111|1111|1111|0001|Rm"}, {"inst": "bxj Rm!=PC" , "a32": "cond|000|1001|0|1111|1111|1111|0010|Rm"}, {"inst": "clz Rd!=PC, Rn!=PC" , "a32": "cond|000|1011|0|1111|Rd|1111|0001|Rn"}, - {"inst": "cmn Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|1011|1|Rn|0000|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W V=W"}, - {"inst": "cmn Rn, Rm, {sop #n}" , "a32": "cond|000|1011|1|Rn|0000|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W V=W"}, - {"inst": "cmn Rn, #immA" , "a32": "cond|001|1011|1|Rn|0000|imm:12" , "io": "N=W Z=W C=W V=W"}, - {"inst": "cmp Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|1010|1|Rn|0000|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W V=W"}, - {"inst": "cmp Rn, Rm, {sop #n}" , "a32": "cond|000|1010|1|Rn|0000|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W V=W"}, - {"inst": "cmp Rn, #immA" , "a32": "cond|001|1010|1|Rn|0000|imm:12" , "io": "N=W Z=W C=W V=W"}, + {"inst": "cmn Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|1011|1|Rn|0000|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W V=W"}, + {"inst": "cmn Rn, Rm, {sop #n}" , "a32": "cond|000|1011|1|Rn|0000|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W V=W"}, + {"inst": "cmn Rn, #immA" , "a32": "cond|001|1011|1|Rn|0000|imm:12" , "io": "N=W Z=W C=W V=W"}, + {"inst": "cmp Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|1010|1|Rn|0000|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W V=W"}, + {"inst": "cmp Rn, Rm, {sop #n}" , "a32": "cond|000|1010|1|Rn|0000|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W V=W"}, + {"inst": "cmp Rn, #immA" , "a32": "cond|001|1010|1|Rn|0000|imm:12" , "io": "N=W Z=W C=W V=W"}, {"inst": "cps #immZ" , "a32": "1111|000|1000|0|0010|0000|000|000|0|immZ:5"}, {"inst": "cpsid #aif" , "a32": "1111|000|1000|0|1100|0000|000|aif:3|0|00000"}, {"inst": "cpsid #aif, #immZ" , "a32": "1111|000|1000|0|1110|0000|000|aif:3|0|immZ:5"}, @@ -55,67 +54,73 @@ {"inst": "eor Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0001|0|Rn|Rd|Rs|0|sop:2|1|Rm"}, {"inst": "eor Rd, Rn, Rm, {sop #n}" , "a32": "cond|000|0001|0|Rn|Rd|n:5|sop:2|0|Rm"}, {"inst": "eor Rd, Rn, #immA" , "a32": "cond|001|0001|0|Rn|Rd|imm:12"}, - {"inst": "eorS Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0001|1|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W"}, - {"inst": "eorS Rd!=PC, Rn, Rm, {sop #n}" , "a32": "cond|000|0001|1|Rn|Rd|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W"}, - {"inst": "eorS Rd!=PC, Rn, #immA" , "a32": "cond|001|0001|1|Rn|Rd|imm:12" , "io": "N=W Z=W C=W"}, + {"inst": "eorS Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0001|1|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W"}, + {"inst": "eorS Rd!=PC, Rn, Rm, {sop #n}" , "a32": "cond|000|0001|1|Rn|Rd|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W"}, + {"inst": "eorS Rd!=PC, Rn, #immA" , "a32": "cond|001|0001|1|Rn|Rd|imm:12" , "io": "N=W Z=W C=W"}, {"inst": "eret" , "a32": "cond|000|1011|0|0000|0000|0000|0110|1110"}, - {"inst": "hlt #immZ" , "a32": "cond|000|1000|0|immZ:12|0111|immZ:4"}, + {"inst": "hlt #immZ" , "a32": "1110|000|1000|0|immZ:12|0111|immZ:4"}, {"inst": "hvc #immZ" , "a32": "cond|000|1010|0|immZ:12|0111|immZ:4"}, - {"inst": "ldm [Rn!=PC]{!}, RdList" , "a32": "cond|100|010W|1|Rn|RdList:16"}, - {"inst": "ldm [Rn!=PC]{!}, RdList" , "a32": "cond|100|011W|1|Rn|RdList:16"}, - {"inst": "ldmda [Rn!=PC]{!}, RdList" , "a32": "cond|100|000W|1|Rn|RdList:16"}, - {"inst": "ldmda [Rn!=PC]{!}, RdList" , "a32": "cond|100|001W|1|Rn|RdList:16"}, - {"inst": "ldmdb [Rn!=PC]{!}, RdList" , "a32": "cond|100|100W|1|Rn|RdList:16"}, - {"inst": "ldmdb [Rn!=PC]{!}, RdList" , "a32": "cond|100|101W|1|Rn|RdList:16"}, - {"inst": "ldmib [Rn!=PC]{!}, RdList" , "a32": "cond|100|110W|1|Rn|RdList:16"}, - {"inst": "ldmib [Rn!=PC]{!}, RdList" , "a32": "cond|100|111W|1|Rn|RdList:16"}, - {"inst": "ldr Rd, [Rn, +/-Rm!=PC, {sop #n}]{@}{!}" , "a32": "cond|011|PU0W|1|Rn|Rd|n:5|sop:2|0|Rm"}, - {"inst": "ldr Rd, [Rn, #+/-off]{@}{!}" , "a32": "cond|010|PU0W|1|Rn|Rd|off:12"}, - {"inst": "ldrb Rd!=PC, [Rn, +/-Rm!=PC, {sop #n}]{@}{!}" , "a32": "cond|011|PU1W|1|Rn|Rd|n:5|sop:2|0|Rm"}, - {"inst": "ldrb Rd!=PC, [Rn, #+/-off]{@}{!}" , "a32": "cond|010|PU1W|1|Rn|Rd|off:12"}, + {"inst": "ldmda [Rn!=PC]{!}, RdList" , "a32": "cond|100|000W|1|Rn|immMask:16" , "imm": "GpListImm(RdList)"}, + {"inst": "ldmdb [Rn!=PC]{!}, RdList" , "a32": "cond|100|100W|1|Rn|immMask:16" , "imm": "GpListImm(RdList)"}, + {"inst": "ldmia [Rn!=PC]{!}, RdList" , "a32": "cond|100|010W|1|Rn|immMask:16" , "imm": "GpListImm(RdList)"}, + {"inst": "ldmib [Rn!=PC]{!}, RdList" , "a32": "cond|100|110W|1|Rn|immMask:16" , "imm": "GpListImm(RdList)"}, + {"inst": "ldmda [Rn!=PC], RdList^" , "a32": "cond|100|0010|1|Rn|immMask:16" , "imm": "GpListImm(RdList)"}, + {"inst": "ldmdb [Rn!=PC], RdList^" , "a32": "cond|100|1010|1|Rn|immMask:16" , "imm": "GpListImm(RdList)"}, + {"inst": "ldmia [Rn!=PC], RdList^" , "a32": "cond|100|0110|1|Rn|immMask:16" , "imm": "GpListImm(RdList)"}, + {"inst": "ldmib [Rn!=PC], RdList^" , "a32": "cond|100|1110|1|Rn|immMask:16" , "imm": "GpListImm(RdList)"}, + {"inst": "ldr Rd, [Rn!=PC, +/-Rm!=PC, {sop #n}]{@}{!}" , "a32": "cond|011|PU0W|1|Rn|Rd|n:5|sop:2|0|Rm"}, + {"inst": "ldr Rd, [Rn!=PC, #+/-off]{@}{!}" , "a32": "cond|010|PU0W|1|Rn|Rd|off:12"}, + {"inst": "ldr Rd, [Rn==PC, #+/-off]" , "a32": "cond|010|1U00|1|Rn|Rd|off:12"}, + {"inst": "ldrb Rd!=PC, [Rn!=PC, +/-Rm!=PC, {sop #n}]{@}{!}" , "a32": "cond|011|PU1W|1|Rn|Rd|n:5|sop:2|0|Rm"}, + {"inst": "ldrb Rd!=PC, [Rn!=PC, #+/-off]{@}{!}" , "a32": "cond|010|PU1W|1|Rn|Rd|off:12"}, + {"inst": "ldrb Rd!=PC, [Rn==PC, #+/-off]" , "a32": "cond|010|1U10|1|Rn|Rd|off:12"}, {"inst": "ldrbt Rd!=PC, [Rn!=PC, +/-Rm!=PC, {sop #n}]@" , "a32": "cond|011|0U11|1|Rn|Rd|n:5|sop:2|0|Rm"}, {"inst": "ldrbt Rd!=PC, [Rn!=PC, #+/-off]@" , "a32": "cond|010|0U11|1|Rn|Rd|off:12"}, - {"inst": "ldrd Rd<=13, Rd2+, [Rn, +/-Rm]{@}{!}" , "a32": "cond|000|PU0W|0|Rn|Rd|0000|1101|Rm"}, - {"inst": "ldrd Rd<=13, Rd2+, [Rn, #+/-off]{!}" , "a32": "cond|000|PU1W|0|Rn|Rd|off:4|1101|off:4"}, + {"inst": "ldrd Rd<=13, Rd2+, [Rn!=PC, +/-Rm]{@}{!}" , "a32": "cond|000|PU0W|0|Rn|Rd|0000|1101|Rm"}, + {"inst": "ldrd Rd<=13, Rd2+, [Rn!=PC, #+/-off]{!}" , "a32": "cond|000|PU1W|0|Rn|Rd|off:4|1101|off:4"}, + {"inst": "ldrd Rd<=13, Rd2+, [Rn==PC, #+/-off]" , "a32": "cond|000|1U10|0|Rn|Rd|off:4|1101|off:4"}, {"inst": "ldrex Rd!=PC, [Rn!=PC]" , "a32": "cond|000|1100|1|Rn|Rd|1111|1001|1111"}, {"inst": "ldrexb Rd!=PC, [Rn!=PC]" , "a32": "cond|000|1110|1|Rn|Rd|1111|1001|1111"}, {"inst": "ldrexd Rd<=13, Rd2+, [Rn!=PC]" , "a32": "cond|000|1101|1|Rn|Rd|1111|1001|1111"}, {"inst": "ldrexh Rd!=PC, [Rn!=PC]" , "a32": "cond|000|1111|1|Rn|Rd|1111|1001|1111"}, - {"inst": "ldrh Rd!=PC, [Rn, +/-Rm!=PC]{@}{!}" , "a32": "cond|000|PU0W|1|Rn|Rd|0000|1011|Rm"}, - {"inst": "ldrh Rd!=PC, [Rn, #+/-off]{@}{!}" , "a32": "cond|000|PU1W|1|Rn|Rd|off:4|1011|off:4"}, + {"inst": "ldrh Rd!=PC, [Rn!=PC, +/-Rm!=PC]{@}{!}" , "a32": "cond|000|PU0W|1|Rn|Rd|0000|1011|Rm"}, + {"inst": "ldrh Rd!=PC, [Rn!=PC, #+/-off]{@}{!}" , "a32": "cond|000|PU1W|1|Rn|Rd|off:4|1011|off:4"}, + {"inst": "ldrh Rd!=PC, [Rn==PC, #+/-off]" , "a32": "cond|000|1U10|1|Rn|Rd|off:4|1011|off:4"}, {"inst": "ldrht Rd!=PC, [Rn!=PC, +/-Rm!=PC]@" , "a32": "cond|000|0U01|1|Rn|Rd|0000|1011|Rm"}, {"inst": "ldrht Rd!=PC, [Rn!=PC, #+/-off]@" , "a32": "cond|000|0U11|1|Rn|Rd|off:4|1011|off:4"}, {"inst": "ldrsb Rd!=PC, [Rn!=PC, +/-Rm!=PC]{@}{!}" , "a32": "cond|000|PU0W|1|Rn|Rd|0000|1101|Rm"}, - {"inst": "ldrsb Rd!=PC, [Rn, #+/-off]{@}{!}" , "a32": "cond|000|PU1W|1|Rn|Rd|off:4|1101|off:4"}, + {"inst": "ldrsb Rd!=PC, [Rn!=PC, #+/-off]{@}{!}" , "a32": "cond|000|PU1W|1|Rn|Rd|off:4|1101|off:4"}, + {"inst": "ldrsb Rd!=PC, [Rn==PC, #+/-off]" , "a32": "cond|000|1U10|1|Rn|Rd|off:4|1101|off:4"}, {"inst": "ldrsbt Rd!=PC, [Rn!=PC, +/-Rm]@" , "a32": "cond|000|0U01|1|Rn|Rd|0000|1101|Rm"}, {"inst": "ldrsbt Rd!=PC, [Rn!=PC, #+/-off]@" , "a32": "cond|000|0U11|1|Rn|Rd|off:4|1101|off:4"}, - {"inst": "ldrsh Rd!=PC, [Rn, +/-Rm!=PC]{@}{!}" , "a32": "cond|000|PU0W|1|Rn|Rd|0000|1111|Rm"}, - {"inst": "ldrsh Rd!=PC, [Rn, #+/-off]{@}{!}" , "a32": "cond|000|PU1W|1|Rn|Rd|off:4|1111|off:4"}, + {"inst": "ldrsh Rd!=PC, [Rn!=PC, +/-Rm!=PC]{@}{!}" , "a32": "cond|000|PU0W|1|Rn|Rd|0000|1111|Rm"}, + {"inst": "ldrsh Rd!=PC, [Rn!=PC, #+/-off]{@}{!}" , "a32": "cond|000|PU1W|1|Rn|Rd|off:4|1111|off:4"}, + {"inst": "ldrsh Rd!=PC, [Rn==PC, #+/-off]" , "a32": "cond|000|1U10|1|Rn|Rd|off:4|1111|off:4"}, {"inst": "ldrsht Rd!=PC, [Rn!=PC, #+/-off]@" , "a32": "cond|000|0U11|1|Rn|Rd|off:4|1111|off:4"}, {"inst": "ldrsht Rd!=PC, [Rn!=PC, +/-Rm!=PC]@" , "a32": "cond|000|0U01|1|Rn|Rd|0000|1111|Rm"}, {"inst": "ldrt Rd!=PC, [Rn!=PC, +/-Rm!=PC, {sop #n}]@" , "a32": "cond|011|0U01|1|Rn|Rd|n:5|sop:2|0|Rm"}, {"inst": "ldrt Rd!=PC, [Rn!=PC, #+/-off]@" , "a32": "cond|010|0U01|1|Rn|Rd|off:12"}, {"inst": "lsl Rd, Rn, #n" , "a32": "cond|000|1101|0|0000|Rd|n:5|000|Rn"}, {"inst": "lsl Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1101|0|0000|Rd|Rm|0001|Rn"}, - {"inst": "lslS Rd, Rn, #n" , "a32": "cond|000|1101|1|0000|Rd|n:5|000|Rn" , "io": "N=W Z=W C=W"}, - {"inst": "lslS Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1101|1|0000|Rd|Rm|0001|Rn" , "io": "N=W Z=W C=W"}, + {"inst": "lslS Rd, Rn, #n" , "a32": "cond|000|1101|1|0000|Rd|n:5|000|Rn" , "io": "N=W Z=W C=W"}, + {"inst": "lslS Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1101|1|0000|Rd|Rm|0001|Rn" , "io": "N=W Z=W C=W"}, {"inst": "lsr Rd, Rn, #n" , "a32": "cond|000|1101|0|0000|Rd|n:5|010|Rn"}, {"inst": "lsr Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1101|0|0000|Rd|Rm|0011|Rn"}, - {"inst": "lsrS Rd, Rn, #n" , "a32": "cond|000|1101|1|0000|Rd|n:5|010|Rn" , "io": "N=W Z=W C=W"}, - {"inst": "lsrS Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1101|1|0000|Rd|Rm|0011|Rn" , "io": "N=W Z=W C=W"}, + {"inst": "lsrS Rd, Rn, #n" , "a32": "cond|000|1101|1|0000|Rd|n:5|010|Rn" , "io": "N=W Z=W C=W"}, + {"inst": "lsrS Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1101|1|0000|Rd|Rm|0011|Rn" , "io": "N=W Z=W C=W"}, {"inst": "mcr #CP, #Op1, Rs!=PC, Cn, Cm, {#Op2}" , "a32": "cond|111|0|Op1:3|0|Cn:4|Rs|CP:4|Op2:3|1|Cm:4"}, {"inst": "mcr2 #CP, #Op1, Rs!=PC, Cn, Cm, {#Op2}" , "a32": "1111|111|0|Op1:3|0|Cn:4|Rs|CP:4|Op2:3|1|Cm:4"}, {"inst": "mcrr #CP, #Op1, Rs!=PC, Rs2!=PC, Cm" , "a32": "cond|110|0010|0|Rs2|Rs|CP:4|Op1:4|Cm:4"}, {"inst": "mcrr2 #CP, #Op1, Rs!=PC, Rs2!=PC, Cm" , "a32": "1111|110|0010|0|Rs2|Rs|CP:4|Op1:4|Cm:4"}, {"inst": "mla Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|000|0001|0|Rd|Ra|Rm|1001|Rn"}, - {"inst": "mlaS Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|000|0001|1|Rd|Ra|Rm|1001|Rn" , "io": "N=W Z=W"}, + {"inst": "mlaS Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|000|0001|1|Rd|Ra|Rm|1001|Rn" , "io": "N=W Z=W"}, {"inst": "mls Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|000|0011|0|Rd|Ra|Rm|1001|Rn"}, {"inst": "mov Rd, Rn, sop Rs" , "a32": "cond|000|1101|0|0000|Rd|Rs|0|sop:2|1|Rn"}, {"inst": "mov Rd, Rn, {sop #n}" , "a32": "cond|000|1101|0|0000|Rd|n:5|sop:2|0|Rn"}, {"inst": "mov Rd, #immA" , "a32": "cond|001|1101|0|0000|Rd|imm:12"}, - {"inst": "movS Rd!=PC, Rn, sop Rs" , "a32": "cond|000|1101|1|0000|Rd|Rs|0|sop:2|1|Rn" , "io": "N=W Z=W C=W"}, - {"inst": "movS Rd!=PC, Rn, {sop #n}" , "a32": "cond|000|1101|1|0000|Rd|n:5|sop:2|0|Rn" , "io": "N=W Z=W C=W"}, - {"inst": "movS Rd!=PC, #immA" , "a32": "cond|001|1101|1|0000|Rd|imm:12" , "io": "N=W Z=W C=W"}, + {"inst": "movS Rd!=PC, Rn, sop Rs" , "a32": "cond|000|1101|1|0000|Rd|Rs|0|sop:2|1|Rn" , "io": "N=W Z=W C=W"}, + {"inst": "movS Rd!=PC, Rn, {sop #n}" , "a32": "cond|000|1101|1|0000|Rd|n:5|sop:2|0|Rn" , "io": "N=W Z=W C=W"}, + {"inst": "movS Rd!=PC, #immA" , "a32": "cond|001|1101|1|0000|Rd|imm:12" , "io": "N=W Z=W C=W"}, {"inst": "movt Rx!=PC, #immZ" , "a32": "cond|001|1010|0|immZ:4|Rx|immZ:12"}, {"inst": "movw Rd!=PC, #immZ" , "a32": "cond|001|1000|0|immZ:4|Rd|immZ:12"}, {"inst": "mrc #CP, #op1, Rd!=PC, Cn, Cm, {#op2}" , "a32": "cond|111|0|op1:3|1|Cn:4|Rd|CP:4|op2:3|1|Cm:4"}, @@ -126,101 +131,100 @@ {"inst": "msr #APSR, Rn!=PC" , "a32": "cond|000|1001|0|APSR:2|00|1111|0000|0000|Rn"}, {"inst": "msr #APSR, #immA" , "a32": "cond|001|1001|0|APSR:2|00|1111|imm:12"}, {"inst": "mul Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|0000|0|Rd|0000|Rm|1001|Rn"}, - {"inst": "mulS Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|0000|1|Rd|0000|Rm|1001|Rn"}, + {"inst": "mulS Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|0000|1|Rd|0000|Rm|1001|Rn" , "io": "N=W Z=W"}, {"inst": "mvn Rd!=PC, Rn!=PC, sop Rs!=PC" , "a32": "cond|000|1111|0|0000|Rd|Rs|0|sop:2|1|Rn"}, {"inst": "mvn Rd, Rn, {sop #n}" , "a32": "cond|000|1111|0|0000|Rd|n:5|sop:2|0|Rn"}, {"inst": "mvn Rd, #immA" , "a32": "cond|001|1111|0|0000|Rd|imm:12"}, - {"inst": "mvnS Rd!=PC, Rn!=PC, sop Rs!=PC" , "a32": "cond|000|1111|1|0000|Rd|Rs|0|sop:2|1|Rn" , "io": "N=W Z=W C=W"}, - {"inst": "mvnS Rd!=PC, Rn, {sop #n}" , "a32": "cond|000|1111|1|0000|Rd|n:5|sop:2|0|Rn" , "io": "N=W Z=W C=W"}, - {"inst": "mvnS Rd!=PC, #immA" , "a32": "cond|001|1111|1|0000|Rd|imm:12" , "io": "N=W Z=W C=W"}, + {"inst": "mvnS Rd!=PC, Rn!=PC, sop Rs!=PC" , "a32": "cond|000|1111|1|0000|Rd|Rs|0|sop:2|1|Rn" , "io": "N=W Z=W C=W"}, + {"inst": "mvnS Rd!=PC, Rn, {sop #n}" , "a32": "cond|000|1111|1|0000|Rd|n:5|sop:2|0|Rn" , "io": "N=W Z=W C=W"}, + {"inst": "mvnS Rd!=PC, #immA" , "a32": "cond|001|1111|1|0000|Rd|imm:12" , "io": "N=W Z=W C=W"}, {"inst": "nop" , "a32": "cond|001|1001|0|0000|1111|0000|0000|0000"}, {"inst": "orr Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|1100|0|Rn|Rd|Rs|0|sop:2|1|Rm"}, {"inst": "orr Rd, Rn, Rm, {sop #n}" , "a32": "cond|000|1100|0|Rn|Rd|n:5|sop:2|0|Rm"}, {"inst": "orr Rd, Rn, #immA" , "a32": "cond|001|1100|0|Rn|Rd|imm:12"}, - {"inst": "orrS Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|1100|1|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W"}, - {"inst": "orrS Rd!=PC, Rn, Rm, {sop #n}" , "a32": "cond|000|1100|1|Rn|Rd|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W"}, - {"inst": "orrS Rd!=PC, Rn, #immA" , "a32": "cond|001|1100|1|Rn|Rd|imm:12" , "io": "N=W Z=W C=W"}, + {"inst": "orrS Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|1100|1|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W"}, + {"inst": "orrS Rd!=PC, Rn, Rm, {sop #n}" , "a32": "cond|000|1100|1|Rn|Rd|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W"}, + {"inst": "orrS Rd!=PC, Rn, #immA" , "a32": "cond|001|1100|1|Rn|Rd|imm:12" , "io": "N=W Z=W C=W"}, {"inst": "pkhbt Rd!=PC, Rn!=PC, Rm!=PC, {lsl #n}" , "a32": "cond|011|0100|0|Rn|Rd|n:5|0|01|Rm"}, {"inst": "pkhtb Rd!=PC, Rn!=PC, Rm!=PC, {asr #n}" , "a32": "cond|011|0100|0|Rn|Rd|n:5|1|01|Rm"}, - {"inst": "pld [Rn, +/-Rm!=PC, {sop #n}]" , "a32": "1111|011|1U10|1|Rn|1111|n:5|sop:2|0|Rm"}, + {"inst": "pld [Rn!=PC, +/-Rm!=PC, {sop #n}]" , "a32": "1111|011|1U10|1|Rn|1111|n:5|sop:2|0|Rm"}, {"inst": "pld [Rn, #+/-off]" , "a32": "1111|010|1U10|1|Rn|1111|off:12"}, {"inst": "pop Rd!=SP" , "a32": "cond|010|0100|1|1101|Rd|0000|0000|0100"}, - {"inst": "pop RdList" , "a32": "cond|100|0101|1|1101|RdList:16"}, + {"inst": "pop RdList" , "a32": "cond|100|0101|1|1101|immMask:16" , "imm": "GpListImm(RdList)"}, {"inst": "push Rs!=SP" , "a32": "cond|010|1001|0|1101|Rs|0000|0000|0100"}, - {"inst": "push RsList" , "a32": "cond|100|1001|0|1101|RsList:16"}, - {"inst": "qadd Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1000|0|Rm|Rd|0000|0101|Rn" , "io": "Q=X"}, + {"inst": "push RsList" , "a32": "cond|100|1001|0|1101|immMask:16" , "imm": "GpListImm(RsList)"}, + {"inst": "qadd Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1000|0|Rm|Rd|0000|0101|Rn" , "io": "Q=X"}, {"inst": "qadd16 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0001|0|Rn|Rd|1111|0001|Rm"}, {"inst": "qadd8 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0001|0|Rn|Rd|1111|1001|Rm"}, {"inst": "qasx Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0001|0|Rn|Rd|1111|0011|Rm"}, - {"inst": "qdadd Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1010|0|Rm|Rd|0000|0101|Rn" , "io": "Q=X"}, - {"inst": "qdsub Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1011|0|Rm|Rd|0000|0101|Rn" , "io": "Q=X"}, + {"inst": "qdadd Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1010|0|Rm|Rd|0000|0101|Rn" , "io": "Q=X"}, + {"inst": "qdsub Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1011|0|Rm|Rd|0000|0101|Rn" , "io": "Q=X"}, {"inst": "qsax Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0001|0|Rn|Rd|1111|0101|Rm"}, - {"inst": "qsub Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1001|0|Rm|Rd|0000|0101|Rn" , "io": "Q=X"}, + {"inst": "qsub Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1001|0|Rm|Rd|0000|0101|Rn" , "io": "Q=X"}, {"inst": "qsub16 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0001|0|Rn|Rd|1111|0111|Rm"}, {"inst": "qsub8 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0001|0|Rn|Rd|1111|1111|Rm"}, {"inst": "rbit Rd!=PC, Rn!=PC" , "a32": "cond|011|0111|1|1111|Rd|1111|0011|Rn"}, {"inst": "rev Rd!=PC, Rn!=PC" , "a32": "cond|011|0101|1|1111|Rd|1111|0011|Rn"}, {"inst": "rev16 Rd!=PC, Rn!=PC" , "a32": "cond|011|0101|1|1111|Rd|1111|1011|Rn"}, {"inst": "revsh Rd!=PC, Rn!=PC" , "a32": "cond|011|0111|1|1111|Rd|1111|1011|Rn"}, - {"inst": "rfe [Rn!=PC]{!}" , "a32": "1111|100|010|W|1|Rn|0000|1010|0000|0000"}, {"inst": "rfeda [Rn!=PC]{!}" , "a32": "1111|100|000|W|1|Rn|0000|1010|0000|0000"}, {"inst": "rfedb [Rn!=PC]{!}" , "a32": "1111|100|100|W|1|Rn|0000|1010|0000|0000"}, + {"inst": "rfeia [Rn!=PC]{!}" , "a32": "1111|100|010|W|1|Rn|0000|1010|0000|0000"}, {"inst": "rfeib [Rn!=PC]{!}" , "a32": "1111|100|110|W|1|Rn|0000|1010|0000|0000"}, {"inst": "ror Rd, Rn, #n" , "a32": "cond|000|1101|0|0000|Rd|n:5|110|Rn"}, {"inst": "ror Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1101|0|0000|Rd|Rm|0111|Rn"}, - {"inst": "rorS Rd, Rn, #n" , "a32": "cond|000|1101|1|0000|Rd|n:5|110|Rn" , "io": "N=W Z=W C=W"}, - {"inst": "rorS Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1101|1|0000|Rd|Rm|0111|Rn" , "io": "N=W Z=W C=W"}, + {"inst": "rorS Rd, Rn, #n" , "a32": "cond|000|1101|1|0000|Rd|n:5|110|Rn" , "io": "N=W Z=W C=W"}, + {"inst": "rorS Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1101|1|0000|Rd|Rm|0111|Rn" , "io": "N=W Z=W C=W"}, {"inst": "rsb Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0011|0|Rn|Rd|Rs|0|sop:2|1|Rm"}, {"inst": "rsb Rd, Rn, Rm, {sop #n}" , "a32": "cond|000|0011|0|Rn|Rd|n:5|sop:2|0|Rm"}, {"inst": "rsb Rd, Rn, #immA" , "a32": "cond|001|0011|0|Rn|Rd|imm:12"}, - {"inst": "rsbS Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0011|1|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W V=W"}, - {"inst": "rsbS Rd!=PC, Rn, Rm, {sop #n}" , "a32": "cond|000|0011|1|Rn|Rd|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W V=W"}, - {"inst": "rsbS Rd!=PC, Rn, #immA" , "a32": "cond|001|0011|1|Rn|Rd|imm:12" , "io": "N=W Z=W C=W V=W"}, + {"inst": "rsbS Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0011|1|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W V=W"}, + {"inst": "rsbS Rd!=PC, Rn, Rm, {sop #n}" , "a32": "cond|000|0011|1|Rn|Rd|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W V=W"}, + {"inst": "rsbS Rd!=PC, Rn, #immA" , "a32": "cond|001|0011|1|Rn|Rd|imm:12" , "io": "N=W Z=W C=W V=W"}, {"inst": "rsc Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0111|0|Rn|Rd|Rs|0|sop:2|1|Rm"}, {"inst": "rsc Rd, Rn, Rm, {sop #n}" , "a32": "cond|000|0111|0|Rn|Rd|n:5|sop:2|0|Rm"}, {"inst": "rsc Rd, Rn, #immA" , "a32": "cond|001|0111|0|Rn|Rd|imm:12"}, - {"inst": "rscS Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0111|1|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W V=W"}, - {"inst": "rscS Rd!=PC, Rn, Rm, {sop #n}" , "a32": "cond|000|0111|1|Rn|Rd|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W V=W"}, - {"inst": "rscS Rd!=PC, Rn, #immA" , "a32": "cond|001|0111|1|Rn|Rd|imm:12" , "io": "N=W Z=W C=W V=W"}, - {"inst": "rrx Rd, Rn" , "a32": "cond|000|1101|0|0000|Rd|00000|110|Rn"}, - {"inst": "rrxS Rd, Rn" , "a32": "cond|000|1101|1|0000|Rd|00000|110|Rn" , "io": "NZ=W C=X"}, - {"inst": "sadd16 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0000|1|Rn|Rd|1111|0001|Rm" , "io": "GE=W"}, - {"inst": "sadd8 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0000|1|Rn|Rd|1111|1001|Rm" , "io": "GE=W"}, - {"inst": "sasx Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0000|1|Rn|Rd|1111|0011|Rm" , "io": "GE=W"}, - {"inst": "sbc Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0110|0|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "C=R"}, - {"inst": "sbc Rd, Rn, Rm, {sop #n}" , "a32": "cond|000|0110|0|Rn|Rd|n:5|sop:2|0|Rm" , "io": "C=R"}, - {"inst": "sbc Rd, Rn, #immA" , "a32": "cond|001|0110|0|Rn|Rd|imm:12" , "io": "C=R"}, - {"inst": "sbcS Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0110|1|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=X V=W"}, - {"inst": "sbcS Rd!=PC, Rn, Rm, {sop #n}" , "a32": "cond|000|0110|1|Rn|Rd|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=X V=W"}, - {"inst": "sbcS Rd!=PC, Rn, #immA" , "a32": "cond|001|0110|1|Rn|Rd|imm:12" , "io": "N=W Z=W C=X V=W"}, - {"inst": "sbfx Rd!=PC, Rn!=PC, #lsb, #width" , "a32": "cond|011|1101|widthM1:5|Rd|lsb:5|101|Rn" , "imm": "SbfxUbfxImm(lsb, width)"}, - {"inst": "sel Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0100|0|Rn|Rd|1111|1011|Rm" , "io": "GE=R"}, - {"inst": "setend #immZ" , "a32": "1111|000|1000|0|0001|0000|00|immZ:1|0|0000|0000" , "ext": "ARMv8-"}, - {"inst": "sevl" , "a32": "cond|001|1001|0|0000|1111|0000|0000|0101"}, + {"inst": "rscS Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0111|1|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W V=W"}, + {"inst": "rscS Rd!=PC, Rn, Rm, {sop #n}" , "a32": "cond|000|0111|1|Rn|Rd|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W V=W"}, + {"inst": "rscS Rd!=PC, Rn, #immA" , "a32": "cond|001|0111|1|Rn|Rd|imm:12" , "io": "N=W Z=W C=W V=W"}, + {"inst": "rrx Rd, Rn" , "a32": "cond|000|1101|0|0000|Rd|00000|110|Rn" , "io": "C=R"}, + {"inst": "rrxS Rd, Rn" , "a32": "cond|000|1101|1|0000|Rd|00000|110|Rn" , "io": "N=W Z=W C=X"}, + {"inst": "sadd16 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0000|1|Rn|Rd|1111|0001|Rm" , "io": "GE=W"}, + {"inst": "sadd8 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0000|1|Rn|Rd|1111|1001|Rm" , "io": "GE=W"}, + {"inst": "sasx Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0000|1|Rn|Rd|1111|0011|Rm" , "io": "GE=W"}, + {"inst": "sbc Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0110|0|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "C=R"}, + {"inst": "sbc Rd, Rn, Rm, {sop #n}" , "a32": "cond|000|0110|0|Rn|Rd|n:5|sop:2|0|Rm" , "io": "C=R"}, + {"inst": "sbc Rd, Rn, #immA" , "a32": "cond|001|0110|0|Rn|Rd|imm:12" , "io": "C=R"}, + {"inst": "sbcS Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0110|1|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=X V=W"}, + {"inst": "sbcS Rd!=PC, Rn, Rm, {sop #n}" , "a32": "cond|000|0110|1|Rn|Rd|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=X V=W"}, + {"inst": "sbcS Rd!=PC, Rn, #immA" , "a32": "cond|001|0110|1|Rn|Rd|imm:12" , "io": "N=W Z=W C=X V=W"}, + {"inst": "sbfx Rd!=PC, Rn!=PC, #lsb, #width" , "a32": "cond|011|1101|widthM1:5|Rd|lsb:5|101|Rn" , "imm": "SbfxUbfxImm(lsb, width)"}, + {"inst": "sel Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0100|0|Rn|Rd|1111|1011|Rm" , "io": "GE=R"}, + {"inst": "setend #immZ" , "a32": "1111|000|1000|0|0001|0000|00|immZ:1|0|0000|0000" , "ext": "ARMv8-"}, {"inst": "shadd16 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0001|1|Rn|Rd|1111|0001|Rm"}, {"inst": "shadd8 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0001|1|Rn|Rd|1111|1001|Rm"}, {"inst": "shasx Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0001|1|Rn|Rd|1111|0011|Rm"}, {"inst": "shsax Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0001|1|Rn|Rd|1111|0101|Rm"}, {"inst": "shsub16 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0001|1|Rn|Rd|1111|0111|Rm"}, {"inst": "shsub8 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0001|1|Rn|Rd|1111|1111|Rm"}, - {"inst": "smlabb Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|000|1000|0|Rd|Ra|Rm|1000|Rn" , "io": "Q=X"}, - {"inst": "smlabt Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|000|1000|0|Rd|Ra|Rm|1100|Rn" , "io": "Q=X"}, - {"inst": "smlatb Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|000|1000|0|Rd|Ra|Rm|1010|Rn" , "io": "Q=X"}, - {"inst": "smlatt Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|000|1000|0|Rd|Ra|Rm|1110|Rn" , "io": "Q=X"}, - {"inst": "smlad Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|011|1000|0|Rd|Ra|Rm|0001|Rn" , "io": "Q=X"}, - {"inst": "smladx Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|011|1000|0|Rd|Ra|Rm|0011|Rn" , "io": "Q=X"}, + {"inst": "smlabb Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|000|1000|0|Rd|Ra|Rm|1000|Rn" , "io": "Q=X"}, + {"inst": "smlabt Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|000|1000|0|Rd|Ra|Rm|1100|Rn" , "io": "Q=X"}, + {"inst": "smlatb Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|000|1000|0|Rd|Ra|Rm|1010|Rn" , "io": "Q=X"}, + {"inst": "smlatt Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|000|1000|0|Rd|Ra|Rm|1110|Rn" , "io": "Q=X"}, + {"inst": "smlad Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|011|1000|0|Rd|Ra|Rm|0001|Rn" , "io": "Q=X"}, + {"inst": "smladx Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|011|1000|0|Rd|Ra|Rm|0011|Rn" , "io": "Q=X"}, {"inst": "smlal RxLo!=PC, RxHi!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|0111|0|RxHi|RxLo|Rm|1001|Rn"}, - {"inst": "smlalS RxLo!=PC, RxHi!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|0111|1|RxHi|RxLo|Rm|1001|Rn" , "io": "N=W Z=W"}, + {"inst": "smlalS RxLo!=PC, RxHi!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|0111|1|RxHi|RxLo|Rm|1001|Rn" , "io": "N=W Z=W"}, {"inst": "smlalbb RxLo!=PC, RxHi!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1010|0|RxHi|RxLo|Rm|1000|Rn"}, {"inst": "smlalbt RxLo!=PC, RxHi!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1010|0|RxHi|RxLo|Rm|1100|Rn"}, {"inst": "smlaltb RxLo!=PC, RxHi!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1010|0|RxHi|RxLo|Rm|1010|Rn"}, {"inst": "smlaltt RxLo!=PC, RxHi!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1010|0|RxHi|RxLo|Rm|1110|Rn"}, {"inst": "smlald RxLo!=PC, RxHi!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|1010|0|RxHi|RxLo|Rm|0001|Rn"}, {"inst": "smlaldx RxLo!=PC, RxHi!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|1010|0|RxHi|RxLo|Rm|0011|Rn"}, - {"inst": "smlawb Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|000|1001|0|Rd|Ra|Rm|1000|Rn" , "io": "Q=X"}, - {"inst": "smlawt Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|000|1001|0|Rd|Ra|Rm|1100|Rn" , "io": "Q=X"}, - {"inst": "smlsd Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|011|1000|0|Rd|Ra|Rm|0101|Rn" , "io": "Q=X"}, - {"inst": "smlsdx Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|011|1000|0|Rd|Ra|Rm|0111|Rn" , "io": "Q=X"}, + {"inst": "smlawb Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|000|1001|0|Rd|Ra|Rm|1000|Rn" , "io": "Q=X"}, + {"inst": "smlawt Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|000|1001|0|Rd|Ra|Rm|1100|Rn" , "io": "Q=X"}, + {"inst": "smlsd Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|011|1000|0|Rd|Ra|Rm|0101|Rn" , "io": "Q=X"}, + {"inst": "smlsdx Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|011|1000|0|Rd|Ra|Rm|0111|Rn" , "io": "Q=X"}, {"inst": "smlsld RxLo!=PC, RxHi!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|1010|0|RxHi|RxLo|Rm|0101|Rn"}, {"inst": "smlsldx RxLo!=PC, RxHi!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|1010|0|RxHi|RxLo|Rm|0111|Rn"}, {"inst": "smmla Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|011|1010|1|Rd|Ra|Rm|0001|Rn"}, @@ -229,50 +233,55 @@ {"inst": "smmlsr Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|011|1010|1|Rd|Ra|Rm|1111|Rn"}, {"inst": "smmul Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|1010|1|Rd|1111|Rm|0001|Rn"}, {"inst": "smmulr Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|1010|1|Rd|1111|Rm|0011|Rn"}, - {"inst": "smuad Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|1000|0|Rd|1111|Rm|0001|Rn" , "io": "Q=X"}, - {"inst": "smuadx Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|1000|0|Rd|1111|Rm|0011|Rn" , "io": "Q=X"}, + {"inst": "smuad Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|1000|0|Rd|1111|Rm|0001|Rn" , "io": "Q=X"}, + {"inst": "smuadx Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|1000|0|Rd|1111|Rm|0011|Rn" , "io": "Q=X"}, {"inst": "smulbb Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1011|0|Rd|0000|Rm|1000|Rn"}, {"inst": "smulbt Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1011|0|Rd|0000|Rm|1100|Rn"}, {"inst": "smultb Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1011|0|Rd|0000|Rm|1010|Rn"}, {"inst": "smultt Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1011|0|Rd|0000|Rm|1110|Rn"}, {"inst": "smull RdLo!=PC, RdHi!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|0110|0|RdHi|RdLo|Rm|1001|Rn"}, - {"inst": "smullS RdLo!=PC, RdHi!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|0110|1|RdHi|RdLo|Rm|1001|Rn" , "io": "N=W Z=W"}, + {"inst": "smullS RdLo!=PC, RdHi!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|0110|1|RdHi|RdLo|Rm|1001|Rn" , "io": "N=W Z=W"}, {"inst": "smulwb Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1001|0|Rd|0000|Rm|1010|Rn"}, {"inst": "smulwt Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|1001|0|Rd|0000|Rm|1110|Rn"}, {"inst": "smusd Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|1000|0|Rd|1111|Rm|0101|Rn"}, {"inst": "smusdx Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|1000|0|Rd|1111|Rm|0111|Rn"}, - {"inst": "srs [Rn==SP]{!}, #mode" , "a32": "1111|100|011|W|0|1101|0000|0101|000|mode:5"}, {"inst": "srsda [Rn==SP]{!}, #mode" , "a32": "1111|100|001|W|0|1101|0000|0101|000|mode:5"}, {"inst": "srsdb [Rn==SP]{!}, #mode" , "a32": "1111|100|101|W|0|1101|0000|0101|000|mode:5"}, + {"inst": "srsia [Rn==SP]{!}, #mode" , "a32": "1111|100|011|W|0|1101|0000|0101|000|mode:5"}, {"inst": "srsib [Rn==SP]{!}, #mode" , "a32": "1111|100|111|W|0|1101|0000|0101|000|mode:5"}, - {"inst": "ssat Rd!=PC, #sat, Rn!=PC" , "a32": "cond|011|0101|imm:5|Rd|00000|00|1|Rn" , "imm": "SsatImm(sat)", "io": "Q=X"}, - {"inst": "ssat Rd!=PC, #sat, Rn!=PC, lsl_or_asr #n" , "a32": "cond|011|0101|imm:5|Rd|n:5|sop:2|1|Rn" , "imm": "SsatImm(sat, n)", "io": "Q=X"}, - {"inst": "ssat16 Rd!=PC, #sat, Rn!=PC" , "a32": "cond|011|0101|0|imm:4|Rd|1111|0011|Rn" , "imm": "Ssat16Imm(sat)", "io": "Q=X"}, - {"inst": "ssax Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0000|1|Rn|Rd|1111|0101|Rm" , "io": "GE=W"}, - {"inst": "ssub16 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0000|1|Rn|Rd|1111|0111|Rm" , "io": "GE=W"}, - {"inst": "ssub8 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0000|1|Rn|Rd|1111|1111|Rm" , "io": "GE=W"}, - {"inst": "stm [Rn!=PC]{!}, RsList" , "a32": "cond|100|010W|0|Rn|RsList:16"}, - {"inst": "stm [Rn!=PC], RsList" , "a32": "cond|100|0110|0|Rn|RsList:16"}, - {"inst": "stmda [Rn!=PC]{!}, RsList" , "a32": "cond|100|000W|0|Rn|RsList:16"}, - {"inst": "stmda [Rn!=PC], RsList" , "a32": "cond|100|0010|0|Rn|RsList:16"}, - {"inst": "stmdb [Rn!=PC]{!}, RsList" , "a32": "cond|100|100W|0|Rn|RsList:16"}, - {"inst": "stmdb [Rn!=PC], RsList" , "a32": "cond|100|1010|0|Rn|RsList:16"}, - {"inst": "stmib [Rn!=PC]{!}, RsList" , "a32": "cond|100|110W|0|Rn|RsList:16"}, - {"inst": "stmib [Rn!=PC], RsList" , "a32": "cond|100|1110|0|Rn|RsList:16"}, - {"inst": "str Rs, [Rn, +/-Rm!=PC, {sop #n}]{@}{!}" , "a32": "cond|011|PU0W|0|Rn|Rs|n:5|sop:2|0|Rm"}, - {"inst": "str Rs, [Rn, #+/-off]{@}{!}" , "a32": "cond|010|PU0W|0|Rn|Rs|off:12"}, - {"inst": "strb Rs!=PC, [Rn, +/-Rm!=PC, {sop #n}]{@}{!}" , "a32": "cond|011|PU1W|0|Rn|Rs|n:5|sop:2|0|Rm"}, - {"inst": "strb Rs!=PC, [Rn, #+/-off]{@}{!}" , "a32": "cond|010|PU1W|0|Rn|Rs|off:12"}, + {"inst": "ssat Rd!=PC, #sat, Rn!=PC" , "a32": "cond|011|0101|imm:5|Rd|00000|00|1|Rn" , "imm": "SsatImm(sat)", "io": "Q=X"}, + {"inst": "ssat Rd!=PC, #sat, Rn!=PC, lsl_or_asr #n" , "a32": "cond|011|0101|imm:5|Rd|n:5|sop:2|1|Rn" , "imm": "SsatImm(sat, n)", "io": "Q=X"}, + {"inst": "ssat16 Rd!=PC, #sat, Rn!=PC" , "a32": "cond|011|0101|0|imm:4|Rd|1111|0011|Rn" , "imm": "Ssat16Imm(sat)", "io": "Q=X"}, + {"inst": "ssax Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0000|1|Rn|Rd|1111|0101|Rm" , "io": "GE=W"}, + {"inst": "ssub16 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0000|1|Rn|Rd|1111|0111|Rm" , "io": "GE=W"}, + {"inst": "ssub8 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0000|1|Rn|Rd|1111|1111|Rm" , "io": "GE=W"}, + {"inst": "stmda [Rn!=PC]{!}, RsList" , "a32": "cond|100|000W|0|Rn|immMask:16" , "imm": "GpListImm(RsList)"}, + {"inst": "stmdb [Rn!=PC]{!}, RsList" , "a32": "cond|100|100W|0|Rn|immMask:16" , "imm": "GpListImm(RsList)"}, + {"inst": "stmia [Rn!=PC]{!}, RsList" , "a32": "cond|100|010W|0|Rn|immMask:16" , "imm": "GpListImm(RsList)"}, + {"inst": "stmib [Rn!=PC]{!}, RsList" , "a32": "cond|100|110W|0|Rn|immMask:16" , "imm": "GpListImm(RsList)"}, + {"inst": "stmda [Rn!=PC], RsList^" , "a32": "cond|100|0010|0|Rn|immMask:16" , "imm": "GpListImm(RsList)"}, + {"inst": "stmdb [Rn!=PC], RsList^" , "a32": "cond|100|1010|0|Rn|immMask:16" , "imm": "GpListImm(RsList)"}, + {"inst": "stmia [Rn!=PC], RsList^" , "a32": "cond|100|0110|0|Rn|immMask:16" , "imm": "GpListImm(RsList)"}, + {"inst": "stmib [Rn!=PC], RsList^" , "a32": "cond|100|1110|0|Rn|immMask:16" , "imm": "GpListImm(RsList)"}, + {"inst": "str Rs, [Rn!=PC, +/-Rm!=PC, {sop #n}]{@}{!}" , "a32": "cond|011|PU0W|0|Rn|Rs|n:5|sop:2|0|Rm"}, + {"inst": "str Rs, [Rn!=PC, #+/-off]{@}{!}" , "a32": "cond|010|PU0W|0|Rn|Rs|off:12"}, + {"inst": "str Rs, [Rn==PC, #+/-off]" , "a32": "cond|010|1U00|0|Rn|Rs|off:12"}, + {"inst": "strb Rs!=PC, [Rn!=PC, +/-Rm!=PC, {sop #n}]{@}{!}" , "a32": "cond|011|PU1W|0|Rn|Rs|n:5|sop:2|0|Rm"}, + {"inst": "strb Rs!=PC, [Rn!=PC, #+/-off]{@}{!}" , "a32": "cond|010|PU1W|0|Rn|Rs|off:12"}, + {"inst": "strb Rs!=PC, [Rn==PC, #+/-off]" , "a32": "cond|010|1U10|0|Rn|Rs|off:12"}, {"inst": "strbt Rs!=PC, [Rn!=PC, +/-Rm!=PC, {sop #n}]@" , "a32": "cond|011|0U11|0|Rn|Rs|n:5|sop:2|0|Rm"}, - {"inst": "strbt Rs!=PC, [Rn, #+/-off]@" , "a32": "cond|010|0U11|0|Rn|Rs|off:12"}, - {"inst": "strd Rs<=13, Rs2+, [Rn, +/-Rm!=PC]{@}{!}" , "a32": "cond|000|PU0W|0|Rn|Rs|0000|1111|Rm"}, - {"inst": "strd Rs<=13, Rs2+, [Rn, #+/-off]{@}{!}" , "a32": "cond|000|PU1W|0|Rn|Rs|off:4|1111|off:4"}, + {"inst": "strbt Rs!=PC, [Rn!=PC, #+/-off]@" , "a32": "cond|010|0U11|0|Rn|Rs|off:12"}, + {"inst": "strbt Rs!=PC, [Rn==PC, #+/-off]" , "a32": "cond|010|0U11|0|Rn|Rs|off:12"}, + {"inst": "strd Rs<=13, Rs2+, [Rn!=PC, +/-Rm!=PC]{@}{!}" , "a32": "cond|000|PU0W|0|Rn|Rs|0000|1111|Rm"}, + {"inst": "strd Rs<=13, Rs2+, [Rn!=PC, #+/-off]{@}{!}" , "a32": "cond|000|PU1W|0|Rn|Rs|off:4|1111|off:4"}, + {"inst": "strd Rs<=13, Rs2+, [Rn==PC, #+/-off]" , "a32": "cond|000|1U10|0|Rn|Rs|off:4|1111|off:4"}, {"inst": "strex Rd!=PC, Rs!=PC, [Rn!=PC]" , "a32": "cond|000|1100|0|Rn|Rd|1111|1001|Rs"}, {"inst": "strexb Rd!=PC, Rs!=PC, [Rn!=PC]" , "a32": "cond|000|1110|0|Rn|Rd|1111|1001|Rs"}, {"inst": "strexd Rd!=PC, Rs!=PC, Rs2+, [Rn!=PC]" , "a32": "cond|000|1101|0|Rn|Rd|1111|1001|Rs"}, {"inst": "strexh Rd!=PC, Rs!=PC, [Rn!=PC]" , "a32": "cond|000|1111|0|Rn|Rd|1111|1001|Rs"}, - {"inst": "strh Rs!=PC, [Rn, +/-Rm!=PC]{@}{!}" , "a32": "cond|000|PU0W|0|Rn|Rs|0000|1011|Rm"}, - {"inst": "strh Rs!=PC, [Rn, #+/-off]{@}{!}" , "a32": "cond|000|PU1W|0|Rn|Rs|off:4|1011|off:4"}, + {"inst": "strh Rs!=PC, [Rn!=PC, +/-Rm!=PC]{@}{!}" , "a32": "cond|000|PU0W|0|Rn|Rs|0000|1011|Rm"}, + {"inst": "strh Rs!=PC, [Rn!=PC, #+/-off]{@}{!}" , "a32": "cond|000|PU1W|0|Rn|Rs|off:4|1011|off:4"}, + {"inst": "strh Rs!=PC, [Rn==PC, #+/-off]" , "a32": "cond|000|1U10|0|Rn|Rs|off:4|1011|off:4"}, {"inst": "strht Rs!=PC, [Rn!=PC, +/-Rm!=PC]@" , "a32": "cond|000|0U01|0|Rn|Rs|0000|1011|Rm"}, {"inst": "strht Rs!=PC, [Rn!=PC, #+/-off]@" , "a32": "cond|000|0U11|0|Rn|Rs|off:4|1011|off:4"}, {"inst": "strt Rs, [Rn!=PC, +/-Rm!=PC, {sop #n}]@" , "a32": "cond|011|0U01|0|Rn|Rs|n:5|sop:2|0|Rm"}, @@ -280,26 +289,26 @@ {"inst": "sub Rd, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0010|0|Rn|Rd|Rs|0|sop:2|1|Rm"}, {"inst": "sub Rd, Rn, Rm, {sop #n}" , "a32": "cond|000|0010|0|Rn|Rd|n:5|sop:2|0|Rm"}, {"inst": "sub Rd, Rn, #immA" , "a32": "cond|001|0010|0|Rn|Rd|imm:12"}, - {"inst": "subS Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0010|1|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W V=W"}, - {"inst": "subS Rd!=PC, Rn, Rm, {sop #n}" , "a32": "cond|000|0010|1|Rn|Rd|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W V=W"}, - {"inst": "subS Rd!=PC, Rn, #immA" , "a32": "cond|001|0010|1|Rn|Rd|imm:12" , "io": "N=W Z=W C=W V=W"}, + {"inst": "subS Rd!=PC, Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|0010|1|Rn|Rd|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W V=W"}, + {"inst": "subS Rd!=PC, Rn, Rm, {sop #n}" , "a32": "cond|000|0010|1|Rn|Rd|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W V=W"}, + {"inst": "subS Rd!=PC, Rn, #immA" , "a32": "cond|001|0010|1|Rn|Rd|imm:12" , "io": "N=W Z=W C=W V=W"}, {"inst": "svc #immZ" , "a32": "cond|1111|immZ:24"}, - {"inst": "sxtab Rd!=PC, Rn!=PC, Rm!=PC, {ror #n}" , "a32": "cond|011|0101|0|Rn|Rd|imm:2|00|0111|Rm" , "imm": "Ror8Imm(n)"}, - {"inst": "sxtab16 Rd!=PC, Rn!=PC, Rm!=PC, {ror #n}" , "a32": "cond|011|0100|0|Rn|Rd|imm:2|00|0111|Rm" , "imm": "Ror8Imm(n)"}, - {"inst": "sxtah Rd!=PC, Rn!=PC, Rm!=PC, {ror #n}" , "a32": "cond|011|0101|1|Rn|Rd|imm:2|00|0111|Rm" , "imm": "Ror8Imm(n)"}, - {"inst": "sxtb Rd!=PC, Rn!=PC, {ror #n}" , "a32": "cond|011|0101|0|1111|Rd|imm:2|00|0111|Rn" , "imm": "Ror8Imm(n)"}, - {"inst": "sxtb16 Rd!=PC, Rn!=PC, {ror #n}" , "a32": "cond|011|0100|0|1111|Rd|imm:2|00|0111|Rn" , "imm": "Ror8Imm(n)"}, - {"inst": "sxth Rd!=PC, Rn!=PC, {ror #n}" , "a32": "cond|011|0101|1|1111|Rd|imm:2|00|0111|Rn" , "imm": "Ror8Imm(n)"}, - {"inst": "teq Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|1001|1|Rn|0000|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W"}, - {"inst": "teq Rn, Rm, {sop #n}" , "a32": "cond|000|1001|1|Rn|0000|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W"}, - {"inst": "teq Rn, #immA" , "a32": "cond|001|1001|1|Rn|0000|imm:12" , "io": "N=W Z=W C=W"}, - {"inst": "tst Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|1000|1|Rn|0000|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W"}, - {"inst": "tst Rn, Rm, {sop #n}" , "a32": "cond|000|1000|1|Rn|0000|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W"}, - {"inst": "tst Rn, #immA" , "a32": "cond|001|1000|1|Rn|0000|imm:12" , "io": "N=W Z=W C=W"}, - {"inst": "uadd16 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0010|1|Rn|Rd|1111|0001|Rm" , "io": "GE=W"}, - {"inst": "uadd8 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0010|1|Rn|Rd|1111|1001|Rm" , "io": "GE=W"}, - {"inst": "uasx Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0010|1|Rn|Rd|1111|0011|Rm" , "io": "GE=W"}, - {"inst": "ubfx Rd!=PC, Rn!=PC, #lsb, #width" , "a32": "cond|011|1111|widthM1:5|Rd|lsb:5|101|Rn" , "imm": "SbfxUbfxImm(lsb, width)"}, + {"inst": "sxtab Rd!=PC, Rn!=PC, Rm!=PC, {ror #n}" , "a32": "cond|011|0101|0|Rn|Rd|imm:2|00|0111|Rm" , "imm": "Ror8Imm(n)"}, + {"inst": "sxtab16 Rd!=PC, Rn!=PC, Rm!=PC, {ror #n}" , "a32": "cond|011|0100|0|Rn|Rd|imm:2|00|0111|Rm" , "imm": "Ror8Imm(n)"}, + {"inst": "sxtah Rd!=PC, Rn!=PC, Rm!=PC, {ror #n}" , "a32": "cond|011|0101|1|Rn|Rd|imm:2|00|0111|Rm" , "imm": "Ror8Imm(n)"}, + {"inst": "sxtb Rd!=PC, Rn!=PC, {ror #n}" , "a32": "cond|011|0101|0|1111|Rd|imm:2|00|0111|Rn" , "imm": "Ror8Imm(n)"}, + {"inst": "sxtb16 Rd!=PC, Rn!=PC, {ror #n}" , "a32": "cond|011|0100|0|1111|Rd|imm:2|00|0111|Rn" , "imm": "Ror8Imm(n)"}, + {"inst": "sxth Rd!=PC, Rn!=PC, {ror #n}" , "a32": "cond|011|0101|1|1111|Rd|imm:2|00|0111|Rn" , "imm": "Ror8Imm(n)"}, + {"inst": "teq Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|1001|1|Rn|0000|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W"}, + {"inst": "teq Rn, Rm, {sop #n}" , "a32": "cond|000|1001|1|Rn|0000|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W"}, + {"inst": "teq Rn, #immA" , "a32": "cond|001|1001|1|Rn|0000|imm:12" , "io": "N=W Z=W C=W"}, + {"inst": "tst Rn!=PC, Rm!=PC, sop Rs!=PC" , "a32": "cond|000|1000|1|Rn|0000|Rs|0|sop:2|1|Rm" , "io": "N=W Z=W C=W"}, + {"inst": "tst Rn, Rm, {sop #n}" , "a32": "cond|000|1000|1|Rn|0000|n:5|sop:2|0|Rm" , "io": "N=W Z=W C=W"}, + {"inst": "tst Rn, #immA" , "a32": "cond|001|1000|1|Rn|0000|imm:12" , "io": "N=W Z=W C=W"}, + {"inst": "uadd16 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0010|1|Rn|Rd|1111|0001|Rm" , "io": "GE=W"}, + {"inst": "uadd8 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0010|1|Rn|Rd|1111|1001|Rm" , "io": "GE=W"}, + {"inst": "uasx Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0010|1|Rn|Rd|1111|0011|Rm" , "io": "GE=W"}, + {"inst": "ubfx Rd!=PC, Rn!=PC, #lsb, #width" , "a32": "cond|011|1111|widthM1:5|Rd|lsb:5|101|Rn" , "imm": "SbfxUbfxImm(lsb, width)"}, {"inst": "udf #immZ" , "a32": "1110|011|1111|1|immZ:12|1111|immZ:4"}, {"inst": "uhadd8 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0011|1|Rn|Rd|1111|1001|Rm"}, {"inst": "uhadd16 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0011|1|Rn|Rd|1111|0001|Rm"}, @@ -309,9 +318,9 @@ {"inst": "uhsub8 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0011|1|Rn|Rd|1111|1111|Rm"}, {"inst": "umaal RxLo!=PC, RxHi!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|0010|0|RxHi|RxLo|Rm|1001|Rn"}, {"inst": "umlal RxLo!=PC, RxHi!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|0101|0|RxHi|RxLo|Rm|1001|Rn"}, - {"inst": "umlalS RxLo!=PC, RxHi!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|0101|1|RxHi|RxLo|Rm|1001|Rn" , "io": "N=W Z=W"}, + {"inst": "umlalS RxLo!=PC, RxHi!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|0101|1|RxHi|RxLo|Rm|1001|Rn" , "io": "N=W Z=W"}, {"inst": "umull RdLo!=PC, RdHi!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|0100|0|RdHi|RdLo|Rm|1001|Rn"}, - {"inst": "umullS RdLo!=PC, RdHi!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|0100|1|RdHi|RdLo|Rm|1001|Rn" , "io": "N=W Z=W"}, + {"inst": "umullS RdLo!=PC, RdHi!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|000|0100|1|RdHi|RdLo|Rm|1001|Rn" , "io": "N=W Z=W"}, {"inst": "uqadd16 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0011|0|Rn|Rd|1111|0001|Rm"}, {"inst": "uqadd8 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0011|0|Rn|Rd|1111|1001|Rm"}, {"inst": "uqasx Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0011|0|Rn|Rd|1111|0011|Rm"}, @@ -322,469 +331,472 @@ {"inst": "usada8 Rd!=PC, Rn!=PC, Rm!=PC, Ra!=PC" , "a32": "cond|011|1100|0|Rd|Ra|Rm|0001|Rn"}, {"inst": "usat Rd!=PC, #sat, Rn!=PC, {lsl_or_asr #n}" , "a32": "cond|011|0111|sat:5|Rd|n:5|sop:2|1|Rn"}, {"inst": "usat16 Rd!=PC, #sat, Rn!=PC" , "a32": "cond|011|0111|0|sat:4|Rd|1111|0011|Rn"}, - {"inst": "usax Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0010|1|Rn|Rd|1111|0101|Rm" , "io": "GE=W"}, - {"inst": "usub16 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0010|1|Rn|Rd|1111|0111|Rm" , "io": "GE=W"}, - {"inst": "usub8 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0010|1|Rn|Rd|1111|1111|Rm" , "io": "GE=W"}, - {"inst": "uxtab Rd!=PC, Rn!=PC, Rm!=PC, {ror #n}" , "a32": "cond|011|0111|0|Rn|Rd|imm:2|00|0111|Rm" , "imm": "Ror8Imm(n)"}, - {"inst": "uxtab16 Rd!=PC, Rn!=PC, Rm!=PC, {ror #n}" , "a32": "cond|011|0110|0|Rn|Rd|imm:2|00|0111|Rm" , "imm": "Ror8Imm(n)"}, - {"inst": "uxtah Rd!=PC, Rn!=PC, Rm!=PC, {ror #n}" , "a32": "cond|011|0111|1|Rn|Rd|imm:2|00|0111|Rm" , "imm": "Ror8Imm(n)"}, - {"inst": "uxtb Rd!=PC, Rn!=PC, {ror #n}" , "a32": "cond|011|0111|0|1111|Rd|imm:2|00|0111|Rn" , "imm": "Ror8Imm(n)"}, - {"inst": "uxtb16 Rd!=PC, Rn!=PC, {ror #n}" , "a32": "cond|011|0110|0|1111|Rd|imm:2|00|0111|Rn" , "imm": "Ror8Imm(n)"}, - {"inst": "uxth Rd!=PC, Rn!=PC, {ror #n}" , "a32": "cond|011|0111|1|1111|Rd|imm:2|00|0111|Rn" , "imm": "Ror8Imm(n)"}, + {"inst": "usax Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0010|1|Rn|Rd|1111|0101|Rm" , "io": "GE=W"}, + {"inst": "usub16 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0010|1|Rn|Rd|1111|0111|Rm" , "io": "GE=W"}, + {"inst": "usub8 Rd!=PC, Rn!=PC, Rm!=PC" , "a32": "cond|011|0010|1|Rn|Rd|1111|1111|Rm" , "io": "GE=W"}, + {"inst": "uxtab Rd!=PC, Rn!=PC, Rm!=PC, {ror #n}" , "a32": "cond|011|0111|0|Rn|Rd|imm:2|00|0111|Rm" , "imm": "Ror8Imm(n)"}, + {"inst": "uxtab16 Rd!=PC, Rn!=PC, Rm!=PC, {ror #n}" , "a32": "cond|011|0110|0|Rn|Rd|imm:2|00|0111|Rm" , "imm": "Ror8Imm(n)"}, + {"inst": "uxtah Rd!=PC, Rn!=PC, Rm!=PC, {ror #n}" , "a32": "cond|011|0111|1|Rn|Rd|imm:2|00|0111|Rm" , "imm": "Ror8Imm(n)"}, + {"inst": "uxtb Rd!=PC, Rn!=PC, {ror #n}" , "a32": "cond|011|0111|0|1111|Rd|imm:2|00|0111|Rn" , "imm": "Ror8Imm(n)"}, + {"inst": "uxtb16 Rd!=PC, Rn!=PC, {ror #n}" , "a32": "cond|011|0110|0|1111|Rd|imm:2|00|0111|Rn" , "imm": "Ror8Imm(n)"}, + {"inst": "uxth Rd!=PC, Rn!=PC, {ror #n}" , "a32": "cond|011|0111|1|1111|Rd|imm:2|00|0111|Rn" , "imm": "Ror8Imm(n)"}, {"inst": "wfe" , "a32": "cond|001|1001|0|0000|1111|0000|0000|0010"}, {"inst": "wfi" , "a32": "cond|001|1001|0|0000|1111|0000|0000|0011"}, {"inst": "yield" , "a32": "cond|001|1001|0|0000|1111|0000|0000|0001"} ]}, {"category": "GP", "data": [ - {"inst": "adc Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|101|Rm:3|Rx:3" , "it": "in" , "io": "C=R"}, - {"inst": "adc Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|1010|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "C=R"}, - {"inst": "adc Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|1010|0|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "C=R"}, - {"inst": "adcS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|101|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=X V=W", "mod": "APSR_IF_NOT_PC"}, - {"inst": "adcS Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|1010|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=X V=W", "mod": "APSR_IF_NOT_PC"}, - {"inst": "adcS Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|1010|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=X V=W", "mod": "APSR_IF_NOT_PC"}, - {"inst": "add Rd!=HI, Rn!=HI, Rm!=HI" , "t16": "0001|100|Rm:3|Rn:3|Rd:3" , "it": "in"}, - {"inst": "add Rx!=XX, Rx!=XX, Rm!=XX" , "t16": "0100|010|0|Rx:1|Rm:4|Rx:3" , "it": "in"}, - {"inst": "add Rx, Rx, Rm==SP" , "t16": "0100|010|0|Rx:1|Rm:4|Rx:3" , "it": "any"}, - {"inst": "add Rx==SP, Rx==SP, Rm" , "t16": "0100|010|0|Rx:1|Rm:4|Rx:3" , "it": "any"}, - {"inst": "add Rx!=HI, Rx!=HI, #immZ" , "t16": "0011|0|Rx:3|immZ:8" , "it": "in"}, - {"inst": "add Rd!=HI, Rn!=HI, #immZ" , "t16": "0001|110|immZ:3|Rn:3|Rd:3" , "it": "in"}, - {"inst": "add Rx==SP, Rx==SP, #immZ*4" , "t16": "1011|00000|immZ:7" , "it": "any"}, - {"inst": "add Rd!=SP, Rn==SP, #immZ*4" , "t16": "1010|1|Rd:3|immZ:8" , "it": "any"}, - {"inst": "add Rd!=XX, Rn!=PC, Rm!=XX, {sop #n}" , "t32": "1110|101|1000|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, - {"inst": "add Rd!=PC, Rn==SP, Rm!=XX, {sop #n}" , "t32": "1110|101|1000|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "mod": "LSL_3_IF_SP"}, - {"inst": "add Rd!=XX, Rn!=PC, #immZ" , "t32": "1111|0|immZ:1|1|0000|0|Rn|0|immZ:3|Rd|immZ:8" , "it": "any"}, - {"inst": "add Rd!=XX, Rn!=PC, #immA" , "t32": "1111|0|imm:1|0|1000|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, - {"inst": "add Rd!=PC, Rn==SP, #immZ" , "t32": "1111|0|immZ:1|1|0000|0|Rn|0|immZ:3|Rd|immZ:8" , "it": "any"}, - {"inst": "add Rd!=PC, Rn==SP, #immA" , "t32": "1111|0|imm:1|0|1000|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, - {"inst": "addS Rx!=HI, Rx!=HI, #immZ" , "t16": "0011|0|Rx:3|immZ:8" , "it": "out", "io": "N=W Z=W C=W V=W"}, - {"inst": "addS Rd!=HI, Rn!=HI, #immZ" , "t16": "0001|110|immZ:3|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W V=W"}, - {"inst": "addS Rd!=HI, Rn!=HI, Rm!=HI" , "t16": "0001|100|Rm:3|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W V=W"}, - {"inst": "addS Rd!=XX, Rn!=PC, Rm!=XX, {sop #n}" , "t32": "1110|101|1000|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, - {"inst": "addS Rd!=PC, Rn==SP, Rm!=XX, {sop #n}" , "t32": "1110|101|1000|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "mod": "LSL_3_IF_SP"}, - {"inst": "addS Rd!=XX, Rn!=PC, #immA" , "t32": "1111|0|imm:1|0|1000|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W V=W"}, - {"inst": "addS Rd!=PC, Rn==SP, #immA" , "t32": "1111|0|imm:1|0|1000|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W V=W"}, - {"inst": "adr Rd!=HI, #relZ*4" , "t16": "1010|0|Rd:3|relZ:8" , "it": "any", "mode": "add"}, - {"inst": "adr Rd!=XX, #relZ" , "t32": "1111|0|relZ:1|10000|0|1111|0|relZ:3|Rd|relZ:8" , "it": "any", "mode": "add"}, - {"inst": "adr Rd!=XX, #relZ" , "t32": "1111|0|relZ:1|10101|0|1111|0|relZ:3|Rd|relZ:8" , "it": "any", "mode": "sub"}, - {"inst": "and Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|000|Rm:3|Rx:3" , "it": "in"}, - {"inst": "and Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|0000|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, - {"inst": "and Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|1010|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, - {"inst": "andS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|000|Rm:3|Rx:3" , "io": "N=W Z=W"}, - {"inst": "andS Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|0000|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "andS Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|1010|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W V=W", "mod": "APSR_IF_NOT_PC"}, - {"inst": "asr Rd!=HI, Rn!=HI, #n" , "t16": "0001|0|n:5|Rn:3|Rd:3" , "it": "in"}, - {"inst": "asr Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|100|Rm:3|Rx:3" , "it": "in"}, - {"inst": "asr Rd!=XX, Rn!=XX, #n" , "t32": "1110|101|0010|0|1111|0|n:3|Rd|n:2|10|Rn" , "it": "any"}, - {"inst": "asr Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0010|0|Rn|1111|Rd|0000|Rm" , "it": "any"}, - {"inst": "asrS Rd!=HI, Rn!=HI, #n" , "t16": "0001|0|n:5|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W"}, - {"inst": "asrS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|100|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, - {"inst": "asrS Rd!=XX, Rn!=XX, #n" , "t32": "1110|101|0010|1|1111|0|n:3|Rd|n:2|10|Rn" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "asrS Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0010|1|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "b #relS*2" , "t16": "1101|cond|relS:8" , "it": "out"}, - {"inst": "b #relS*2" , "t16": "1110|0|relS:11" , "it": "out last"}, - {"inst": "b #relS*2" , "t32": "1111|0|relS[19]|cond|relS[16:11]|10|ja|0|jb|relS[10:0]" , "it": "out", "calc": {"ja": "relS[19] ^ relS[18] ^ 1", "jb": "relS[19] ^ relS[17] ^ 1"}}, - {"inst": "b #relS*2" , "t32": "1111|0|relS[23]| relS[20:11]|10|ja|1|jb|relS[10:0]" , "it": "out last", "calc": {"ja": "relS[23] ^ relS[22] ^ 1", "jb": "relS[23] ^ relS[21] ^ 1"}}, - {"inst": "bfc Rd!=XX, #lsb, #width" , "t32": "1111|001|1011|0|1111|0|lsb:3|Rd|lsb:2|0|msb:5" , "it": "any", "imm": "BfcBfiImm(lsb, width)"}, - {"inst": "bfi Rd!=XX, Rn!=XX, #lsb, #width" , "t32": "1111|001|1011|0|Rn|0|lsb:3|Rd|lsb:2|0|msb:5" , "it": "any", "imm": "BfcBfiImm(lsb, width)"}, - {"inst": "bic Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|001|110|Rm:3|Rx:3" , "it": "in"}, - {"inst": "bic Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|0001|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, - {"inst": "bic Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|0001|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, - {"inst": "bicS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|001|110|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, - {"inst": "bicS Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|0001|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "bicS Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|0001|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "bkpt #immZ" , "t16": "1011|111|0|immZ:8" , "it": "uncond"}, - {"inst": "bl #relS*2" , "t32": "1111|0|relS[23]|relS[20:11]|11|ja|1|jb|relS[10:0]" , "it": "out last"}, - {"inst": "blx Rm!=PC" , "t16": "0100|011|11|Rm:4|000" , "it": "out last"}, - {"inst": "blx #relS*4" , "t32": "1111|0|relS[22]|relS[19:10]|11|ja|0|jb|relS[9:0]|0" , "it": "out last"}, - {"inst": "bx Rm" , "t16": "0100|011|10|Rm:4|000" , "it": "out last"}, - {"inst": "bxj Rm!=XX" , "t32": "1111|001|1110|0|Rm|1000|1111|00000000" , "it": "out last"}, - {"inst": "cbz Rn!=HI, #relZ*2" , "t16": "1011|00|relZ:1|1|relZ:5|Rn:3" , "it": "out"}, - {"inst": "cbnz Rn!=HI, #relZ*2" , "t16": "1011|10|relZ:1|1|relZ:5|Rn:3" , "it": "out"}, - {"inst": "clz Rd!=XX, Rn!=XX" , "t32": "1111|101|0101|1|Rm|1111|Rd|1000|Rn" , "it": "any"}, - {"inst": "cmn Rn!=HI, Rm!=HI" , "t16": "0100|001|011|Rm:3|Rn:3" , "it": "any", "io": "N=W Z=W C=W V=W"}, - {"inst": "cmn Rn!=PC, Rm!=XX, {sop #n}" , "t32": "1110|101|1000|1|Rn|0|n:3|1111|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W V=W"}, - {"inst": "cmn Rn!=PC, #immA" , "t32": "1111|0|imm:1|0|1000|1|Rn|0|imm:3|1111|imm:8" , "it": "any", "io": "N=W Z=W C=W V=W"}, - {"inst": "cmp Rn!=HI, #immZ" , "t16": "0010|1|Rn:3|immZ:8" , "it": "any", "io": "N=W Z=W C=W V=W"}, - {"inst": "cmp Rn!=HI, Rm!=HI" , "t16": "0100|001|010|Rm:3|Rn:3" , "it": "any", "io": "N=W Z=W C=W V=W"}, - {"inst": "cmp Rn!=PC, Rm!=PC" , "t16": "0100|010|1|Rn:1|Rm:4|Rn:3" , "it": "any", "io": "N=W Z=W C=W V=W", "mod": "UNPRED_IF_ALL_LOW"}, - {"inst": "cmp Rn!=PC, Rm!=XX, {sop #n}" , "t32": "1110|101|1101|1|Rn|0|n:3|1111|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W V=W"}, - {"inst": "cmp Rn!=PC, #immA" , "t32": "1111|0|imm:1|0|1101|1|Rn|0|imm:3|1111|imm:8" , "it": "any", "io": "N=W Z=W C=W V=W"}, - {"inst": "dbg #immZ" , "t32": "1111|001|1101|0|1111|1000|0000|1111|immZ:4" , "it": "any"}, - {"inst": "eor Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|001|Rm:3|Rx:3" , "it": "in"}, - {"inst": "eor Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|0100|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, - {"inst": "eor Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|0100|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, - {"inst": "eorS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|001|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, - {"inst": "eorS Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|0100|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "eorS Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|0100|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "it #FirstCond!=15" , "t16": "1011|111|1|FirstCond[3:0]|1000" , "it": "out def"}, - {"inst": "ite #FirstCond!=15" , "t16": "1011|111|1|FirstCond[3:0]|X100" , "it": "out def"}, - {"inst": "itee #FirstCond!=15" , "t16": "1011|111|1|FirstCond[3:0]|XY10" , "it": "out def"}, - {"inst": "iteee #FirstCond!=15" , "t16": "1011|111|1|FirstCond[3:0]|XYZ1" , "it": "out def"}, - {"inst": "iteet #FirstCond!=15" , "t16": "1011|111|1|FirstCond[3:0]|XYZ1" , "it": "out def"}, - {"inst": "itet #FirstCond!=15" , "t16": "1011|111|1|FirstCond[3:0]|XY10" , "it": "out def"}, - {"inst": "itete #FirstCond!=15" , "t16": "1011|111|1|FirstCond[3:0]|XYZ1" , "it": "out def"}, - {"inst": "itett #FirstCond!=15" , "t16": "1011|111|1|FirstCond[3:0]|XYZ1" , "it": "out def"}, - {"inst": "itt #FirstCond!=15" , "t16": "1011|111|1|FirstCond[3:0]|X100" , "it": "out def"}, - {"inst": "itte #FirstCond!=15" , "t16": "1011|111|1|FirstCond[3:0]|XY10" , "it": "out def"}, - {"inst": "ittee #FirstCond!=15" , "t16": "1011|111|1|FirstCond[3:0]|XYZ1" , "it": "out def"}, - {"inst": "ittet #FirstCond!=15" , "t16": "1011|111|1|FirstCond[3:0]|XYZ1" , "it": "out def"}, - {"inst": "ittt #FirstCond!=15" , "t16": "1011|111|1|FirstCond[3:0]|XY10" , "it": "out def"}, - {"inst": "ittte #FirstCond!=15" , "t16": "1011|111|1|FirstCond[3:0]|XYZ1" , "it": "out def"}, - {"inst": "itttt #FirstCond!=15" , "t16": "1011|111|1|FirstCond[3:0]|XYZ1" , "it": "out def"}, - {"inst": "ldm [Rn!=HI]{!}, RdList" , "t16": "1100|1|Rn:3|RdList:8" , "it": "any", "mod": "T16_LDM"}, - {"inst": "ldm [Rn!=PC]{!}, RdList" , "t32": "1110|100|010W|1|Rn|RdList[15:14]|0|RdList[12:0]" , "it": "any", "mod": "T32_LDM"}, - {"inst": "ldmdb [Rn!=PC]{!}, RdList" , "t32": "1110|100|100W|1|Rn|RdList[15:14]|0|RdList[12:0]" , "it": "any", "mod": "T32_LDM"}, - {"inst": "ldr Rd!=HI, [Rn!=HI, Rm!=HI]" , "t16": "0101|100|Rm:3|Rn:3|Rd:3" , "it": "any"}, - {"inst": "ldr Rd, [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|0010|1|Rn|Rd|0|00000|n:2|Rm" , "it": "any"}, - {"inst": "ldr Rd!=HI, [Rn!=HI, #off*4]" , "t16": "0110|1|off:5|Rn:3|Rd:3" , "it": "any"}, - {"inst": "ldr Rd!=HI, [Rn==SP, #off*4]" , "t16": "1001|1|Rd:3|off:8" , "it": "any"}, - {"inst": "ldr Rd!=HI, [Rn==PC, #off*4]" , "t16": "0100|1|Rd:3|off:8" , "it": "any"}, - {"inst": "ldr Rd, [Rn!=PC, #off]" , "t32": "1111|100|0110|1|Rn|Rd|off:12" , "it": "any"}, - {"inst": "ldr Rd, [Rn!=PC, #+/-off]{@}{!}" , "t32": "1111|100|0010|1|Rn|Rd|1PUW|off:8" , "it": "any"}, - {"inst": "ldr Rd, [Rn==PC, #+/-off]" , "t32": "1111|100|0U10|1|Rn|Rd|off:12" , "it": "any"}, - {"inst": "ldrb Rd!=HI, [Rn!=HI, Rm!=HI]" , "t16": "0101|110|Rm:3|Rn:3|Rd:3" , "it": "any"}, - {"inst": "ldrb Rd!=XX, [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|0000|1|Rn|Rd|0|00000|n:2|Rm" , "it": "any"}, - {"inst": "ldrb Rd!=HI, [Rn!=HI, #off*4]" , "t16": "0111|1|off:5|Rn:3|Rd:3" , "it": "any"}, - {"inst": "ldrb Rd!=XX, [Rn!=PC, #off]" , "t32": "1111|100|0100|1|Rn|Rd|off:12" , "it": "any"}, - {"inst": "ldrb Rd!=XX, [Rn!=PC, #+/-off]{!}" , "t32": "1111|100|0000|1|Rn|Rd|1PUW|off:8" , "it": "any"}, - {"inst": "ldrb Rd!=XX, [Rn==PC, #+/-off]" , "t32": "1111|100|0U00|1|Rn|Rd|off:12" , "it": "any"}, - {"inst": "ldrbt Rd!=XX, [Rn!=PC, #off]" , "t32": "1111|100|0000|1|Rn|Rd|1110|off:8" , "it": "any"}, - {"inst": "ldrd Rd!=XX, Rd2!=XX, [Rn==PC, #+/-off*4]" , "t32": "1110|100|PU10|1|Rn|Rd|Rd2|off:8" , "it": "any"}, - {"inst": "ldrd Rd!=XX, Rd2!=XX, [Rn!=PC, #+/-off*4]{@}{!}" , "t32": "1110|100|PU1W|1|Rn|Rd|Rd2|off:8" , "it": "any"}, - {"inst": "ldrex Rd!=XX, [Rn!=PC, #off*4]" , "t32": "1110|100|0010|1|Rn|Rd|1111|off:8" , "it": "any"}, - {"inst": "ldrh Rd!=HI, [Rn!=HI, Rm!=HI]" , "t16": "0101|101|Rm:3|Rn:3|Rd:3" , "it": "any"}, - {"inst": "ldrh Rd!=XX, [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|0001|1|Rn|Rd|0|00000|n:2|Rm" , "it": "any"}, - {"inst": "ldrh Rd!=HI, [Rn!=HI, #off*4]" , "t16": "1000|1|off:5|Rn:3|Rd:3" , "it": "any"}, - {"inst": "ldrh Rd!=XX, [Rn!=PC, #off]" , "t32": "1111|100|0101|1|Rn|Rd|off:12" , "it": "any"}, - {"inst": "ldrh Rd!=XX, [Rn!=PC, #+/-off]{@}{!}" , "t32": "1111|100|0001|1|Rn|Rd|1PUW|off:8" , "it": "any"}, - {"inst": "ldrh Rd!=XX, [Rn==PC, #+/-off]" , "t32": "1111|100|0U01|1|Rn|Rd|off:12" , "it": "any"}, - {"inst": "ldrht Rd!=XX, [Rn!=PC, #off]" , "t32": "1111|100|0001|1|Rn|Rd|1110|off:8" , "it": "any"}, - {"inst": "ldrsb Rd!=HI, [Rn!=HI, Rm!=HI]" , "t16": "0101|011|Rm:3|Rn:3|Rd:3" , "it": "any"}, - {"inst": "ldrsb Rd!=XX, [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|1000|1|Rn|Rd|0|00000|n:2|Rm" , "it": "any"}, - {"inst": "ldrsb Rd!=XX, [Rn!=PC, #off]" , "t32": "1111|100|1100|1|Rn|Rd|off:12" , "it": "any"}, - {"inst": "ldrsb Rd!=XX, [Rn!=PC, #+/-off]{@}{!}" , "t32": "1111|100|1000|1|Rn|Rd|1PUW|off:8" , "it": "any"}, - {"inst": "ldrsb Rd!=XX, [Rn==PC, #+/-off]" , "t32": "1111|100|1U00|1|Rn|Rd|off:12" , "it": "any"}, - {"inst": "ldrsbt Rd!=XX, [Rn!=PC, #off]" , "t32": "1111|100|1000|1|Rn|Rd|1110|off:8" , "it": "any"}, - {"inst": "ldrsh Rd!=HI, [Rn!=HI, Rm!=HI]" , "t16": "0101|111|Rm:3|Rn:3|Rd:3" , "it": "any"}, - {"inst": "ldrsh Rd!=XX, [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|1001|1|Rn|Rd|0|00000|n:2|Rm" , "it": "any"}, - {"inst": "ldrsh Rd!=XX, [Rn!=PC, #off]" , "t32": "1111|100|1101|1|Rn|Rd|off:12" , "it": "any"}, - {"inst": "ldrsh Rd!=XX, [Rn!=PC, #+/-off]{@}{!}" , "t32": "1111|100|1001|1|Rn|Rd|1PUW|off:8" , "it": "any"}, - {"inst": "ldrsh Rd!=XX, [Rn==PC, #+/-off]" , "t32": "1111|100|1U01|1|Rn|Rd|off:12" , "it": "any"}, - {"inst": "ldrsht Rd!=XX, [Rn!=PC, #off]" , "t32": "1111|100|1001|1|Rn|Rd|1110|off:8" , "it": "any"}, - {"inst": "ldrt Rd!=XX, [Rn!=PC, #off]" , "t32": "1111|100|0010|1|Rn|Rd|1110|off:8" , "it": "any"}, - {"inst": "lsl Rd!=HI, Rn!=HI, #n" , "t16": "0000|0|n:5|Rn:3|Rd:3" , "it": "in"}, - {"inst": "lsl Rd!=XX, Rn!=XX, #n" , "t32": "1110|101|0010|0|1111|0|n:3|Rd|n:2|00|Rn" , "it": "any"}, - {"inst": "lsl Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|010|Rm:3|Rx:3" , "it": "in"}, - {"inst": "lsl Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0000|0|Rn|1111|Rd|0000|Rm" , "it": "any"}, - {"inst": "lslS Rd!=HI, Rn!=HI, #n" , "t16": "0000|0|n:5|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W"}, - {"inst": "lslS Rd!=XX, Rn!=XX, #n" , "t32": "1110|101|0010|1|1111|0|n:3|Rd|n:2|00|Rn" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "lslS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|010|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, - {"inst": "lslS Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1110|101|0000|1|Rn|1111|Rd|0000|Rm" , "it": "any"}, - {"inst": "lsr Rd!=HI, Rn!=HI, #n" , "t16": "0000|1|n:5|Rn:3|Rd:3" , "it": "in"}, - {"inst": "lsr Rd!=XX, Rn!=XX, #n" , "t32": "1110|101|0010|0|1111|0|n:3|Rd|n:2|01|Rn" , "it": "any"}, - {"inst": "lsr Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|011|Rm:3|Rx:3" , "it": "in"}, - {"inst": "lsr Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0001|0|Rn|1111|Rd|0000|Rm" , "it": "any"}, - {"inst": "lsrS Rd!=HI, Rn!=HI, #n" , "t16": "0000|1|n:5|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W"}, - {"inst": "lsrS Rd!=XX, Rn!=XX, #n" , "t32": "1110|101|0010|1|1111|0|n:3|Rd|n:2|01|Rn" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "lsrS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|011|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, - {"inst": "lsrS Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1110|101|0001|1|Rn|1111|Rd|0000|Rm" , "it": "any"}, - {"inst": "mcr #CP, #Op1, Rs!=XX, Cn, Cm, {#Op2}" , "t32": "1110|111|0|Op1:3|0|Cn:4|Rs|CP:4|Op2:3|1|Cm:4" , "ext": "ARMv6T2+"}, - {"inst": "mcr2 #CP, #Op1, Rs!=XX, Cn, Cm, {#Op2}" , "t32": "1111|111|0|Op1:3|0|Cn:4|Rs|CP:4|Op2:3|1|Cm:4" , "ext": "ARMv6T2+"}, - {"inst": "mcrr #CP, #Op1, Rs!=XX, Rs2!=XX, Cm" , "t32": "1110|110|0010|0|Rs2|Rs|CP:4|Op1:4|Cm:4" , "ext": "ARMv6T2+"}, - {"inst": "mcrr2 #CP, #Op1, Rs!=XX, Rs2!=XX, Cm" , "t32": "1111|110|0010|0|Rs2|Rs|CP:4|Op1:4|Cm:4" , "ext": "ARMv6T2+"}, - {"inst": "mla Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1000|0|Rn|Ra|Rd|0000|Rm" , "it": "any"}, - {"inst": "mls Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1000|0|Rn|Ra|Rd|0001|Rm" , "it": "any"}, - {"inst": "mov Rd, Rn" , "t16": "0100|0110|Rd:1|Rn:4|Rd:3" , "it": "in", "mod": "ARMv6T2_IF_LOW"}, - {"inst": "mov Rx!=HI, Rx!=HI, lsl Rm!=HI" , "t16": "0100|000|010|Rm:3|Rx:3" , "it": "in"}, - {"inst": "mov Rx!=HI, Rx!=HI, lsr Rm!=HI" , "t16": "0100|000|011|Rm:3|Rx:3" , "it": "in"}, - {"inst": "mov Rx!=HI, Rx!=HI, asr Rm!=HI" , "t16": "0100|000|100|Rm:3|Rx:3" , "it": "in"}, - {"inst": "mov Rx!=HI, Rx!=HI, ror Rm!=HI" , "t16": "0100|000|111|Rm:3|Rx:3" , "it": "in"}, - {"inst": "mov Rd!=HI, Rn!=HI, lsl #n" , "t16": "0000|0|n:5|Rn:3|Rd:3" , "it": "in"}, - {"inst": "mov Rd!=HI, Rn!=HI, lsr #n" , "t16": "0000|1|n:5|Rn:3|Rd:3" , "it": "in"}, - {"inst": "mov Rd!=HI, Rn!=HI, asr #n" , "t16": "0001|0|n:5|Rn:3|Rd:3" , "it": "in"}, - {"inst": "mov Rd!=HI, #immZ" , "t16": "0010|0|Rd:3|immZ:8" , "it": "in"}, - {"inst": "mov Rd!=PC, Rn" , "t32": "1110|101|0010|0|1111|0000|Rd|0000|Rn" , "it": "any", "mod": "UNPRED_COMPLEX"}, - {"inst": "mov Rd!=XX, Rn!=XX, sop #n" , "t32": "1110|101|0010|0|1111|0|n:3|Rd|n:2|sop:2|Rn" , "it": "any"}, - {"inst": "mov Rd!=XX, Rn!=XX, sop Rm!=XX" , "t32": "1111|101|00|sop:2|0|Rn|1111|Rd|0000|Rm" , "it": "any"}, - {"inst": "mov Rd!=XX, #immA" , "t32": "1111|0|imm:1|0|0010|0|1111|0|imm:3|Rd|imm:8" , "it": "any"}, - {"inst": "movS Rd!=HI, Rn!=HI" , "t16": "0000|0000|00|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W"}, - {"inst": "movS Rx!=HI, Rx!=HI, lsl Rm!=HI" , "t16": "0100|000|010|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, - {"inst": "movS Rx!=HI, Rx!=HI, lsr Rm!=HI" , "t16": "0100|000|011|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, - {"inst": "movS Rx!=HI, Rx!=HI, asr Rm!=HI" , "t16": "0100|000|100|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, - {"inst": "movS Rx!=HI, Rx!=HI, ror Rm!=HI" , "t16": "0100|000|111|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, - {"inst": "movS Rd!=HI, Rn!=HI, lsl #n" , "t16": "0000|0|n:5|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W"}, - {"inst": "movS Rd!=HI, Rn!=HI, lsr #n" , "t16": "0000|1|n:5|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W"}, - {"inst": "movS Rd!=HI, Rn!=HI, asr #n" , "t16": "0001|0|n:5|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W"}, - {"inst": "movS Rd!=HI, #immZ" , "t16": "0010|0|Rd:3|immZ:8" , "it": "out", "io": "N=W Z=W C=W"}, - {"inst": "movS Rd!=XX, Rn" , "t32": "1110|101|0010|1|1111|0000|Rd|0000|Rn" , "it": "any", "mod": "UNPRED_COMPLEX"}, - {"inst": "movS Rd!=XX, Rn!=XX, sop Rm!=XX" , "t32": "1110|101|00|sop:2|1|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "movS Rd!=XX, Rn!=XX, sop #n" , "t32": "1110|101|0010|1|1111|0|n:3|Rd|n:2|sop:2|Rn" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "movS Rd!=XX, #immA" , "t32": "1111|0|imm:1|0|0010|1|1111|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "movt Rx!=XX, #immZ" , "t32": "1111|0|immZ:1|1|0110|0|immZ:4|0|immZ:3|Rx|immZ:8" , "it": "any"}, - {"inst": "movw Rd!=XX, #immZ" , "t32": "1111|0|immZ:1|1|0010|0|immZ:4|0|immZ:3|Rd|immZ:8" , "it": "any"}, - {"inst": "mrc #CP, #op1, Rd!=XX, Cn, Cm, {#op2}" , "t32": "1110|111|0|op1:3|1|Cn:4|Rd|CP:4|op2:3|1|Cm:4"}, - {"inst": "mrc2 #CP, #op1, Rd!=XX, Cn, Cm, {#op2}" , "t32": "1111|111|0|op1:3|1|Cn:4|Rd|CP:4|op2:3|1|Cm:4"}, - {"inst": "mrrc #CP, #op1, Rd!=XX, Rd2!=Rd, Cm" , "t32": "1110|110|0010|1|Rd2|Rd|CP:4|op1:4|Cm:4"}, - {"inst": "mrrc2 #CP, #op1, Rd!=XX, Rd2!=Rd, Cm" , "t32": "1111|110|0010|1|Rd2|Rd|CP:4|op1:4|Cm:4"}, - {"inst": "mrs Rd!=XX, #APSR" , "t32": "11110011111|APSR:1|1111|1000|Rd|0000|0000" , "it": "any"}, - {"inst": "msr #APSR, Rn!=PC" , "t32": "1111|001|1100|0|Rn|1100|APSR:2|00|0000|0000" , "it": "any"}, - {"inst": "mul Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|001|101|Rm:3|Rx:3" , "it": "in"}, - {"inst": "mulS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|001|101|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, - {"inst": "mul Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1000|0|Rn|1111|Rd|0000|Rm" , "it": "any"}, - {"inst": "mvn Rd!=HI, Rn!=HI" , "t16": "0100|001|111|Rn:3|Rd:3" , "it": "in"}, - {"inst": "mvn Rd!=XX, Rn!=XX, {sop #n}" , "t32": "1110|101|0011|0|1111|0|n:3|Rd|n:2|sop:2|Rn" , "it": "any"}, - {"inst": "mvn Rd!=XX, #immA" , "t32": "1111|0|imm:1|0|0011|0|1111|0|imm:3|Rd|imm:8" , "it": "any"}, - {"inst": "mvnS Rd!=HI, Rn!=HI" , "t16": "0100|001|111|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W"}, - {"inst": "mvnS Rd!=XX, Rn!=XX, {sop #n}" , "t32": "1110|101|0011|1|1111|0|n:3|Rd|n:2|sop:2|Rn" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "mvnS Rd!=XX, #immA" , "t32": "1111|0|imm:1|0|0011|1|1111|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "nop" , "t16": "1011|111|1000|0|0000" , "it": "any"}, - {"inst": "nop" , "t32": "1111|001|1101|0|1111|1000|0000|0000|0000" , "it": "any"}, - {"inst": "orn Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|0011|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, - {"inst": "orn Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|0011|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, - {"inst": "ornS Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|0011|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "ornS Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|0011|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "orr Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|001|100|Rm:3|Rx:3" , "it": "in"}, - {"inst": "orr Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|0010|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, - {"inst": "orr Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|0010|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, - {"inst": "orrS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|001|100|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, - {"inst": "orrS Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|0010|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "orrS Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|0010|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "pkhbt Rd!=XX, Rn!=XX, Rm!=XX, {lsl #n}" , "t32": "1110|101|0110|0|Rn|0|n:3|Rd|n:2|00|Rm" , "it": "any"}, - {"inst": "pkhtb Rd!=XX, Rn!=XX, Rm!=XX, {asr #n}" , "t32": "1110|101|0110|0|Rn|0|n:3|Rd|n:2|10|Rm" , "it": "any"}, - {"inst": "pld [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|0000|1|Rn|1111|0000|00|n:2|Rm" , "it": "any"}, - {"inst": "pld [Rn!=PC, #off]" , "t32": "1111|100|0100|1|Rn|1111|off:12" , "it": "any"}, - {"inst": "pld [Rn!=PC, #-off]" , "t32": "1111|100|0000|1|Rn|1111|1100|off:8" , "it": "any"}, - {"inst": "pld [Rn==PC, #+/-off]" , "t32": "1111|100|0U00|1|Rn|1111|off:12" , "it": "any"}, - {"inst": "pldw [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|0001|1|Rn|1111|0000|00|n:2|Rm" , "it": "any"}, - {"inst": "pldw [Rn!=PC, #off]" , "t32": "1111|100|0101|1|Rn|1111|off:12" , "it": "any"}, - {"inst": "pldw [Rn!=PC, #-off]" , "t32": "1111|100|0001|1|Rn|1111|1100|off:8" , "it": "any"}, - {"inst": "pop Rd!=SP" , "t32": "1111|100|0010|1|1101|Rd|1011|00000100" , "it": "any"}, - {"inst": "pop RdList" , "t16": "1011|110|RdList[15]|RdList[7:0]" , "it": "any"}, - {"inst": "pop RdList" , "t32": "1110|100|0101|1|1101|RdList[15:14]|0|RdList[12:0]" , "it": "any"}, - {"inst": "push Rs!=XX" , "t32": "1111|100|0010|0|1101|Rs|1101|0000|0100" , "it": "any"}, - {"inst": "push RsList" , "t16": "1011|010|RsList[14]|RsList[7:0]" , "it": "any"}, - {"inst": "push RsList" , "t32": "1110|100|0101|0|1101|0|RsList[14]|0|RsList[12:0]" , "it": "any"}, - {"inst": "qadd Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|0|Rm|1111|Rd|1000|Rn" , "it": "any", "io": "Q=X"}, - {"inst": "qadd16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|1|Rm|1111|Rd|0001|Rn" , "it": "any"}, - {"inst": "qadd8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|0|Rm|1111|Rd|0001|Rn" , "it": "any"}, - {"inst": "qasx Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0101|0|Rm|1111|Rd|0001|Rn" , "it": "any"}, - {"inst": "qdadd Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|0|Rm|1111|Rd|1001|Rn" , "it": "any", "io": "Q=X"}, - {"inst": "qdsub Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|0|Rm|1111|Rd|1011|Rn" , "it": "any", "io": "Q=X"}, - {"inst": "qsax Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0111|0|Rm|1111|Rd|0001|Rn" , "it": "any"}, - {"inst": "qsub Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|0|Rm|1111|Rd|1010|Rn" , "it": "any", "io": "Q=X"}, - {"inst": "qsub16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|1|Rm|1111|Rd|0001|Rn" , "it": "any"}, - {"inst": "qsub8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|0|Rm|1111|Rd|0001|Rn" , "it": "any"}, - {"inst": "rbit Rd!=XX, Rn!=XX" , "t32": "1111|101|0100|1|Rm|1111|Rd|1010|Rn" , "it": "any"}, - {"inst": "rev Rd!=HI, Rn!=HI" , "t16": "1011|101|000|Rn:3|Rd:3" , "it": "any"}, - {"inst": "rev Rd!=XX, Rn!=XX" , "t32": "1111|101|0100|1|Rm|1111|Rd|1000|Rn" , "it": "any"}, - {"inst": "rev16 Rd!=HI, Rn!=HI" , "t16": "1011|101|001|Rn:3|Rd:3" , "it": "any"}, - {"inst": "rev16 Rd!=XX, Rn!=XX" , "t32": "1111|101|0100|1|Rm|1111|Rd|1001|Rn" , "it": "any"}, - {"inst": "revsh Rd!=HI, Rn!=HI" , "t16": "1011|101|011|Rn:3|Rd:3" , "it": "any"}, - {"inst": "revsh Rd!=XX, Rn!=XX" , "t32": "1111|101|0100|1|Rm|1111|Rd|1011|Rn" , "it": "any"}, - {"inst": "ror Rd!=XX, Rn!=XX, #n" , "t32": "1110|101|0010|0|1111|0|n:3|Rd|n:2|11|Rn" , "it": "any"}, - {"inst": "ror Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|111|Rm:3|Rx:3" , "it": "in"}, - {"inst": "ror Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0011|0|Rn|1111|Rd|0000|Rm" , "it": "any"}, - {"inst": "rorS Rd!=XX, Rn!=XX, #n" , "t32": "1110|101|0010|1|1111|0|n:3|Rd|n:2|11|Rn" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "rorS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|111|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, - {"inst": "rorS Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0011|1|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "rsb Rd!=HI, Rn!=HI, #zero" , "t16": "0100|001001|Rn:3|Rd:3" , "it": "in"}, - {"inst": "rsb Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|1110|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, - {"inst": "rsb Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|1110|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, - {"inst": "rsbS Rd!=HI, Rn!=HI, #zero" , "t16": "0100|001001|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W V=W"}, - {"inst": "rsbS Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|1110|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W V=W"}, - {"inst": "rsbS Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|1110|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W V=W"}, - {"inst": "rrx Rd!=XX, Rn!=XX" , "t32": "1110|101|0010|0|1111|0000|Rd|0011|Rn" , "it": "any"}, - {"inst": "rrxS Rd!=XX, Rn!=XX" , "t32": "1110|101|0010|1|1111|0000|Rd|0011|Rn" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "sadd16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|1|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "GE=W"}, - {"inst": "sadd8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|0|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "GE=W"}, - {"inst": "sasx Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0101|0|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "GE=W"}, - {"inst": "sbc Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|110|Rm:3|Rx:3" , "it": "in"}, - {"inst": "sbc Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|1011|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, - {"inst": "sbc Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|1011|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, - {"inst": "sbcS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|110|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W V=W"}, - {"inst": "sbcS Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|1011|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, - {"inst": "sbcS Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|1011|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W V=W"}, - {"inst": "sbfx Rd!=XX, Rn!=XX, #lsb, #width" , "t32": "1111|001|1010|0|Rn|0|lsb:3|Rd|lsb:2|0|widthM1:5" , "it": "any", "imm": "SbfxUbfxImm(lsb, width)"}, - {"inst": "sel Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0101|0|Rn|1111|Rd|1000|Rm" , "it": "any"}, - {"inst": "setend #immZ" , "t16": "1011|0110|010|1|immZ:1|000" , "it": "out"}, - {"inst": "sev" , "t16": "1011|1111|0100|0000" , "it": "any"}, - {"inst": "sev" , "t32": "1111|001|1101|0|1111|1000|0000|0000|0000" , "it": "any"}, - {"inst": "shadd16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|1|Rn|1111|Rd|0010|Rm" , "it": "any"}, - {"inst": "shadd8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|0|Rn|1111|Rd|0010|Rm" , "it": "any"}, - {"inst": "shasx Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0101|0|Rn|1111|Rd|0010|Rm" , "it": "any"}, - {"inst": "shsax Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0111|0|Rn|1111|Rd|0010|Rm" , "it": "any"}, - {"inst": "shsub16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|1|Rn|1111|Rd|0010|Rm" , "it": "any"}, - {"inst": "shsub8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|0|Rn|1111|Rd|0010|Rm" , "it": "any"}, - {"inst": "smlabb Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1001|1|Rn|Ra|Rd|0000|Rm" , "it": "any", "io": "Q=X"}, - {"inst": "smlabt Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1001|1|Rn|Ra|Rd|0001|Rm" , "it": "any", "io": "Q=X"}, - {"inst": "smlatb Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1001|1|Rn|Ra|Rd|0010|Rm" , "it": "any", "io": "Q=X"}, - {"inst": "smlatt Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1001|1|Rn|Ra|Rd|0011|Rm" , "it": "any", "io": "Q=X"}, - {"inst": "smlad Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1001|0|Rn|Ra|Rd|0000|Rm" , "it": "any", "io": "Q=X"}, - {"inst": "smladx Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1001|0|Rn|Ra|Rd|0001|Rm" , "it": "any", "io": "Q=X"}, - {"inst": "smlal RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1110|0|Rn|RxLo|RxHi|0000|Rm" , "it": "any"}, - {"inst": "smlalbb RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1110|0|Rn|RxLo|RxHi|1000|Rm" , "it": "any"}, - {"inst": "smlalbt RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1110|0|Rn|RxLo|RxHi|1001|Rm" , "it": "any"}, - {"inst": "smlaltb RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1110|0|Rn|RxLo|RxHi|1010|Rm" , "it": "any"}, - {"inst": "smlaltt RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1110|0|Rn|RxLo|RxHi|1011|Rm" , "it": "any"}, - {"inst": "smlald RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1110|0|Rn|RxLo|RxHi|1100|Rm" , "it": "any"}, - {"inst": "smlaldx RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1110|0|Rn|RxLo|RxHi|1101|Rm" , "it": "any"}, - {"inst": "smlawb Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1001|1|Rn|Ra|Rd|0000|Rm" , "it": "any", "io": "Q=X"}, - {"inst": "smlawt Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1001|1|Rn|Ra|Rd|0001|Rm" , "it": "any", "io": "Q=X"}, - {"inst": "smlsd Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1010|1|Rn|Ra|Rd|0000|Rm" , "it": "any", "io": "Q=X"}, - {"inst": "smlsdx Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1010|1|Rn|Ra|Rd|0001|Rm" , "it": "any", "io": "Q=X"}, - {"inst": "smlsld RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1110|1|Rn|RxLo|RxHi|1100|Rm" , "it": "any", "io": "Q=X"}, - {"inst": "smlsldx RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1110|1|Rn|RxLo|RxHi|1101|Rm" , "it": "any", "io": "Q=X"}, - {"inst": "smmla Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1010|1|Rn|Ra|Rd|0000|Rm" , "it": "any"}, - {"inst": "smmlar Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1010|1|Rn|Ra|Rd|0001|Rm" , "it": "any"}, - {"inst": "smmls Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1011|0|Rn|Ra|Rd|0000|Rm" , "it": "any"}, - {"inst": "smmlsr Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1011|0|Rn|Ra|Rd|0001|Rm" , "it": "any"}, - {"inst": "smmul Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1010|1|Rn|1111|Rd|0000|Rm" , "it": "any"}, - {"inst": "smmulr Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1010|1|Rn|1111|Rd|0001|Rm" , "it": "any"}, - {"inst": "smuad Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1001|0|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "Q=X"}, - {"inst": "smuadx Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1001|0|Rn|1111|Rd|0001|Rm" , "it": "any", "io": "Q=X"}, - {"inst": "smulbb Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1000|1|Rn|1111|Rd|0000|Rm" , "it": "any"}, - {"inst": "smulbt Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1000|1|Rn|1111|Rd|0001|Rm" , "it": "any"}, - {"inst": "smultb Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1000|1|Rn|1111|Rd|0010|Rm" , "it": "any"}, - {"inst": "smultt Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1000|1|Rn|1111|Rd|0011|Rm" , "it": "any"}, - {"inst": "smull RdLo!=XX, RdHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1100|0|Rn|RdLo|RdHi|0000|Rm" , "it": "any"}, - {"inst": "smulwb Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1001|1|Rn|1111|Rd|0000|Rm" , "it": "any"}, - {"inst": "smulwt Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1001|1|Rn|1111|Rd|0001|Rm" , "it": "any"}, - {"inst": "smusd Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1010|0|Rn|1111|Rd|0000|Rm" , "it": "any"}, - {"inst": "smusdx Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1010|0|Rn|1111|Rd|0001|Rm" , "it": "any"}, - {"inst": "ssat Rd!=XX, #sat, Rn!=XX" , "t32": "1111|001|100|00|Rn|0|000|Rd|00|0|imm:5" , "it": "any", "imm": "SsatImm(sat)", "io": "Q=X"}, - {"inst": "ssat Rd!=XX, #sat, Rn!=XX, lsl_or_asr #n" , "t32": "1111|001|100|sop:2|Rn|0|n:3|Rd|n:2|0|imm:5" , "it": "any", "imm": "SsatImm(sat, n)", "io": "Q=X"}, - {"inst": "ssat16 Rd!=XX, #sat, Rn!=XX" , "t32": "1111|001|1001|0|Rn|0000|Rd|0000|imm:4" , "it": "any", "imm": "Ssat16Imm(sat)", "io": "Q=X"}, - {"inst": "ssax Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0111|0|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "GE=W"}, - {"inst": "ssub16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|1|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "GE=W"}, - {"inst": "ssub8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|0|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "GE=W"}, - {"inst": "stm [Rn!=HI]!, RsList" , "t16": "1100|0|Rn:3|RsList:8" , "it": "any"}, - {"inst": "stm [Rn!=PC]{!}, RsList" , "t32": "1110|100|010W|0|Rn|0|RsList[14]|0|RsList[12:0]" , "it": "any"}, - {"inst": "stmdb [Rn!=PC]{!}, RsList" , "t32": "1110|100|100W|0|Rn|0|RsList[14]|0|RsList[12:0]" , "it": "any"}, - {"inst": "str Rs!=HI, [Rn!=HI, Rm!=HI]" , "t16": "0101|000|Rm:3|Rn:3|Rs:3" , "it": "any"}, - {"inst": "str Rs!=PC, [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|0010|0|Rn|Rs|0|00000|n:2|Rm" , "it": "any"}, - {"inst": "str Rs!=HI, [Rn==SP, #off*4]" , "t16": "1001|0|Rs:3|off:8" , "it": "any"}, - {"inst": "str Rs!=HI, [Rn!=HI, #off*4]" , "t16": "0110|0|off:5|Rn:3|Rs:3" , "it": "any"}, - {"inst": "str Rs!=PC, [Rn!=PC, #off]" , "t32": "1111|100|0110|0|Rn|Rs|off:12" , "it": "any"}, - {"inst": "str Rs!=PC, [Rn!=PC, #+/-off]{@}{!}" , "t32": "1111|100|0010|0|Rn|Rs|1PUW|off:8" , "it": "any"}, - {"inst": "strb Rs!=HI, [Rn!=HI, Rm!=HI]" , "t16": "0101|010|Rm:3|Rn:3|Rs:3" , "it": "any"}, - {"inst": "strb Rs!=XX, [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|0000|0|Rn|Rs|0|00000|n:2|Rm" , "it": "any"}, - {"inst": "strb Rs!=HI, [Rn!=HI, #off*4]" , "t16": "0111|0|off:5|Rn:3|Rs:3" , "it": "any"}, - {"inst": "strb Rs!=XX, [Rn!=PC, #off]" , "t32": "1111|100|0100|0|Rn|Rs|off:12" , "it": "any"}, - {"inst": "strb Rs!=XX, [Rn!=PC, #+/-off]{@}{!}" , "t32": "1111|100|0000|0|Rn|Rs|1PUW|off:8" , "it": "any"}, - {"inst": "strbt Rs!=XX, [Rn!=PC, #off]" , "t32": "1111|100|0000|0|Rn|Rs|1110|off:8" , "it": "any"}, - {"inst": "strd Rs!=XX, Rs2!=XX, [Rn!=PC, #off]{@}{!}" , "t32": "1110|100|PU1W|0|Rn|Rs|Rs2|off:8" , "it": "any"}, - {"inst": "strex Rd!=XX, Rs!=XX, [Rn!=PC, #off]" , "t32": "1110|100|0010|0|Rn|Rs|Rd|off:8" , "it": "any", "mod": "UNPRED_COMPLEX"}, - {"inst": "strexb Rd!=XX, Rs!=XX, [Rn!=PC]" , "t32": "1110|100|0110|0|Rn|Rs|1111|0100|Rd" , "it": "any", "mod": "UNPRED_COMPLEX"}, - {"inst": "strexd Rd!=XX, Rs!=XX, Rs2!=XX, [Rn!=PC]" , "t32": "1110|100|0110|0|Rn|Rs|Rs2|0111|Rd" , "it": "any", "mod": "UNPRED_COMPLEX"}, - {"inst": "strexh Rd!=XX, Rs!=XX, [Rn!=PC]" , "t32": "1110|100|0110|0|Rn|Rs|1111|0101|Rd" , "it": "any", "mod": "UNPRED_COMPLEX"}, - {"inst": "strh Rs!=HI, [Rn!=HI, Rm!=HI]" , "t16": "0101|001|Rm:3|Rn:3|Rs:3" , "it": "any"}, - {"inst": "strh Rs!=XX, [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|0001|0|Rn|Rs|0|00000|n:2|Rm" , "it": "any"}, - {"inst": "strh Rs!=HI, [Rn!=HI, #off*4]" , "t16": "1000|0|off:5|Rn:3|Rs:3" , "it": "any"}, - {"inst": "strh Rs!=XX, [Rn!=PC, #off]" , "t32": "1111|100|0101|0|Rn|Rs|off:12" , "it": "any"}, - {"inst": "strh Rs!=XX, [Rn!=PC, #+/-off]{@}{!}" , "t32": "1111|100|0001|0|Rn|Rs|1PUW|off:8" , "it": "any"}, - {"inst": "strht Rs!=XX, [Rn!=PC, #off]" , "t32": "1111|100|0001|0|Rn|Rs|1110|off:8" , "it": "any"}, - {"inst": "strt Rs!=XX, [Rn!=PC, #off]" , "t32": "1111|100|0010|0|Rn|Rs|1110|off:8" , "it": "any"}, - {"inst": "sub Rd!=HI, Rn!=HI, Rm!=HI" , "t16": "0001|101|Rm:3|Rn:3|Rd:3" , "it": "in"}, - {"inst": "sub Rd!=HI, Rn!=HI, #immZ" , "t16": "0001|111|immZ:3|Rn:3|Rd:3" , "it": "in"}, - {"inst": "sub Rx!=HI, Rx!=HI, #immZ" , "t16": "0011|1|Rx:3|immZ:8" , "it": "in"}, - {"inst": "sub Rx==SP, Rx==SP, #immZ*4" , "t16": "1011|00001|immZ:7" , "it": "any"}, - {"inst": "sub Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|1101|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, - {"inst": "sub Rd!=PC, Rn==SP, Rm!=XX, {sop #n}" , "t32": "1110|101|1101|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, - {"inst": "sub Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|1101|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, - {"inst": "sub Rd!=PC, Rn==SP, #immA" , "t32": "1111|0|imm:1|0|1101|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, - {"inst": "sub Rd!=XX, Rn!=XX, #immZ" , "t32": "1111|0|immZ:1|1|0101|0|Rn|0|immZ:3|Rd|immZ:8" , "it": "any"}, - {"inst": "sub Rd!=HI, Rn!=HI, Rm!=HI" , "t16": "0001|101|Rm:3|Rn:3|Rd:3" , "it": "in"}, - {"inst": "subS Rd!=HI, Rn!=HI, #immZ" , "t16": "0001|111|immZ:3|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W V=W"}, - {"inst": "subS Rx!=HI, Rx!=HI, #immZ" , "t16": "0001|1|Rx:3|immZ:8" , "it": "out", "io": "N=W Z=W C=W V=W"}, - {"inst": "subS Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|1101|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W V=W"}, - {"inst": "subS Rd!=PC, Rn==SP, Rm!=XX, {sop #n}" , "t32": "1110|101|1101|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W V=W"}, - {"inst": "subS Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|1101|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W V=W"}, - {"inst": "subS Rd!=PC, Rn==SP, #immA" , "t32": "1111|0|imm:1|0|1101|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W V=W"}, - {"inst": "subS Rd!=XX, Rn!=XX, #immZ" , "t32": "1111|0|immZ:1|1|0101|1|Rn|0|immZ:3|Rd|immZ:8" , "it": "any", "io": "N=W Z=W C=W V=W"}, - {"inst": "svc #immZ" , "t16": "1101|1111|immZ:8" , "it": "any"}, - {"inst": "sxtab Rd!=XX, Rn!=XX, Rm!=XX, {ror #n}" , "t32": "1111|101|0010|0|Rn|1111|Rd|1|0|imm:2|Rm" , "it": "any", "imm": "Ror8Imm(n)"}, - {"inst": "sxtab16 Rd!=XX, Rn!=XX, Rm!=XX, {ror #n}" , "t32": "1111|101|0001|0|Rn|1111|Rd|1|0|imm:2|Rm" , "it": "any", "imm": "Ror8Imm(n)"}, - {"inst": "sxtah Rd!=XX, Rn!=XX, Rm!=XX, {ror #n}" , "t32": "1111|101|0000|0|Rn|1111|Rd|1|0|imm:2|Rm" , "it": "any", "imm": "Ror8Imm(n)"}, - {"inst": "sxtb Rd!=HI, Rn!=HI, {ror #zero}" , "t16": "1011|001|001|Rn:3|Rd:3" , "it": "any"}, - {"inst": "sxtb Rd!=XX, Rn!=XX, {ror #n}" , "t32": "1111|101|0010|0|1111|1111|Rd|10|imm:2|Rn" , "it": "any", "imm": "Ror8Imm(n)"}, - {"inst": "sxtb16 Rd!=XX, Rn!=XX, {ror #n}" , "t32": "1111|101|0001|0|1111|1111|Rd|10|imm:2|Rn" , "it": "any", "imm": "Ror8Imm(n)"}, - {"inst": "sxth Rd!=HI, Rn!=HI, {ror #zero}" , "t16": "1011|001|000|Rn:3|Rd:3" , "it": "any"}, - {"inst": "sxth Rd!=XX, Rn!=XX, {ror #n}" , "t32": "1111|101|0000|0|1111|1111|Rd|10|imm:2|Rn" , "it": "any", "imm": "Ror8Imm(n)"}, - {"inst": "tbb Rn!=SP, Rn!=XX" , "t32": "1110|100|0110|1|Rn|1111|0000|0000|Rn" , "it": "out last"}, - {"inst": "tbh Rn!=SP, Rn!=XX" , "t32": "1110|100|0110|1|Rn|1111|0000|0001|Rn" , "it": "out last"}, - {"inst": "teq Rn!=XX, Rn!=XX, {sop #n}" , "t32": "1110|101|0100|1|Rn|0|n:3|1111|n:2|sop:2|Rn" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "teq Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|0100|1|Rn|0|imm:3|1111|imm:8" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "tst Rn!=HI, Rn!=HI" , "t16": "0100|00|1000|Rn:3|Rn:3" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "tst Rn!=XX, Rn!=XX, {sop #n}" , "t32": "1110|101|0000|1|Rn|0|n:3|1111|n:2|sop:2|Rn" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "tst Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|0000|1|Rn|0|imm:3|1111|imm:8" , "it": "any", "io": "N=W Z=W C=W"}, - {"inst": "uadd16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|1|Rn|1111|Rd|0100|Rm" , "it": "any", "io": "GE=W"}, - {"inst": "uadd8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|0|Rn|1111|Rd|0100|Rm" , "it": "any", "io": "GE=W"}, - {"inst": "uasx Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0101|0|Rn|1111|Rd|0100|Rm" , "it": "any", "io": "GE=W"}, - {"inst": "ubfx Rd!=XX, Rn!=XX, #lsb, #width" , "t32": "1111|001|1110|0|Rn|0|lsb:3|Rd|lsb:2|0|widthM1:5" , "it": "any", "imm": "SbfxUbfxImm(lsb, width)"}, - {"inst": "uhadd8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|0|Rn|1111|Rd|0110|Rm" , "it": "any"}, - {"inst": "uhadd16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|1|Rn|1111|Rd|0110|Rm" , "it": "any"}, - {"inst": "uhasx Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0101|0|Rn|1111|Rd|0110|Rm" , "it": "any"}, - {"inst": "uhsax Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0111|0|Rn|1111|Rd|0110|Rm" , "it": "any"}, - {"inst": "uhsub16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|1|Rn|1111|Rd|0110|Rm" , "it": "any"}, - {"inst": "uhsub8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|0|Rn|1111|Rd|0110|Rm" , "it": "any"}, - {"inst": "umaal RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1111|0|Rn|RxLo|RxHi|0110|Rm" , "it": "any"}, - {"inst": "umlal RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1111|0|Rn|RxLo|RxHi|0000|Rm" , "it": "any"}, - {"inst": "umull RdLo!=XX, RdHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1101|0|Rn|RdLo|RdHi|0000|Rm" , "it": "any"}, - {"inst": "uqadd16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|1|Rn|1111|Rd|0101|Rm" , "it": "any"}, - {"inst": "uqadd8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|0|Rn|1111|Rd|0101|Rm" , "it": "any"}, - {"inst": "uqasx Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0101|0|Rn|1111|Rd|0101|Rm" , "it": "any"}, - {"inst": "uqsax Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0111|0|Rn|1111|Rd|0101|Rm" , "it": "any"}, - {"inst": "uqsub16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|1|Rn|1111|Rd|0101|Rm" , "it": "any"}, - {"inst": "uqsub8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|0|Rn|1111|Rd|0101|Rm" , "it": "any"}, - {"inst": "usad8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1011|1|Rn|1111|Rd|0000|Rm" , "it": "any"}, - {"inst": "usada8 Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1011|1|Rn|Ra|Rd|0000|Rm" , "it": "any"}, - {"inst": "usat Rd!=XX, #sat, Rn!=XX, {lsl_or_asr #n}" , "t32": "1111|001|110|sop:2|Rn|0|n:3|Rd|n:2|0|sat:5" , "it": "any", "io": "Q=X"}, - {"inst": "usat16 Rd!=XX, #sat, Rn!=XX" , "t32": "1111|001|1101|0|Rn|0000|Rd|0000|sat:4" , "it": "any", "io": "Q=X"}, - {"inst": "usax Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0111|0|Rn|1111|Rd|0100|Rm" , "it": "any", "io": "GE=W"}, - {"inst": "usub16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|1|Rn|1111|Rd|0100|Rm" , "it": "any", "io": "GE=W"}, - {"inst": "usub8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|0|Rn|1111|Rd|0100|Rm" , "it": "any", "io": "GE=W"}, - {"inst": "uxtab Rd!=XX, Rn!=XX, Rm!=XX, {ror #n}" , "t32": "1111|101|0010|1|Rn|1111|Rd|10|imm:2|Rm" , "it": "any", "imm": "Ror8Imm(n)"}, - {"inst": "uxtab16 Rd!=XX, Rn!=XX, Rm!=XX, {ror #n}" , "t32": "1111|101|0001|1|Rn|1111|Rd|10|imm:2|Rm" , "it": "any", "imm": "Ror8Imm(n)"}, - {"inst": "uxtah Rd!=XX, Rn!=XX, Rm!=XX, {ror #n}" , "t32": "1111|101|0000|1|Rn|1111|Rd|10|imm:2|Rm" , "it": "any", "imm": "Ror8Imm(n)"}, - {"inst": "uxtb Rd!=HI, Rn!=HI, {ror #zero}" , "t16": "1011|001|011|Rn:3|Rd:3" , "it": "any"}, - {"inst": "uxtb Rd!=XX, Rn!=XX, {ror #n}" , "t32": "1111|101|0010|1|1111|1111|Rd|10|imm:2|Rn" , "it": "any", "imm": "Ror8Imm(n)"}, - {"inst": "uxtb16 Rd!=XX, Rn!=XX, {ror #n}" , "t32": "1111|101|0001|1|1111|1111|Rd|10|imm:2|Rn" , "it": "any"}, - {"inst": "uxth Rd!=HI, Rn!=HI, {ror #zero}" , "t16": "1011|001|010|Rn:3|Rd:3" , "it": "any"}, - {"inst": "uxth Rd!=XX, Rn!=XX, {ror #n}" , "t32": "1111|101|0000|1|1111|1111|Rd|10|imm:2|Rn" , "it": "any", "imm": "Ror8Imm(n)"}, - {"inst": "wfe" , "t16": "1011|1111|0010|0000" , "it": "any"}, - {"inst": "wfe" , "t32": "1111|001|1101|0|1111|1000|0000|0000|0010" , "it": "any"}, - {"inst": "wfi" , "t16": "1011|1111|0011|0000" , "it": "any"}, - {"inst": "wfi" , "t32": "1111|001|1101|0|1111|1000|0000|0000|0011" , "it": "any"}, - {"inst": "yield" , "t16": "1011|1111|0001|0000" , "it": "any"}, - {"inst": "yield" , "t32": "1111|001|1101|0|1111|1000|0000|0000|0001" , "it": "any"} + {"inst": "adc Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|101|Rm:3|Rx:3" , "it": "in" , "io": "C=R"}, + {"inst": "adc Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|1010|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "C=R"}, + {"inst": "adc Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|1010|0|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "C=R"}, + {"inst": "adcS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|101|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=X V=W", "mod": "APSR_IF_NOT_PC"}, + {"inst": "adcS Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|1010|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=X V=W", "mod": "APSR_IF_NOT_PC"}, + {"inst": "adcS Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|1010|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=X V=W", "mod": "APSR_IF_NOT_PC"}, + {"inst": "add Rd!=HI, Rn!=HI, Rm!=HI" , "t16": "0001|100|Rm:3|Rn:3|Rd:3" , "it": "in"}, + {"inst": "add Rx!=XX, Rx!=XX, Rm!=XX" , "t16": "0100|010|0|Rx:1|Rm:4|Rx:3" , "it": "in"}, + {"inst": "add Rx, Rx, Rm==SP" , "t16": "0100|010|0|Rx:1|Rm:4|Rx:3" , "it": "any"}, + {"inst": "add Rx==SP, Rx==SP, Rm" , "t16": "0100|010|0|Rx:1|Rm:4|Rx:3" , "it": "any"}, + {"inst": "add Rx!=HI, Rx!=HI, #immZ" , "t16": "0011|0|Rx:3|immZ:8" , "it": "in"}, + {"inst": "add Rd!=HI, Rn!=HI, #immZ" , "t16": "0001|110|immZ:3|Rn:3|Rd:3" , "it": "in"}, + {"inst": "add Rx==SP, Rx==SP, #immZ*4" , "t16": "1011|00000|immZ:7" , "it": "any"}, + {"inst": "add Rd!=SP, Rn==SP, #immZ*4" , "t16": "1010|1|Rd:3|immZ:8" , "it": "any"}, + {"inst": "add Rd!=XX, Rn!=PC, Rm!=XX, {sop #n}" , "t32": "1110|101|1000|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, + {"inst": "add Rd!=PC, Rn==SP, Rm!=XX, {sop #n}" , "t32": "1110|101|1000|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "mod": "LSL_3_IF_SP"}, + {"inst": "add Rd!=XX, Rn!=PC, #immZ" , "t32": "1111|0|immZ:1|1|0000|0|Rn|0|immZ:3|Rd|immZ:8" , "it": "any"}, + {"inst": "add Rd!=XX, Rn!=PC, #immA" , "t32": "1111|0|imm:1|0|1000|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, + {"inst": "add Rd!=PC, Rn==SP, #immZ" , "t32": "1111|0|immZ:1|1|0000|0|Rn|0|immZ:3|Rd|immZ:8" , "it": "any"}, + {"inst": "add Rd!=PC, Rn==SP, #immA" , "t32": "1111|0|imm:1|0|1000|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, + {"inst": "addS Rx!=HI, Rx!=HI, #immZ" , "t16": "0011|0|Rx:3|immZ:8" , "it": "out", "io": "N=W Z=W C=W V=W"}, + {"inst": "addS Rd!=HI, Rn!=HI, #immZ" , "t16": "0001|110|immZ:3|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W V=W"}, + {"inst": "addS Rd!=HI, Rn!=HI, Rm!=HI" , "t16": "0001|100|Rm:3|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W V=W"}, + {"inst": "addS Rd!=XX, Rn!=PC, Rm!=XX, {sop #n}" , "t32": "1110|101|1000|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W V=W"}, + {"inst": "addS Rd!=PC, Rn==SP, Rm!=XX, {sop #n}" , "t32": "1110|101|1000|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W V=W", "mod": "LSL_3_IF_SP"}, + {"inst": "addS Rd!=XX, Rn!=PC, #immA" , "t32": "1111|0|imm:1|0|1000|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W V=W"}, + {"inst": "addS Rd!=PC, Rn==SP, #immA" , "t32": "1111|0|imm:1|0|1000|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W V=W"}, + {"inst": "adr Rd!=HI, #relZ*4" , "t16": "1010|0|Rd:3|relZ:8" , "it": "any"}, + {"inst": "adr Rd!=XX, #relZ" , "t32": "1111|0|relZ:1|10N0N|0|1111|0|relZ:3|Rd|relZ:8" , "it": "any"}, + {"inst": "and Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|000|Rm:3|Rx:3" , "it": "in"}, + {"inst": "and Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|0000|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, + {"inst": "and Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|1010|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, + {"inst": "andS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|000|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, + {"inst": "andS Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|0000|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "andS Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|1010|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W", "mod": "APSR_IF_NOT_PC"}, + {"inst": "asr Rd!=HI, Rn!=HI, #n" , "t16": "0001|0|n:5|Rn:3|Rd:3" , "it": "in"}, + {"inst": "asr Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|100|Rm:3|Rx:3" , "it": "in"}, + {"inst": "asr Rd!=XX, Rn!=XX, #n" , "t32": "1110|101|0010|0|1111|0|n:3|Rd|n:2|10|Rn" , "it": "any"}, + {"inst": "asr Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0010|0|Rn|1111|Rd|0000|Rm" , "it": "any"}, + {"inst": "asrS Rd!=HI, Rn!=HI, #n" , "t16": "0001|0|n:5|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W"}, + {"inst": "asrS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|100|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, + {"inst": "asrS Rd!=XX, Rn!=XX, #n" , "t32": "1110|101|0010|1|1111|0|n:3|Rd|n:2|10|Rn" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "asrS Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0010|1|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "b #relS*2" , "t16": "1110|0|relS:11" , "it": "out last"}, + {"inst": "b #relS*2" , "t32": "1111|0|relS[23]|relS[20:11]|10|ja|1|jb|relS[10:0]" , "it": "out last", "calc": {"ja": "relS[23] ^ relS[22] ^ 1", "jb": "relS[23] ^ relS[21] ^ 1"}}, + {"inst": "b #relS*2" , "t16": "1101|cond|relS:8" , "it": "out"}, + {"inst": "b #relS*2" , "t32": "1111|0|relS[19]|cond|relS[16:11]|10|ja|0|jb|relS[10:0]" , "it": "out" , "calc": {"ja": "relS[19] ^ relS[18] ^ 1", "jb": "relS[19] ^ relS[17] ^ 1"}}, + {"inst": "bfc Rd!=XX, #lsb, #width" , "t32": "1111|001|1011|0|1111|0|lsb:3|Rd|lsb:2|0|msb:5" , "it": "any", "imm": "BfcBfiImm(lsb, width)"}, + {"inst": "bfi Rd!=XX, Rn!=XX, #lsb, #width" , "t32": "1111|001|1011|0|Rn|0|lsb:3|Rd|lsb:2|0|msb:5" , "it": "any", "imm": "BfcBfiImm(lsb, width)"}, + {"inst": "bic Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|001|110|Rm:3|Rx:3" , "it": "in"}, + {"inst": "bic Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|0001|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, + {"inst": "bic Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|0001|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, + {"inst": "bicS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|001|110|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, + {"inst": "bicS Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|0001|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "bicS Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|0001|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "bkpt #immZ" , "t16": "1011|111|0|immZ:8" , "it": "uncond"}, + {"inst": "bl #relS*2" , "t32": "1111|0|relS[23]|relS[20:11]|11|ja|1|jb|relS[10:0]" , "it": "out last", "calc": {"ja": "relS[23] ^ relS[22] ^ 1", "jb": "relS[23] ^ relS[21] ^ 1"}}, + {"inst": "blx Rm!=PC" , "t16": "0100|011|11|Rm:4|000" , "it": "out last"}, + {"inst": "blx #relS*4" , "t32": "1111|0|relS[22]|relS[19:10]|11|ja|0|jb|relS[9:0]|0" , "it": "out last", "calc": {"ja": "relS[22] ^ relS[21] ^ 1", "jb": "relS[22] ^ relS[20] ^ 1"}}, + {"inst": "bx Rm" , "t16": "0100|011|10|Rm:4|000" , "it": "out last"}, + {"inst": "bxj Rm!=XX" , "t32": "1111|001|1110|0|Rm|1000|1111|00000000" , "it": "out last"}, + {"inst": "cbz Rn!=HI, #relZ*2" , "t16": "1011|00|relZ:1|1|relZ:5|Rn:3" , "it": "out"}, + {"inst": "cbnz Rn!=HI, #relZ*2" , "t16": "1011|10|relZ:1|1|relZ:5|Rn:3" , "it": "out"}, + {"inst": "clz Rd!=XX, Rn!=XX" , "t32": "1111|101|0101|1|Rm|1111|Rd|1000|Rn" , "it": "any"}, + {"inst": "cmn Rn!=HI, Rm!=HI" , "t16": "0100|001|011|Rm:3|Rn:3" , "it": "any", "io": "N=W Z=W C=W V=W"}, + {"inst": "cmn Rn!=PC, Rm!=XX, {sop #n}" , "t32": "1110|101|1000|1|Rn|0|n:3|1111|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W V=W"}, + {"inst": "cmn Rn!=PC, #immA" , "t32": "1111|0|imm:1|0|1000|1|Rn|0|imm:3|1111|imm:8" , "it": "any", "io": "N=W Z=W C=W V=W"}, + {"inst": "cmp Rn!=HI, #immZ" , "t16": "0010|1|Rn:3|immZ:8" , "it": "any", "io": "N=W Z=W C=W V=W"}, + {"inst": "cmp Rn!=HI, Rm!=HI" , "t16": "0100|001|010|Rm:3|Rn:3" , "it": "any", "io": "N=W Z=W C=W V=W"}, + {"inst": "cmp Rn!=PC, Rm!=PC" , "t16": "0100|010|1|Rn:1|Rm:4|Rn:3" , "it": "any", "io": "N=W Z=W C=W V=W", "mod": "UNPRED_IF_ALL_LOW"}, + {"inst": "cmp Rn!=PC, Rm!=XX, {sop #n}" , "t32": "1110|101|1101|1|Rn|0|n:3|1111|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W V=W"}, + {"inst": "cmp Rn!=PC, #immA" , "t32": "1111|0|imm:1|0|1101|1|Rn|0|imm:3|1111|imm:8" , "it": "any", "io": "N=W Z=W C=W V=W"}, + {"inst": "dbg #immZ" , "t32": "1111|001|1101|0|1111|1000|0000|1111|immZ:4" , "it": "any"}, + {"inst": "eor Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|001|Rm:3|Rx:3" , "it": "in"}, + {"inst": "eor Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|0100|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, + {"inst": "eor Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|0100|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, + {"inst": "eorS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|001|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, + {"inst": "eorS Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|0100|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "eorS Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|0100|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "hlt #immZ" , "t16": "1011|1010|10|immZ:6" , "it": "out", "ext": "ARMv8+"}, + {"inst": "it #cond!=15" , "t16": "1011|111|1|cond[3:0]|1000" , "it": "out def"}, + {"inst": "ite #cond!=15" , "t16": "1011|111|1|cond[3:0]|X100" , "it": "out def"}, + {"inst": "itee #cond!=15" , "t16": "1011|111|1|cond[3:0]|XY10" , "it": "out def"}, + {"inst": "iteee #cond!=15" , "t16": "1011|111|1|cond[3:0]|XYZ1" , "it": "out def"}, + {"inst": "iteet #cond!=15" , "t16": "1011|111|1|cond[3:0]|XYZ1" , "it": "out def"}, + {"inst": "itet #cond!=15" , "t16": "1011|111|1|cond[3:0]|XY10" , "it": "out def"}, + {"inst": "itete #cond!=15" , "t16": "1011|111|1|cond[3:0]|XYZ1" , "it": "out def"}, + {"inst": "itett #cond!=15" , "t16": "1011|111|1|cond[3:0]|XYZ1" , "it": "out def"}, + {"inst": "itt #cond!=15" , "t16": "1011|111|1|cond[3:0]|X100" , "it": "out def"}, + {"inst": "itte #cond!=15" , "t16": "1011|111|1|cond[3:0]|XY10" , "it": "out def"}, + {"inst": "ittee #cond!=15" , "t16": "1011|111|1|cond[3:0]|XYZ1" , "it": "out def"}, + {"inst": "ittet #cond!=15" , "t16": "1011|111|1|cond[3:0]|XYZ1" , "it": "out def"}, + {"inst": "ittt #cond!=15" , "t16": "1011|111|1|cond[3:0]|XY10" , "it": "out def"}, + {"inst": "ittte #cond!=15" , "t16": "1011|111|1|cond[3:0]|XYZ1" , "it": "out def"}, + {"inst": "itttt #cond!=15" , "t16": "1011|111|1|cond[3:0]|XYZ1" , "it": "out def"}, + {"inst": "ldmia [Rn!=HI]{!}, RdList" , "t16": "1100|1|Rn:3|imm:8" , "it": "any", "imm": "GpListImm(RdList, 0xFF)"}, + {"inst": "ldmia [Rn!=PC]{!}, RdList" , "t32": "1110|100|010W|1|Rn|immMask[15:14]|0|immMask[12:0]" , "it": "any", "imm": "GpListImm(RdList, 0xDFFF)"}, + {"inst": "ldmdb [Rn!=PC]{!}, RdList" , "t32": "1110|100|100W|1|Rn|immMask[15:14]|0|immMask[12:0]" , "it": "any", "imm": "GpListImm(RdList, 0xDFFF)"}, + {"inst": "ldr Rd!=HI, [Rn!=HI, Rm!=HI]" , "t16": "0101|100|Rm:3|Rn:3|Rd:3" , "it": "any"}, + {"inst": "ldr Rd, [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|0010|1|Rn|Rd|0|00000|n:2|Rm" , "it": "any"}, + {"inst": "ldr Rd!=HI, [Rn!=HI, #off*4]" , "t16": "0110|1|off:5|Rn:3|Rd:3" , "it": "any"}, + {"inst": "ldr Rd!=HI, [Rn==SP, #off*4]" , "t16": "1001|1|Rd:3|off:8" , "it": "any"}, + {"inst": "ldr Rd!=HI, [Rn==PC, #off*4]" , "t16": "0100|1|Rd:3|off:8" , "it": "any"}, + {"inst": "ldr Rd, [Rn!=PC, #off]" , "t32": "1111|100|0110|1|Rn|Rd|off:12" , "it": "any"}, + {"inst": "ldr Rd, [Rn!=PC, #+/-off]{@}{!}" , "t32": "1111|100|0010|1|Rn|Rd|1PUW|off:8" , "it": "any"}, + {"inst": "ldr Rd, [Rn==PC, #+/-off]" , "t32": "1111|100|0U10|1|Rn|Rd|off:12" , "it": "any"}, + {"inst": "ldrb Rd!=HI, [Rn!=HI, Rm!=HI]" , "t16": "0101|110|Rm:3|Rn:3|Rd:3" , "it": "any"}, + {"inst": "ldrb Rd!=XX, [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|0000|1|Rn|Rd|0|00000|n:2|Rm" , "it": "any"}, + {"inst": "ldrb Rd!=HI, [Rn!=HI, #off*4]" , "t16": "0111|1|off:5|Rn:3|Rd:3" , "it": "any"}, + {"inst": "ldrb Rd!=XX, [Rn!=PC, #off]" , "t32": "1111|100|0100|1|Rn|Rd|off:12" , "it": "any"}, + {"inst": "ldrb Rd!=XX, [Rn!=PC, #+/-off]{!}" , "t32": "1111|100|0000|1|Rn|Rd|1PUW|off:8" , "it": "any"}, + {"inst": "ldrb Rd!=XX, [Rn==PC, #+/-off]" , "t32": "1111|100|0U00|1|Rn|Rd|off:12" , "it": "any"}, + {"inst": "ldrbt Rd!=XX, [Rn!=PC, #off]" , "t32": "1111|100|0000|1|Rn|Rd|1110|off:8" , "it": "any"}, + {"inst": "ldrd Rd!=XX, Rd2!=XX, [Rn==PC, #+/-off*4]" , "t32": "1110|100|1U10|1|Rn|Rd|Rd2|off:8" , "it": "any"}, + {"inst": "ldrd Rd!=XX, Rd2!=XX, [Rn!=PC, #+/-off*4]{@}{!}" , "t32": "1110|100|PU1W|1|Rn|Rd|Rd2|off:8" , "it": "any"}, + {"inst": "ldrex Rd!=XX, [Rn!=PC, #off*4]" , "t32": "1110|100|0010|1|Rn|Rd|1111|off:8" , "it": "any"}, + {"inst": "ldrh Rd!=HI, [Rn!=HI, Rm!=HI]" , "t16": "0101|101|Rm:3|Rn:3|Rd:3" , "it": "any"}, + {"inst": "ldrh Rd!=XX, [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|0001|1|Rn|Rd|0|00000|n:2|Rm" , "it": "any"}, + {"inst": "ldrh Rd!=HI, [Rn!=HI, #off*4]" , "t16": "1000|1|off:5|Rn:3|Rd:3" , "it": "any"}, + {"inst": "ldrh Rd!=XX, [Rn!=PC, #off]" , "t32": "1111|100|0101|1|Rn|Rd|off:12" , "it": "any"}, + {"inst": "ldrh Rd!=XX, [Rn!=PC, #+/-off]{@}{!}" , "t32": "1111|100|0001|1|Rn|Rd|1PUW|off:8" , "it": "any"}, + {"inst": "ldrh Rd!=XX, [Rn==PC, #+/-off]" , "t32": "1111|100|0U01|1|Rn|Rd|off:12" , "it": "any"}, + {"inst": "ldrht Rd!=XX, [Rn!=PC, #off]" , "t32": "1111|100|0001|1|Rn|Rd|1110|off:8" , "it": "any"}, + {"inst": "ldrsb Rd!=HI, [Rn!=HI, Rm!=HI]" , "t16": "0101|011|Rm:3|Rn:3|Rd:3" , "it": "any"}, + {"inst": "ldrsb Rd!=XX, [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|1000|1|Rn|Rd|0|00000|n:2|Rm" , "it": "any"}, + {"inst": "ldrsb Rd!=XX, [Rn!=PC, #off]" , "t32": "1111|100|1100|1|Rn|Rd|off:12" , "it": "any"}, + {"inst": "ldrsb Rd!=XX, [Rn!=PC, #+/-off]{@}{!}" , "t32": "1111|100|1000|1|Rn|Rd|1PUW|off:8" , "it": "any"}, + {"inst": "ldrsb Rd!=XX, [Rn==PC, #+/-off]" , "t32": "1111|100|1U00|1|Rn|Rd|off:12" , "it": "any"}, + {"inst": "ldrsbt Rd!=XX, [Rn!=PC, #off]" , "t32": "1111|100|1000|1|Rn|Rd|1110|off:8" , "it": "any"}, + {"inst": "ldrsh Rd!=HI, [Rn!=HI, Rm!=HI]" , "t16": "0101|111|Rm:3|Rn:3|Rd:3" , "it": "any"}, + {"inst": "ldrsh Rd!=XX, [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|1001|1|Rn|Rd|0|00000|n:2|Rm" , "it": "any"}, + {"inst": "ldrsh Rd!=XX, [Rn!=PC, #off]" , "t32": "1111|100|1101|1|Rn|Rd|off:12" , "it": "any"}, + {"inst": "ldrsh Rd!=XX, [Rn!=PC, #+/-off]{@}{!}" , "t32": "1111|100|1001|1|Rn|Rd|1PUW|off:8" , "it": "any"}, + {"inst": "ldrsh Rd!=XX, [Rn==PC, #+/-off]" , "t32": "1111|100|1U01|1|Rn|Rd|off:12" , "it": "any"}, + {"inst": "ldrsht Rd!=XX, [Rn!=PC, #off]" , "t32": "1111|100|1001|1|Rn|Rd|1110|off:8" , "it": "any"}, + {"inst": "ldrt Rd!=XX, [Rn!=PC, #off]" , "t32": "1111|100|0010|1|Rn|Rd|1110|off:8" , "it": "any"}, + {"inst": "lsl Rd!=HI, Rn!=HI, #n" , "t16": "0000|0|n:5|Rn:3|Rd:3" , "it": "in"}, + {"inst": "lsl Rd!=XX, Rn!=XX, #n" , "t32": "1110|101|0010|0|1111|0|n:3|Rd|n:2|00|Rn" , "it": "any"}, + {"inst": "lsl Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|010|Rm:3|Rx:3" , "it": "in"}, + {"inst": "lsl Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0000|0|Rn|1111|Rd|0000|Rm" , "it": "any"}, + {"inst": "lslS Rd!=HI, Rn!=HI, #n" , "t16": "0000|0|n:5|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W"}, + {"inst": "lslS Rd!=XX, Rn!=XX, #n" , "t32": "1110|101|0010|1|1111|0|n:3|Rd|n:2|00|Rn" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "lslS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|010|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, + {"inst": "lslS Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1110|101|0000|1|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "lsr Rd!=HI, Rn!=HI, #n" , "t16": "0000|1|n:5|Rn:3|Rd:3" , "it": "in"}, + {"inst": "lsr Rd!=XX, Rn!=XX, #n" , "t32": "1110|101|0010|0|1111|0|n:3|Rd|n:2|01|Rn" , "it": "any"}, + {"inst": "lsr Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|011|Rm:3|Rx:3" , "it": "in"}, + {"inst": "lsr Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0001|0|Rn|1111|Rd|0000|Rm" , "it": "any"}, + {"inst": "lsrS Rd!=HI, Rn!=HI, #n" , "t16": "0000|1|n:5|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W"}, + {"inst": "lsrS Rd!=XX, Rn!=XX, #n" , "t32": "1110|101|0010|1|1111|0|n:3|Rd|n:2|01|Rn" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "lsrS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|011|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, + {"inst": "lsrS Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1110|101|0001|1|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "mcr #CP, #Op1, Rs!=XX, Cn, Cm, {#Op2}" , "t32": "1110|111|0|Op1:3|0|Cn:4|Rs|CP:4|Op2:3|1|Cm:4" , "ext": "ARMv6T2+"}, + {"inst": "mcr2 #CP, #Op1, Rs!=XX, Cn, Cm, {#Op2}" , "t32": "1111|111|0|Op1:3|0|Cn:4|Rs|CP:4|Op2:3|1|Cm:4" , "ext": "ARMv6T2+"}, + {"inst": "mcrr #CP, #Op1, Rs!=XX, Rs2!=XX, Cm" , "t32": "1110|110|0010|0|Rs2|Rs|CP:4|Op1:4|Cm:4" , "ext": "ARMv6T2+"}, + {"inst": "mcrr2 #CP, #Op1, Rs!=XX, Rs2!=XX, Cm" , "t32": "1111|110|0010|0|Rs2|Rs|CP:4|Op1:4|Cm:4" , "ext": "ARMv6T2+"}, + {"inst": "mla Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1000|0|Rn|Ra|Rd|0000|Rm" , "it": "any"}, + {"inst": "mls Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1000|0|Rn|Ra|Rd|0001|Rm" , "it": "any"}, + {"inst": "mov Rd, Rn" , "t16": "0100|0110|Rd:1|Rn:4|Rd:3" , "it": "in", "mod": "ARMv6T2_IF_LOW"}, + {"inst": "mov Rx!=HI, Rx!=HI, lsl Rm!=HI" , "t16": "0100|000|010|Rm:3|Rx:3" , "it": "in"}, + {"inst": "mov Rx!=HI, Rx!=HI, lsr Rm!=HI" , "t16": "0100|000|011|Rm:3|Rx:3" , "it": "in"}, + {"inst": "mov Rx!=HI, Rx!=HI, asr Rm!=HI" , "t16": "0100|000|100|Rm:3|Rx:3" , "it": "in"}, + {"inst": "mov Rx!=HI, Rx!=HI, ror Rm!=HI" , "t16": "0100|000|111|Rm:3|Rx:3" , "it": "in"}, + {"inst": "mov Rd!=HI, Rn!=HI, lsl #n" , "t16": "0000|0|n:5|Rn:3|Rd:3" , "it": "in"}, + {"inst": "mov Rd!=HI, Rn!=HI, lsr #n" , "t16": "0000|1|n:5|Rn:3|Rd:3" , "it": "in"}, + {"inst": "mov Rd!=HI, Rn!=HI, asr #n" , "t16": "0001|0|n:5|Rn:3|Rd:3" , "it": "in"}, + {"inst": "mov Rd!=HI, #immZ" , "t16": "0010|0|Rd:3|immZ:8" , "it": "in"}, + {"inst": "mov Rd!=PC, Rn" , "t32": "1110|101|0010|0|1111|0000|Rd|0000|Rn" , "it": "any", "mod": "UNPRED_COMPLEX"}, + {"inst": "mov Rd!=XX, Rn!=XX, sop #n" , "t32": "1110|101|0010|0|1111|0|n:3|Rd|n:2|sop:2|Rn" , "it": "any"}, + {"inst": "mov Rd!=XX, Rn!=XX, sop Rm!=XX" , "t32": "1111|101|00|sop:2|0|Rn|1111|Rd|0000|Rm" , "it": "any"}, + {"inst": "mov Rd!=XX, #immA" , "t32": "1111|0|imm:1|0|0010|0|1111|0|imm:3|Rd|imm:8" , "it": "any"}, + {"inst": "movS Rd!=HI, Rn!=HI" , "t16": "0000|0000|00|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W"}, + {"inst": "movS Rx!=HI, Rx!=HI, lsl Rm!=HI" , "t16": "0100|000|010|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, + {"inst": "movS Rx!=HI, Rx!=HI, lsr Rm!=HI" , "t16": "0100|000|011|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, + {"inst": "movS Rx!=HI, Rx!=HI, asr Rm!=HI" , "t16": "0100|000|100|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, + {"inst": "movS Rx!=HI, Rx!=HI, ror Rm!=HI" , "t16": "0100|000|111|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, + {"inst": "movS Rd!=HI, Rn!=HI, lsl #n" , "t16": "0000|0|n:5|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W"}, + {"inst": "movS Rd!=HI, Rn!=HI, lsr #n" , "t16": "0000|1|n:5|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W"}, + {"inst": "movS Rd!=HI, Rn!=HI, asr #n" , "t16": "0001|0|n:5|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W"}, + {"inst": "movS Rd!=HI, #immZ" , "t16": "0010|0|Rd:3|immZ:8" , "it": "out", "io": "N=W Z=W C=W"}, + {"inst": "movS Rd!=XX, Rn" , "t32": "1110|101|0010|1|1111|0000|Rd|0000|Rn" , "it": "any", "io": "N=W Z=W C=W", "mod": "UNPRED_COMPLEX"}, + {"inst": "movS Rd!=XX, Rn!=XX, sop Rm!=XX" , "t32": "1110|101|00|sop:2|1|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "movS Rd!=XX, Rn!=XX, sop #n" , "t32": "1110|101|0010|1|1111|0|n:3|Rd|n:2|sop:2|Rn" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "movS Rd!=XX, #immA" , "t32": "1111|0|imm:1|0|0010|1|1111|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "movt Rx!=XX, #immZ" , "t32": "1111|0|immZ:1|1|0110|0|immZ:4|0|immZ:3|Rx|immZ:8" , "it": "any"}, + {"inst": "movw Rd!=XX, #immZ" , "t32": "1111|0|immZ:1|1|0010|0|immZ:4|0|immZ:3|Rd|immZ:8" , "it": "any"}, + {"inst": "mrc #CP, #op1, Rd!=XX, Cn, Cm, {#op2}" , "t32": "1110|111|0|op1:3|1|Cn:4|Rd|CP:4|op2:3|1|Cm:4" , "it": "any"}, + {"inst": "mrc2 #CP, #op1, Rd!=XX, Cn, Cm, {#op2}" , "t32": "1111|111|0|op1:3|1|Cn:4|Rd|CP:4|op2:3|1|Cm:4" , "it": "any"}, + {"inst": "mrrc #CP, #op1, Rd!=XX, Rd2!=Rd, Cm" , "t32": "1110|110|0010|1|Rd2|Rd|CP:4|op1:4|Cm:4" , "it": "any"}, + {"inst": "mrrc2 #CP, #op1, Rd!=XX, Rd2!=Rd, Cm" , "t32": "1111|110|0010|1|Rd2|Rd|CP:4|op1:4|Cm:4" , "it": "any"}, + {"inst": "mrs Rd!=XX, #APSR" , "t32": "11110011111|APSR:1|1111|1000|Rd|0000|0000" , "it": "any"}, + {"inst": "msr #APSR, Rn!=PC" , "t32": "1111|001|1100|0|Rn|1100|APSR:2|00|0000|0000" , "it": "any"}, + {"inst": "mul Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|001|101|Rm:3|Rx:3" , "it": "in"}, + {"inst": "mulS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|001|101|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W"}, + {"inst": "mul Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1000|0|Rn|1111|Rd|0000|Rm" , "it": "any"}, + {"inst": "mvn Rd!=HI, Rn!=HI" , "t16": "0100|001|111|Rn:3|Rd:3" , "it": "in"}, + {"inst": "mvn Rd!=XX, Rn!=XX, {sop #n}" , "t32": "1110|101|0011|0|1111|0|n:3|Rd|n:2|sop:2|Rn" , "it": "any"}, + {"inst": "mvn Rd!=XX, #immA" , "t32": "1111|0|imm:1|0|0011|0|1111|0|imm:3|Rd|imm:8" , "it": "any"}, + {"inst": "mvnS Rd!=HI, Rn!=HI" , "t16": "0100|001|111|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W"}, + {"inst": "mvnS Rd!=XX, Rn!=XX, {sop #n}" , "t32": "1110|101|0011|1|1111|0|n:3|Rd|n:2|sop:2|Rn" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "mvnS Rd!=XX, #immA" , "t32": "1111|0|imm:1|0|0011|1|1111|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "nop" , "t16": "1011|111|1000|0|0000" , "it": "any"}, + {"inst": "nop" , "t32": "1111|001|1101|0|1111|1000|0000|0000|0000" , "it": "any"}, + {"inst": "orn Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|0011|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, + {"inst": "orn Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|0011|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, + {"inst": "ornS Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|0011|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "ornS Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|0011|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "orr Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|001|100|Rm:3|Rx:3" , "it": "in"}, + {"inst": "orr Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|0010|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, + {"inst": "orr Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|0010|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, + {"inst": "orrS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|001|100|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, + {"inst": "orrS Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|0010|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "orrS Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|0010|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "pkhbt Rd!=XX, Rn!=XX, Rm!=XX, {lsl #n}" , "t32": "1110|101|0110|0|Rn|0|n:3|Rd|n:2|00|Rm" , "it": "any"}, + {"inst": "pkhtb Rd!=XX, Rn!=XX, Rm!=XX, {asr #n}" , "t32": "1110|101|0110|0|Rn|0|n:3|Rd|n:2|10|Rm" , "it": "any"}, + {"inst": "pld [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|0000|1|Rn|1111|0000|00|n:2|Rm" , "it": "any"}, + {"inst": "pld [Rn!=PC, #off]" , "t32": "1111|100|0100|1|Rn|1111|off:12" , "it": "any"}, + {"inst": "pld [Rn!=PC, #-off]" , "t32": "1111|100|0000|1|Rn|1111|1100|off:8" , "it": "any"}, + {"inst": "pld [Rn==PC, #+/-off]" , "t32": "1111|100|0U00|1|Rn|1111|off:12" , "it": "any"}, + {"inst": "pldw [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|0001|1|Rn|1111|0000|00|n:2|Rm" , "it": "any"}, + {"inst": "pldw [Rn!=PC, #off]" , "t32": "1111|100|0101|1|Rn|1111|off:12" , "it": "any"}, + {"inst": "pldw [Rn!=PC, #-off]" , "t32": "1111|100|0001|1|Rn|1111|1100|off:8" , "it": "any"}, + {"inst": "pop Rd!=SP" , "t32": "1111|100|0010|1|1101|Rd|1011|00000100" , "it": "any"}, + {"inst": "pop RdList" , "t16": "1011|110|immMask[15]|immMask[7:0]" , "it": "any", "imm": "GpListImm(RsList, 0x80FF)"}, + {"inst": "pop RdList" , "t32": "1110|100|0101|1|1101|immMask[15:14]|0|immMask[12:0]" , "it": "any", "imm": "GpListImm(RsList, 0xDFFF)"}, + {"inst": "push Rs!=XX" , "t32": "1111|100|0010|0|1101|Rs|1101|0000|0100" , "it": "any"}, + {"inst": "push RsList" , "t16": "1011|010|immMask[14]|immMask[7:0]" , "it": "any", "imm": "GpListImm(RsList, 0x40FF)"}, + {"inst": "push RsList" , "t32": "1110|100|0101|0|1101|0|immMask[14]|0|immMask[12:0]" , "it": "any", "imm": "GpListImm(RsList, 0x5FFF)"}, + {"inst": "qadd Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|0|Rm|1111|Rd|1000|Rn" , "it": "any", "io": "Q=X"}, + {"inst": "qadd16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|1|Rm|1111|Rd|0001|Rn" , "it": "any"}, + {"inst": "qadd8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|0|Rm|1111|Rd|0001|Rn" , "it": "any"}, + {"inst": "qasx Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0101|0|Rm|1111|Rd|0001|Rn" , "it": "any"}, + {"inst": "qdadd Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|0|Rm|1111|Rd|1001|Rn" , "it": "any", "io": "Q=X"}, + {"inst": "qdsub Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|0|Rm|1111|Rd|1011|Rn" , "it": "any", "io": "Q=X"}, + {"inst": "qsax Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0111|0|Rm|1111|Rd|0001|Rn" , "it": "any"}, + {"inst": "qsub Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|0|Rm|1111|Rd|1010|Rn" , "it": "any", "io": "Q=X"}, + {"inst": "qsub16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|1|Rm|1111|Rd|0001|Rn" , "it": "any"}, + {"inst": "qsub8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|0|Rm|1111|Rd|0001|Rn" , "it": "any"}, + {"inst": "rbit Rd!=XX, Rn!=XX" , "t32": "1111|101|0100|1|Rm|1111|Rd|1010|Rn" , "it": "any"}, + {"inst": "rev Rd!=HI, Rn!=HI" , "t16": "1011|101|000|Rn:3|Rd:3" , "it": "any"}, + {"inst": "rev Rd!=XX, Rn!=XX" , "t32": "1111|101|0100|1|Rm|1111|Rd|1000|Rn" , "it": "any"}, + {"inst": "rev16 Rd!=HI, Rn!=HI" , "t16": "1011|101|001|Rn:3|Rd:3" , "it": "any"}, + {"inst": "rev16 Rd!=XX, Rn!=XX" , "t32": "1111|101|0100|1|Rm|1111|Rd|1001|Rn" , "it": "any"}, + {"inst": "revsh Rd!=HI, Rn!=HI" , "t16": "1011|101|011|Rn:3|Rd:3" , "it": "any"}, + {"inst": "revsh Rd!=XX, Rn!=XX" , "t32": "1111|101|0100|1|Rm|1111|Rd|1011|Rn" , "it": "any"}, + {"inst": "ror Rd!=XX, Rn!=XX, #n" , "t32": "1110|101|0010|0|1111|0|n:3|Rd|n:2|11|Rn" , "it": "any"}, + {"inst": "ror Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|111|Rm:3|Rx:3" , "it": "in"}, + {"inst": "ror Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0011|0|Rn|1111|Rd|0000|Rm" , "it": "any"}, + {"inst": "rorS Rd!=XX, Rn!=XX, #n" , "t32": "1110|101|0010|1|1111|0|n:3|Rd|n:2|11|Rn" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "rorS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|111|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W"}, + {"inst": "rorS Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0011|1|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "rsb Rd!=HI, Rn!=HI, #zero" , "t16": "0100|001001|Rn:3|Rd:3" , "it": "in"}, + {"inst": "rsb Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|1110|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, + {"inst": "rsb Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|1110|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, + {"inst": "rsbS Rd!=HI, Rn!=HI, #zero" , "t16": "0100|001001|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W V=W"}, + {"inst": "rsbS Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|1110|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W V=W"}, + {"inst": "rsbS Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|1110|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W V=W"}, + {"inst": "rrx Rd!=XX, Rn!=XX" , "t32": "1110|101|0010|0|1111|0000|Rd|0011|Rn" , "it": "any", "io": "C=R"}, + {"inst": "rrxS Rd!=XX, Rn!=XX" , "t32": "1110|101|0010|1|1111|0000|Rd|0011|Rn" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "sadd16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|1|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "GE=W"}, + {"inst": "sadd8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|0|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "GE=W"}, + {"inst": "sasx Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0101|0|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "GE=W"}, + {"inst": "sbc Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|110|Rm:3|Rx:3" , "it": "in"}, + {"inst": "sbc Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|1011|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, + {"inst": "sbc Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|1011|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, + {"inst": "sbcS Rx!=HI, Rx!=HI, Rm!=HI" , "t16": "0100|000|110|Rm:3|Rx:3" , "it": "out", "io": "N=W Z=W C=W V=W"}, + {"inst": "sbcS Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|1011|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W V=W"}, + {"inst": "sbcS Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|1011|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W V=W"}, + {"inst": "sbfx Rd!=XX, Rn!=XX, #lsb, #width" , "t32": "1111|001|1010|0|Rn|0|lsb:3|Rd|lsb:2|0|widthM1:5" , "it": "any", "imm": "SbfxUbfxImm(lsb, width)"}, + {"inst": "sel Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0101|0|Rn|1111|Rd|1000|Rm" , "it": "any"}, + {"inst": "setend #immZ" , "t16": "1011|0110|010|1|immZ:1|000" , "it": "out"}, + {"inst": "shadd16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|1|Rn|1111|Rd|0010|Rm" , "it": "any"}, + {"inst": "shadd8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|0|Rn|1111|Rd|0010|Rm" , "it": "any"}, + {"inst": "shasx Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0101|0|Rn|1111|Rd|0010|Rm" , "it": "any"}, + {"inst": "shsax Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0111|0|Rn|1111|Rd|0010|Rm" , "it": "any"}, + {"inst": "shsub16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|1|Rn|1111|Rd|0010|Rm" , "it": "any"}, + {"inst": "shsub8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|0|Rn|1111|Rd|0010|Rm" , "it": "any"}, + {"inst": "smlabb Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1001|1|Rn|Ra|Rd|0000|Rm" , "it": "any", "io": "Q=X"}, + {"inst": "smlabt Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1001|1|Rn|Ra|Rd|0001|Rm" , "it": "any", "io": "Q=X"}, + {"inst": "smlatb Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1001|1|Rn|Ra|Rd|0010|Rm" , "it": "any", "io": "Q=X"}, + {"inst": "smlatt Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1001|1|Rn|Ra|Rd|0011|Rm" , "it": "any", "io": "Q=X"}, + {"inst": "smlad Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1001|0|Rn|Ra|Rd|0000|Rm" , "it": "any", "io": "Q=X"}, + {"inst": "smladx Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1001|0|Rn|Ra|Rd|0001|Rm" , "it": "any", "io": "Q=X"}, + {"inst": "smlal RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1110|0|Rn|RxLo|RxHi|0000|Rm" , "it": "any"}, + {"inst": "smlalbb RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1110|0|Rn|RxLo|RxHi|1000|Rm" , "it": "any"}, + {"inst": "smlalbt RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1110|0|Rn|RxLo|RxHi|1001|Rm" , "it": "any"}, + {"inst": "smlaltb RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1110|0|Rn|RxLo|RxHi|1010|Rm" , "it": "any"}, + {"inst": "smlaltt RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1110|0|Rn|RxLo|RxHi|1011|Rm" , "it": "any"}, + {"inst": "smlald RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1110|0|Rn|RxLo|RxHi|1100|Rm" , "it": "any"}, + {"inst": "smlaldx RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1110|0|Rn|RxLo|RxHi|1101|Rm" , "it": "any"}, + {"inst": "smlawb Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1001|1|Rn|Ra|Rd|0000|Rm" , "it": "any", "io": "Q=X"}, + {"inst": "smlawt Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1001|1|Rn|Ra|Rd|0001|Rm" , "it": "any", "io": "Q=X"}, + {"inst": "smlsd Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1010|1|Rn|Ra|Rd|0000|Rm" , "it": "any", "io": "Q=X"}, + {"inst": "smlsdx Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1010|1|Rn|Ra|Rd|0001|Rm" , "it": "any", "io": "Q=X"}, + {"inst": "smlsld RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1110|1|Rn|RxLo|RxHi|1100|Rm" , "it": "any", "io": "Q=X"}, + {"inst": "smlsldx RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1110|1|Rn|RxLo|RxHi|1101|Rm" , "it": "any", "io": "Q=X"}, + {"inst": "smmla Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1010|1|Rn|Ra|Rd|0000|Rm" , "it": "any"}, + {"inst": "smmlar Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1010|1|Rn|Ra|Rd|0001|Rm" , "it": "any"}, + {"inst": "smmls Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1011|0|Rn|Ra|Rd|0000|Rm" , "it": "any"}, + {"inst": "smmlsr Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1011|0|Rn|Ra|Rd|0001|Rm" , "it": "any"}, + {"inst": "smmul Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1010|1|Rn|1111|Rd|0000|Rm" , "it": "any"}, + {"inst": "smmulr Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1010|1|Rn|1111|Rd|0001|Rm" , "it": "any"}, + {"inst": "smuad Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1001|0|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "Q=X"}, + {"inst": "smuadx Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1001|0|Rn|1111|Rd|0001|Rm" , "it": "any", "io": "Q=X"}, + {"inst": "smulbb Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1000|1|Rn|1111|Rd|0000|Rm" , "it": "any"}, + {"inst": "smulbt Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1000|1|Rn|1111|Rd|0001|Rm" , "it": "any"}, + {"inst": "smultb Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1000|1|Rn|1111|Rd|0010|Rm" , "it": "any"}, + {"inst": "smultt Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1000|1|Rn|1111|Rd|0011|Rm" , "it": "any"}, + {"inst": "smull RdLo!=XX, RdHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1100|0|Rn|RdLo|RdHi|0000|Rm" , "it": "any"}, + {"inst": "smulwb Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1001|1|Rn|1111|Rd|0000|Rm" , "it": "any"}, + {"inst": "smulwt Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1001|1|Rn|1111|Rd|0001|Rm" , "it": "any"}, + {"inst": "smusd Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1010|0|Rn|1111|Rd|0000|Rm" , "it": "any"}, + {"inst": "smusdx Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1010|0|Rn|1111|Rd|0001|Rm" , "it": "any"}, + {"inst": "ssat Rd!=XX, #sat, Rn!=XX" , "t32": "1111|001|100|00|Rn|0|000|Rd|00|0|imm:5" , "it": "any", "imm": "SsatImm(sat)", "io": "Q=X"}, + {"inst": "ssat Rd!=XX, #sat, Rn!=XX, lsl_or_asr #n" , "t32": "1111|001|100|sop:2|Rn|0|n:3|Rd|n:2|0|imm:5" , "it": "any", "imm": "SsatImm(sat, n)", "io": "Q=X"}, + {"inst": "ssat16 Rd!=XX, #sat, Rn!=XX" , "t32": "1111|001|1001|0|Rn|0000|Rd|0000|imm:4" , "it": "any", "imm": "Ssat16Imm(sat)", "io": "Q=X"}, + {"inst": "ssax Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0111|0|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "GE=W"}, + {"inst": "ssub16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|1|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "GE=W"}, + {"inst": "ssub8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|0|Rn|1111|Rd|0000|Rm" , "it": "any", "io": "GE=W"}, + {"inst": "stmia [Rn!=HI]!, RsList" , "t16": "1100|0|Rn:3|immMask:8" , "it": "any", "imm": "GpListImm(RsList, 0xFF)"}, + {"inst": "stmia [Rn!=PC]{!}, RsList" , "t32": "1110|100|010W|0|Rn|0|immMask[14]|0|immMask[12:0]" , "it": "any", "imm": "GpListImm(RsList, 0x5FFF)"}, + {"inst": "stmdb [Rn!=PC]{!}, RsList" , "t32": "1110|100|100W|0|Rn|0|immMask[14]|0|immMask[12:0]" , "it": "any", "imm": "GpListImm(RsList, 0x5FFF)"}, + {"inst": "str Rs!=HI, [Rn!=HI, Rm!=HI]" , "t16": "0101|000|Rm:3|Rn:3|Rs:3" , "it": "any"}, + {"inst": "str Rs!=PC, [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|0010|0|Rn|Rs|0|00000|n:2|Rm" , "it": "any"}, + {"inst": "str Rs!=HI, [Rn==SP, #off*4]" , "t16": "1001|0|Rs:3|off:8" , "it": "any"}, + {"inst": "str Rs!=HI, [Rn!=HI, #off*4]" , "t16": "0110|0|off:5|Rn:3|Rs:3" , "it": "any"}, + {"inst": "str Rs!=PC, [Rn!=PC, #off]" , "t32": "1111|100|0110|0|Rn|Rs|off:12" , "it": "any"}, + {"inst": "str Rs!=PC, [Rn!=PC, #+/-off]{@}{!}" , "t32": "1111|100|0010|0|Rn|Rs|1PUW|off:8" , "it": "any"}, + {"inst": "strb Rs!=HI, [Rn!=HI, Rm!=HI]" , "t16": "0101|010|Rm:3|Rn:3|Rs:3" , "it": "any"}, + {"inst": "strb Rs!=XX, [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|0000|0|Rn|Rs|0|00000|n:2|Rm" , "it": "any"}, + {"inst": "strb Rs!=HI, [Rn!=HI, #off*4]" , "t16": "0111|0|off:5|Rn:3|Rs:3" , "it": "any"}, + {"inst": "strb Rs!=XX, [Rn!=PC, #off]" , "t32": "1111|100|0100|0|Rn|Rs|off:12" , "it": "any"}, + {"inst": "strb Rs!=XX, [Rn!=PC, #+/-off]{@}{!}" , "t32": "1111|100|0000|0|Rn|Rs|1PUW|off:8" , "it": "any"}, + {"inst": "strbt Rs!=XX, [Rn!=PC, #off]" , "t32": "1111|100|0000|0|Rn|Rs|1110|off:8" , "it": "any"}, + {"inst": "strd Rs!=XX, Rs2!=XX, [Rn!=PC, #off]{@}{!}" , "t32": "1110|100|PU1W|0|Rn|Rs|Rs2|off:8" , "it": "any"}, + {"inst": "strex Rd!=XX, Rs!=XX, [Rn!=PC, #off]" , "t32": "1110|100|0010|0|Rn|Rs|Rd|off:8" , "it": "any", "mod": "UNPRED_COMPLEX"}, + {"inst": "strexb Rd!=XX, Rs!=XX, [Rn!=PC]" , "t32": "1110|100|0110|0|Rn|Rs|1111|0100|Rd" , "it": "any", "mod": "UNPRED_COMPLEX"}, + {"inst": "strexd Rd!=XX, Rs!=XX, Rs2!=XX, [Rn!=PC]" , "t32": "1110|100|0110|0|Rn|Rs|Rs2|0111|Rd" , "it": "any", "mod": "UNPRED_COMPLEX"}, + {"inst": "strexh Rd!=XX, Rs!=XX, [Rn!=PC]" , "t32": "1110|100|0110|0|Rn|Rs|1111|0101|Rd" , "it": "any", "mod": "UNPRED_COMPLEX"}, + {"inst": "strh Rs!=HI, [Rn!=HI, Rm!=HI]" , "t16": "0101|001|Rm:3|Rn:3|Rs:3" , "it": "any"}, + {"inst": "strh Rs!=XX, [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|0001|0|Rn|Rs|0|00000|n:2|Rm" , "it": "any"}, + {"inst": "strh Rs!=HI, [Rn!=HI, #off*4]" , "t16": "1000|0|off:5|Rn:3|Rs:3" , "it": "any"}, + {"inst": "strh Rs!=XX, [Rn!=PC, #off]" , "t32": "1111|100|0101|0|Rn|Rs|off:12" , "it": "any"}, + {"inst": "strh Rs!=XX, [Rn!=PC, #+/-off]{@}{!}" , "t32": "1111|100|0001|0|Rn|Rs|1PUW|off:8" , "it": "any"}, + {"inst": "strht Rs!=XX, [Rn!=PC, #off]" , "t32": "1111|100|0001|0|Rn|Rs|1110|off:8" , "it": "any"}, + {"inst": "strt Rs!=XX, [Rn!=PC, #off]" , "t32": "1111|100|0010|0|Rn|Rs|1110|off:8" , "it": "any"}, + {"inst": "sub Rd!=HI, Rn!=HI, Rm!=HI" , "t16": "0001|101|Rm:3|Rn:3|Rd:3" , "it": "in"}, + {"inst": "sub Rd!=HI, Rn!=HI, #immZ" , "t16": "0001|111|immZ:3|Rn:3|Rd:3" , "it": "in"}, + {"inst": "sub Rx!=HI, Rx!=HI, #immZ" , "t16": "0011|1|Rx:3|immZ:8" , "it": "in"}, + {"inst": "sub Rx==SP, Rx==SP, #immZ*4" , "t16": "1011|00001|immZ:7" , "it": "any"}, + {"inst": "sub Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|1101|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, + {"inst": "sub Rd!=PC, Rn==SP, Rm!=XX, {sop #n}" , "t32": "1110|101|1101|0|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any"}, + {"inst": "sub Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|1101|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, + {"inst": "sub Rd!=PC, Rn==SP, #immA" , "t32": "1111|0|imm:1|0|1101|0|Rn|0|imm:3|Rd|imm:8" , "it": "any"}, + {"inst": "sub Rd!=XX, Rn!=XX, #immZ" , "t32": "1111|0|immZ:1|1|0101|0|Rn|0|immZ:3|Rd|immZ:8" , "it": "any"}, + {"inst": "sub Rd!=HI, Rn!=HI, Rm!=HI" , "t16": "0001|101|Rm:3|Rn:3|Rd:3" , "it": "in"}, + {"inst": "subS Rd!=HI, Rn!=HI, #immZ" , "t16": "0001|111|immZ:3|Rn:3|Rd:3" , "it": "out", "io": "N=W Z=W C=W V=W"}, + {"inst": "subS Rx!=HI, Rx!=HI, #immZ" , "t16": "0001|1|Rx:3|immZ:8" , "it": "out", "io": "N=W Z=W C=W V=W"}, + {"inst": "subS Rd!=XX, Rn!=XX, Rm!=XX, {sop #n}" , "t32": "1110|101|1101|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W V=W"}, + {"inst": "subS Rd!=PC, Rn==SP, Rm!=XX, {sop #n}" , "t32": "1110|101|1101|1|Rn|0|n:3|Rd|n:2|sop:2|Rm" , "it": "any", "io": "N=W Z=W C=W V=W"}, + {"inst": "subS Rd!=XX, Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|1101|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W V=W"}, + {"inst": "subS Rd!=PC, Rn==SP, #immA" , "t32": "1111|0|imm:1|0|1101|1|Rn|0|imm:3|Rd|imm:8" , "it": "any", "io": "N=W Z=W C=W V=W"}, + {"inst": "subS Rd!=XX, Rn!=XX, #immZ" , "t32": "1111|0|immZ:1|1|0101|1|Rn|0|immZ:3|Rd|immZ:8" , "it": "any", "io": "N=W Z=W C=W V=W"}, + {"inst": "svc #immZ" , "t16": "1101|1111|immZ:8" , "it": "any"}, + {"inst": "sxtab Rd!=XX, Rn!=XX, Rm!=XX, {ror #n}" , "t32": "1111|101|0010|0|Rn|1111|Rd|1|0|imm:2|Rm" , "it": "any", "imm": "Ror8Imm(n)"}, + {"inst": "sxtab16 Rd!=XX, Rn!=XX, Rm!=XX, {ror #n}" , "t32": "1111|101|0001|0|Rn|1111|Rd|1|0|imm:2|Rm" , "it": "any", "imm": "Ror8Imm(n)"}, + {"inst": "sxtah Rd!=XX, Rn!=XX, Rm!=XX, {ror #n}" , "t32": "1111|101|0000|0|Rn|1111|Rd|1|0|imm:2|Rm" , "it": "any", "imm": "Ror8Imm(n)"}, + {"inst": "sxtb Rd!=HI, Rn!=HI, {ror #zero}" , "t16": "1011|001|001|Rn:3|Rd:3" , "it": "any"}, + {"inst": "sxtb Rd!=XX, Rn!=XX, {ror #n}" , "t32": "1111|101|0010|0|1111|1111|Rd|10|imm:2|Rn" , "it": "any", "imm": "Ror8Imm(n)"}, + {"inst": "sxtb16 Rd!=XX, Rn!=XX, {ror #n}" , "t32": "1111|101|0001|0|1111|1111|Rd|10|imm:2|Rn" , "it": "any", "imm": "Ror8Imm(n)"}, + {"inst": "sxth Rd!=HI, Rn!=HI, {ror #zero}" , "t16": "1011|001|000|Rn:3|Rd:3" , "it": "any"}, + {"inst": "sxth Rd!=XX, Rn!=XX, {ror #n}" , "t32": "1111|101|0000|0|1111|1111|Rd|10|imm:2|Rn" , "it": "any", "imm": "Ror8Imm(n)"}, + {"inst": "tbb Rn!=SP, Rn!=XX" , "t32": "1110|100|0110|1|Rn|1111|0000|0000|Rn" , "it": "out last"}, + {"inst": "tbh Rn!=SP, Rn!=XX" , "t32": "1110|100|0110|1|Rn|1111|0000|0001|Rn" , "it": "out last"}, + {"inst": "teq Rn!=XX, Rn!=XX, {sop #n}" , "t32": "1110|101|0100|1|Rn|0|n:3|1111|n:2|sop:2|Rn" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "teq Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|0100|1|Rn|0|imm:3|1111|imm:8" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "tst Rn!=HI, Rn!=HI" , "t16": "0100|00|1000|Rn:3|Rn:3" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "tst Rn!=XX, Rn!=XX, {sop #n}" , "t32": "1110|101|0000|1|Rn|0|n:3|1111|n:2|sop:2|Rn" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "tst Rn!=XX, #immA" , "t32": "1111|0|imm:1|0|0000|1|Rn|0|imm:3|1111|imm:8" , "it": "any", "io": "N=W Z=W C=W"}, + {"inst": "uadd16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|1|Rn|1111|Rd|0100|Rm" , "it": "any", "io": "GE=W"}, + {"inst": "uadd8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|0|Rn|1111|Rd|0100|Rm" , "it": "any", "io": "GE=W"}, + {"inst": "uasx Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0101|0|Rn|1111|Rd|0100|Rm" , "it": "any", "io": "GE=W"}, + {"inst": "ubfx Rd!=XX, Rn!=XX, #lsb, #width" , "t32": "1111|001|1110|0|Rn|0|lsb:3|Rd|lsb:2|0|widthM1:5" , "it": "any", "imm": "SbfxUbfxImm(lsb, width)"}, + {"inst": "uhadd8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|0|Rn|1111|Rd|0110|Rm" , "it": "any"}, + {"inst": "uhadd16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|1|Rn|1111|Rd|0110|Rm" , "it": "any"}, + {"inst": "uhasx Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0101|0|Rn|1111|Rd|0110|Rm" , "it": "any"}, + {"inst": "uhsax Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0111|0|Rn|1111|Rd|0110|Rm" , "it": "any"}, + {"inst": "uhsub16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|1|Rn|1111|Rd|0110|Rm" , "it": "any"}, + {"inst": "uhsub8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|0|Rn|1111|Rd|0110|Rm" , "it": "any"}, + {"inst": "umaal RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1111|0|Rn|RxLo|RxHi|0110|Rm" , "it": "any"}, + {"inst": "umlal RxLo!=XX, RxHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1111|0|Rn|RxLo|RxHi|0000|Rm" , "it": "any"}, + {"inst": "umull RdLo!=XX, RdHi!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1101|0|Rn|RdLo|RdHi|0000|Rm" , "it": "any"}, + {"inst": "uqadd16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|1|Rn|1111|Rd|0101|Rm" , "it": "any"}, + {"inst": "uqadd8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0100|0|Rn|1111|Rd|0101|Rm" , "it": "any"}, + {"inst": "uqasx Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0101|0|Rn|1111|Rd|0101|Rm" , "it": "any"}, + {"inst": "uqsax Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0111|0|Rn|1111|Rd|0101|Rm" , "it": "any"}, + {"inst": "uqsub16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|1|Rn|1111|Rd|0101|Rm" , "it": "any"}, + {"inst": "uqsub8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|0|Rn|1111|Rd|0101|Rm" , "it": "any"}, + {"inst": "usad8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1011|1|Rn|1111|Rd|0000|Rm" , "it": "any"}, + {"inst": "usada8 Rd!=XX, Rn!=XX, Rm!=XX, Ra!=XX" , "t32": "1111|101|1011|1|Rn|Ra|Rd|0000|Rm" , "it": "any"}, + {"inst": "usat Rd!=XX, #sat, Rn!=XX, {lsl_or_asr #n}" , "t32": "1111|001|110|sop:2|Rn|0|n:3|Rd|n:2|0|sat:5" , "it": "any", "io": "Q=X"}, + {"inst": "usat16 Rd!=XX, #sat, Rn!=XX" , "t32": "1111|001|1101|0|Rn|0000|Rd|0000|sat:4" , "it": "any", "io": "Q=X"}, + {"inst": "usax Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0111|0|Rn|1111|Rd|0100|Rm" , "it": "any", "io": "GE=W"}, + {"inst": "usub16 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|1|Rn|1111|Rd|0100|Rm" , "it": "any", "io": "GE=W"}, + {"inst": "usub8 Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|0110|0|Rn|1111|Rd|0100|Rm" , "it": "any", "io": "GE=W"}, + {"inst": "uxtab Rd!=XX, Rn!=XX, Rm!=XX, {ror #n}" , "t32": "1111|101|0010|1|Rn|1111|Rd|10|imm:2|Rm" , "it": "any", "imm": "Ror8Imm(n)"}, + {"inst": "uxtab16 Rd!=XX, Rn!=XX, Rm!=XX, {ror #n}" , "t32": "1111|101|0001|1|Rn|1111|Rd|10|imm:2|Rm" , "it": "any", "imm": "Ror8Imm(n)"}, + {"inst": "uxtah Rd!=XX, Rn!=XX, Rm!=XX, {ror #n}" , "t32": "1111|101|0000|1|Rn|1111|Rd|10|imm:2|Rm" , "it": "any", "imm": "Ror8Imm(n)"}, + {"inst": "uxtb Rd!=HI, Rn!=HI, {ror #zero}" , "t16": "1011|001|011|Rn:3|Rd:3" , "it": "any"}, + {"inst": "uxtb Rd!=XX, Rn!=XX, {ror #n}" , "t32": "1111|101|0010|1|1111|1111|Rd|10|imm:2|Rn" , "it": "any", "imm": "Ror8Imm(n)"}, + {"inst": "uxtb16 Rd!=XX, Rn!=XX, {ror #n}" , "t32": "1111|101|0001|1|1111|1111|Rd|10|imm:2|Rn" , "it": "any", "imm": "Ror8Imm(n)"}, + {"inst": "uxth Rd!=HI, Rn!=HI, {ror #zero}" , "t16": "1011|001|010|Rn:3|Rd:3" , "it": "any"}, + {"inst": "uxth Rd!=XX, Rn!=XX, {ror #n}" , "t32": "1111|101|0000|1|1111|1111|Rd|10|imm:2|Rn" , "it": "any", "imm": "Ror8Imm(n)"}, + {"inst": "wfe" , "t16": "1011|1111|0010|0000" , "it": "any"}, + {"inst": "wfe" , "t32": "1111|001|1101|0|1111|1000|0000|0000|0010" , "it": "any"}, + {"inst": "wfi" , "t16": "1011|1111|0011|0000" , "it": "any"}, + {"inst": "wfi" , "t32": "1111|001|1101|0|1111|1000|0000|0000|0011" , "it": "any"}, + {"inst": "yield" , "t16": "1011|1111|0001|0000" , "it": "any"}, + {"inst": "yield" , "t32": "1111|001|1101|0|1111|1000|0000|0000|0001" , "it": "any"} ]}, {"category": "GP GP_EXT", "level": "ARMv7+", "data": [ - {"inst": "clrex" , "a32": "1111|010|1011|1|1111|1111|0000|0001|1111" , "ext": "ARMv7+"}, - {"inst": "dbg #immZ" , "a32": "cond|001|1001|0|0000|1111|0000|1111|immZ:4" , "ext": "ARMv7+ ARMv8-"}, - {"inst": "dmb #immZ" , "a32": "1111|010|1011|1|1111|1111|0000|0101|immZ:4" , "ext": "ARMv7+"}, - {"inst": "dsb #immZ" , "a32": "1111|010|1011|1|1111|1111|0000|0100|immZ:4" , "ext": "ARMv7+"}, - {"inst": "isb #immZ" , "a32": "1111|010|1011|1|1111|1111|0000|0110|immZ:4" , "ext": "ARMv7+"}, - {"inst": "pldw [Rn, +/-Rm!=PC, {sop #n}]" , "a32": "1111|011|1U00|1|Rn|1111|n:5|sop:2|0|Rm" , "ext": "ARMv7+ MP"}, - {"inst": "pldw [Rn, #+/-off]" , "a32": "1111|010|1U00|1|Rn|1111|off:12" , "ext": "ARMv7+ MP"}, - {"inst": "pli [Rn, +/-Rm!=PC, {sop #n}]" , "a32": "1111|011|0U10|1|Rn|1111|n:5|sop:2|0|Rm" , "ext": "ARMv7+"}, - {"inst": "pli [Rn, #+/-off]" , "a32": "1111|010|0U10|1|Rn|1111|off:12" , "ext": "ARMv7+"}, - {"inst": "sev" , "a32": "cond|001|1001|0|0000|1111|0000|0000|0100" , "ext": "ARMv7+"} + {"inst": "clrex" , "a32": "1111|010|1011|1|1111|1111|0000|0001|1111"}, + {"inst": "dbg #immZ" , "a32": "cond|001|1001|0|0000|1111|0000|1111|immZ:4" , "ext": "ARMv8-"}, + {"inst": "dmb #immZ" , "a32": "1111|010|1011|1|1111|1111|0000|0101|immZ:4"}, + {"inst": "dsb #immZ" , "a32": "1111|010|1011|1|1111|1111|0000|0100|immZ:4"}, + {"inst": "isb #immZ" , "a32": "1111|010|1011|1|1111|1111|0000|0110|immZ:4"}, + {"inst": "pldw [Rn!=PC, +/-Rm!=PC, {sop #n}]" , "a32": "1111|011|1U00|1|Rn|1111|n:5|sop:2|0|Rm" , "ext": "MP"}, + {"inst": "pldw [Rn!=PC, #+/-off]" , "a32": "1111|010|1U00|1|Rn|1111|off:12" , "ext": "MP"}, + {"inst": "pli [Rn, +/-Rm!=PC, {sop #n}]" , "a32": "1111|011|0U10|1|Rn|1111|n:5|sop:2|0|Rm"}, + {"inst": "pli [Rn, #+/-off]" , "a32": "1111|010|0U10|1|Rn|1111|off:12"}, + {"inst": "sev" , "a32": "cond|001|1001|0|0000|1111|0000|0000|0100"}, + {"inst": "sevl" , "a32": "cond|001|1001|0|0000|1111|0000|0000|0101"} ]}, {"category": "GP GP_EXT", "level": "ARMv7+", "data": [ - {"inst": "clrex" , "t32": "1111|001|1101|1|1111|1000|1111|0010|1111" , "it": "any"}, - {"inst": "dmb #immZ" , "t32": "1111|001|1101|1|1111|1000|1111|0101|immZ:4" , "it": "any"}, - {"inst": "dsb #immZ" , "t32": "1111|001|1101|1|1111|1000|1111|0100|immZ:4" , "it": "any"}, - {"inst": "ldrexb Rd!=XX, [Rn!=PC]" , "t32": "1110|100|0110|1|Rn|Rd|1111|0100|1111" , "it": "any"}, - {"inst": "ldrexd Rd!=XX, Rd2!=XX, [Rn!=PC]" , "t32": "1110|100|0110|1|Rn|Rd|Rd2 |0111|1111" , "it": "any"}, - {"inst": "ldrexh Rd!=XX, [Rn!=PC]" , "t32": "1110|100|0110|1|Rn|Rd|1111|0101|1111" , "it": "any"}, - {"inst": "isb #immZ" , "t32": "1111|001|1101|1|1111|1000|1111|0110|immZ:4" , "it": "any"}, - {"inst": "pli [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|1000|1|Rn|1111|0000|00|n:2|Rm" , "it": "any"}, - {"inst": "pli [Rn!=PC, #off]" , "t32": "1111|100|1100|1|Rn|1111|off:12" , "it": "any"}, - {"inst": "pli [Rn!=PC, #-off]" , "t32": "1111|100|1000|1|Rn|1111|1100|off:8" , "it": "any"}, - {"inst": "pli [Rn==PC, #+/-off]" , "t32": "1111|100|1U00|1|Rn|1111|off:12" , "it": "any"} + {"inst": "clrex" , "t32": "1111|001|1101|1|1111|1000|1111|0010|1111" , "it": "any"}, + {"inst": "dmb #immZ" , "t32": "1111|001|1101|1|1111|1000|1111|0101|immZ:4" , "it": "any"}, + {"inst": "dsb #immZ" , "t32": "1111|001|1101|1|1111|1000|1111|0100|immZ:4" , "it": "any"}, + {"inst": "ldrexb Rd!=XX, [Rn!=PC]" , "t32": "1110|100|0110|1|Rn|Rd|1111|0100|1111" , "it": "any"}, + {"inst": "ldrexd Rd!=XX, Rd2!=XX, [Rn!=PC]" , "t32": "1110|100|0110|1|Rn|Rd|Rd2 |0111|1111" , "it": "any"}, + {"inst": "ldrexh Rd!=XX, [Rn!=PC]" , "t32": "1110|100|0110|1|Rn|Rd|1111|0101|1111" , "it": "any"}, + {"inst": "isb #immZ" , "t32": "1111|001|1101|1|1111|1000|1111|0110|immZ:4" , "it": "any"}, + {"inst": "pli [Rn!=PC, Rm!=XX, {lsl #n}]" , "t32": "1111|100|1000|1|Rn|1111|0000|00|n:2|Rm" , "it": "any"}, + {"inst": "pli [Rn!=PC, #off]" , "t32": "1111|100|1100|1|Rn|1111|off:12" , "it": "any"}, + {"inst": "pli [Rn!=PC, #-off]" , "t32": "1111|100|1000|1|Rn|1111|1100|off:8" , "it": "any"}, + {"inst": "pli [Rn==PC, #+/-off]" , "t32": "1111|100|1U00|1|Rn|1111|off:12" , "it": "any"}, + {"inst": "sev" , "t16": "1011|1111|0100|0000" , "it": "any"}, + {"inst": "sev" , "t32": "1111|001|1101|0|1111|1000|0000|0000|0000" , "it": "any"}, + {"inst": "sevl" , "t16": "1011|1111|0101|0000" , "it": "any"}, + {"inst": "sevl" , "t32": "1111|001|1101|0|1111|1000|0000|0000|0101" , "it": "any"} ]}, {"category": "GP GP_EXT", "level": "ARMv8+", "data": [ @@ -805,20 +817,23 @@ ]}, {"category": "GP GP_EXT", "level": "ARMv8+", "data": [ - {"inst": "lda Rd!=PC, [Rn!=PC]" , "t32": "1110|100|0110|1|Rn|Rd|1111|1010|1111" , "it": "any"}, - {"inst": "ldab Rd!=PC, [Rn!=PC]" , "t32": "1110|100|0110|1|Rn|Rd|1111|1000|1111" , "it": "any"}, - {"inst": "ldaex Rd!=PC, [Rn!=PC]" , "t32": "1110|100|0110|1|Rn|Rd|1111|1110|1111" , "it": "any"}, - {"inst": "ldaexb Rd!=PC, [Rn!=PC]" , "t32": "1110|100|0110|1|Rn|Rd|1111|1100|1111" , "it": "any"}, - {"inst": "ldaexd Rd!=PC, Rd2!=PC, [Rn!=PC]" , "t32": "1110|100|0110|1|Rn|Rd|Rd2|1111|1111" , "it": "any"}, - {"inst": "ldaexh Rd!=PC, [Rn!=PC]" , "t32": "1110|100|0110|1|Rn|Rd|1111|1101|1111" , "it": "any"}, - {"inst": "ldah Rd!=PC, [Rn!=PC]" , "t32": "1110|100|0110|1|Rn|Rd|1111|1001|1111" , "it": "any"}, - {"inst": "stl Rs!=PC, [Rn!=PC]" , "t32": "1110|100|0110|0|Rn|Rs|1111|1010|1111"}, - {"inst": "stlb Rs!=PC, [Rn!=PC]" , "t32": "1110|100|0110|0|Rn|Rs|1111|1000|1111"}, - {"inst": "stlex Rd!=PC, Rs!=PC, [Rn!=PC]" , "t32": "1110|100|0110|0|Rn|Rs|1111|1110|Rd"}, - {"inst": "stlexb Rd!=PC, Rs!=PC, [Rn!=PC]" , "t32": "1110|100|0110|0|Rn|Rs|1111|1100|Rd"}, - {"inst": "stlexd Rd!=PC, Rs!=PC, Rs2!=PC, [Rn!=PC]" , "t32": "1110|100|0110|0|Rn|Rs|Rs2|1111|Rd"}, - {"inst": "stlexh Rd!=PC, Rs!=PC, [Rn!=PC]" , "t32": "1110|100|0110|0|Rn|Rs|1111|1101|Rd"}, - {"inst": "stlh Rs!=PC, [Rn!=PC]" , "t32": "1110|100|0110|0|Rn|Rs|1111|1001|1111"} + {"inst": "dcps1" , "t32": "1111|011|1100|0|1111|1000|0000|0000|0001" , "it": "out"}, + {"inst": "dcps2" , "t32": "1111|011|1100|0|1111|1000|0000|0000|0010" , "it": "out"}, + {"inst": "dcps3" , "t32": "1111|011|1100|0|1111|1000|0000|0000|0011" , "it": "out"}, + {"inst": "lda Rd!=PC, [Rn!=PC]" , "t32": "1110|100|0110|1|Rn|Rd|1111|1010|1111" , "it": "any"}, + {"inst": "ldab Rd!=PC, [Rn!=PC]" , "t32": "1110|100|0110|1|Rn|Rd|1111|1000|1111" , "it": "any"}, + {"inst": "ldaex Rd!=PC, [Rn!=PC]" , "t32": "1110|100|0110|1|Rn|Rd|1111|1110|1111" , "it": "any"}, + {"inst": "ldaexb Rd!=PC, [Rn!=PC]" , "t32": "1110|100|0110|1|Rn|Rd|1111|1100|1111" , "it": "any"}, + {"inst": "ldaexd Rd!=PC, Rd2!=PC, [Rn!=PC]" , "t32": "1110|100|0110|1|Rn|Rd|Rd2|1111|1111" , "it": "any"}, + {"inst": "ldaexh Rd!=PC, [Rn!=PC]" , "t32": "1110|100|0110|1|Rn|Rd|1111|1101|1111" , "it": "any"}, + {"inst": "ldah Rd!=PC, [Rn!=PC]" , "t32": "1110|100|0110|1|Rn|Rd|1111|1001|1111" , "it": "any"}, + {"inst": "stl Rs!=PC, [Rn!=PC]" , "t32": "1110|100|0110|0|Rn|Rs|1111|1010|1111" , "it": "any"}, + {"inst": "stlb Rs!=PC, [Rn!=PC]" , "t32": "1110|100|0110|0|Rn|Rs|1111|1000|1111" , "it": "any"}, + {"inst": "stlex Rd!=PC, Rs!=PC, [Rn!=PC]" , "t32": "1110|100|0110|0|Rn|Rs|1111|1110|Rd" , "it": "any"}, + {"inst": "stlexb Rd!=PC, Rs!=PC, [Rn!=PC]" , "t32": "1110|100|0110|0|Rn|Rs|1111|1100|Rd" , "it": "any"}, + {"inst": "stlexd Rd!=PC, Rs!=PC, Rs2!=PC, [Rn!=PC]" , "t32": "1110|100|0110|0|Rn|Rs|Rs2|1111|Rd" , "it": "any"}, + {"inst": "stlexh Rd!=PC, Rs!=PC, [Rn!=PC]" , "t32": "1110|100|0110|0|Rn|Rs|1111|1101|Rd" , "it": "any"}, + {"inst": "stlh Rs!=PC, [Rn!=PC]" , "t32": "1110|100|0110|0|Rn|Rs|1111|1001|1111" , "it": "any"} ]}, {"category": "GP GP_EXT", "ext": "IDIVA", "data": [ @@ -827,8 +842,28 @@ ]}, {"category": "GP GP_EXT", "ext": "IDIVT", "data": [ - {"inst": "sdiv Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1100|1|Rn|1111|Rd|1111|Rm" , "it": "any"}, - {"inst": "udiv Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1101|1|Rn|1111|Rd|1111|Rm" , "it": "any"} + {"inst": "sdiv Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1100|1|Rn|1111|Rd|1111|Rm" , "it": "any"}, + {"inst": "udiv Rd!=XX, Rn!=XX, Rm!=XX" , "t32": "1111|101|1101|1|Rn|1111|Rd|1111|Rm" , "it": "any"} + ]}, + + {"category": "GP GP_EXT", "data": [ + {"inst": "csdb" , "a32": "cond|001|1001|0|0000|1111|0000|0001|0100"}, + {"inst": "ssbb" , "a32": "1111|010|1011|1|1111|1111|0000|0100|0000"}, + {"inst": "pssbb" , "a32": "1111|010|1011|1|1111|1111|0000|0100|0100"} + ]}, + + {"category": "GP GP_EXT", "data": [ + {"inst": "csdb" , "t32": "1111|001|1101|0|1111|1000|0000|0001|0100" , "it": "out"}, + {"inst": "ssbb" , "t32": "1111|001|1101|1|1111|1000|1111|0100|0000" , "it": "any"}, + {"inst": "pssbb" , "t32": "1111|001|1101|1|1111|1000|1111|0100|0100" , "it": "any"} + ]}, + + {"category": "GP GP_EXT", "ext": "CLRBHB", "data": [ + {"inst": "clrbhb" , "a32": "cond|001|1001|0|0000|1111|0000|0001|0110"} + ]}, + + {"category": "GP GP_EXT", "ext": "CLRBHB", "data": [ + {"inst": "clrbhb" , "t32": "1111|001|1101|0|1111|1000|0000|0001|0110" , "it": "any"} ]}, {"category": "GP GP_EXT CRYPTO_HASH", "ext": "CRC32", "data": [ @@ -841,12 +876,36 @@ ]}, {"category": "GP GP_EXT CRYPTO_HASH", "ext": "CRC32", "data": [ - {"inst": "crc32b Rd!=PC, Rn!=PC, Rm!=PC" , "t32": "1111|101|0110|0|Rn|1111|Rd|10|00|Rm" , "it": "out"}, - {"inst": "crc32h Rd!=PC, Rn!=PC, Rm!=PC" , "t32": "1111|101|0110|0|Rn|1111|Rd|10|01|Rm" , "it": "out"}, - {"inst": "crc32w Rd!=PC, Rn!=PC, Rm!=PC" , "t32": "1111|101|0110|0|Rn|1111|Rd|10|10|Rm" , "it": "out"}, - {"inst": "crc32cb Rd!=PC, Rn!=PC, Rm!=PC" , "t32": "1111|101|0110|1|Rn|1111|Rd|10|00|Rm" , "it": "out"}, - {"inst": "crc32ch Rd!=PC, Rn!=PC, Rm!=PC" , "t32": "1111|101|0110|1|Rn|1111|Rd|10|01|Rm" , "it": "out"}, - {"inst": "crc32cw Rd!=PC, Rn!=PC, Rm!=PC" , "t32": "1111|101|0110|1|Rn|1111|Rd|10|10|Rm" , "it": "out"} + {"inst": "crc32b Rd!=PC, Rn!=PC, Rm!=PC" , "t32": "1111|101|0110|0|Rn|1111|Rd|10|00|Rm" , "it": "out"}, + {"inst": "crc32h Rd!=PC, Rn!=PC, Rm!=PC" , "t32": "1111|101|0110|0|Rn|1111|Rd|10|01|Rm" , "it": "out"}, + {"inst": "crc32w Rd!=PC, Rn!=PC, Rm!=PC" , "t32": "1111|101|0110|0|Rn|1111|Rd|10|10|Rm" , "it": "out"}, + {"inst": "crc32cb Rd!=PC, Rn!=PC, Rm!=PC" , "t32": "1111|101|0110|1|Rn|1111|Rd|10|00|Rm" , "it": "out"}, + {"inst": "crc32ch Rd!=PC, Rn!=PC, Rm!=PC" , "t32": "1111|101|0110|1|Rn|1111|Rd|10|01|Rm" , "it": "out"}, + {"inst": "crc32cw Rd!=PC, Rn!=PC, Rm!=PC" , "t32": "1111|101|0110|1|Rn|1111|Rd|10|10|Rm" , "it": "out"} + ]}, + + {"category": "GP GP_EXT", "ext": "PAN", "data": [ + {"inst": "setpan #immZ" , "a32": "1111|000|1000|1|0000|0000|00|immZ:1|0|0000|0000"} + ]}, + + {"category": "GP GP_EXT", "ext": "PAN", "data": [ + {"inst": "setpan #immZ" , "t16": "1011|0110|0001|immZ:1|000" , "it": "out"} + ]}, + + {"category": "GP GP_EXT", "ext": "RAS", "data": [ + {"inst": "esb" , "a32": "cond|001|1001|0|0000|1111|0000|0001|0000"} + ]}, + + {"category": "GP GP_EXT", "ext": "RAS", "data": [ + {"inst": "esb" , "t32": "1111|001|1101|0|1111|1000|0000|0001|0000" , "it": "any"} + ]}, + + {"category": "GP GP_EXT", "ext": "SB", "data": [ + {"inst": "sb" , "a32": "1111|010|1011|1|1111|1111|0000|0111|0000"} + ]}, + + {"category": "GP GP_EXT", "ext": "SB", "data": [ + {"inst": "sb" , "t32": "1111|001|1101|1|1111|1000|1111|0111|0000" , "it": "out"} ]}, {"category": "GP GP_EXT", "ext": "SECURITY", "data": [ @@ -854,7 +913,1569 @@ ]}, {"category": "GP GP_EXT", "ext": "SECURITY", "data": [ - {"inst": "smc #immZ" , "t32": "1111|011|1111|1|immZ:4|1000|000000000000"} + {"inst": "smc #immZ" , "t32": "1111|011|1111|1|immZ:4|1000|000000000000" , "it": "any"} + ]}, + + {"category": "FP", "ext": "FP", "data": [ + {"inst": "vabs.f32 Sd, Sn" , "a32": "cond|11101|'Vd|11|00|00|Vd|10|10|1|1|'Vn|0|Vn"}, + {"inst": "vabs.f64 Dd, Dn" , "a32": "cond|11101|Vd'|11|00|00|Vd|10|11|1|1|Vn'|0|Vn"}, + {"inst": "vadd.f32 Sd, Sn, Sm" , "a32": "cond|11100|'Vd|11|Vn|Vd|1010|'Vn|0|'Vm|0|Vm"}, + {"inst": "vadd.f64 Dd, Dn, Dm" , "a32": "cond|11100|Vd'|11|Vn|Vd|1011|Vn'|0|Vm'|0|Vm"}, + {"inst": "vcmp.f32 Sn, Sm" , "a32": "cond|11101|'Vn|11|01|00|Vn|10|10|01|'Vm|0|Vm"}, + {"inst": "vcmp.f32 Sn, #zero" , "a32": "cond|11101|'Vn|11|01|01|Vn|10|10|01|00|0000"}, + {"inst": "vcmp.f64 Dn, Dm" , "a32": "cond|11101|Vn'|11|01|00|Vn|10|11|01|Vm'|0|Vm"}, + {"inst": "vcmp.f64 Dn, #zero" , "a32": "cond|11101|Vn'|11|01|01|Vn|10|11|01|00|0000"}, + {"inst": "vcmpe.f32 Sn, Sm" , "a32": "cond|11101|'Vn|11|01|00|Vn|10|10|11|'Vm|0|Vm"}, + {"inst": "vcmpe.f32 Sn, #zero" , "a32": "cond|11101|'Vn|11|01|01|Vn|10|10|11|00|0000"}, + {"inst": "vcmpe.f64 Dn, Dm" , "a32": "cond|11101|Vn'|11|01|00|Vn|10|11|11|Vm'|0|Vm"}, + {"inst": "vcmpe.f64 Dn, #zero" , "a32": "cond|11101|Vn'|11|01|01|Vn|10|11|11|00|0000"}, + {"inst": "vcvt.f32.f64 Sd, Dn" , "a32": "cond|11101|'Vd|11|01|11|Vd|10111|1|Vn'|0|Vn"}, + {"inst": "vcvt.f64.f32 Dd, Sn" , "a32": "cond|11101|Vd'|11|01|11|Vd|10101|1|'Vn|0|Vn"}, + {"inst": "vcvt.f32.s32 Sd, Sn" , "a32": "cond|11101|'Vd|11|10|00|Vd|10101|1|'Vn|0|Vn"}, + {"inst": "vcvt.f32.u32 Sd, Sn" , "a32": "cond|11101|'Vd|11|10|00|Vd|10100|1|'Vn|0|Vn"}, + {"inst": "vcvt.f64.s32 Dd, Sn" , "a32": "cond|11101|Vd'|11|10|00|Vd|10111|1|'Vn|0|Vn"}, + {"inst": "vcvt.f64.u32 Dd, Sn" , "a32": "cond|11101|Vd'|11|10|00|Vd|10110|1|'Vn|0|Vn"}, + {"inst": "vcvt.f32.s16 Sx, Sx, #fbits" , "a32": "cond|11101|'Vx|11|10|10|Vx|10100|1|imm[0]|0|imm[4:1]" , "imm": "VecFBitsVFP(16, fbits)"}, + {"inst": "vcvt.s16.f32 Sx, Sx, #fbits" , "a32": "cond|11101|'Vx|11|11|10|Vx|10100|1|imm[0]|0|imm[4:1]" , "imm": "VecFBitsVFP(16, fbits)"}, + {"inst": "vcvt.f32.u16 Sx, Sx, #fbits" , "a32": "cond|11101|'Vx|11|10|11|Vx|10100|1|imm[0]|0|imm[4:1]" , "imm": "VecFBitsVFP(16, fbits)"}, + {"inst": "vcvt.u16.f32 Sx, Sx, #fbits" , "a32": "cond|11101|'Vx|11|11|11|Vx|10100|1|imm[0]|0|imm[4:1]" , "imm": "VecFBitsVFP(16, fbits)"}, + {"inst": "vcvt.f32.s32 Sx, Sx, #fbits" , "a32": "cond|11101|'Vx|11|10|10|Vx|10101|1|imm[0]|0|imm[4:1]" , "imm": "VecFBitsVFP(32, fbits)"}, + {"inst": "vcvt.s32.f32 Sx, Sx, #fbits" , "a32": "cond|11101|'Vx|11|11|10|Vx|10101|1|imm[0]|0|imm[4:1]" , "imm": "VecFBitsVFP(32, fbits)"}, + {"inst": "vcvt.f32.u32 Sx, Sx, #fbits" , "a32": "cond|11101|'Vx|11|10|11|Vx|10101|1|imm[0]|0|imm[4:1]" , "imm": "VecFBitsVFP(32, fbits)"}, + {"inst": "vcvt.u32.f32 Sx, Sx, #fbits" , "a32": "cond|11101|'Vx|11|11|11|Vx|10101|1|imm[0]|0|imm[4:1]" , "imm": "VecFBitsVFP(32, fbits)"}, + {"inst": "vcvt.f64.s16 Dx, Dx, #fbits" , "a32": "cond|11101|Vx'|11|10|10|Vx|10110|1|imm[0]|0|imm[4:1]" , "imm": "VecFBitsVFP(16, fbits)"}, + {"inst": "vcvt.s16.f64 Dx, Dx, #fbits" , "a32": "cond|11101|Vx'|11|11|10|Vx|10110|1|imm[0]|0|imm[4:1]" , "imm": "VecFBitsVFP(16, fbits)"}, + {"inst": "vcvt.f64.u16 Dx, Dx, #fbits" , "a32": "cond|11101|Vx'|11|10|11|Vx|10110|1|imm[0]|0|imm[4:1]" , "imm": "VecFBitsVFP(16, fbits)"}, + {"inst": "vcvt.u16.f64 Dx, Dx, #fbits" , "a32": "cond|11101|Vx'|11|11|11|Vx|10110|1|imm[0]|0|imm[4:1]" , "imm": "VecFBitsVFP(16, fbits)"}, + {"inst": "vcvt.f64.s32 Dx, Dx, #fbits" , "a32": "cond|11101|Vx'|11|10|10|Vx|10111|1|imm[0]|0|imm[4:1]" , "imm": "VecFBitsVFP(32, fbits)"}, + {"inst": "vcvt.s32.f64 Dx, Dx, #fbits" , "a32": "cond|11101|Vx'|11|11|10|Vx|10111|1|imm[0]|0|imm[4:1]" , "imm": "VecFBitsVFP(32, fbits)"}, + {"inst": "vcvt.f64.u32 Dx, Dx, #fbits" , "a32": "cond|11101|Vx'|11|10|11|Vx|10111|1|imm[0]|0|imm[4:1]" , "imm": "VecFBitsVFP(32, fbits)"}, + {"inst": "vcvt.u32.f64 Dx, Dx, #fbits" , "a32": "cond|11101|Vx'|11|11|11|Vx|10111|1|imm[0]|0|imm[4:1]" , "imm": "VecFBitsVFP(32, fbits)"}, + {"inst": "vcvtr.s32.f32 Sd, Sn" , "a32": "cond|11101|'Vd|11|11|01|Vd|10100|1|'Vn|0|Vn"}, + {"inst": "vcvtr.s32.f64 Sd, Dn" , "a32": "cond|11101|'Vd|11|11|01|Vd|10110|1|Vn'|0|Vn"}, + {"inst": "vcvtr.u32.f32 Sd, Sn" , "a32": "cond|11101|'Vd|11|11|00|Vd|10100|1|'Vn|0|Vn"}, + {"inst": "vcvtr.u32.f64 Sd, Dn" , "a32": "cond|11101|'Vd|11|11|00|Vd|10110|1|Vn'|0|Vn"}, + {"inst": "vdiv.f32 Sd, Sn, Sm" , "a32": "cond|11101|'Vd|00|Vn|Vd|10|10|'Vn|0|'Vm|0|Vm"}, + {"inst": "vdiv.f64 Dd, Dn, Dm" , "a32": "cond|11101|Vd'|00|Vn|Vd|10|11|Vn'|0|Vm'|0|Vm"}, + {"inst": "vldr.32 Sd, [Rn, #+/-off*4]" , "a32": "cond|1101U|'Vd|01|Rn|Vd|1010|off:8"}, + {"inst": "vldr.64 Dd, [Rn, #+/-off*4]" , "a32": "cond|1101U|Vd'|01|Rn|Vd|1011|off:8"}, + {"inst": "vmla.f32 Sx, Sn, Sm" , "a32": "cond|11100|'Vx|00|Vn|Vx|10|10|'Vn|0|'Vm|0|Vm"}, + {"inst": "vmla.f64 Dx, Dn, Dm" , "a32": "cond|11100|Vx'|00|Vn|Vx|10|11|Vn'|0|Vm'|0|Vm"}, + {"inst": "vmls.f32 Sx, Sn, Sm" , "a32": "cond|11100|'Vx|00|Vn|Vx|10|10|'Vn|1|'Vm|0|Vm"}, + {"inst": "vmls.f64 Dx, Dn, Dm" , "a32": "cond|11100|Vx'|00|Vn|Vx|10|11|Vn'|1|Vm'|0|Vm"}, + {"inst": "vmov.f32 Sd, Sn" , "a32": "cond|11101|'Vd|11|0000|Vd|1010|0|1|'Vn|0|Vn"}, + {"inst": "vmov.f64 Dd, Dn" , "a32": "cond|11101|Vd'|11|0000|Vd|1011|0|1|Vn'|0|Vn"}, + {"inst": "vmov.f32 Sd, #immVFP" , "a32": "cond|11101|'Vd|11|imm:4|Vd|1010|0000|imm:4" , "imm": "VecVFPImm(immVFP)"}, + {"inst": "vmov.f64 Dd, #immVFP" , "a32": "cond|11101|Vd'|11|imm:4|Vd|1011|0000|imm:4" , "imm": "VecVFPImm(immVFP)"}, + {"inst": "vmul.f32 Sd, Sn, Sm" , "a32": "cond|11100|'Vd|10|Vn|Vd|10|10|'Vn|0|'Vm|0|Vm"}, + {"inst": "vmul.f64 Dd, Dn, Dm" , "a32": "cond|11100|Vd'|10|Vn|Vd|10|11|Vn'|0|Vm'|0|Vm"}, + {"inst": "vneg.f32 Sd, Sn" , "a32": "cond|11101|'Vd|11|0001|Vd|10|10|01|'Vn|0|Vn"}, + {"inst": "vneg.f64 Dd, Dn" , "a32": "cond|11101|Vd'|11|0001|Vd|10|11|01|Vn'|0|Vn"}, + {"inst": "vnmla.f32 Sx, Sn, Sm" , "a32": "cond|11100|'Vx|01|Vn|Vx|10|10|'Vn|1|'Vm|0|Vm"}, + {"inst": "vnmla.f64 Dx, Dn, Dm" , "a32": "cond|11100|Vx'|01|Vn|Vx|10|11|Vn'|1|Vm'|0|Vm"}, + {"inst": "vnmls.f32 Sx, Sn, Sm" , "a32": "cond|11100|'Vx|01|Vn|Vx|10|10|'Vn|0|'Vm|0|Vm"}, + {"inst": "vnmls.f64 Dx, Dn, Dm" , "a32": "cond|11100|Vx'|01|Vn|Vx|10|11|Vn'|0|Vm'|0|Vm"}, + {"inst": "vnmul.f32 Sd, Sn, Sm" , "a32": "cond|11100|'Vd|10|Vn|Vd|10|10|'Vn|1|'Vm|0|Vm"}, + {"inst": "vnmul.f64 Dd, Dn, Dm" , "a32": "cond|11100|Vd'|10|Vn|Vd|10|11|Vn'|1|Vm'|0|Vm"}, + {"inst": "vsqrt.f32 Sd, Sn" , "a32": "cond|11101|'Vd|11|0001|Vd|10|10|11|'Vn|0|Vn"}, + {"inst": "vsqrt.f64 Dd, Dn" , "a32": "cond|11101|Vd'|11|0001|Vd|10|11|11|Vn'|0|Vn"}, + {"inst": "vstr.32 Ss, [Rn, #+/-off*4]" , "a32": "cond|1101U|'Vs|00|Rn|Vs|1010|off:8"}, + {"inst": "vstr.64 Ds, [Rn, #+/-off*4]" , "a32": "cond|1101U|Vs'|00|Rn|Vs|1011|off:8"}, + {"inst": "vsub.f32 Sd, Sn, Sm" , "a32": "cond|11100|'Vd|11|Vn|Vd|10|10|'Vn|1|'Vm|0|Vm"}, + {"inst": "vsub.f64 Dd, Dn, Dm" , "a32": "cond|11100|Vd'|11|Vn|Vd|10|11|Vn'|1|Vm'|0|Vm"} + ]}, + + {"category": "FP", "ext": "FP", "data": [ + {"inst": "vabs.f32 Sd, Sn" , "t32": "1110|11101|'Vd|11|00|00|Vd|10|10|1|1|'Vn|0|Vn" , "it": "any"}, + {"inst": "vabs.f64 Dd, Dn" , "t32": "1110|11101|Vd'|11|00|00|Vd|10|11|1|1|Vn'|0|Vn" , "it": "any"}, + {"inst": "vadd.f32 Sd, Sn, Sm" , "t32": "1110|11100|'Vd|11|Vn|Vd|1010|'Vn|0|'Vm|0|Vm" , "it": "any"}, + {"inst": "vadd.f64 Dd, Dn, Dm" , "t32": "1110|11100|Vd'|11|Vn|Vd|1011|Vn'|0|Vm'|0|Vm" , "it": "any"}, + {"inst": "vcmp.f32 Sn, Sm" , "t32": "1110|11101|'Vn|11|01|00|Vn|10|10|01|'Vm|0|Vm" , "it": "any"}, + {"inst": "vcmp.f32 Sn, #zero" , "t32": "1110|11101|'Vn|11|01|01|Vn|10|10|01|00|0000" , "it": "any"}, + {"inst": "vcmp.f64 Dn, Dm" , "t32": "1110|11101|Vn'|11|01|00|Vn|10|11|01|Vm'|0|Vm" , "it": "any"}, + {"inst": "vcmp.f64 Dn, #zero" , "t32": "1110|11101|Vn'|11|01|01|Vn|10|11|01|00|0000" , "it": "any"}, + {"inst": "vcmpe.f32 Sn, Sm" , "t32": "1110|11101|'Vn|11|01|00|Vn|10|10|11|'Vm|0|Vm" , "it": "any"}, + {"inst": "vcmpe.f32 Sn, #zero" , "t32": "1110|11101|'Vn|11|01|01|Vn|10|10|11|00|0000" , "it": "any"}, + {"inst": "vcmpe.f64 Dn, Dm" , "t32": "1110|11101|Vn'|11|01|00|Vn|10|11|11|Vm'|0|Vm" , "it": "any"}, + {"inst": "vcmpe.f64 Dn, #zero" , "t32": "1110|11101|Vn'|11|01|01|Vn|10|11|11|00|0000" , "it": "any"}, + {"inst": "vcvt.f32.f64 Sd, Dn" , "t32": "1110|11101|'Vd|11|01|11|Vd|10111|1|Vn'|0|Vn" , "it": "any"}, + {"inst": "vcvt.f64.f32 Dd, Sn" , "t32": "1110|11101|Vd'|11|01|11|Vd|10101|1|'Vn|0|Vn" , "it": "any"}, + {"inst": "vcvt.f32.s32 Sd, Sn" , "t32": "1110|11101|'Vd|11|10|00|Vd|10101|1|'Vn|0|Vn" , "it": "any"}, + {"inst": "vcvt.f32.u32 Sd, Sn" , "t32": "1110|11101|'Vd|11|10|00|Vd|10100|1|'Vn|0|Vn" , "it": "any"}, + {"inst": "vcvt.f64.s32 Dd, Sn" , "t32": "1110|11101|Vd'|11|10|00|Vd|10111|1|'Vn|0|Vn" , "it": "any"}, + {"inst": "vcvt.f64.u32 Dd, Sn" , "t32": "1110|11101|Vd'|11|10|00|Vd|10110|1|'Vn|0|Vn" , "it": "any"}, + {"inst": "vcvt.f32.s16 Sx, Sx, #fbits" , "t32": "1110|11101|'Vx|11|10|10|Vx|10100|1|imm[0]|0|imm[4:1]" , "it": "any", "imm": "VecFBitsVFP(16, fbits)"}, + {"inst": "vcvt.s16.f32 Sx, Sx, #fbits" , "t32": "1110|11101|'Vx|11|11|10|Vx|10100|1|imm[0]|0|imm[4:1]" , "it": "any", "imm": "VecFBitsVFP(16, fbits)"}, + {"inst": "vcvt.f32.u16 Sx, Sx, #fbits" , "t32": "1110|11101|'Vx|11|10|11|Vx|10100|1|imm[0]|0|imm[4:1]" , "it": "any", "imm": "VecFBitsVFP(16, fbits)"}, + {"inst": "vcvt.u16.f32 Sx, Sx, #fbits" , "t32": "1110|11101|'Vx|11|11|11|Vx|10100|1|imm[0]|0|imm[4:1]" , "it": "any", "imm": "VecFBitsVFP(16, fbits)"}, + {"inst": "vcvt.f32.s32 Sx, Sx, #fbits" , "t32": "1110|11101|'Vx|11|10|10|Vx|10101|1|imm[0]|0|imm[4:1]" , "it": "any", "imm": "VecFBitsVFP(32, fbits)"}, + {"inst": "vcvt.s32.f32 Sx, Sx, #fbits" , "t32": "1110|11101|'Vx|11|11|10|Vx|10101|1|imm[0]|0|imm[4:1]" , "it": "any", "imm": "VecFBitsVFP(32, fbits)"}, + {"inst": "vcvt.f32.u32 Sx, Sx, #fbits" , "t32": "1110|11101|'Vx|11|10|11|Vx|10101|1|imm[0]|0|imm[4:1]" , "it": "any", "imm": "VecFBitsVFP(32, fbits)"}, + {"inst": "vcvt.u32.f32 Sx, Sx, #fbits" , "t32": "1110|11101|'Vx|11|11|11|Vx|10101|1|imm[0]|0|imm[4:1]" , "it": "any", "imm": "VecFBitsVFP(32, fbits)"}, + {"inst": "vcvt.f64.s16 Dx, Dx, #fbits" , "t32": "1110|11101|Vx'|11|10|10|Vx|10110|1|imm[0]|0|imm[4:1]" , "it": "any", "imm": "VecFBitsVFP(16, fbits)"}, + {"inst": "vcvt.s16.f64 Dx, Dx, #fbits" , "t32": "1110|11101|Vx'|11|11|10|Vx|10110|1|imm[0]|0|imm[4:1]" , "it": "any", "imm": "VecFBitsVFP(16, fbits)"}, + {"inst": "vcvt.f64.u16 Dx, Dx, #fbits" , "t32": "1110|11101|Vx'|11|10|11|Vx|10110|1|imm[0]|0|imm[4:1]" , "it": "any", "imm": "VecFBitsVFP(16, fbits)"}, + {"inst": "vcvt.u16.f64 Dx, Dx, #fbits" , "t32": "1110|11101|Vx'|11|11|11|Vx|10110|1|imm[0]|0|imm[4:1]" , "it": "any", "imm": "VecFBitsVFP(16, fbits)"}, + {"inst": "vcvt.f64.s32 Dx, Dx, #fbits" , "t32": "1110|11101|Vx'|11|10|10|Vx|10111|1|imm[0]|0|imm[4:1]" , "it": "any", "imm": "VecFBitsVFP(32, fbits)"}, + {"inst": "vcvt.s32.f64 Dx, Dx, #fbits" , "t32": "1110|11101|Vx'|11|11|10|Vx|10111|1|imm[0]|0|imm[4:1]" , "it": "any", "imm": "VecFBitsVFP(32, fbits)"}, + {"inst": "vcvt.f64.u32 Dx, Dx, #fbits" , "t32": "1110|11101|Vx'|11|10|11|Vx|10111|1|imm[0]|0|imm[4:1]" , "it": "any", "imm": "VecFBitsVFP(32, fbits)"}, + {"inst": "vcvt.u32.f64 Dx, Dx, #fbits" , "t32": "1110|11101|Vx'|11|11|11|Vx|10111|1|imm[0]|0|imm[4:1]" , "it": "any", "imm": "VecFBitsVFP(32, fbits)"}, + {"inst": "vcvtr.s32.f32 Sd, Sn" , "t32": "1110|11101|'Vd|11|11|01|Vd|10100|1|'Vn|0|Vn" , "it": "any"}, + {"inst": "vcvtr.s32.f64 Sd, Dn" , "t32": "1110|11101|'Vd|11|11|01|Vd|10110|1|Vn'|0|Vn" , "it": "any"}, + {"inst": "vcvtr.u32.f32 Sd, Sn" , "t32": "1110|11101|'Vd|11|11|00|Vd|10100|1|'Vn|0|Vn" , "it": "any"}, + {"inst": "vcvtr.u32.f64 Sd, Dn" , "t32": "1110|11101|'Vd|11|11|00|Vd|10110|1|Vn'|0|Vn" , "it": "any"}, + {"inst": "vdiv.f32 Sd, Sn, Sm" , "t32": "1110|11101|'Vd|00|Vn|Vd|10|10|'Vn|0|'Vm|0|Vm" , "it": "any"}, + {"inst": "vdiv.f64 Dd, Dn, Dm" , "t32": "1110|11101|Vd'|00|Vn|Vd|10|11|Vn'|0|Vm'|0|Vm" , "it": "any"}, + {"inst": "vldr.32 Sd, [Rn, #+/-off*4]" , "t32": "1110|1101U|'Vd|01|Rn|Vd|1010|off:8" , "it": "any"}, + {"inst": "vldr.64 Dd, [Rn, #+/-off*4]" , "t32": "1110|1101U|Vd'|01|Rn|Vd|1011|off:8" , "it": "any"}, + {"inst": "vmla.f64 Dx, Dn, Dm" , "t32": "1110|11100|Vx'|00|Vn|Vx|10|11|Vn'|0|Vm'|0|Vm" , "it": "any"}, + {"inst": "vmls.f64 Dx, Dn, Dm" , "t32": "1110|11100|Vx'|00|Vn|Vx|10|11|Vn'|1|Vm'|0|Vm" , "it": "any"}, + {"inst": "vmov.f32 Sd, Sn" , "t32": "1110|11101|'Vd|11|0000|Vd|1010|0|1|'Vn|0|Vn" , "it": "any"}, + {"inst": "vmov.f64 Dd, Dn" , "t32": "1110|11101|Vd'|11|0000|Vd|1011|0|1|Vn'|0|Vn" , "it": "any"}, + {"inst": "vmov.f32 Sd, #immVFP" , "t32": "1110|11101|'Vd|11|imm:4|Vd|1010|0000|imm:4" , "it": "any", "imm": "VecVFPImm(immVFP)"}, + {"inst": "vmov.f64 Dd, #immVFP" , "t32": "1110|11101|Vd'|11|imm:4|Vd|1011|0000|imm:4" , "it": "any", "imm": "VecVFPImm(immVFP)"}, + {"inst": "vmul.f32 Sd, Sn, Sm" , "t32": "1110|11100|'Vd|10|Vn|Vd|10|10|'Vn|0|'Vm|0|Vm" , "it": "any"}, + {"inst": "vmul.f64 Dd, Dn, Dm" , "t32": "1110|11100|Vd'|10|Vn|Vd|10|11|Vn'|0|Vm'|0|Vm" , "it": "any"}, + {"inst": "vneg.f32 Sd, Sn" , "t32": "1110|11101|'Vd|11|0001|Vd|10|10|01|'Vn|0|Vn" , "it": "any"}, + {"inst": "vneg.f64 Dd, Dn" , "t32": "1110|11101|Vd'|11|0001|Vd|10|11|01|Vn'|0|Vn" , "it": "any"}, + {"inst": "vnmla.f32 Sx, Sn, Sm" , "t32": "1110|11100|'Vx|01|Vn|Vx|10|10|'Vn|1|'Vm|0|Vm" , "it": "any"}, + {"inst": "vnmla.f64 Dx, Dn, Dm" , "t32": "1110|11100|Vx'|01|Vn|Vx|10|11|Vn'|1|Vm'|0|Vm" , "it": "any"}, + {"inst": "vnmls.f32 Sx, Sn, Sm" , "t32": "1110|11100|'Vx|01|Vn|Vx|10|10|'Vn|0|'Vm|0|Vm" , "it": "any"}, + {"inst": "vnmls.f64 Dx, Dn, Dm" , "t32": "1110|11100|Vx'|01|Vn|Vx|10|11|Vn'|0|Vm'|0|Vm" , "it": "any"}, + {"inst": "vnmul.f32 Sd, Sn, Sm" , "t32": "1110|11100|'Vd|10|Vn|Vd|10|10|'Vn|1|'Vm|0|Vm" , "it": "any"}, + {"inst": "vnmul.f64 Dd, Dn, Dm" , "t32": "1110|11100|Vd'|10|Vn|Vd|10|11|Vn'|1|Vm'|0|Vm" , "it": "any"}, + {"inst": "vsqrt.f32 Sd, Sn" , "t32": "1110|11101|'Vd|11|0001|Vd|10|10|11|'Vn|0|Vn" , "it": "any"}, + {"inst": "vsqrt.f64 Dd, Dn" , "t32": "1110|11101|Vd'|11|0001|Vd|1011|1|1|Vn'|0|Vn" , "it": "any"}, + {"inst": "vstr.32 Ss, [Rn, #+/-off*4]" , "t32": "1110|1101U|'Vs|00|Rn|Vs|1010|off:8" , "it": "any"}, + {"inst": "vstr.64 Ds, [Rn, #+/-off*4]" , "t32": "1110|1101U|Vs'|00|Rn|Vs|1011|off:8" , "it": "any"}, + {"inst": "vsub.f32 Sd, Sn, Sm" , "t32": "1110|11100|'Vd|11|Vn|Vd|10|10|'Vn|1|'Vm|0|Vm" , "it": "any"}, + {"inst": "vsub.f64 Dd, Dn, Dm" , "t32": "1110|11100|Vd'|11|Vn|Vd|10|11|Vn'|1|Vm'|0|Vm" , "it": "any"} + ]}, + + {"category": "FP", "ext": "FP FP16", "data": [ + {"inst": "vabs.f16 Sd, Sn" , "a32": "1110|11101|'Vd|11|00|00|Vd|10|01|1|1|'Vn|0|Vn"}, + {"inst": "vadd.f16 Sd, Sn, Sm" , "a32": "1110|11100|'Vd|11|Vn|Vd|1001|'Vn|0|'Vm|0|Vm"}, + {"inst": "vcmp.f16 Sn, Sm" , "a32": "1110|11101|'Vn|11|01|00|Vn|10|01|01|'Vm|0|Vm"}, + {"inst": "vcmp.f16 Sn, #zero" , "a32": "1110|11101|'Vn|11|01|01|Vn|10|01|01|00|0000"}, + {"inst": "vcmpe.f16 Sn, Sm" , "a32": "1110|11101|'Vn|11|01|00|Vn|10|01|11|'Vm|0|Vm"}, + {"inst": "vcmpe.f16 Sn, #zero" , "a32": "1110|11101|'Vn|11|01|01|Vn|10|01|11|00|0000"}, + {"inst": "vdiv.f16 Sd, Sn, Sm" , "a32": "1110|11101|'Vd|00|Vn|Vd|10|01|'Vn|0|'Vm|0|Vm"}, + {"inst": "vldr.16 Sd, [Rn, #+/-off*2]" , "a32": "1110|1101U|'Vd|01|Rn|Vd|1001|off:8"}, + {"inst": "vmla.f16 Sx, Sn, Sm" , "a32": "1110|11100|'Vx|00|Vn|Vx|10|01|'Vn|0|'Vm|0|Vm"}, + {"inst": "vmls.f16 Sx, Sn, Sm" , "a32": "1110|11100|'Vx|00|Vn|Vx|10|01|'Vn|1|'Vm|0|Vm"}, + {"inst": "vmov.f16 Rd!=PC, Sn" , "a32": "1110|11100|0|01|Vn|Rd|1001|'Vn|00|1|0000"}, + {"inst": "vmov.f16 Sd, Rn!=PC" , "a32": "1110|11100|0|00|Vd|Rn|1001|'Vd|00|1|0000"}, + {"inst": "vmov.f16 Sd, #immVFP" , "a32": "1110|11101|'Vd|11|imm:4|Vd|1001|0000|imm:4" , "imm": "VecVFPImm(immVFP)"}, + {"inst": "vmovx.f16 Sd, Sn" , "a32": "1111|11101|'Vd|11|00|00|Vd|1010|01|'Vn|0|Vn"}, + {"inst": "vmul.f16 Sd, Sn, Sm" , "a32": "1110|11100|'Vd|10|Vn|Vd|10|01|'Vn|0|'Vm|0|Vm"}, + {"inst": "vmul.f16 Dd, Dn, Dm<=07[#i]" , "a32": "1111|00101|Vd'|01|Vn|Vd|1001|Vn'|1|i:1|0|i:1|Vm:3"}, + {"inst": "vmul.f16 Vd, Vn, Dm<=07[#i]" , "a32": "1111|00111|Vd'|01|Vn|Vd|1001|Vn'|1|i:1|0|i:1|Vm:3"}, + {"inst": "vneg.f16 Sd, Sn" , "a32": "1110|11101|'Vd|11|0001|Vd|10|01|01|'Vn|0|Vn"}, + {"inst": "vnmla.f16 Sx, Sn, Sm" , "a32": "1110|11100|'Vx|01|Vn|Vx|10|01|'Vn|1|'Vm|0|Vm"}, + {"inst": "vnmls.f16 Sx, Sn, Sm" , "a32": "1110|11100|'Vx|01|Vn|Vx|10|01|'Vn|0|'Vm|0|Vm"}, + {"inst": "vnmul.f16 Sd, Sn, Sm" , "a32": "1110|11100|'Vd|10|Vn|Vd|10|01|'Vn|1|'Vm|0|Vm"}, + {"inst": "vsqrt.f16 Sd, Sn" , "a32": "1110|11101|'Vd|11|0001|Vd|10|01|11|'Vn|0|Vn"}, + {"inst": "vstr.16 Ss, [Rn, #+/-off*2]" , "a32": "1110|1101U|'Vs|00|Rn|Vs|1001|off:8"}, + {"inst": "vsub.f16 Sd, Sn, Sm" , "a32": "1110|11100|'Vd|11|Vn|Vd|10|01|'Vn|1|'Vm|0|Vm"} + ]}, + + {"category": "FP", "ext": "FP FP16", "data": [ + {"inst": "vabs.f16 Sd, Sn" , "t32": "1110|11101|'Vd|11|00|00|Vd|10|01|1|1|'Vn|0|Vn" , "it": "out"}, + {"inst": "vadd.f16 Sd, Sn, Sm" , "t32": "1110|11100|'Vd|11|Vn|Vd|1001|'Vn|0|'Vm|0|Vm" , "it": "out"}, + {"inst": "vcmp.f16 Sn, Sm" , "t32": "1110|11101|'Vn|11|01|00|Vn|10|01|01|'Vm|0|Vm" , "it": "out"}, + {"inst": "vcmp.f16 Sn, #zero" , "t32": "1110|11101|'Vn|11|01|01|Vn|10|01|01|00|0000" , "it": "out"}, + {"inst": "vcmpe.f16 Sn, Sm" , "t32": "1110|11101|'Vn|11|01|00|Vn|10|01|11|'Vm|0|Vm" , "it": "out"}, + {"inst": "vcmpe.f16 Sn, #zero" , "t32": "1110|11101|'Vn|11|01|01|Vn|10|01|11|00|0000" , "it": "out"}, + {"inst": "vdiv.f16 Sd, Sn, Sm" , "t32": "1110|11101|'Vd|00|Vn|Vd|10|01|'Vn|0|'Vm|0|Vm" , "it": "out"}, + {"inst": "vldr.16 Sd, [Rn, #+/-off*2]" , "t32": "1110|1101U|'Vd|01|Rn|Vd|1001|off:8" , "it": "out"}, + {"inst": "vmla.f16-32 Sx, Sn, Sm" , "t32": "1110|11100|'Vx|00|Vn|Vx|10|sz|'Vn|0|'Vm|0|Vm" , "it": "out"}, + {"inst": "vmls.f16-32 Sx, Sn, Sm" , "t32": "1110|11100|'Vx|00|Vn|Vx|10|sz|'Vn|1|'Vm|0|Vm" , "it": "out"}, + {"inst": "vmov.f16 Rd!=PC, Sn" , "t32": "1110|11100|0|01|Vn|Rd|1001|'Vn|00|1|0000" , "it": "out"}, + {"inst": "vmov.f16 Sd, Rn!=PC" , "t32": "1110|11100|0|00|Vd|Rn|1001|'Vd|00|1|0000" , "it": "out"}, + {"inst": "vmov.f16 Sd, #immVFP" , "t32": "1110|11101|'Vd|11|imm:4|Vd|1001|0000|imm:4" , "it": "out", "imm": "VecVFPImm(immVFP)"}, + {"inst": "vmovx.f16 Sd, Sn" , "t32": "1111|11101|'Vd|11|00|00|Vd|1010|01|'Vn|0|Vn" , "it": "out"}, + {"inst": "vmul.f16 Sd, Sn, Sm" , "t32": "1110|11100|'Vd|10|Vn|Vd|10|01|'Vn|0|'Vm|0|Vm" , "it": "out"}, + {"inst": "vmul.f16 Dd, Dn, Dm<=07[#i]" , "t32": "1110|11111|Vd'|01|Vn|Vd|1001|Vn'|1|i:1|0|i:1|Vm:3" , "it": "out"}, + {"inst": "vmul.f16 Vd, Vn, Dm<=07[#i]" , "t32": "1111|11111|Vd'|01|Vn|Vd|1001|Vn'|1|i:1|0|i:1|Vm:3" , "it": "out"}, + {"inst": "vneg.f16 Sd, Sn" , "t32": "1110|11101|'Vd|11|0001|Vd|10|01|01|'Vn|0|Vn" , "it": "out"}, + {"inst": "vnmla.f16 Sx, Sn, Sm" , "t32": "1110|11100|'Vx|01|Vn|Vx|10|01|'Vn|1|'Vm|0|Vm" , "it": "out"}, + {"inst": "vnmls.f16 Sx, Sn, Sm" , "t32": "1110|11100|'Vx|01|Vn|Vx|10|01|'Vn|0|'Vm|0|Vm" , "it": "out"}, + {"inst": "vnmul.f16 Sd, Sn, Sm" , "t32": "1110|11100|'Vd|10|Vn|Vd|10|01|'Vn|1|'Vm|0|Vm" , "it": "out"}, + {"inst": "vsqrt.f16 Sd, Sn" , "t32": "1110|11101|'Vd|11|0001|Vd|10|01|11|'Vn|0|Vn" , "it": "out"}, + {"inst": "vstr.16 Ss, [Rn, #+/-off*2]" , "t32": "1110|1101U|'Vs|00|Rn|Vs|1001|off:8" , "it": "out"}, + {"inst": "vsub.f16 Sd, Sn, Sm" , "t32": "1110|11100|'Vd|11|Vn|Vd|10|01|'Vn|1|'Vm|0|Vm" , "it": "out"} + ]}, + + {"category": "ASIMD", "ext": "VFPv4", "data": [ + {"inst": "vfma.f16 Sx, Sn, Sm" , "a32": "1110|11101|'Vx|10|Vn|Vx|10|01|'Vn|0|'Vm|0|Vm" , "ext": "VFPv4 FP16"}, + {"inst": "vfma.f32 Sx, Sn, Sm" , "a32": "cond|11101|'Vx|10|Vn|Vx|10|10|'Vn|0|'Vm|0|Vm" , "ext": "VFPv4"}, + {"inst": "vfma.f64 Dx, Dn, Dm" , "a32": "cond|11101|Vx'|10|Vn|Vx|10|11|Vn'|0|Vm'|0|Vm" , "ext": "VFPv4"}, + {"inst": "vfms.f16 Sx, Sn, Sm" , "a32": "1110|11101|'Vx|10|Vn|Vx|10|01|'Vn|1|'Vm|0|Vm" , "ext": "VFPv4 FP16"}, + {"inst": "vfms.f32 Sx, Sn, Sm" , "a32": "cond|11101|'Vx|10|Vn|Vx|10|10|'Vn|1|'Vm|0|Vm" , "ext": "VFPv4"}, + {"inst": "vfms.f64 Dx, Dn, Dm" , "a32": "cond|11101|Vx'|10|Vn|Vx|10|11|Vn'|1|Vm'|0|Vm" , "ext": "VFPv4"}, + {"inst": "vfnma.f16 Sx, Sn, Sm" , "a32": "1110|11101|'Vx|01|Vn|Vx|10|01|'Vn|1|'Vm|0|Vm" , "ext": "VFPv4 FP16"}, + {"inst": "vfnma.f32 Sx, Sn, Sm" , "a32": "cond|11101|'Vx|01|Vn|Vx|10|10|'Vn|1|'Vm|0|Vm" , "ext": "VFPv4"}, + {"inst": "vfnma.f64 Dx, Dn, Dm" , "a32": "cond|11101|Vx'|01|Vn|Vx|10|11|Vn'|1|Vm'|0|Vm" , "ext": "VFPv4"}, + {"inst": "vfnms.f16 Sx, Sn, Sm" , "a32": "1110|11101|'Vx|01|Vn|Vx|10|01|'Vn|0|'Vm|0|Vm" , "ext": "VFPv4 FP16"}, + {"inst": "vfnms.f32 Sx, Sn, Sm" , "a32": "cond|11101|'Vx|01|Vn|Vx|10|10|'Vn|0|'Vm|0|Vm" , "ext": "VFPv4"}, + {"inst": "vfnms.f64 Dx, Dn, Dm" , "a32": "cond|11101|Vx'|01|Vn|Vx|10|11|Vn'|0|Vm'|0|Vm" , "ext": "VFPv4"} + ]}, + + {"category": "ASIMD", "ext": "VFPv4", "data": [ + {"inst": "vfma.f16 Sx, Sn, Sm" , "t32": "1110|11101|'Vx|10|Vn|Vx|10|01|'Vn|0|'Vm|0|Vm" , "it": "out", "ext": "VFPv4 FP16"}, + {"inst": "vfma.f32 Sx, Sn, Sm" , "t32": "1110|11101|'Vx|10|Vn|Vx|10|10|'Vn|0|'Vm|0|Vm" , "it": "any", "ext": "VFPv4"}, + {"inst": "vfma.f64 Dx, Dn, Dm" , "t32": "1110|11101|Vx'|10|Vn|Vx|10|11|Vn'|0|Vm'|0|Vm" , "it": "any", "ext": "VFPv4"}, + {"inst": "vfms.f16 Sx, Sn, Sm" , "t32": "1110|11101|'Vx|10|Vn|Vx|10|01|'Vn|1|'Vm|0|Vm" , "it": "out", "ext": "VFPv4 FP16"}, + {"inst": "vfms.f32 Sx, Sn, Sm" , "t32": "1110|11101|'Vx|10|Vn|Vx|10|10|'Vn|1|'Vm|0|Vm" , "it": "any", "ext": "VFPv4"}, + {"inst": "vfms.f64 Dx, Dn, Dm" , "t32": "1110|11101|Vx'|10|Vn|Vx|10|11|Vn'|1|Vm'|0|Vm" , "it": "any", "ext": "VFPv4"}, + {"inst": "vfnma.f16 Sx, Sn, Sm" , "t32": "1110|11101|'Vx|01|Vn|Vx|10|01|'Vn|1|'Vm|0|Vm" , "it": "out", "ext": "VFPv4 FP16"}, + {"inst": "vfnma.f32 Sx, Sn, Sm" , "t32": "1110|11101|'Vx|01|Vn|Vx|10|10|'Vn|1|'Vm|0|Vm" , "it": "any", "ext": "VFPv4"}, + {"inst": "vfnma.f64 Dx, Dn, Dm" , "t32": "1110|11101|Vx'|01|Vn|Vx|10|11|Vn'|1|Vm'|0|Vm" , "it": "any", "ext": "VFPv4"}, + {"inst": "vfnms.f16 Sx, Sn, Sm" , "t32": "1110|11101|'Vx|01|Vn|Vx|10|01|'Vn|0|'Vm|0|Vm" , "it": "out", "ext": "VFPv4 FP16"}, + {"inst": "vfnms.f32 Sx, Sn, Sm" , "t32": "1110|11101|'Vx|01|Vn|Vx|10|10|'Vn|0|'Vm|0|Vm" , "it": "any", "ext": "VFPv4"}, + {"inst": "vfnms.f64 Dx, Dn, Dm" , "t32": "1110|11101|Vx'|01|Vn|Vx|10|11|Vn'|0|Vm'|0|Vm" , "it": "any", "ext": "VFPv4"} + ]}, + + {"category": "ASIMD", "ext": "ASIMD", "data": [ + {"inst": "vaba.x8-32 Dd, Dn, Dm" , "a32": "1111|001U0|Vd'|sz|Vn|Vd|0111|Vn'|0|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vaba.x8-32 Vd, Vn, Vm" , "a32": "1111|001U0|Vd'|sz|Vn|Vd|0111|Vn'|1|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vabal.x8-32 Vd, Dn, Dm" , "a32": "1111|001U1|Vd'|sz|Vn|Vd|0101|Vn'|0|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vabd.f16 Dd, Dn, Dm" , "a32": "1111|00110|Vd'|11|Vn|Vd|1101|Vn'|0|Vm'|0|Vm" , "ext": "ASIMD FP16"}, + {"inst": "vabd.f16 Vd, Vn, Vm" , "a32": "1111|00110|Vd'|11|Vn|Vd|1101|Vn'|1|Vm'|0|Vm" , "ext": "ASIMD FP16"}, + {"inst": "vabd.f32 Dd, Dn, Dm" , "a32": "1111|00110|Vd'|10|Vn|Vd|1101|Vn'|0|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vabd.f32 Vd, Vn, Vm" , "a32": "1111|00110|Vd'|10|Vn|Vd|1101|Vn'|1|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vabd.x8-32 Dd, Dn, Dm" , "a32": "1111|001U0|Vd'|sz|Vn|Vd|0111|Vn'|0|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vabd.x8-32 Vd, Vn, Vm" , "a32": "1111|001U0|Vd'|sz|Vn|Vd|0111|Vn'|1|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vabdl.x8-32 Vd, Dn, Dm" , "a32": "1111|001U1|Vd'|sz|Vn|Vd|0111|Vn'|0|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vabs.f16 Dd, Dn" , "a32": "1111|00111|Vd'|11|01|01|Vd|01|11|0|0|Vn'|0|Vn" , "ext": "ASIMD FP16"}, + {"inst": "vabs.f16 Vd, Vn" , "a32": "1111|00111|Vd'|11|01|01|Vd|01|11|0|1|Vn'|0|Vn" , "ext": "ASIMD FP16"}, + {"inst": "vabs.f32 Dd, Dn" , "a32": "1111|00111|Vd'|11|10|01|Vd|01|11|0|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vabs.f32 Vd, Vn" , "a32": "1111|00111|Vd'|11|10|01|Vd|01|11|0|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vabs.s8-32 Dd, Dn" , "a32": "1111|00111|Vd'|11|sz|01|Vd|00|11|0|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vabs.s8-32 Vd, Vn" , "a32": "1111|00111|Vd'|11|sz|01|Vd|00|11|0|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vacge.f16 Dd, Dn, Dm" , "a32": "1111|00110|Vd'|01|Vn|Vd|1110|Vn'|0|Vm'|1|Vm" , "ext": "ASIMD FP16"}, + {"inst": "vacge.f16 Vd, Vn, Vm" , "a32": "1111|00110|Vd'|01|Vn|Vd|1110|Vn'|1|Vm'|1|Vm" , "ext": "ASIMD FP16"}, + {"inst": "vacge.f32 Dd, Dn, Dm" , "a32": "1111|00110|Vd'|00|Vn|Vd|1110|Vn'|0|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vacge.f32 Vd, Vn, Vm" , "a32": "1111|00110|Vd'|00|Vn|Vd|1110|Vn'|1|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vacgt.f16 Dd, Dn, Dm" , "a32": "1111|00110|Vd'|11|Vn|Vd|1110|Vn'|0|Vm'|1|Vm" , "ext": "ASIMD FP16"}, + {"inst": "vacgt.f16 Vd, Vn, Vm" , "a32": "1111|00110|Vd'|11|Vn|Vd|1110|Vn'|1|Vm'|1|Vm" , "ext": "ASIMD FP16"}, + {"inst": "vacgt.f32 Dd, Dn, Dm" , "a32": "1111|00110|Vd'|10|Vn|Vd|1110|Vn'|0|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vacgt.f32 Vd, Vn, Vm" , "a32": "1111|00110|Vd'|10|Vn|Vd|1110|Vn'|1|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vacle.f16 Dd, Dn, Dm" , "a32": "1111|00110|Vd'|01|Vm|Vd|1110|Vm'|0|Vn'|1|Vn" , "ext": "ASIMD FP16"}, + {"inst": "vacle.f16 Vd, Vn, Vm" , "a32": "1111|00110|Vd'|01|Vm|Vd|1110|Vm'|1|Vn'|1|Vn" , "ext": "ASIMD FP16"}, + {"inst": "vacle.f32 Dd, Dn, Dm" , "a32": "1111|00110|Vd'|00|Vm|Vd|1110|Vm'|0|Vn'|1|Vn" , "ext": "ASIMD"}, + {"inst": "vacle.f32 Vd, Vn, Vm" , "a32": "1111|00110|Vd'|00|Vm|Vd|1110|Vm'|1|Vn'|1|Vn" , "ext": "ASIMD"}, + {"inst": "vaclt.f16 Dd, Dn, Dm" , "a32": "1111|00110|Vd'|11|Vm|Vd|1110|Vm'|0|Vn'|1|Vn" , "ext": "ASIMD FP16"}, + {"inst": "vaclt.f16 Vd, Vn, Vm" , "a32": "1111|00110|Vd'|11|Vm|Vd|1110|Vm'|1|Vn'|1|Vn" , "ext": "ASIMD FP16"}, + {"inst": "vaclt.f32 Dd, Dn, Dm" , "a32": "1111|00110|Vd'|10|Vm|Vd|1110|Vm'|0|Vn'|1|Vn" , "ext": "ASIMD"}, + {"inst": "vaclt.f32 Vd, Vn, Vm" , "a32": "1111|00110|Vd'|10|Vm|Vd|1110|Vm'|1|Vn'|1|Vn" , "ext": "ASIMD"}, + {"inst": "vadd.f16 Dd, Dn, Dm" , "a32": "1111|00100|Vd'|01|Vn|Vd|1101|Vn'|0|Vm'|0|Vm" , "ext": "ASIMD FP16"}, + {"inst": "vadd.f16 Vd, Vn, Vm" , "a32": "1111|00100|Vd'|01|Vn|Vd|1101|Vn'|1|Vm'|0|Vm" , "ext": "ASIMD FP16"}, + {"inst": "vadd.f32 Dd, Dn, Dm" , "a32": "1111|00100|Vd'|00|Vn|Vd|1101|Vn'|0|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vadd.f32 Vd, Vn, Vm" , "a32": "1111|00100|Vd'|00|Vn|Vd|1101|Vn'|1|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vadd.x8-64 Dd, Dn, Dm" , "a32": "1111|00100|Vd'|sz|Vn|Vd|1000|Vn'|0|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vadd.x8-64 Vd, Vn, Vm" , "a32": "1111|00100|Vd'|sz|Vn|Vd|1000|Vn'|1|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vaddhn.x16-64 Dd, Vn, Vm" , "a32": "1111|00101|Vd'|szM1:2|Vn|Vd|0100|Vn'|0|Vm'|0|Vm" , "ext": "ASIMD", "vecOp": "narrow"}, + {"inst": "vaddl.x8-32 Vd, Dn, Dm" , "a32": "1111|001U1|Vd'|sz|Vn|Vd|0000|Vn'|0|Vm'|0|Vm" , "ext": "ASIMD", "vecOp": "widen"}, + {"inst": "vaddw.x8-32 Vd, Vn, Dm" , "a32": "1111|001U1|Vd'|sz|Vn|Vd|0001|Vn'|0|Vm'|0|Vm" , "ext": "ASIMD", "vecOp": "widen"}, + {"inst": "vand.any Dd, Dn, Dm" , "a32": "1111|00100|Vd'|00|Vn|Vd|0001|Vn'|0|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vand.any Vd, Vn, Vm" , "a32": "1111|00100|Vd'|00|Vn|Vd|0001|Vn'|1|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vand.x16-64 Dx, #immV" , "a32": "1111|001|imm:1|1|Vx'|000|imm:3|Vx|cmode:4|0011|imm:4" , "ext": "ASIMD", "imm": "VecBicOrrImm(sz, 1, immV)", "pseudoOf": "vbic"}, + {"inst": "vand.x16-64 Vx, #immV" , "a32": "1111|001|imm:1|1|Vx'|000|imm:3|Vx|cmode:4|0111|imm:4" , "ext": "ASIMD", "imm": "VecBicOrrImm(sz, 1, immV)", "pseudoOf": "vbic"}, + {"inst": "vbic.any Dd, Dn, Dm" , "a32": "1111|00100|Vd'|01|Vn|Vd|0001|Vn'|0|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vbic.any Vd, Vn, Vm" , "a32": "1111|00100|Vd'|01|Vn|Vd|0001|Vn'|1|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vbic.x16-64 Dx, #immV" , "a32": "1111|001|imm:1|1|Vx'|000|imm:3|Vx|cmode:4|0011|imm:4" , "ext": "ASIMD", "imm": "VecBicOrrImm(sz, 0, immV)"}, + {"inst": "vbic.x16-64 Vx, #immV" , "a32": "1111|001|imm:1|1|Vx'|000|imm:3|Vx|cmode:4|0111|imm:4" , "ext": "ASIMD", "imm": "VecBicOrrImm(sz, 0, immV)"}, + {"inst": "vbif.any Dd, Dn, Dm" , "a32": "1111|00110|Vd'|11|Vn|Vd|0001|Vn'|0|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vbif.any Vd, Vn, Vm" , "a32": "1111|00110|Vd'|11|Vn|Vd|0001|Vn'|1|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vbit.any Dd, Dn, Dm" , "a32": "1111|00110|Vd'|10|Vn|Vd|0001|Vn'|0|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vbit.any Vd, Vn, Vm" , "a32": "1111|00110|Vd'|10|Vn|Vd|0001|Vn'|1|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vbsl.any Dd, Dn, Dm" , "a32": "1111|00110|Vd'|01|Vn|Vd|0001|Vn'|0|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vbsl.any Vd, Vn, Vm" , "a32": "1111|00110|Vd'|01|Vn|Vd|0001|Vn'|1|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vceq.f16 Dd, Dn, Dm" , "a32": "1111|00100|Vd'|01|Vn|Vd|1110|Vn'|0|Vm'|0|Vm" , "ext": "ASIMD FP16"}, + {"inst": "vceq.f16 Vd, Vn, Vm" , "a32": "1111|00100|Vd'|01|Vn|Vd|1110|Vn'|1|Vm'|0|Vm" , "ext": "ASIMD FP16"}, + {"inst": "vceq.f32 Dd, Dn, Dm" , "a32": "1111|00100|Vd'|00|Vn|Vd|1110|Vn'|0|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vceq.f32 Vd, Vn, Vm" , "a32": "1111|00100|Vd'|00|Vn|Vd|1110|Vn'|1|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vceq.f16 Dd, Dn, #zero" , "a32": "1111|00111|Vd'|11|01|01|Vd|01010|0|Vn'|0|Vn" , "ext": "ASIMD FP16"}, + {"inst": "vceq.f16 Vd, Vn, #zero" , "a32": "1111|00111|Vd'|11|01|01|Vd|01010|1|Vn'|0|Vn" , "ext": "ASIMD FP16"}, + {"inst": "vceq.f32 Dd, Dn, #zero" , "a32": "1111|00111|Vd'|11|10|01|Vd|01010|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vceq.f32 Vd, Vn, #zero" , "a32": "1111|00111|Vd'|11|10|01|Vd|01010|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vceq.x8-32 Dd, Dn, Dm" , "a32": "1111|00110|Vd'|sz|Vn|Vd|1000|Vn'|0|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vceq.x8-32 Vd, Vn, Vm" , "a32": "1111|00110|Vd'|sz|Vn|Vd|1000|Vn'|1|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vceq.x8-32 Dd, Dn, #zero" , "a32": "1111|00111|Vd'|11|sz|01|Vd|00010|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vceq.x8-32 Vd, Vn, #zero" , "a32": "1111|00111|Vd'|11|sz|01|Vd|00010|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcge.f16 Dd, Dn, Dm" , "a32": "1111|00110|Vd'|01|Vn|Vd|1110|Vn'|0|Vm'|0|Vm" , "ext": "ASIMD FP16"}, + {"inst": "vcge.f16 Vd, Vn, Vm" , "a32": "1111|00110|Vd'|01|Vn|Vd|1110|Vn'|1|Vm'|0|Vm" , "ext": "ASIMD FP16"}, + {"inst": "vcge.f32 Dd, Dn, Dm" , "a32": "1111|00110|Vd'|00|Vn|Vd|1110|Vn'|0|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vcge.f32 Vd, Vn, Vm" , "a32": "1111|00110|Vd'|00|Vn|Vd|1110|Vn'|1|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vcge.f16 Dd, Dn, #zero" , "a32": "1111|00111|Vd'|11|01|01|Vd|01001|0|Vn'|0|Vn" , "ext": "ASIMD FP16"}, + {"inst": "vcge.f16 Vd, Vn, #zero" , "a32": "1111|00111|Vd'|11|01|01|Vd|01001|1|Vn'|0|Vn" , "ext": "ASIMD FP16"}, + {"inst": "vcge.f32 Dd, Dn, #zero" , "a32": "1111|00111|Vd'|11|10|01|Vd|01001|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcge.f32 Vd, Vn, #zero" , "a32": "1111|00111|Vd'|11|10|01|Vd|01001|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcge.x8-32 Dd, Dn, Dm" , "a32": "1111|001U0|Vd'|sz|Vn|Vd|0011|Vn'|0|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vcge.x8-32 Vd, Vn, Vm" , "a32": "1111|001U0|Vd'|sz|Vn|Vd|0011|Vn'|1|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vcge.s8-32 Dd, Dn, #zero" , "a32": "1111|00111|Vd'|11|sz|01|Vd|00001|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcge.s8-32 Vd, Vn, #zero" , "a32": "1111|00111|Vd'|11|sz|01|Vd|00001|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcgt.f16 Dd, Dn, Dm" , "a32": "1111|00110|Vd'|11|Vn|Vd|1110|Vn'|0|Vm'|0|Vm" , "ext": "ASIMD FP16"}, + {"inst": "vcgt.f16 Vd, Vn, Vm" , "a32": "1111|00110|Vd'|11|Vn|Vd|1110|Vn'|1|Vm'|0|Vm" , "ext": "ASIMD FP16"}, + {"inst": "vcgt.f32 Dd, Dn, Dm" , "a32": "1111|00110|Vd'|10|Vn|Vd|1110|Vn'|0|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vcgt.f32 Vd, Vn, Vm" , "a32": "1111|00110|Vd'|10|Vn|Vd|1110|Vn'|1|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vcgt.f16 Dd, Dn, #zero" , "a32": "1111|00111|Vd'|11|01|01|Vd|01000|0|Vn'|0|Vn" , "ext": "ASIMD FP16"}, + {"inst": "vcgt.f16 Vd, Vn, #zero" , "a32": "1111|00111|Vd'|11|01|01|Vd|01000|1|Vn'|0|Vn" , "ext": "ASIMD FP16"}, + {"inst": "vcgt.f32 Dd, Dn, #zero" , "a32": "1111|00111|Vd'|11|10|01|Vd|01000|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcgt.f32 Vd, Vn, #zero" , "a32": "1111|00111|Vd'|11|10|01|Vd|01000|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcgt.x8-32 Dd, Dn, Dm" , "a32": "1111|001U0|Vd'|sz|Vn|Vd|0011|Vn'|0|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vcgt.x8-32 Vd, Vn, Vm" , "a32": "1111|001U0|Vd'|sz|Vn|Vd|0011|Vn'|1|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vcgt.s8-32 Dd, Dn, #zero" , "a32": "1111|00111|Vd'|11|sz|01|Vd|00000|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcgt.s8-32 Vd, Vn, #zero" , "a32": "1111|00111|Vd'|11|sz|01|Vd|00000|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcle.f16 Dd, Dn, Dm" , "a32": "1111|00110|Vd'|01|Vm|Vd|1110|Vm'|0|Vn'|0|Vn" , "ext": "ASIMD FP16"}, + {"inst": "vcle.f16 Vd, Vn, Vm" , "a32": "1111|00110|Vd'|01|Vm|Vd|1110|Vm'|1|Vn'|0|Vn" , "ext": "ASIMD FP16"}, + {"inst": "vcle.f32 Dd, Dn, Dm" , "a32": "1111|00110|Vd'|00|Vm|Vd|1110|Vm'|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcle.f32 Vd, Vn, Vm" , "a32": "1111|00110|Vd'|00|Vm|Vd|1110|Vm'|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcle.f16 Dd, Dn, #zero" , "a32": "1111|00111|Vd'|11|01|01|Vd|01011|0|Vn'|0|Vn" , "ext": "ASIMD FP16"}, + {"inst": "vcle.f16 Vd, Vn, #zero" , "a32": "1111|00111|Vd'|11|01|01|Vd|01011|1|Vn'|0|Vn" , "ext": "ASIMD FP16"}, + {"inst": "vcle.f32 Dd, Dn, #zero" , "a32": "1111|00111|Vd'|11|10|01|Vd|01011|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcle.f32 Vd, Vn, #zero" , "a32": "1111|00111|Vd'|11|10|01|Vd|01011|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcle.x8-32 Dd, Dn, Dm" , "a32": "1111|001U0|Vd'|sz|Vm|Vd|0011|Vm'|0|Vn'|1|Vn" , "ext": "ASIMD"}, + {"inst": "vcle.x8-32 Vd, Vn, Vm" , "a32": "1111|001U0|Vd'|sz|Vm|Vd|0011|Vm'|1|Vn'|1|Vn" , "ext": "ASIMD"}, + {"inst": "vcle.s8-32 Dd, Dn, #zero" , "a32": "1111|00111|Vd'|11|sz|01|Vd|00011|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcle.s8-32 Vd, Vn, #zero" , "a32": "1111|00111|Vd'|11|sz|01|Vd|00011|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcls.x8-32 Dd, Dn" , "a32": "1111|00111|Vd'|11|sz|00|Vd|01000|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcls.x8-32 Vd, Vn" , "a32": "1111|00111|Vd'|11|sz|00|Vd|01000|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vclt.f16 Dd, Dn, Dm" , "a32": "1111|00110|Vd'|11|Vm|Vd|1110|Vm'|0|Vn'|0|Vn" , "ext": "ASIMD FP16"}, + {"inst": "vclt.f16 Vd, Vn, Vm" , "a32": "1111|00110|Vd'|11|Vm|Vd|1110|Vm'|1|Vn'|0|Vn" , "ext": "ASIMD FP16"}, + {"inst": "vclt.f32 Dd, Dn, Dm" , "a32": "1111|00110|Vd'|10|Vm|Vd|1110|Vm'|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vclt.f32 Vd, Vn, Vm" , "a32": "1111|00110|Vd'|10|Vm|Vd|1110|Vm'|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vclt.f16 Dd, Dn, #zero" , "a32": "1111|00111|Vd'|11|01|01|Vd|01100|0|Vn'|0|Vn" , "ext": "ASIMD FP16"}, + {"inst": "vclt.f16 Vd, Vn, #zero" , "a32": "1111|00111|Vd'|11|01|01|Vd|01100|1|Vn'|0|Vn" , "ext": "ASIMD FP16"}, + {"inst": "vclt.f32 Dd, Dn, #zero" , "a32": "1111|00111|Vd'|11|10|01|Vd|01100|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vclt.f32 Vd, Vn, #zero" , "a32": "1111|00111|Vd'|11|10|01|Vd|01100|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vclt.x8-32 Dd, Dn, Dm" , "a32": "1111|001U0|Vd'|sz|Vm|Vd|0011|Vm'|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vclt.x8-32 Vd, Vn, Vm" , "a32": "1111|001U0|Vd'|sz|Vm|Vd|0011|Vm'|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vclt.s8-32 Dd, Dn, #zero" , "a32": "1111|00111|Vd'|11|sz|01|Vd|00100|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vclt.s8-32 Vd, Vn, #zero" , "a32": "1111|00111|Vd'|11|sz|01|Vd|00100|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vclz.x8-32 Dd, Dn" , "a32": "1111|00111|Vd'|11|sz|00|Vd|01001|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vclz.x8-32 Vd, Vn" , "a32": "1111|00111|Vd'|11|sz|00|Vd|01001|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcnt.x8 Dd, Dn" , "a32": "1111|00111|Vd'|11|00|00|Vd|01010|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcnt.x8 Vd, Vn" , "a32": "1111|00111|Vd'|11|00|00|Vd|01010|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcvt.s32.f32 Dd, Dn" , "a32": "1111|00111|Vd'|11|10|11|Vd|01110|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcvt.s32.f32 Vd, Vn" , "a32": "1111|00111|Vd'|11|10|11|Vd|01110|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcvt.u32.f32 Dd, Dn" , "a32": "1111|00111|Vd'|11|10|11|Vd|01111|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcvt.u32.f32 Vd, Vn" , "a32": "1111|00111|Vd'|11|10|11|Vd|01111|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcvt.f32.s32 Dd, Dn" , "a32": "1111|00111|Vd'|11|10|11|Vd|01100|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcvt.f32.s32 Vd, Vn" , "a32": "1111|00111|Vd'|11|10|11|Vd|01100|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcvt.f32.u32 Dd, Dn" , "a32": "1111|00111|Vd'|11|10|11|Vd|01101|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcvt.f32.u32 Vd, Vn" , "a32": "1111|00111|Vd'|11|10|11|Vd|01101|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vcvt.f32.s32 Dd, Dn, #fbits" , "a32": "1111|00101|Vd'|imm:6|Vd|11100|0|Vn'|1|Vn" , "ext": "ASIMD", "imm": "VecFBitsASIMD(fbits)"}, + {"inst": "vcvt.f32.s32 Vd, Vn, #fbits" , "a32": "1111|00101|Vd'|imm:6|Vd|11100|1|Vn'|1|Vn" , "ext": "ASIMD", "imm": "VecFBitsASIMD(fbits)"}, + {"inst": "vcvt.s32.f32 Dd, Dn, #fbits" , "a32": "1111|00101|Vd'|imm:6|Vd|11110|0|Vn'|1|Vn" , "ext": "ASIMD", "imm": "VecFBitsASIMD(fbits)"}, + {"inst": "vcvt.s32.f32 Vd, Vn, #fbits" , "a32": "1111|00101|Vd'|imm:6|Vd|11110|1|Vn'|1|Vn" , "ext": "ASIMD", "imm": "VecFBitsASIMD(fbits)"}, + {"inst": "vcvt.f32.u32 Dd, Dn, #fbits" , "a32": "1111|00111|Vd'|imm:6|Vd|11100|0|Vn'|1|Vn" , "ext": "ASIMD", "imm": "VecFBitsASIMD(fbits)"}, + {"inst": "vcvt.f32.u32 Vd, Vn, #fbits" , "a32": "1111|00111|Vd'|imm:6|Vd|11100|1|Vn'|1|Vn" , "ext": "ASIMD", "imm": "VecFBitsASIMD(fbits)"}, + {"inst": "vcvt.u32.f32 Dd, Dn, #fbits" , "a32": "1111|00111|Vd'|imm:6|Vd|11110|0|Vn'|1|Vn" , "ext": "ASIMD", "imm": "VecFBitsASIMD(fbits)"}, + {"inst": "vcvt.u32.f32 Vd, Vn, #fbits" , "a32": "1111|00111|Vd'|imm:6|Vd|11110|1|Vn'|1|Vn" , "ext": "ASIMD", "imm": "VecFBitsASIMD(fbits)"}, + {"inst": "vcvta.s32.f32 Sd, Sn" , "a32": "1111|11101|'Vd|11|11|00|Vd|10101|1|'Vn|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvta.s32.f64 Sd, Dn" , "a32": "1111|11101|'Vd|11|11|00|Vd|10111|1|Vn'|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvta.u32.f32 Sd, Sn" , "a32": "1111|11101|'Vd|11|11|00|Vd|10100|1|'Vn|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvta.u32.f64 Sd, Dn" , "a32": "1111|11101|'Vd|11|11|00|Vd|10110|1|Vn'|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtm.s32.f32 Dd, Dn" , "a32": "1111|00111|Vd'|11|10|11|Vd|00110|0|Vn'|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtm.s32.f32 Vd, Vn" , "a32": "1111|00111|Vd'|11|10|11|Vd|00110|1|Vn'|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtm.u32.f32 Dd, Dn" , "a32": "1111|00111|Vd'|11|10|11|Vd|00111|0|Vn'|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtm.u32.f32 Vd, Vn" , "a32": "1111|00111|Vd'|11|10|11|Vd|00111|1|Vn'|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtm.s32.f32 Sd, Sn" , "a32": "1111|11101|'Vd|11|11|11|Vd|10101|1|'Vn|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtm.s32.f64 Sd, Dn" , "a32": "1111|11101|'Vd|11|11|11|Vd|10111|1|Vn'|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtm.u32.f32 Sd, Sn" , "a32": "1111|11101|'Vd|11|11|11|Vd|10100|1|'Vn|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtm.u32.f64 Sd, Dn" , "a32": "1111|11101|'Vd|11|11|11|Vd|10110|1|Vn'|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtn.s32.f32 Dd, Dn" , "a32": "1111|00111|Vd'|11|10|11|Vd|00010|0|Vn'|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtn.s32.f32 Vd, Vn" , "a32": "1111|00111|Vd'|11|10|11|Vd|00010|1|Vn'|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtn.u32.f32 Dd, Dn" , "a32": "1111|00111|Vd'|11|10|11|Vd|00011|0|Vn'|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtn.u32.f32 Vd, Vn" , "a32": "1111|00111|Vd'|11|10|11|Vd|00011|1|Vn'|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtn.s32.f32 Sd, Sn" , "a32": "1111|11101|'Vd|11|11|01|Vd|10101|1|'Vn|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtn.s32.f64 Sd, Dn" , "a32": "1111|11101|'Vd|11|11|01|Vd|10111|1|Vn'|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtn.u32.f32 Sd, Sn" , "a32": "1111|11101|'Vd|11|11|01|Vd|10100|1|'Vn|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtn.u32.f64 Sd, Dn" , "a32": "1111|11101|'Vd|11|11|01|Vd|10110|1|Vn'|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtp.s32.f32 Dd, Dn" , "a32": "1111|00111|Vd'|11|10|11|Vd|00100|0|Vn'|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtp.s32.f32 Vd, Vn" , "a32": "1111|00111|Vd'|11|10|11|Vd|00100|1|Vn'|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtp.u32.f32 Dd, Dn" , "a32": "1111|00111|Vd'|11|10|11|Vd|00101|0|Vn'|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtp.u32.f32 Vd, Vn" , "a32": "1111|00111|Vd'|11|10|11|Vd|00101|1|Vn'|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtp.s32.f32 Sd, Sn" , "a32": "1111|11101|'Vd|11|11|10|Vd|10101|1|'Vn|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtp.s32.f64 Sd, Dn" , "a32": "1111|11101|'Vd|11|11|10|Vd|10111|1|Vn'|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtp.u32.f32 Sd, Sn" , "a32": "1111|11101|'Vd|11|11|10|Vd|10100|1|'Vn|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vcvtp.u32.f64 Sd, Dn" , "a32": "1111|11101|'Vd|11|11|10|Vd|10110|1|Vn'|0|Vn" , "ext": "ARMv8+"}, + {"inst": "vdup.8 Dd, Rn!=PC" , "a32": "cond|11101|1|00|Vd|Rn|1011|Vd'|0|0|1|0000" , "ext": "ASIMD"}, + {"inst": "vdup.8 Vd, Rn!=PC" , "a32": "cond|11101|1|10|Vd|Rn|1011|Vd'|0|0|1|0000" , "ext": "ASIMD"}, + {"inst": "vdup.16 Dd, Rn!=PC" , "a32": "cond|11101|0|00|Vd|Rn|1011|Vd'|0|1|1|0000" , "ext": "ASIMD"}, + {"inst": "vdup.16 Vd, Rn!=PC" , "a32": "cond|11101|0|10|Vd|Rn|1011|Vd'|0|1|1|0000" , "ext": "ASIMD"}, + {"inst": "vdup.32 Dd, Rn!=PC" , "a32": "cond|11101|0|00|Vd|Rn|1011|Vd'|0|0|1|0000" , "ext": "ASIMD"}, + {"inst": "vdup.32 Vd, Rn!=PC" , "a32": "cond|11101|0|10|Vd|Rn|1011|Vd'|0|0|1|0000" , "ext": "ASIMD"}, + {"inst": "vdup.8 Dd, Dn[#i]" , "a32": "1111|00111|Vd'|11|i:3|1|Vd|1100|0|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vdup.8 Vd, Dn[#i]" , "a32": "1111|00111|Vd'|11|i:3|1|Vd|1100|0|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vdup.16 Dd, Dn[#i]" , "a32": "1111|00111|Vd'|11|i:2|10|Vd|1100|0|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vdup.16 Vd, Dn[#i]" , "a32": "1111|00111|Vd'|11|i:2|10|Vd|1100|0|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vdup.32 Dd, Dn[#i]" , "a32": "1111|00111|Vd'|11|i:1|100|Vd|1100|0|0|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "vdup.32 Vd, Dn[#i]" , "a32": "1111|00111|Vd'|11|i:1|100|Vd|1100|0|1|Vn'|0|Vn" , "ext": "ASIMD"}, + {"inst": "veor.any Dd, Dn, Dm" , "a32": "1111|00110|Vd'|00|Vn|Vd|0001|Vn'|0|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "veor.any Vd, Vn, Vm" , "a32": "1111|00110|Vd'|00|Vn|Vd|0001|Vn'|1|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vext.8 Dd, Dn, Dm, #immZ<=07" , "a32": "1111|00101|Vd'|11|Vn|Vd|immZ:4|Vn'|0|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vext.8 Vd, Vn, Vm, #immZ<=15" , "a32": "1111|00101|Vd'|11|Vn|Vd|immZ:4|Vn'|1|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vfma.f16 Dx, Dn, Dm" , "a32": "1111|00100|Vx'|01|Vn|Vx|1100|Vn'|0|Vm'|1|Vm" , "ext": "ASIMD FP16"}, + {"inst": "vfma.f16 Vx, Vn, Vm" , "a32": "1111|00100|Vx'|01|Vn|Vx|1100|Vn'|1|Vm'|1|Vm" , "ext": "ASIMD FP16"}, + {"inst": "vfma.f32 Dx, Dn, Dm" , "a32": "1111|00100|Vx'|00|Vn|Vx|1100|Vn'|0|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vfma.f32 Vx, Vn, Vm" , "a32": "1111|00100|Vx'|00|Vn|Vx|1100|Vn'|1|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vfms.f16 Dx, Dn, Dm" , "a32": "1111|00100|Vx'|11|Vn|Vx|1100|Vn'|0|Vm'|1|Vm" , "ext": "ASIMD FP16"}, + {"inst": "vfms.f16 Vx, Vn, Vm" , "a32": "1111|00100|Vx'|11|Vn|Vx|1100|Vn'|1|Vm'|1|Vm" , "ext": "ASIMD FP16"}, + {"inst": "vfms.f32 Dx, Dn, Dm" , "a32": "1111|00100|Vx'|10|Vn|Vx|1100|Vn'|0|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vfms.f32 Vx, Vn, Vm" , "a32": "1111|00100|Vx'|10|Vn|Vx|1100|Vn'|1|Vm'|1|Vm" , "ext": "ASIMD"}, + {"inst": "vhadd.x8-32 Dd, Dn, Dm" , "a32": "1111|001U0|Vd'|sz|Vn|Vd|0000|Vn'|0|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vhadd.x8-32 Vd, Vn, Vm" , "a32": "1111|001U0|Vd'|sz|Vn|Vd|0000|Vn'|1|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vhsub.x8-32 Dd, Dn, Dm" , "a32": "1111|001U0|Vd'|sz|Vn|Vd|0010|Vn'|0|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vhsub.x8-32 Vd, Vn, Vm" , "a32": "1111|001U0|Vd'|sz|Vn|Vd|0010|Vn'|1|Vm'|0|Vm" , "ext": "ASIMD"}, + {"inst": "vins.f16 Sd, Sn" , "a32": "1111|11101|'Vd|11|0000|Vd|1010|11|'Vn|0|Vn" , "ext": "FP16"}, + {"inst": "vld1.8-64 Dd, [Rn!=PC]" , "a32": "1111|01000|Vd'|10|Rn|Vd|0111|sz|0|align:1|1111" , "ext": "ASIMD"}, + {"inst": "vld1.8-64 Dd, [Rn!=PC, Rm!=XX]@" , "a32": "1111|01000|Vd'|10|Rn|Vd|0111|sz|0|align:1|Rm" , "ext": "ASIMD"}, + {"inst": "vld1.8-64 Dd, [Rn!=PC, #off==8]@" , "a32": "1111|01000|Vd'|10|Rn|Vd|0111|sz|0|align:1|1101" , "ext": "ASIMD"}, + {"inst": "vld1.8-64 2x{Dd<=30}+, [Rn!=PC]" , "a32": "1111|01000|Vd'|10|Rn|Vd|1010|sz|0|align:1|1111" , "ext": "ASIMD"}, + {"inst": "vld1.8-64 2x{Dd<=30}+, [Rn!=PC, Rm!=XX]@" , "a32": "1111|01000|Vd'|10|Rn|Vd|1010|sz|0|align:1|Rm" , "ext": "ASIMD"}, + {"inst": "vld1.8-64 2x{Dd<=30}+, [Rn!=PC, #off==16]@" , "a32": "1111|01000|Vd'|10|Rn|Vd|1010|sz|0|align:1|1101" , "ext": "ASIMD"}, + {"inst": "vld1.8-64 3x{Dd<=29}+, [Rn!=PC]" , "a32": "1111|01000|Vd'|10|Rn|Vd|0110|sz|0|align:1|1111" , "ext": "ASIMD"}, + {"inst": "vld1.8-64 3x{Dd<=29}+, [Rn!=PC, Rm!=XX]@" , "a32": "1111|01000|Vd'|10|Rn|Vd|0110|sz|0|align:1|Rm" , "ext": "ASIMD"}, + {"inst": "vld1.8-64 3x{Dd<=29}+, [Rn!=PC, #off==24]@" , "a32": "1111|01000|Vd'|10|Rn|Vd|0110|sz|0|align:1|1101" , "ext": "ASIMD"}, + {"inst": "vld1.8-64 4x{Dd<=28}+, [Rn!=PC]" , "a32": "1111|01000|Vd'|10|Rn|Vd|0010|sz|0|align:1|1111" , "ext": "ASIMD"}, + {"inst": "vld1.8-64 4x{Dd<=28}+, [Rn!=PC, Rm!=XX]@" , "a32": "1111|01000|Vd'|10|Rn|Vd|0010|sz|0|align:1|Rm" , "ext": "ASIMD"}, + {"inst": "vld1.8-64 4x{Dd<=28}+, [Rn!=PC, #off==32]@" , "a32": "1111|01000|Vd'|10|Rn|Vd|0010|sz|0|align:1|1101" , "ext": "ASIMD"}, + {"inst": "vld1.8 Dd[#i], [Rn!=PC]" , "a32": "1111|01001|Vd'|10|Rn|Vd|0000|i:3|align:1|1111" , "ext": "ASIMD"}, + {"inst": "vld1.8 Dd[#i], [Rn!=PC, Rm!=XX]@" , "a32": "1111|01001|Vd'|10|Rn|Vd|0000|i:3|align:1|Rm" , "ext": "ASIMD"}, + {"inst": "vld1.8 Dd[#i], [Rn!=PC, #off==1]@" , "a32": "1111|01001|Vd'|10|Rn|Vd|0000|i:3|align:1|1101" , "ext": "ASIMD"}, + {"inst": "vld1.16 Dd[#i], [Rn!=PC]" , "a32": "1111|01001|Vd'|10|Rn|Vd|0100|i:2|0|align:1|1111" , "ext": "ASIMD"}, + {"inst": "vld1.16 Dd[#i], [Rn!=PC, Rm!=XX]@" , "a32": "1111|01001|Vd'|10|Rn|Vd|0100|i:2|0|align:1|Rm" , "ext": "ASIMD"}, + {"inst": "vld1.16 Dd[#i], [Rn!=PC, #off==2]@" , "a32": "1111|01001|Vd'|10|Rn|Vd|0100|i:2|0|align:1|1101" , "ext": "ASIMD"}, + {"inst": "vld1.32 Dd[#i], [Rn!=PC]" , "a32": "1111|01001|Vd'|10|Rn|Vd|1000|i:1|0|align:2|1111" , "ext": "ASIMD"}, + {"inst": "vld1.32 Dd[#i], [Rn!=PC, Rm!=XX]@" , "a32": "1111|01001|Vd'|10|Rn|Vd|1000|i:1|0|align:2|Rm" , "ext": "ASIMD"}, + {"inst": "vld1.32 Dd[#i], [Rn!=PC, #off==4]@" , "a32": "1111|01001|Vd'|10|Rn|Vd|1000|i:1|0|align:2|1101" , "ext": "ASIMD"}, + {"inst": "vld1r.8-32 Dd, [Rn!=PC]" , "a32": "1111|01001|Vd'|10|Rn|Vd|1100|sz|0|align:1|1111" , "ext": "ASIMD"}, + {"inst": "vld1r.8-32 Dd, [Rn!=PC, Rm!=XX]@" , "a32": "1111|01001|Vd'|10|Rn|Vd|1100|sz|0|align:1|Rm" , "ext": "ASIMD"}, + {"inst": "vld1r.8-32 Dd, [Rn!=PC, #off==1<" , "op": "0F 01 FC" , "ext": "CLZERO"}, - {"inst": "cmovo x:r16, r16/m16" , "op": "RM: 66 0F 40 /r" , "ext": "CMOV" , "io": "OF=R"}, - {"inst": "cmovo X:r32, r32/m32" , "op": "RM: 0F 40 /r" , "ext": "CMOV" , "io": "OF=R"}, - {"inst": "cmovo X:r64, r64/m64" , "op": "RM: REX.W 0F 40 /r" , "ext": "CMOV" , "io": "OF=R"}, - {"inst": "cmovno x:r16, r16/m16" , "op": "RM: 66 0F 41 /r" , "ext": "CMOV" , "io": "OF=R"}, - {"inst": "cmovno X:r32, r32/m32" , "op": "RM: 0F 41 /r" , "ext": "CMOV" , "io": "OF=R"}, - {"inst": "cmovno X:r64, r64/m64" , "op": "RM: REX.W 0F 41 /r" , "ext": "CMOV" , "io": "OF=R"}, - {"inst": "cmovb|cmovnae|cmovc x:r16, r16/m16" , "op": "RM: 66 0F 42 /r" , "ext": "CMOV" , "io": "CF=R"}, - {"inst": "cmovb|cmovnae|cmovc X:r32, r32/m32" , "op": "RM: 0F 42 /r" , "ext": "CMOV" , "io": "CF=R"}, - {"inst": "cmovb|cmovnae|cmovc X:r64, r64/m64" , "op": "RM: REX.W 0F 42 /r" , "ext": "CMOV" , "io": "CF=R"}, - {"inst": "cmovae|cmovnb|cmovnc x:r16, r16/m16" , "op": "RM: 66 0F 43 /r" , "ext": "CMOV" , "io": "CF=R"}, - {"inst": "cmovae|cmovnb|cmovnc X:r32, r32/m32" , "op": "RM: 0F 43 /r" , "ext": "CMOV" , "io": "CF=R"}, - {"inst": "cmovae|cmovnb|cmovnc X:r64, r64/m64" , "op": "RM: REX.W 0F 43 /r" , "ext": "CMOV" , "io": "CF=R"}, - {"inst": "cmove|cmovz x:r16, r16/m16" , "op": "RM: 66 0F 44 /r" , "ext": "CMOV" , "io": "ZF=R"}, - {"inst": "cmove|cmovz X:r32, r32/m32" , "op": "RM: 0F 44 /r" , "ext": "CMOV" , "io": "ZF=R"}, - {"inst": "cmove|cmovz X:r64, r64/m64" , "op": "RM: REX.W 0F 44 /r" , "ext": "CMOV" , "io": "ZF=R"}, - {"inst": "cmovne|cmovnz x:r16, r16/m16" , "op": "RM: 66 0F 45 /r" , "ext": "CMOV" , "io": "ZF=R"}, - {"inst": "cmovne|cmovnz X:r32, r32/m32" , "op": "RM: 0F 45 /r" , "ext": "CMOV" , "io": "ZF=R"}, - {"inst": "cmovne|cmovnz X:r64, r64/m64" , "op": "RM: REX.W 0F 45 /r" , "ext": "CMOV" , "io": "ZF=R"}, - {"inst": "cmovbe|cmovna x:r16, r16/m16" , "op": "RM: 66 0F 46 /r" , "ext": "CMOV" , "io": "CF=R ZF=R"}, - {"inst": "cmovbe|cmovna X:r32, r32/m32" , "op": "RM: 0F 46 /r" , "ext": "CMOV" , "io": "CF=R ZF=R"}, - {"inst": "cmovbe|cmovna X:r64, r64/m64" , "op": "RM: REX.W 0F 46 /r" , "ext": "CMOV" , "io": "CF=R ZF=R"}, - {"inst": "cmova|cmovnbe x:r16, r16/m16" , "op": "RM: 66 0F 47 /r" , "ext": "CMOV" , "io": "CF=R ZF=R"}, - {"inst": "cmova|cmovnbe X:r32, r32/m32" , "op": "RM: 0F 47 /r" , "ext": "CMOV" , "io": "CF=R ZF=R"}, - {"inst": "cmova|cmovnbe X:r64, r64/m64" , "op": "RM: REX.W 0F 47 /r" , "ext": "CMOV" , "io": "CF=R ZF=R"}, - {"inst": "cmovs x:r16, r16/m16" , "op": "RM: 66 0F 48 /r" , "ext": "CMOV" , "io": "SF=R"}, - {"inst": "cmovs X:r32, r32/m32" , "op": "RM: 0F 48 /r" , "ext": "CMOV" , "io": "SF=R"}, - {"inst": "cmovs X:r64, r64/m64" , "op": "RM: REX.W 0F 48 /r" , "ext": "CMOV" , "io": "SF=R"}, - {"inst": "cmovns x:r16, r16/m16" , "op": "RM: 66 0F 49 /r" , "ext": "CMOV" , "io": "SF=R"}, - {"inst": "cmovns X:r32, r32/m32" , "op": "RM: 0F 49 /r" , "ext": "CMOV" , "io": "SF=R"}, - {"inst": "cmovns X:r64, r64/m64" , "op": "RM: REX.W 0F 49 /r" , "ext": "CMOV" , "io": "SF=R"}, - {"inst": "cmovp|cmovpe x:r16, r16/m16" , "op": "RM: 66 0F 4A /r" , "ext": "CMOV" , "io": "PF=R"}, - {"inst": "cmovp|cmovpe X:r32, r32/m32" , "op": "RM: 0F 4A /r" , "ext": "CMOV" , "io": "PF=R"}, - {"inst": "cmovp|cmovpe X:r64, r64/m64" , "op": "RM: REX.W 0F 4A /r" , "ext": "CMOV" , "io": "PF=R"}, - {"inst": "cmovnp|cmovpo x:r16, r16/m16" , "op": "RM: 66 0F 4B /r" , "ext": "CMOV" , "io": "PF=R"}, - {"inst": "cmovnp|cmovpo X:r32, r32/m32" , "op": "RM: 0F 4B /r" , "ext": "CMOV" , "io": "PF=R"}, - {"inst": "cmovnp|cmovpo X:r64, r64/m64" , "op": "RM: REX.W 0F 4B /r" , "ext": "CMOV" , "io": "PF=R"}, - {"inst": "cmovl|cmovnge x:r16, r16/m16" , "op": "RM: 66 0F 4C /r" , "ext": "CMOV" , "io": "SF=R OF=R"}, - {"inst": "cmovl|cmovnge X:r32, r32/m32" , "op": "RM: 0F 4C /r" , "ext": "CMOV" , "io": "SF=R OF=R"}, - {"inst": "cmovl|cmovnge X:r64, r64/m64" , "op": "RM: REX.W 0F 4C /r" , "ext": "CMOV" , "io": "SF=R OF=R"}, - {"inst": "cmovge|cmovnl x:r16, r16/m16" , "op": "RM: 66 0F 4D /r" , "ext": "CMOV" , "io": "SF=R OF=R"}, - {"inst": "cmovge|cmovnl X:r32, r32/m32" , "op": "RM: 0F 4D /r" , "ext": "CMOV" , "io": "SF=R OF=R"}, - {"inst": "cmovge|cmovnl X:r64, r64/m64" , "op": "RM: REX.W 0F 4D /r" , "ext": "CMOV" , "io": "SF=R OF=R"}, - {"inst": "cmovle|cmovng x:r16, r16/m16" , "op": "RM: 66 0F 4E /r" , "ext": "CMOV" , "io": "ZF=R SF=R OF=R"}, - {"inst": "cmovle|cmovng X:r32, r32/m32" , "op": "RM: 0F 4E /r" , "ext": "CMOV" , "io": "ZF=R SF=R OF=R"}, - {"inst": "cmovle|cmovng X:r64, r64/m64" , "op": "RM: REX.W 0F 4E /r" , "ext": "CMOV" , "io": "ZF=R SF=R OF=R"}, - {"inst": "cmovg|cmovnle x:r16, r16/m16" , "op": "RM: 66 0F 4F /r" , "ext": "CMOV" , "io": "ZF=R SF=R OF=R"}, - {"inst": "cmovg|cmovnle X:r32, r32/m32" , "op": "RM: 0F 4F /r" , "ext": "CMOV" , "io": "ZF=R SF=R OF=R"}, - {"inst": "cmovg|cmovnle X:r64, r64/m64" , "op": "RM: REX.W 0F 4F /r" , "ext": "CMOV" , "io": "ZF=R SF=R OF=R"}, - {"inst": "cmpbexadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 E6 /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpbexadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 E6 /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpbxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 E2 /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpbxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 E2 /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmplexadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 EE /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmplexadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 EE /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmplxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 EC /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmplxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 EC /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpnbexadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 E7 /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpnbexadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 E7 /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpnbxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 E3 /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpnbxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 E3 /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpnlexadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 EF /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpnlexadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 EF /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpnlxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 ED /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpnlxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 ED /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpnoxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 E1 /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpnoxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 E1 /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpnpxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 EB /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpnpxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 EB /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpnsxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 E9 /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpnsxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 E9 /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpnzxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 E5 /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpnzxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 E5 /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpoxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 E0 /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpoxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 E0 /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmppxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 EA /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmppxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 EA /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpsxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 E8 /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpsxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 E8 /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "[lock|xacqrel] cmpxchg x:r8/m8, r8, " , "op": "MR: 0F B0 /r" , "ext": "I486" , "io": "OF=W SF=W ZF=W AF=W PF=W CF=W"}, - {"inst": "[lock|xacqrel] cmpxchg x:r16/m16, r16, " , "op": "MR: 66 0F B1 /r" , "ext": "I486" , "io": "OF=W SF=W ZF=W AF=W PF=W CF=W"}, - {"inst": "[lock|xacqrel] cmpxchg X:r32/m32, r32, " , "op": "MR: 0F B1 /r" , "ext": "I486" , "io": "OF=W SF=W ZF=W AF=W PF=W CF=W"}, - {"inst": "[lock|xacqrel] cmpxchg X:r64/m64, r64, " , "op": "MR: REX.W 0F B1 /r" , "ext": "I486" , "io": "OF=W SF=W ZF=W AF=W PF=W CF=W"}, - {"inst": "[lock|xacqrel] cmpxchg8b X:m64,X:,X:,," , "op": "0F C7 /1" , "ext": "CMPXCHG8B" , "io": "ZF=W"}, - {"inst": "[lock|xacqrel] cmpxchg16b X:m128,X:,X:,,","op": "REX.W 0F C7 /1" , "ext": "CMPXCHG16B" , "io": "ZF=W"}, - {"inst": "cmpzxadd X:m32, X:r32, R:r32" , "op": "VEX.128.66.0F38.W0 E4 /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cmpzxadd X:m64, X:r64, R:r64" , "op": "VEX.128.66.0F38.W1 E4 /r" , "ext": "CMPCCXADD" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, - {"inst": "cpuid X:, W:, X:, W:" , "op": "0F A2" , "ext": "I486" , "volatile": true}, - {"inst": "lahf w:" , "op": "9F" , "ext": "LAHFSAHF" , "io": "SF=R ZF=R AF=R PF=R CF=R"}, - {"inst": "lfence" , "op": "0F AE E8" , "ext": "SSE2"}, - {"inst": "lzcnt w:r16, r16/m16" , "op": "RM: 66 F3 0F BD /r" , "ext": "LZCNT" , "io": "OF=U SF=U ZF=W AF=U PF=U CF=W"}, - {"inst": "lzcnt W:r32, r32/m32" , "op": "RM: F3 0F BD /r" , "ext": "LZCNT" , "io": "OF=U SF=U ZF=W AF=U PF=U CF=W"}, - {"inst": "lzcnt W:r64, r64/m64" , "op": "RM: REX.W F3 0F BD /r" , "ext": "LZCNT" , "io": "OF=U SF=U ZF=W AF=U PF=U CF=W"}, - {"inst": "mcommit" , "op": "F3 0F 01 FA" , "ext": "MCOMMIT" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"}, - {"inst": "mfence" , "op": "0F AE F0" , "ext": "SSE2"}, - {"inst": "movbe w:r16, m16" , "op": "RM: 66 0F 38 F0 /r" , "ext": "MOVBE"}, - {"inst": "movbe W:r32, m32" , "op": "RM: 0F 38 F0 /r" , "ext": "MOVBE"}, - {"inst": "movbe W:r64, m64" , "op": "RM: REX.W 0F 38 F0 /r" , "ext": "MOVBE"}, - {"inst": "movbe W:m16, r16" , "op": "MR: 66 0F 38 F1 /r" , "ext": "MOVBE"}, - {"inst": "movbe W:m32, r32" , "op": "MR: 0F 38 F1 /r" , "ext": "MOVBE"}, - {"inst": "movbe W:m64, r64" , "op": "MR: REX.W 0F 38 F1 /r" , "ext": "MOVBE"}, - {"inst": "movdiri W:m32, r32" , "op": "MR: 0F 38 F9 /r" , "ext": "MOVDIRI"}, - {"inst": "movdiri W:m64, r64" , "op": "MR: REX.W 0F 38 F9 /r" , "ext": "MOVDIRI"}, - {"inst": "movdir64b W:m512(es:r32), m512" , "op": "RM: 66 0F 38 F8 /r" , "ext": "MOVDIR64B"}, - {"inst": "movdir64b W:m512(es:r64), m512" , "op": "RM: 66 0F 38 F8 /r" , "ext": "MOVDIR64B"}, - {"inst": "movnti W:m32, r32" , "op": "MR: 0F C3 /r" , "ext": "SSE2"}, - {"inst": "movnti W:m64, r64" , "op": "MR: REX.W 0F C3 /r" , "ext": "SSE2"}, - {"inst": "mulx W:r32, W:r32, ~r32/m32, ~" , "op": "RVM: VEX.LZ.F2.0F38.W0 F6 /r" , "ext": "BMI2"}, - {"inst": "mulx W:r64, W:r64, ~r64/m64, ~" , "op": "RVM: VEX.LZ.F2.0F38.W1 F6 /r" , "ext": "BMI2"}, - {"inst": "pdep W:r32, r32, r32/m32" , "op": "RVM: VEX.LZ.F2.0F38.W0 F5 /r" , "ext": "BMI2"}, - {"inst": "pdep W:r64, r64, r64/m64" , "op": "RVM: VEX.LZ.F2.0F38.W1 F5 /r" , "ext": "BMI2"}, - {"inst": "pext W:r32, r32, r32/m32" , "op": "RVM: VEX.LZ.F3.0F38.W0 F5 /r" , "ext": "BMI2"}, - {"inst": "pext W:r64, r64, r64/m64" , "op": "RVM: VEX.LZ.F3.0F38.W1 F5 /r" , "ext": "BMI2"}, - {"inst": "popcnt w:r16, r16/m16" , "op": "RM: 66 F3 0F B8 /r" , "ext": "POPCNT" , "io": "OF=0 SF=0 ZF=W AF=0 PF=0 CF=0"}, - {"inst": "popcnt W:r32, r32/m32" , "op": "RM: F3 0F B8 /r" , "ext": "POPCNT" , "io": "OF=0 SF=0 ZF=W AF=0 PF=0 CF=0"}, - {"inst": "popcnt W:r64, r64/m64" , "op": "RM: REX.W F3 0F B8 /r" , "ext": "POPCNT" , "io": "OF=0 SF=0 ZF=W AF=0 PF=0 CF=0"}, - {"inst": "prefetch R:mem" , "op": "0F 0D /0" , "ext": "3DNOW"}, - {"inst": "prefetchit0 R:mem" , "op": "0F 18 /7" , "ext": "PREFETCHI" , "arch": "X64"}, - {"inst": "prefetchit1 R:mem" , "op": "0F 18 /6" , "ext": "PREFETCHI" , "arch": "X64"}, - {"inst": "prefetchnta R:mem" , "op": "0F 18 /0" , "ext": "SSE"}, - {"inst": "prefetcht0 R:mem" , "op": "0F 18 /1" , "ext": "SSE"}, - {"inst": "prefetcht1 R:mem" , "op": "0F 18 /2" , "ext": "SSE"}, - {"inst": "prefetcht2 R:mem" , "op": "0F 18 /3" , "ext": "SSE"}, - {"inst": "prefetchw R:mem" , "op": "0F 0D /1" , "ext": "PREFETCHW" , "io": "OF=U SF=U ZF=U AF=U PF=U CF=U"}, - {"inst": "prefetchwt1 R:mem" , "op": "0F 0D /2" , "ext": "PREFETCHWT1", "io": "OF=U SF=U ZF=U AF=U PF=U CF=U"}, - {"inst": "ptwrite R:r32/m32" , "op": "F3 0F AE /4" , "ext": "PTWRITE"}, - {"inst": "ptwrite R:r64/m64" , "op": "REX.W F3 0F AE /4" , "ext": "PTWRITE"}, - {"inst": "rdpid W:r32" , "op": "R: F3 0F C7 /7" , "ext": "RDPID" , "arch": "X86"}, - {"inst": "rdpid W:r64" , "op": "R: F3 0F C7 /7" , "ext": "RDPID" , "arch": "X64"}, - {"inst": "rdpkru W:, W:, R:" , "op": "0F 01 EE" , "ext": "OSPKE"}, - {"inst": "rdpru W:, W:, R:" , "op": "0F 01 FD" , "ext": "RDPRU"}, - {"inst": "rdrand w:r16" , "op": "66 0F C7 /6" , "ext": "RDRAND" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"}, - {"inst": "rdrand W:r32" , "op": "0F C7 /6" , "ext": "RDRAND" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"}, - {"inst": "rdrand W:r64" , "op": "REX.W 0F C7 /6" , "ext": "RDRAND" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"}, - {"inst": "rdseed w:r16" , "op": "66 0F C7 /7" , "ext": "RDSEED" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"}, - {"inst": "rdseed W:r32" , "op": "0F C7 /7" , "ext": "RDSEED" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"}, - {"inst": "rdseed W:r64" , "op": "REX.W 0F C7 /7" , "ext": "RDSEED" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"}, - {"inst": "rdtsc W:, W:" , "op": "0F 31" , "ext": "RDTSC"}, - {"inst": "rdtscp W:, W:, W:" , "op": "0F 01 F9" , "ext": "RDTSCP"}, - {"inst": "rorx W:r32, r32/m32, ib/ub" , "op": "RM: VEX.LZ.F2.0F3A.W0 F0 /r ib" , "ext": "BMI2"}, - {"inst": "rorx W:r64, r64/m64, ib/ub" , "op": "RM: VEX.LZ.F2.0F3A.W1 F0 /r ib" , "ext": "BMI2"}, - {"inst": "sahf R:" , "op": "9E" , "ext": "LAHFSAHF" , "io": "SF=W ZF=W AF=W PF=W CF=W"}, - {"inst": "sarx W:r32, r32/m32, r32" , "op": "RMV: VEX.LZ.F3.0F38.W0 F7 /r" , "ext": "BMI2"}, - {"inst": "sarx W:r64, r64/m64, r64" , "op": "RMV: VEX.LZ.F3.0F38.W1 F7 /r" , "ext": "BMI2"}, - {"inst": "serialize" , "op": "0F 01 E8" , "ext": "SERIALIZE"}, - {"inst": "sfence" , "op": "0F AE F8" , "ext": "SSE"}, - {"inst": "shlx W:r32, r32/m32, r32" , "op": "RMV: VEX.LZ.66.0F38.W0 F7 /r" , "ext": "BMI2"}, - {"inst": "shlx W:r64, r64/m64, r64" , "op": "RMV: VEX.LZ.66.0F38.W1 F7 /r" , "ext": "BMI2"}, - {"inst": "shrx W:r32, r32/m32, r32" , "op": "RMV: VEX.LZ.F2.0F38.W0 F7 /r" , "ext": "BMI2"}, - {"inst": "shrx W:r64, r64/m64, r64" , "op": "RMV: VEX.LZ.F2.0F38.W1 F7 /r" , "ext": "BMI2"}, - {"inst": "tzcnt w:r16, r16/m16" , "op": "RM: 66 F3 0F BC /r" , "ext": "BMI" , "io": "OF=U SF=U ZF=W AF=U PF=U CF=W"}, - {"inst": "tzcnt W:r32, r32/m32" , "op": "RM: F3 0F BC /r" , "ext": "BMI" , "io": "OF=U SF=U ZF=W AF=U PF=U CF=W"}, - {"inst": "tzcnt W:r64, r64/m64" , "op": "RM: REX.W F3 0F BC /r" , "ext": "BMI" , "io": "OF=U SF=U ZF=W AF=U PF=U CF=W"}, - {"inst": "[lock|xacqrel] xadd x:r8/m8, x:r8" , "op": "MR: 0F C0 /r" , "ext": "I486" , "io": "OF=W SF=W ZF=W AF=W PF=W CF=W"}, - {"inst": "[lock|xacqrel] xadd x:r16/m16, x:r16" , "op": "MR: 66 0F C1 /r" , "ext": "I486" , "io": "OF=W SF=W ZF=W AF=W PF=W CF=W"}, - {"inst": "[lock|xacqrel] xadd X:r32/m32, X:r32" , "op": "MR: 0F C1 /r" , "ext": "I486" , "io": "OF=W SF=W ZF=W AF=W PF=W CF=W"}, - {"inst": "[lock|xacqrel] xadd X:r64/m64, X:r64" , "op": "MR: REX.W 0F C1 /r" , "ext": "I486" , "io": "OF=W SF=W ZF=W AF=W PF=W CF=W"} + {"category": "GP GP_EXT", "ext": "I486", "data": [ + {"inst": "[lock|xacqrel] cmpxchg x:r8/m8, r8, " , "op": "MR: 0F B0 /r" , "io": "OF=W SF=W ZF=W AF=W PF=W CF=W"}, + {"inst": "[lock|xacqrel] cmpxchg x:r16/m16, r16, " , "op": "MR: 66 0F B1 /r" , "io": "OF=W SF=W ZF=W AF=W PF=W CF=W"}, + {"inst": "[lock|xacqrel] cmpxchg X:r32/m32, r32, " , "op": "MR: 0F B1 /r" , "io": "OF=W SF=W ZF=W AF=W PF=W CF=W"}, + {"inst": "[lock|xacqrel] cmpxchg X:r64/m64, r64, " , "op": "MR: REX.W 0F B1 /r" , "io": "OF=W SF=W ZF=W AF=W PF=W CF=W"}, + {"inst": "cpuid X:, W:, X:, W:" , "op": "0F A2" , "volatile": true}, + {"inst": "[lock|xacqrel] xadd x:r8/m8, x:r8" , "op": "MR: 0F C0 /r" , "io": "OF=W SF=W ZF=W AF=W PF=W CF=W"}, + {"inst": "[lock|xacqrel] xadd x:r16/m16, x:r16" , "op": "MR: 66 0F C1 /r" , "io": "OF=W SF=W ZF=W AF=W PF=W CF=W"}, + {"inst": "[lock|xacqrel] xadd X:r32/m32, X:r32" , "op": "MR: 0F C1 /r" , "io": "OF=W SF=W ZF=W AF=W PF=W CF=W"}, + {"inst": "[lock|xacqrel] xadd X:r64/m64, X:r64" , "op": "MR: REX.W 0F C1 /r" , "io": "OF=W SF=W ZF=W AF=W PF=W CF=W"} ]}, - {"category": "GP GP_EXT CRYPTO_HASH", "data": [ - {"inst": "crc32 X:r32, r8/m8" , "op": "RM: F2 0F 38 F0 /r" , "ext": "SSE4_2"}, - {"inst": "crc32 X:r32, r16/m16" , "op": "RM: 66 F2 0F 38 F1 /r" , "ext": "SSE4_2"}, - {"inst": "crc32 X:r32, r32/m32" , "op": "RM: F2 0F 38 F1 /r" , "ext": "SSE4_2"}, - {"inst": "crc32 X:r64, r8/m8" , "op": "RM: REX.W F2 0F 38 F0 /r" , "ext": "SSE4_2"}, - {"inst": "crc32 X:r64, r64/m64" , "op": "RM: REX.W F2 0F 38 F1 /r" , "ext": "SSE4_2"} + {"category": "GP GP_EXT", "ext": "3DNOW", "volatile": true, "data": [ + {"inst": "prefetch R:mem" , "op": "0F 0D /0"} + ]}, + + {"category": "GP GP_EXT", "ext": "ADX", "data": [ + {"inst": "adcx X:~r32, ~r32/m32" , "op": "RM: 66 0F 38 F6 /r" , "io": "CF=X"}, + {"inst": "adcx X:~r64, ~r64/m64" , "op": "RM: REX.W 66 0F 38 F6 /r" , "io": "CF=X"}, + {"inst": "adox X:~r32, ~r32/m32" , "op": "RM: F3 0F 38 F6 /r" , "io": "OF=X"}, + {"inst": "adox X:~r64, ~r64/m64" , "op": "RM: REX.W F3 0F 38 F6 /r" , "io": "OF=X"} + ]}, + + {"category": "GP GP_EXT", "ext": "BMI", "data": [ + {"inst": "andn W:r32, r32, r32/m32" , "op": "RVM: VEX.LZ.0F38.W0 F2 /r" , "io": "OF=0 SF=W ZF=W AF=U PF=U CF=0"}, + {"inst": "andn W:r64, r64, r64/m64" , "op": "RVM: VEX.LZ.0F38.W1 F2 /r" , "io": "OF=0 SF=W ZF=W AF=U PF=U CF=0"}, + {"inst": "bextr W:r32, r32/m32, r32" , "op": "RMV: VEX.LZ.0F38.W0 F7 /r" , "io": "OF=0 SF=U ZF=W AF=U PF=U CF=0"}, + {"inst": "bextr W:r64, r64/m64, r64" , "op": "RMV: VEX.LZ.0F38.W1 F7 /r" , "io": "OF=0 SF=U ZF=W AF=U PF=U CF=0"}, + {"inst": "blsi W:r32, r32/m32" , "op": "VM: VEX.LZ.0F38.W0 F3 /3" , "io": "OF=0 SF=W ZF=W AF=U PF=U CF=W"}, + {"inst": "blsi W:r64, r64/m64" , "op": "VM: VEX.LZ.0F38.W1 F3 /3" , "io": "OF=0 SF=W ZF=W AF=U PF=U CF=W"}, + {"inst": "blsmsk W:r32, r32/m32" , "op": "VM: VEX.LZ.0F38.W0 F3 /2" , "io": "OF=0 SF=W ZF=0 AF=U PF=U CF=W"}, + {"inst": "blsmsk W:r64, r64/m64" , "op": "VM: VEX.LZ.0F38.W1 F3 /2" , "io": "OF=0 SF=W ZF=0 AF=U PF=U CF=W"}, + {"inst": "blsr W:r32, r32/m32" , "op": "VM: VEX.LZ.0F38.W0 F3 /1" , "io": "OF=0 SF=W ZF=W AF=U PF=U CF=W"}, + {"inst": "blsr W:r64, r64/m64" , "op": "VM: VEX.LZ.0F38.W1 F3 /1" , "io": "OF=0 SF=W ZF=W AF=U PF=U CF=W"}, + {"inst": "tzcnt w:r16, r16/m16" , "op": "RM: 66 F3 0F BC /r" , "io": "OF=U SF=U ZF=W AF=U PF=U CF=W"}, + {"inst": "tzcnt W:r32, r32/m32" , "op": "RM: F3 0F BC /r" , "io": "OF=U SF=U ZF=W AF=U PF=U CF=W"}, + {"inst": "tzcnt W:r64, r64/m64" , "op": "RM: REX.W F3 0F BC /r" , "io": "OF=U SF=U ZF=W AF=U PF=U CF=W"} + ]}, + + {"category": "GP GP_EXT", "ext": "BMI2", "data": [ + {"inst": "bzhi W:r32, r32/m32, r32" , "op": "RMV: VEX.LZ.0F38.W0 F5 /r" , "io": "OF=0 SF=W ZF=W AF=U PF=U CF=W"}, + {"inst": "bzhi W:r64, r64/m64, r64" , "op": "RMV: VEX.LZ.0F38.W1 F5 /r" , "io": "OF=0 SF=W ZF=W AF=U PF=U CF=W"}, + {"inst": "mulx W:r32, W:r32, ~r32/m32, ~" , "op": "RVM: VEX.LZ.F2.0F38.W0 F6 /r"}, + {"inst": "mulx W:r64, W:r64, ~r64/m64, ~" , "op": "RVM: VEX.LZ.F2.0F38.W1 F6 /r"}, + {"inst": "pdep W:r32, r32, r32/m32" , "op": "RVM: VEX.LZ.F2.0F38.W0 F5 /r"}, + {"inst": "pdep W:r64, r64, r64/m64" , "op": "RVM: VEX.LZ.F2.0F38.W1 F5 /r"}, + {"inst": "pext W:r32, r32, r32/m32" , "op": "RVM: VEX.LZ.F3.0F38.W0 F5 /r"}, + {"inst": "pext W:r64, r64, r64/m64" , "op": "RVM: VEX.LZ.F3.0F38.W1 F5 /r"}, + {"inst": "rorx W:r32, r32/m32, ib/ub" , "op": "RM: VEX.LZ.F2.0F3A.W0 F0 /r ib"}, + {"inst": "rorx W:r64, r64/m64, ib/ub" , "op": "RM: VEX.LZ.F2.0F3A.W1 F0 /r ib"}, + {"inst": "sarx W:r32, r32/m32, r32" , "op": "RMV: VEX.LZ.F3.0F38.W0 F7 /r"}, + {"inst": "sarx W:r64, r64/m64, r64" , "op": "RMV: VEX.LZ.F3.0F38.W1 F7 /r"}, + {"inst": "shlx W:r32, r32/m32, r32" , "op": "RMV: VEX.LZ.66.0F38.W0 F7 /r"}, + {"inst": "shlx W:r64, r64/m64, r64" , "op": "RMV: VEX.LZ.66.0F38.W1 F7 /r"}, + {"inst": "shrx W:r32, r32/m32, r32" , "op": "RMV: VEX.LZ.F2.0F38.W0 F7 /r"}, + {"inst": "shrx W:r64, r64/m64, r64" , "op": "RMV: VEX.LZ.F2.0F38.W1 F7 /r"} + ]}, + + {"category": "GP GP_EXT", "ext": "CET_SS", "volatile": true, "data": [ + {"inst": "incsspd r32" , "op": "F3 0F AE /5"}, + {"inst": "incsspq r64" , "op": "REX.W F3 0F AE /5"}, + {"inst": "rdsspd W:r32" , "op": "F3 0F 1E /1"}, + {"inst": "rdsspq W:r64" , "op": "REX.W F3 0F 1E /1"}, + {"inst": "rstorssp R:m64" , "op": "F3 0F 01 /5" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"}, + {"inst": "saveprevssp" , "op": "F3 0F 01 EA" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"} + ]}, + + {"category": "GP GP_EXT", "ext": "CLDEMOTE", "data": [ + {"inst": "cldemote R:mem" , "op": "0F 1C /0"} + ]}, + + {"category": "GP GP_EXT", "ext": "CLFLUSH", "data": [ + {"inst": "clflush R:mem" , "op": "0F AE /7"} + ]}, + + {"category": "GP GP_EXT", "ext": "CLFLUSHOPT", "data": [ + {"inst": "clflushopt R:mem" , "op": "66 0F AE /7"} + ]}, + + {"category": "GP GP_EXT", "ext": "CLWB", "data": [ + {"inst": "clwb R:mem" , "op": "66 0F AE /6"} + ]}, + + {"category": "GP GP_EXT", "ext": "CLZERO", "data": [ + {"inst": "clzero R:" , "op": "0F 01 FC"} + ]}, + + {"category": "GP GP_EXT", "ext": "CMOV", "data": [ + {"inst": "cmovo x:r16, r16/m16" , "op": "RM: 66 0F 40 /r" , "io": "OF=R"}, + {"inst": "cmovo X:r32, r32/m32" , "op": "RM: 0F 40 /r" , "io": "OF=R"}, + {"inst": "cmovo X:r64, r64/m64" , "op": "RM: REX.W 0F 40 /r" , "io": "OF=R"}, + {"inst": "cmovno x:r16, r16/m16" , "op": "RM: 66 0F 41 /r" , "io": "OF=R"}, + {"inst": "cmovno X:r32, r32/m32" , "op": "RM: 0F 41 /r" , "io": "OF=R"}, + {"inst": "cmovno X:r64, r64/m64" , "op": "RM: REX.W 0F 41 /r" , "io": "OF=R"}, + {"inst": "cmovb|cmovnae|cmovc x:r16, r16/m16" , "op": "RM: 66 0F 42 /r" , "io": "CF=R"}, + {"inst": "cmovb|cmovnae|cmovc X:r32, r32/m32" , "op": "RM: 0F 42 /r" , "io": "CF=R"}, + {"inst": "cmovb|cmovnae|cmovc X:r64, r64/m64" , "op": "RM: REX.W 0F 42 /r" , "io": "CF=R"}, + {"inst": "cmovae|cmovnb|cmovnc x:r16, r16/m16" , "op": "RM: 66 0F 43 /r" , "io": "CF=R"}, + {"inst": "cmovae|cmovnb|cmovnc X:r32, r32/m32" , "op": "RM: 0F 43 /r" , "io": "CF=R"}, + {"inst": "cmovae|cmovnb|cmovnc X:r64, r64/m64" , "op": "RM: REX.W 0F 43 /r" , "io": "CF=R"}, + {"inst": "cmove|cmovz x:r16, r16/m16" , "op": "RM: 66 0F 44 /r" , "io": "ZF=R"}, + {"inst": "cmove|cmovz X:r32, r32/m32" , "op": "RM: 0F 44 /r" , "io": "ZF=R"}, + {"inst": "cmove|cmovz X:r64, r64/m64" , "op": "RM: REX.W 0F 44 /r" , "io": "ZF=R"}, + {"inst": "cmovne|cmovnz x:r16, r16/m16" , "op": "RM: 66 0F 45 /r" , "io": "ZF=R"}, + {"inst": "cmovne|cmovnz X:r32, r32/m32" , "op": "RM: 0F 45 /r" , "io": "ZF=R"}, + {"inst": "cmovne|cmovnz X:r64, r64/m64" , "op": "RM: REX.W 0F 45 /r" , "io": "ZF=R"}, + {"inst": "cmovbe|cmovna x:r16, r16/m16" , "op": "RM: 66 0F 46 /r" , "io": "CF=R ZF=R"}, + {"inst": "cmovbe|cmovna X:r32, r32/m32" , "op": "RM: 0F 46 /r" , "io": "CF=R ZF=R"}, + {"inst": "cmovbe|cmovna X:r64, r64/m64" , "op": "RM: REX.W 0F 46 /r" , "io": "CF=R ZF=R"}, + {"inst": "cmova|cmovnbe x:r16, r16/m16" , "op": "RM: 66 0F 47 /r" , "io": "CF=R ZF=R"}, + {"inst": "cmova|cmovnbe X:r32, r32/m32" , "op": "RM: 0F 47 /r" , "io": "CF=R ZF=R"}, + {"inst": "cmova|cmovnbe X:r64, r64/m64" , "op": "RM: REX.W 0F 47 /r" , "io": "CF=R ZF=R"}, + {"inst": "cmovs x:r16, r16/m16" , "op": "RM: 66 0F 48 /r" , "io": "SF=R"}, + {"inst": "cmovs X:r32, r32/m32" , "op": "RM: 0F 48 /r" , "io": "SF=R"}, + {"inst": "cmovs X:r64, r64/m64" , "op": "RM: REX.W 0F 48 /r" , "io": "SF=R"}, + {"inst": "cmovns x:r16, r16/m16" , "op": "RM: 66 0F 49 /r" , "io": "SF=R"}, + {"inst": "cmovns X:r32, r32/m32" , "op": "RM: 0F 49 /r" , "io": "SF=R"}, + {"inst": "cmovns X:r64, r64/m64" , "op": "RM: REX.W 0F 49 /r" , "io": "SF=R"}, + {"inst": "cmovp|cmovpe x:r16, r16/m16" , "op": "RM: 66 0F 4A /r" , "io": "PF=R"}, + {"inst": "cmovp|cmovpe X:r32, r32/m32" , "op": "RM: 0F 4A /r" , "io": "PF=R"}, + {"inst": "cmovp|cmovpe X:r64, r64/m64" , "op": "RM: REX.W 0F 4A /r" , "io": "PF=R"}, + {"inst": "cmovnp|cmovpo x:r16, r16/m16" , "op": "RM: 66 0F 4B /r" , "io": "PF=R"}, + {"inst": "cmovnp|cmovpo X:r32, r32/m32" , "op": "RM: 0F 4B /r" , "io": "PF=R"}, + {"inst": "cmovnp|cmovpo X:r64, r64/m64" , "op": "RM: REX.W 0F 4B /r" , "io": "PF=R"}, + {"inst": "cmovl|cmovnge x:r16, r16/m16" , "op": "RM: 66 0F 4C /r" , "io": "SF=R OF=R"}, + {"inst": "cmovl|cmovnge X:r32, r32/m32" , "op": "RM: 0F 4C /r" , "io": "SF=R OF=R"}, + {"inst": "cmovl|cmovnge X:r64, r64/m64" , "op": "RM: REX.W 0F 4C /r" , "io": "SF=R OF=R"}, + {"inst": "cmovge|cmovnl x:r16, r16/m16" , "op": "RM: 66 0F 4D /r" , "io": "SF=R OF=R"}, + {"inst": "cmovge|cmovnl X:r32, r32/m32" , "op": "RM: 0F 4D /r" , "io": "SF=R OF=R"}, + {"inst": "cmovge|cmovnl X:r64, r64/m64" , "op": "RM: REX.W 0F 4D /r" , "io": "SF=R OF=R"}, + {"inst": "cmovle|cmovng x:r16, r16/m16" , "op": "RM: 66 0F 4E /r" , "io": "ZF=R SF=R OF=R"}, + {"inst": "cmovle|cmovng X:r32, r32/m32" , "op": "RM: 0F 4E /r" , "io": "ZF=R SF=R OF=R"}, + {"inst": "cmovle|cmovng X:r64, r64/m64" , "op": "RM: REX.W 0F 4E /r" , "io": "ZF=R SF=R OF=R"}, + {"inst": "cmovg|cmovnle x:r16, r16/m16" , "op": "RM: 66 0F 4F /r" , "io": "ZF=R SF=R OF=R"}, + {"inst": "cmovg|cmovnle X:r32, r32/m32" , "op": "RM: 0F 4F /r" , "io": "ZF=R SF=R OF=R"}, + {"inst": "cmovg|cmovnle X:r64, r64/m64" , "op": "RM: REX.W 0F 4F /r" , "io": "ZF=R SF=R OF=R"} + ]}, + + {"category": "GP GP_EXT", "ext": "CMPCCXADD", "data": [ + {"inst": "cmpbexadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 E6 /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpbexadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 E6 /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpbxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 E2 /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpbxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 E2 /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmplexadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 EE /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmplexadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 EE /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmplxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 EC /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmplxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 EC /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpnbexadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 E7 /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpnbexadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 E7 /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpnbxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 E3 /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpnbxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 E3 /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpnlexadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 EF /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpnlexadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 EF /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpnlxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 ED /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpnlxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 ED /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpnoxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 E1 /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpnoxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 E1 /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpnpxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 EB /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpnpxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 EB /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpnsxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 E9 /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpnsxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 E9 /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpnzxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 E5 /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpnzxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 E5 /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpoxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 E0 /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpoxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 E0 /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmppxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 EA /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmppxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 EA /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpsxadd X:m32, X:r32, R:r32" , "op": "MVR: VEX.128.66.0F38.W0 E8 /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpsxadd X:m64, X:r64, R:r64" , "op": "MVR: VEX.128.66.0F38.W1 E8 /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpzxadd X:m32, X:r32, R:r32" , "op": "VEX.128.66.0F38.W0 E4 /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"}, + {"inst": "cmpzxadd X:m64, X:r64, R:r64" , "op": "VEX.128.66.0F38.W1 E4 /r" , "io": "CF=W OF=W SF=W ZF=W AF=W PF=W"} + ]}, + + {"category": "GP GP_EXT", "ext": "CMPXCHG8B", "data": [ + {"inst": "[lock|xacqrel] cmpxchg8b X:m64,X:,X:,," , "op": "0F C7 /1" , "io": "ZF=W"} + ]}, + + {"category": "GP GP_EXT", "ext": "CMPXCHG16B", "data": [ + {"inst": "[lock|xacqrel] cmpxchg16b X:m128,X:,X:,,","op": "REX.W 0F C7 /1" , "io": "ZF=W"} + ]}, + + {"category": "GP GP_EXT", "ext": "FSGSBASE", "arch": "X64", "volatile": true, "data": [ + {"inst": "rdfsbase W:r32" , "op": "F3 0F AE /0"}, + {"inst": "rdfsbase W:r64" , "op": "REX.W F3 0F AE /0"}, + {"inst": "rdgsbase W:r32" , "op": "F3 0F AE /1"}, + {"inst": "rdgsbase W:r64" , "op": "REX.W F3 0F AE /1"}, + {"inst": "wrfsbase R:r32" , "op": "F3 0F AE /2"}, + {"inst": "wrfsbase R:r64" , "op": "REX.W F3 0F AE /2"}, + {"inst": "wrgsbase R:r32" , "op": "F3 0F AE /3"}, + {"inst": "wrgsbase R:r64" , "op": "REX.W F3 0F AE /3"} + ]}, + + {"category": "GP GP_EXT", "ext": "FXSR", "volatile": true, "data": [ + {"inst": "fxrstor R:mem" , "op": "0F AE /1" , "io": "C0=W C1=W C2=W C3=W"}, + {"inst": "fxrstor64 R:mem" , "op": "REX.W 0F AE /1" , "io": "C0=W C1=W C2=W C3=W"}, + {"inst": "fxsave W:mem" , "op": "0F AE /0" , "io": "C0=R C1=R C2=R C3=R"}, + {"inst": "fxsave64 W:mem" , "op": "REX.W 0F AE /0" , "io": "C0=R C1=R C2=R C3=R"} + ]}, + + {"category": "GP GP_EXT", "ext": "LAHFSAHF", "data": [ + {"inst": "lahf w:" , "op": "9F" , "io": "SF=R ZF=R AF=R PF=R CF=R"}, + {"inst": "sahf R:" , "op": "9E" , "io": "SF=W ZF=W AF=W PF=W CF=W"} + ]}, + + {"category": "GP GP_EXT", "ext": "LWP", "volatile": true, "data": [ + {"inst": "llwpcb R:r32" , "op": "XOP.L0.P0.M09.W0 12 /0"}, + {"inst": "llwpcb R:r64" , "op": "XOP.L0.P0.M09.W1 12 /0"}, + {"inst": "lwpins R:r32, R:r32/m32, id/ud" , "op": "VM: XOP.L0.P0.M0A.W0 12 /0 id"}, + {"inst": "lwpins R:r64, R:r32/m32, id/ud" , "op": "VM: XOP.L0.P0.M0A.W1 12 /0 id"}, + {"inst": "lwpval R:r32, R:r32/m32, id/ud" , "op": "VM: XOP.L0.P0.M0A.W0 12 /1 id"}, + {"inst": "lwpval R:r64, R:r32/m32, id/ud" , "op": "VM: XOP.L0.P0.M0A.W1 12 /1 id"}, + {"inst": "slwpcb W:r32" , "op": "XOP.L0.P0.M09.W0 12 /1"}, + {"inst": "slwpcb W:r64" , "op": "XOP.L0.P0.M09.W1 12 /1"} + ]}, + + {"category": "GP GP_EXT", "ext": "LZCNT", "data": [ + {"inst": "lzcnt w:r16, r16/m16" , "op": "RM: 66 F3 0F BD /r" , "io": "OF=U SF=U ZF=W AF=U PF=U CF=W"}, + {"inst": "lzcnt W:r32, r32/m32" , "op": "RM: F3 0F BD /r" , "io": "OF=U SF=U ZF=W AF=U PF=U CF=W"}, + {"inst": "lzcnt W:r64, r64/m64" , "op": "RM: REX.W F3 0F BD /r" , "io": "OF=U SF=U ZF=W AF=U PF=U CF=W"} + ]}, + + {"category": "GP GP_EXT", "ext": "MONITORX", "volatile": true, "data": [ + {"inst": "monitorx R:, R:, R:" , "op": "0F 01 FA"}, + {"inst": "mwaitx R:, R:, R:" , "op": "0F 01 FB"} + ]}, + + {"category": "GP GP_EXT", "ext": "MCOMMIT", "data": [ + {"inst": "mcommit" , "op": "F3 0F 01 FA" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"} + ]}, + + {"category": "GP GP_EXT", "ext": "MOVBE", "data": [ + {"inst": "movbe w:r16, m16" , "op": "RM: 66 0F 38 F0 /r"}, + {"inst": "movbe W:r32, m32" , "op": "RM: 0F 38 F0 /r"}, + {"inst": "movbe W:r64, m64" , "op": "RM: REX.W 0F 38 F0 /r"}, + {"inst": "movbe W:m16, r16" , "op": "MR: 66 0F 38 F1 /r"}, + {"inst": "movbe W:m32, r32" , "op": "MR: 0F 38 F1 /r"}, + {"inst": "movbe W:m64, r64" , "op": "MR: REX.W 0F 38 F1 /r"} + ]}, + + {"category": "GP GP_EXT", "ext": "MOVDIRI", "data": [ + {"inst": "movdiri W:m32, r32" , "op": "MR: 0F 38 F9 /r"}, + {"inst": "movdiri W:m64, r64" , "op": "MR: REX.W 0F 38 F9 /r"} + ]}, + + {"category": "GP GP_EXT", "ext": "MOVDIR64B", "data": [ + {"inst": "movdir64b W:m512(es:r32), m512" , "op": "RM: 66 0F 38 F8 /r"}, + {"inst": "movdir64b W:m512(es:r64), m512" , "op": "RM: 66 0F 38 F8 /r"} + ]}, + + {"category": "GP GP_EXT", "ext": "PCONFIG", "volatile": true, "data": [ + {"inst": "pconfig" , "op": "0F 01 C5"} + ]}, + + {"category": "GP GP_EXT", "ext": "POPCNT", "data": [ + {"inst": "popcnt w:r16, r16/m16" , "op": "RM: 66 F3 0F B8 /r" , "io": "OF=0 SF=0 ZF=W AF=0 PF=0 CF=0"}, + {"inst": "popcnt W:r32, r32/m32" , "op": "RM: F3 0F B8 /r" , "io": "OF=0 SF=0 ZF=W AF=0 PF=0 CF=0"}, + {"inst": "popcnt W:r64, r64/m64" , "op": "RM: REX.W F3 0F B8 /r" , "io": "OF=0 SF=0 ZF=W AF=0 PF=0 CF=0"} + ]}, + + {"category": "GP GP_EXT", "ext": "OSPKE", "data": [ + {"inst": "rdpkru W:, W:, R:" , "op": "0F 01 EE"} + ]}, + + {"category": "GP GP_EXT", "ext": "PREFETCHI", "arch": "X64", "volatile": true, "data": [ + {"inst": "prefetchit0 R:mem" , "op": "0F 18 /7"}, + {"inst": "prefetchit1 R:mem" , "op": "0F 18 /6"} + ]}, + + {"category": "GP GP_EXT", "ext": "PREFETCHW", "volatile": true, "data": [ + {"inst": "prefetchw R:mem" , "op": "0F 0D /1" , "io": "OF=U SF=U ZF=U AF=U PF=U CF=U"} + ]}, + + {"category": "GP GP_EXT", "ext": "PREFETCHWT1", "volatile": true, "data": [ + {"inst": "prefetchwt1 R:mem" , "op": "0F 0D /2" , "io": "OF=U SF=U ZF=U AF=U PF=U CF=U"} + ]}, + + {"category": "GP GP_EXT", "ext": "PTWRITE", "volatile": true, "data": [ + {"inst": "ptwrite R:r32/m32" , "op": "F3 0F AE /4"}, + {"inst": "ptwrite R:r64/m64" , "op": "REX.W F3 0F AE /4"} + ]}, + + {"category": "GP GP_EXT", "ext": "RAO_INT", "volatile": true, "data": [ + {"inst": "aadd X:m32, r32" , "op": "MR: 0F 38 FC /r"}, + {"inst": "aadd X:m64, r64" , "op": "MR: REX.W 0F 38 FC /r"}, + {"inst": "aand X:m32, r32" , "op": "MR: 66 0F 38 FC /r"}, + {"inst": "aand X:m64, r64" , "op": "MR: REX.W 66 0F 38 FC /r"}, + {"inst": "aor X:m32, r32" , "op": "MR: F2 0F 38 FC /r"}, + {"inst": "aor X:m64, r64" , "op": "MR: REX.W F2 0F 38 FC /r"}, + {"inst": "axor X:m32, r32" , "op": "MR: F3 0F 38 FC /r"}, + {"inst": "axor X:m64, r64" , "op": "MR: REX.W F3 0F 38 FC /r"} + ]}, + + {"category": "GP GP_EXT", "ext": "RDPID", "data": [ + {"inst": "rdpid W:r32" , "op": "R: F3 0F C7 /7" , "arch": "X86"}, + {"inst": "rdpid W:r64" , "op": "R: F3 0F C7 /7" , "arch": "X64"} + ]}, + + {"category": "GP GP_EXT", "ext": "RDPRU", "data": [ + {"inst": "rdpru W:, W:, R:" , "op": "0F 01 FD"} + ]}, + + {"category": "GP GP_EXT", "ext": "RDRAND", "data": [ + {"inst": "rdrand w:r16" , "op": "66 0F C7 /6" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"}, + {"inst": "rdrand W:r32" , "op": "0F C7 /6" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"}, + {"inst": "rdrand W:r64" , "op": "REX.W 0F C7 /6" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"} + ]}, + + {"category": "GP GP_EXT", "ext": "RDSEED", "data": [ + {"inst": "rdseed w:r16" , "op": "66 0F C7 /7" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"}, + {"inst": "rdseed W:r32" , "op": "0F C7 /7" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"}, + {"inst": "rdseed W:r64" , "op": "REX.W 0F C7 /7" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"} + ]}, + + {"category": "GP GP_EXT", "ext": "RDTSC", "data": [ + {"inst": "rdtsc W:, W:" , "op": "0F 31"} + ]}, + + {"category": "GP GP_EXT", "ext": "RDTSCP", "data": [ + {"inst": "rdtscp W:, W:, W:" , "op": "0F 01 F9"} + ]}, + + {"category": "GP GP_EXT", "ext": "RTM", "volatile": true, "data": [ + {"inst": "xabort ib/ub" , "op": "C6 /7 ib"}, + {"inst": "xbegin rel16" , "op": "66 C7 /7 cw"}, + {"inst": "xbegin rel32" , "op": "C7 /7 cd"}, + {"inst": "xend" , "op": "0F 01 D5"} + ]}, + + {"category": "GP GP_EXT", "ext": "SERIALIZE", "volatile": true, "data": [ + {"inst": "serialize" , "op": "0F 01 E8"} + ]}, + + {"category": "GP GP_EXT", "ext": "SSE", "volatile": true, "data": [ + {"inst": "prefetchnta R:mem" , "op": "0F 18 /0"}, + {"inst": "prefetcht0 R:mem" , "op": "0F 18 /1"}, + {"inst": "prefetcht1 R:mem" , "op": "0F 18 /2"}, + {"inst": "prefetcht2 R:mem" , "op": "0F 18 /3"}, + {"inst": "sfence" , "op": "0F AE F8"} + ]}, + + {"category": "GP GP_EXT", "ext": "SSE2", "volatile": true, "data": [ + {"inst": "lfence" , "op": "0F AE E8"}, + {"inst": "mfence" , "op": "0F AE F0"}, + {"inst": "movnti W:m32, r32" , "op": "MR: 0F C3 /r"}, + {"inst": "movnti W:m64, r64" , "op": "MR: REX.W 0F C3 /r"} + ]}, + + {"category": "GP GP_EXT CRYPTO_HASH", "ext": "SSE4_2", "data": [ + {"inst": "crc32 X:r32, r8/m8" , "op": "RM: F2 0F 38 F0 /r"}, + {"inst": "crc32 X:r32, r16/m16" , "op": "RM: 66 F2 0F 38 F1 /r"}, + {"inst": "crc32 X:r32, r32/m32" , "op": "RM: F2 0F 38 F1 /r"}, + {"inst": "crc32 X:r64, r8/m8" , "op": "RM: REX.W F2 0F 38 F0 /r"}, + {"inst": "crc32 X:r64, r64/m64" , "op": "RM: REX.W F2 0F 38 F1 /r"} + ]}, + + {"category": "GP GP_EXT", "ext": "TSE", "arch": "X64", "volatile": true, "data": [ + {"inst": "pbndkb W:, R:, W:" , "op": "0F 01 C7" , "io": "OF=0 SF=0 ZF=W AF=0 PF=0 CF=0"} + ]}, + + {"category": "GP GP_EXT", "ext": "TSX", "volatile": true, "data": [ + {"inst": "xtest" , "op": "0F 01 D6" , "io": "OF=0 SF=0 ZF=W AF=0 PF=0 CF=0"} + ]}, + + {"category": "GP GP_EXT", "ext": "TSXLDTRK", "volatile": true, "data": [ + {"inst": "xresldtrk" , "op": "F2 0F 01 E9"}, + {"inst": "xsusldtrk" , "op": "F2 0F 01 E8"} + ]}, + + {"category": "GP GP_EXT", "ext": "UINTR", "arch": "X64", "volatile": true, "data": [ + {"inst": "uiret" , "op": "F3 0F 01 EC"}, + {"inst": "clui" , "op": "F3 0F 01 EE"}, + {"inst": "stui" , "op": "F3 0F 01 EF"}, + {"inst": "testui" , "op": "F3 0F 01 ED" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"}, + {"inst": "senduipi R:r64" , "op": "R: F3 0F C7 /6"} + ]}, + + {"category": "GP GP_EXT", "ext": "WAITPKG", "volatile": true, "data": [ + {"inst": "tpause R:r32, , " , "op": "66 0F AE /6" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"}, + {"inst": "umonitor R:mem(ds:r32)" , "op": "F3 0F AE /6" , "arch": "X86"}, + {"inst": "umonitor R:mem(ds:r64)" , "op": "F3 0F AE /6" , "arch": "X64"}, + {"inst": "umwait R:r32, , " , "op": "F2 0F AE /6" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"} + ]}, + + {"category": "GP GP_EXT", "ext": "XSAVE", "volatile": true, "data": [ + {"inst": "xgetbv W:, W:, R:" , "op": "0F 01 D0" , "io": "XCR=R"}, + {"inst": "xrstor R:mem, , " , "op": "0F AE /5" , "io": "XCR=R"}, + {"inst": "xrstor64 R:mem, , " , "op": "REX.W 0F AE /5" , "io": "XCR=R"}, + {"inst": "xsave W:mem, , " , "op": "0F AE /4" , "io": "XCR=R"}, + {"inst": "xsave64 W:mem, , " , "op": "REX.W 0F AE /4" , "io": "XCR=R"} + ]}, + + {"category": "GP GP_EXT", "ext": "XSAVEC", "volatile": true, "data": [ + {"inst": "xsavec W:mem, , " , "op": "0F C7 /4" , "io": "XCR=R"}, + {"inst": "xsavec64 W:mem, , " , "op": "REX.W 0F C7 /4" , "io": "XCR=R"} + ]}, + + {"category": "GP GP_EXT", "ext": "XSAVEOPT", "volatile": true, "data": [ + {"inst": "xsaveopt W:mem, , " , "op": "0F AE /6" , "io": "XCR=R"}, + {"inst": "xsaveopt64 W:mem, , " , "op": "REX.W 0F AE /6" , "io": "XCR=R"} ]}, {"category": "GP", "volatile": true, "data": [ @@ -863,21 +1068,35 @@ {"inst": "xlatb" , "op": "D7"} ]}, - {"category": "GP", "deprecated": true, "data": [ - {"inst": "aaa x:" , "op": "37" , "arch": "X86", "io": "OF=U SF=U ZF=U AF=W PF=U CF=W"}, - {"inst": "aas x:" , "op": "3F" , "arch": "X86", "io": "OF=U SF=U ZF=U AF=W PF=U CF=W"}, - {"inst": "aad x:, ib/ub" , "op": "D5 ib" , "arch": "X86", "io": "OF=U SF=W ZF=W AF=U PF=W CF=U"}, - {"inst": "aam x:, ib/ub" , "op": "D4 ib" , "arch": "X86", "io": "OF=U SF=W ZF=W AF=U PF=W CF=U"}, - {"inst": "arpl x:r16/m16, R:r16" , "op": "MR: 63 /r" , "arch": "X86", "io": "ZF=W"}, - {"inst": "bound R:r16, R:m32" , "op": "RM: 66 62 /r" , "arch": "X86"}, - {"inst": "bound R:r32, R:m64" , "op": "RM: 62 /r" , "arch": "X86"}, - {"inst": "daa x:" , "op": "27" , "arch": "X86", "io": "OF=U SF=W ZF=W AF=W PF=W CF=W"}, - {"inst": "das x:" , "op": "2F" , "arch": "X86", "io": "OF=U SF=W ZF=W AF=W PF=W CF=W"}, - {"inst": "into" , "op": "CE" , "arch": "X86", "io": "OF=R"}, - {"inst": "popa" , "op": "66 61" , "arch": "X86"}, - {"inst": "popad" , "op": "61" , "arch": "X86"}, - {"inst": "pusha" , "op": "66 60" , "arch": "X86"}, - {"inst": "pushad" , "op": "60" , "arch": "X86"} + {"category": "GP", "deprecated": true, "arch": "X86", "data": [ + {"inst": "aaa x:" , "op": "37" , "io": "OF=U SF=U ZF=U AF=W PF=U CF=W"}, + {"inst": "aas x:" , "op": "3F" , "io": "OF=U SF=U ZF=U AF=W PF=U CF=W"}, + {"inst": "aad x:, ib/ub" , "op": "D5 ib" , "io": "OF=U SF=W ZF=W AF=U PF=W CF=U"}, + {"inst": "aam x:, ib/ub" , "op": "D4 ib" , "io": "OF=U SF=W ZF=W AF=U PF=W CF=U"}, + {"inst": "arpl x:r16/m16, R:r16" , "op": "MR: 63 /r" , "io": "ZF=W"}, + {"inst": "bound R:r16, R:m32" , "op": "RM: 66 62 /r"}, + {"inst": "bound R:r32, R:m64" , "op": "RM: 62 /r"}, + {"inst": "daa x:" , "op": "27" , "io": "OF=U SF=W ZF=W AF=W PF=W CF=W"}, + {"inst": "das x:" , "op": "2F" , "io": "OF=U SF=W ZF=W AF=W PF=W CF=W"}, + {"inst": "into" , "op": "CE" , "io": "OF=R"}, + {"inst": "popa" , "op": "66 61"}, + {"inst": "popad" , "op": "61"}, + {"inst": "pusha" , "op": "66 60"}, + {"inst": "pushad" , "op": "60"} + ]}, + + {"category": "GP GP_EXT", "ext": "MPX", "deprecated": true, "data": [ + {"inst": "bndcl R:bnd, r32/m32" , "op": "RM: F3 0F 1A /r" , "arch": "X86"}, + {"inst": "bndcl R:bnd, r64/m64" , "op": "RM: F3 0F 1A /r" , "arch": "X64"}, + {"inst": "bndcn R:bnd, r32/m32" , "op": "RM: F2 0F 1B /r" , "arch": "X86"}, + {"inst": "bndcn R:bnd, r64/m64" , "op": "RM: F2 0F 1B /r" , "arch": "X64"}, + {"inst": "bndcu R:bnd, r32/m32" , "op": "RM: F2 0F 1A /r" , "arch": "X86"}, + {"inst": "bndcu R:bnd, r64/m64" , "op": "RM: F2 0F 1A /r" , "arch": "X64"}, + {"inst": "bndldx W:bnd, mib" , "op": "RM: 0F 1A /r"}, + {"inst": "bndmk W:bnd, mem" , "op": "RM: F3 0F 1B /r"}, + {"inst": "bndmov W:bnd, bnd/mem" , "op": "RM: 66 0F 1A /r"}, + {"inst": "bndmov W:bnd/mem, bnd" , "op": "MR: 66 0F 1B /r"}, + {"inst": "bndstx W:mib, bnd" , "op": "MR: 0F 1B /r"} ]}, {"category": "GP GP_EXT", "ext": "TBM", "deprecated": true, "data": [ @@ -901,141 +1120,84 @@ {"inst": "t1mskc W:r64, r64/m64" , "op": "VM: XOP.LZ.M09.W1 01 /7"} ]}, - {"category": "GP GP_EXT", "ext": "MPX", "deprecated": true, "data": [ - {"inst": "bndcl R:bnd, r32/m32" , "op": "RM: F3 0F 1A /r" , "arch": "X86"}, - {"inst": "bndcl R:bnd, r64/m64" , "op": "RM: F3 0F 1A /r" , "arch": "X64"}, - {"inst": "bndcn R:bnd, r32/m32" , "op": "RM: F2 0F 1B /r" , "arch": "X86"}, - {"inst": "bndcn R:bnd, r64/m64" , "op": "RM: F2 0F 1B /r" , "arch": "X64"}, - {"inst": "bndcu R:bnd, r32/m32" , "op": "RM: F2 0F 1A /r" , "arch": "X86"}, - {"inst": "bndcu R:bnd, r64/m64" , "op": "RM: F2 0F 1A /r" , "arch": "X64"}, - {"inst": "bndldx W:bnd, mib" , "op": "RM: 0F 1A /r"}, - {"inst": "bndmk W:bnd, mem" , "op": "RM: F3 0F 1B /r"}, - {"inst": "bndmov W:bnd, bnd/mem" , "op": "RM: 66 0F 1A /r"}, - {"inst": "bndmov W:bnd/mem, bnd" , "op": "MR: 66 0F 1B /r"}, - {"inst": "bndstx W:mib, bnd" , "op": "MR: 0F 1B /r"} - ]}, - - {"category": "GP GP_EXT", "volatile": true, "data": [ - {"inst": "fxrstor R:mem" , "op": "0F AE /1" , "ext": "FXSR" , "io": "C0=W C1=W C2=W C3=W"}, - {"inst": "fxrstor64 R:mem" , "op": "REX.W 0F AE /1" , "ext": "FXSR" , "io": "C0=W C1=W C2=W C3=W"}, - {"inst": "fxsave W:mem" , "op": "0F AE /0" , "ext": "FXSR" , "io": "C0=R C1=R C2=R C3=R"}, - {"inst": "fxsave64 W:mem" , "op": "REX.W 0F AE /0" , "ext": "FXSR" , "io": "C0=R C1=R C2=R C3=R"}, - {"inst": "xgetbv W:, W:, R:" , "op": "0F 01 D0" , "ext": "XSAVE" , "io": "XCR=R"}, - {"inst": "xrstor R:mem, , " , "op": "0F AE /5" , "ext": "XSAVE" , "io": "XCR=R"}, - {"inst": "xrstor64 R:mem, , " , "op": "REX.W 0F AE /5" , "ext": "XSAVE" , "io": "XCR=R"}, - {"inst": "xsave W:mem, , " , "op": "0F AE /4" , "ext": "XSAVE" , "io": "XCR=R"}, - {"inst": "xsave64 W:mem, , " , "op": "REX.W 0F AE /4" , "ext": "XSAVE" , "io": "XCR=R"}, - {"inst": "xsavec W:mem, , " , "op": "0F C7 /4" , "ext": "XSAVEC" , "io": "XCR=R"}, - {"inst": "xsavec64 W:mem, , " , "op": "REX.W 0F C7 /4" , "ext": "XSAVEC" , "io": "XCR=R"}, - {"inst": "xsaveopt W:mem, , " , "op": "0F AE /6" , "ext": "XSAVEOPT", "io": "XCR=R"}, - {"inst": "xsaveopt64 W:mem, , " , "op": "REX.W 0F AE /6" , "ext": "XSAVEOPT", "io": "XCR=R"} - ]}, - - {"category": "GP GP_EXT", "volatile": true, "data": [ - {"inst": "incsspd r32" , "op": "F3 0F AE /5" , "ext": "CET_SS"}, - {"inst": "incsspq r64" , "op": "REX.W F3 0F AE /5" , "ext": "CET_SS"}, - {"inst": "monitorx R:, R:, R:" , "op": "0F 01 FA" , "ext": "MONITORX"}, - {"inst": "mwaitx R:, R:, R:" , "op": "0F 01 FB" , "ext": "MONITORX"}, - {"inst": "rdsspd W:r32" , "op": "F3 0F 1E /1" , "ext": "CET_SS"}, - {"inst": "rdsspq W:r64" , "op": "REX.W F3 0F 1E /1" , "ext": "CET_SS"}, - {"inst": "rstorssp R:m64" , "op": "F3 0F 01 /5" , "ext": "CET_SS" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"}, - {"inst": "saveprevssp" , "op": "F3 0F 01 EA" , "ext": "CET_SS" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"}, - {"inst": "tpause R:r32, , " , "op": "66 0F AE /6" , "ext": "WAITPKG" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"}, - {"inst": "umonitor R:mem(ds:r32)" , "op": "F3 0F AE /6" , "ext": "WAITPKG" , "arch": "X86"}, - {"inst": "umonitor R:mem(ds:r64)" , "op": "F3 0F AE /6" , "ext": "WAITPKG" , "arch": "X64"}, - {"inst": "umwait R:r32, , " , "op": "F2 0F AE /6" , "ext": "WAITPKG" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"} - ]}, - - {"category": "GP GP_EXT", "ext": "LWP", "volatile": true, "data": [ - {"inst": "llwpcb R:r32" , "op": "XOP.L0.P0.M09.W0 12 /0"}, - {"inst": "llwpcb R:r64" , "op": "XOP.L0.P0.M09.W1 12 /0"}, - {"inst": "lwpins R:r32, R:r32/m32, id/ud" , "op": "VM: XOP.L0.P0.M0A.W0 12 /0 id"}, - {"inst": "lwpins R:r64, R:r32/m32, id/ud" , "op": "VM: XOP.L0.P0.M0A.W1 12 /0 id"}, - {"inst": "lwpval R:r32, R:r32/m32, id/ud" , "op": "VM: XOP.L0.P0.M0A.W0 12 /1 id"}, - {"inst": "lwpval R:r64, R:r32/m32, id/ud" , "op": "VM: XOP.L0.P0.M0A.W1 12 /1 id"}, - {"inst": "slwpcb W:r32" , "op": "XOP.L0.P0.M09.W0 12 /1"}, - {"inst": "slwpcb W:r64" , "op": "XOP.L0.P0.M09.W1 12 /1"} - ]}, - - {"category": "GP GP_EXT", "ext": "FSGSBASE", "arch": "X64", "volatile": true, "data": [ - {"inst": "rdfsbase W:r32" , "op": "F3 0F AE /0"}, - {"inst": "rdfsbase W:r64" , "op": "REX.W F3 0F AE /0"}, - {"inst": "rdgsbase W:r32" , "op": "F3 0F AE /1"}, - {"inst": "rdgsbase W:r64" , "op": "REX.W F3 0F AE /1"}, - {"inst": "wrfsbase R:r32" , "op": "F3 0F AE /2"}, - {"inst": "wrfsbase R:r64" , "op": "REX.W F3 0F AE /2"}, - {"inst": "wrgsbase R:r32" , "op": "F3 0F AE /3"}, - {"inst": "wrgsbase R:r64" , "op": "REX.W F3 0F AE /3"} - ]}, - - {"category": "GP GP_EXT", "ext": "UINTR", "arch": "X64", "volatile": true, "data": [ - {"inst": "uiret" , "op": "F3 0F 01 EC"}, - {"inst": "clui" , "op": "F3 0F 01 EE"}, - {"inst": "stui" , "op": "F3 0F 01 EF"}, - {"inst": "testui" , "op": "F3 0F 01 ED" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"}, - {"inst": "senduipi R:r64" , "op": "R: F3 0F C7 /6"} - ]}, - - {"category": "GP GP_EXT", "ext": "PCONFIG", "volatile": true, "data": [ - {"inst": "pconfig" , "op": "0F 01 C5"} - ]}, - - {"category": "GP GP_EXT", "ext": "TSE", "arch": "X64", "volatile": true, "data": [ - {"inst": "pbndkb" , "op": "0F 01 C7"} - ]}, - - {"category": "GP GP_EXT", "volatile": true, "data": [ - {"inst": "xabort ib/ub" , "op": "C6 /7 ib" , "ext": "RTM"}, - {"inst": "xbegin rel16" , "op": "66 C7 /7 cw" , "ext": "RTM"}, - {"inst": "xbegin rel32" , "op": "C7 /7 cd" , "ext": "RTM"}, - {"inst": "xend" , "op": "0F 01 D5" , "ext": "RTM"}, - {"inst": "xresldtrk" , "op": "F2 0F 01 E9" , "ext": "TSXLDTRK"}, - {"inst": "xsusldtrk" , "op": "F2 0F 01 E8" , "ext": "TSXLDTRK"}, - {"inst": "xtest" , "op": "0F 01 D6" , "ext": "TSX" , "io": "OF=0 SF=0 ZF=W AF=0 PF=0 CF=0"} - ]}, - {"category": "GP", "volatile": true, "privilege": "L0", "data": [ - {"inst": "clrssbsy R:m64" , "op": "F3 0F AE /6" , "ext": "CET_SS" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"}, {"inst": "clts" , "op": "0F 06"}, - {"inst": "endbr32" , "op": "F3 0F 1E FB" , "ext": "CET_IBT"}, - {"inst": "endbr64" , "op": "F3 0F 1E FA" , "ext": "CET_IBT"}, - {"inst": "getsec " , "op": "0F 37" , "ext": "SMX"}, {"inst": "hlt" , "op": "F4"}, - {"inst": "hreset ib/ub, W:" , "op": "F3 0F 3A F0 /0 ib" , "ext": "HRESET"}, - {"inst": "invd" , "op": "0F 08" , "ext": "I486" }, - {"inst": "invlpg R:mem" , "op": "0F 01 /7" , "ext": "I486"}, - {"inst": "invpcid R:r32, R:m128" , "op": "RM: 66 0F 38 82 /r" , "ext": "I486" , "arch": "X86"}, - {"inst": "invpcid R:r64, R:m128" , "op": "RM: 66 0F 38 82 /r" , "ext": "I486" , "arch": "X64"}, {"inst": "lgdt R:mem" , "op": "0F 01 /2"}, {"inst": "lidt R:mem" , "op": "0F 01 /3"}, {"inst": "lldt R:r16/m16" , "op": "0F 00 /2"}, {"inst": "lmsw R:r16/m16" , "op": "0F 01 /6"}, {"inst": "ltr R:r16/m16" , "op": "0F 00 /3"}, - {"inst": "monitor R:, R:, R:" , "op": "0F 01 C8" , "ext": "MONITOR"}, - {"inst": "mwait R:, R:" , "op": "0F 01 C9" , "ext": "MONITOR"}, {"inst": "rdpmc W:, W:, R:" , "op": "0F 33"}, - {"inst": "rdmsr W:, W:, R:" , "op": "0F 32" , "ext": "MSR" , "io": "MSR=R"}, - {"inst": "rdmsrlist R:, W:, X:" , "op": "F2 0F 01 C6" , "ext": "MSRLIST" , "arch": "X64", "io": "MSR=R"}, - {"inst": "setssbsy" , "op": "F3 0F 01 E8" , "ext": "CET_SS"}, {"inst": "swapgs" , "op": "0F 01 F8" , "arch": "X64"}, {"inst": "sysexit" , "op": "0F 35"}, {"inst": "sysexitq" , "op": "REX.W 0F 35"}, {"inst": "sysret" , "op": "0F 07" , "arch": "X64"}, - {"inst": "sysretq" , "op": "REX.W 0F 07" , "arch": "X64"}, - {"inst": "wbinvd" , "op": "0F 09" , "ext": "I486"}, - {"inst": "wbnoinvd" , "op": "F3 0F 09" , "ext": "WBNOINVD"}, - {"inst": "wrmsrns R:, R:, R:" , "op": "0F 01 C6" , "ext": "WRMSRNS" , "io": "MSR=W"}, - {"inst": "wrmsr R:, R:, R:" , "op": "0F 30" , "ext": "MSR" , "io": "MSR=W"}, - {"inst": "wrmsrlist R:, R:, X:" , "op": "F3 0F 01 C6" , "ext": "MSRLIST" , "arch": "X64", "io": "MSR=W"}, - {"inst": "wrssd W:r32/m32, r32" , "op": "MR: 0F 38 F6 /r" , "ext": "CET_SS"}, - {"inst": "wrssq W:r64/m64, r64" , "op": "MR: REX.W 0F 38 F6 /r" , "ext": "CET_SS"}, - {"inst": "xrstors R:mem, , " , "op": "0F C7 /3" , "ext": "XSAVES" , "io": "XCR=R"}, - {"inst": "xrstors64 R:mem, , " , "op": "REX.W 0F C7 /3" , "ext": "XSAVES" , "io": "XCR=R"}, - {"inst": "wrussd W:r32/m32, r32" , "op": "MR: 66 0F 38 F5 /r" , "ext": "CET_SS"}, - {"inst": "wrussq W:r64/m64, r64" , "op": "MR: REX.W 66 0F 38 F5 /r" , "ext": "CET_SS"}, - {"inst": "xsaves W:mem, , " , "op": "0F C7 /5" , "ext": "XSAVES" , "io": "XCR=R"}, - {"inst": "xsaves64 W:mem, , " , "op": "REX.W 0F C7 /5" , "ext": "XSAVES" , "io": "XCR=R"}, - {"inst": "xsetbv R:, R:, R:" , "op": "0F 01 D1" , "ext": "XSAVE" , "io": "XCR=W"} + {"inst": "sysretq" , "op": "REX.W 0F 07" , "arch": "X64"} + ]}, + + {"category": "GP", "ext": "I486", "volatile": true, "privilege": "L0", "data": [ + {"inst": "invd" , "op": "0F 08"}, + {"inst": "invlpg R:mem" , "op": "0F 01 /7"}, + {"inst": "invpcid R:r32, R:m128" , "op": "RM: 66 0F 38 82 /r" , "arch": "X86"}, + {"inst": "invpcid R:r64, R:m128" , "op": "RM: 66 0F 38 82 /r" , "arch": "X64"}, + {"inst": "wbinvd" , "op": "0F 09"} + ]}, + + {"category": "GP GP_EXT", "ext": "CET_IBT", "volatile": true, "privilege": "L0", "data": [ + {"inst": "endbr32" , "op": "F3 0F 1E FB"}, + {"inst": "endbr64" , "op": "F3 0F 1E FA"} + ]}, + + {"category": "GP GP_EXT", "ext": "CET_SS", "volatile": true, "privilege": "L0", "data": [ + {"inst": "clrssbsy R:m64" , "op": "F3 0F AE /6" , "io": "OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W"}, + {"inst": "setssbsy" , "op": "F3 0F 01 E8"}, + {"inst": "wrssd W:r32/m32, r32" , "op": "MR: 0F 38 F6 /r"}, + {"inst": "wrssq W:r64/m64, r64" , "op": "MR: REX.W 0F 38 F6 /r"}, + {"inst": "wrussd W:r32/m32, r32" , "op": "MR: 66 0F 38 F5 /r"}, + {"inst": "wrussq W:r64/m64, r64" , "op": "MR: REX.W 66 0F 38 F5 /r"} + ]}, + + {"category": "GP GP_EXT", "ext": "HRESET", "volatile": true, "privilege": "L0", "data": [ + {"inst": "hreset ib/ub, W:" , "op": "F3 0F 3A F0 /0 ib"} + ]}, + + {"category": "GP GP_EXT", "ext": "MONITOR", "volatile": true, "privilege": "L0", "data": [ + {"inst": "monitor R:, R:, R:" , "op": "0F 01 C8"}, + {"inst": "mwait R:, R:" , "op": "0F 01 C9"} + ]}, + + {"category": "GP GP_EXT", "ext": "MSR", "volatile": true, "privilege": "L0", "data": [ + {"inst": "rdmsr W:, W:, R:" , "op": "0F 32" , "io": "MSR=R"}, + {"inst": "wrmsr R:, R:, R:" , "op": "0F 30" , "io": "MSR=W"} + ]}, + + {"category": "GP GP_EXT", "ext": "MSRLIST", "arch": "X64", "volatile": true, "privilege": "L0", "data": [ + {"inst": "rdmsrlist R:, W:, X:" , "op": "F2 0F 01 C6" , "io": "MSR=R"}, + {"inst": "wrmsrlist R:, R:, X:" , "op": "F3 0F 01 C6" , "io": "MSR=W"} + ]}, + + {"category": "GP GP_EXT", "ext": "SMX", "volatile": true, "privilege": "L0", "data": [ + {"inst": "getsec " , "op": "0F 37"} + ]}, + + {"category": "GP GP_EXT", "ext": "WBNOINVD", "volatile": true, "privilege": "L0", "data": [ + {"inst": "wbnoinvd" , "op": "F3 0F 09"} + ]}, + + {"category": "GP GP_EXT", "ext": "WRMSRNS", "volatile": true, "privilege": "L0", "data": [ + {"inst": "wrmsrns R:, R:, R:" , "op": "0F 01 C6" , "io": "MSR=W"} + ]}, + + {"category": "GP GP_EXT", "ext": "XSAVE", "volatile": true, "privilege": "L0", "data": [ + {"inst": "xsetbv R:, R:, R:" , "op": "0F 01 D1" , "io": "XCR=W"} + ]}, + + {"category": "GP GP_EXT", "ext": "XSAVES", "volatile": true, "privilege": "L0", "data": [ + {"inst": "xrstors R:mem, , " , "op": "0F C7 /3" , "io": "XCR=R"}, + {"inst": "xrstors64 R:mem, , " , "op": "REX.W 0F C7 /3" , "io": "XCR=R"}, + {"inst": "xsaves W:mem, , " , "op": "0F C7 /5" , "io": "XCR=R"}, + {"inst": "xsaves64 W:mem, , " , "op": "REX.W 0F C7 /5" , "io": "XCR=R"} ]}, {"category": "VIRTUALIZATION", "volatile": true, "data": [ @@ -1108,14 +1270,6 @@ {"inst": "fbstp W:m80bcd" , "op": "DF /6" , "io": "C0=U C1=W C2=U C3=U", "fpuStack": "pop"}, {"inst": "fchs" , "op": "D9 E0" , "io": "C0=U C1=0 C2=U C3=U"}, {"inst": "fclex" , "op": "9B DB E2" , "io": "C0=U C1=U C2=U C3=U"}, - {"inst": "fcmovb st(i)" , "op": "DA C0+i" , "io": "C0=U C1=W C2=U C3=U CF=R" , "ext": "CMOV"}, - {"inst": "fcmovbe st(i)" , "op": "DA D0+i" , "io": "C0=U C1=W C2=U C3=U CF=R ZF=R", "ext": "CMOV"}, - {"inst": "fcmove st(i)" , "op": "DA C8+i" , "io": "C0=U C1=W C2=U C3=U ZF=R" , "ext": "CMOV"}, - {"inst": "fcmovnb st(i)" , "op": "DB C0+i" , "io": "C0=U C1=W C2=U C3=U CF=R" , "ext": "CMOV"}, - {"inst": "fcmovnbe st(i)" , "op": "DB D0+i" , "io": "C0=U C1=W C2=U C3=U CF=R ZF=R", "ext": "CMOV"}, - {"inst": "fcmovne st(i)" , "op": "DB C8+i" , "io": "C0=U C1=W C2=U C3=U ZF=R" , "ext": "CMOV"}, - {"inst": "fcmovnu st(i)" , "op": "DB D8+i" , "io": "C0=U C1=W C2=U C3=U PF=R" , "ext": "CMOV"}, - {"inst": "fcmovu st(i)" , "op": "DA D8+i" , "io": "C0=U C1=W C2=U C3=U PF=R" , "ext": "CMOV"}, {"inst": "fcom" , "op": "D8 D1" , "io": "C0=W C1=0 C2=W C3=W"}, {"inst": "fcom R:m32fp" , "op": "D8 /2" , "io": "C0=W C1=0 C2=W C3=W"}, {"inst": "fcom R:m64fp" , "op": "DC /2" , "io": "C0=W C1=0 C2=W C3=W"}, @@ -1164,9 +1318,6 @@ {"inst": "fistp W:m16int" , "op": "DF /3" , "io": "C0=U C1=W C2=U C3=U", "fpuStack": "pop"}, {"inst": "fistp W:m32int" , "op": "DB /3" , "io": "C0=U C1=W C2=U C3=U", "fpuStack": "pop"}, {"inst": "fistp W:m64int" , "op": "DF /7" , "io": "C0=U C1=W C2=U C3=U", "fpuStack": "pop"}, - {"inst": "fisttp W:m16int" , "op": "DF /1" , "io": "C0=U C1=0 C2=U C3=U", "fpuStack": "pop", "ext": "SSE3"}, - {"inst": "fisttp W:m32int" , "op": "DB /1" , "io": "C0=U C1=0 C2=U C3=U", "fpuStack": "pop", "ext": "SSE3"}, - {"inst": "fisttp W:m64int" , "op": "DD /1" , "io": "C0=U C1=0 C2=U C3=U", "fpuStack": "pop", "ext": "SSE3"}, {"inst": "fisub R:m16int" , "op": "DE /4" , "io": "C0=U C1=W C2=U C3=U"}, {"inst": "fisub R:m32int" , "op": "DA /4" , "io": "C0=U C1=W C2=U C3=U"}, {"inst": "fisubr R:m16int" , "op": "DE /5" , "io": "C0=U C1=W C2=U C3=U"}, @@ -1249,6 +1400,23 @@ {"inst": "fyl2xp1" , "op": "D9 F9" , "io": "C0=U C1=W C2=U C3=U", "fpuStack": "pop"} ]}, + {"category": "FPU", "ext": "FPU CMOV", "data": [ + {"inst": "fcmovb st(i)" , "op": "DA C0+i" , "io": "C0=U C1=W C2=U C3=U CF=R" }, + {"inst": "fcmovbe st(i)" , "op": "DA D0+i" , "io": "C0=U C1=W C2=U C3=U CF=R ZF=R"}, + {"inst": "fcmove st(i)" , "op": "DA C8+i" , "io": "C0=U C1=W C2=U C3=U ZF=R" }, + {"inst": "fcmovnb st(i)" , "op": "DB C0+i" , "io": "C0=U C1=W C2=U C3=U CF=R" }, + {"inst": "fcmovnbe st(i)" , "op": "DB D0+i" , "io": "C0=U C1=W C2=U C3=U CF=R ZF=R"}, + {"inst": "fcmovne st(i)" , "op": "DB C8+i" , "io": "C0=U C1=W C2=U C3=U ZF=R" }, + {"inst": "fcmovnu st(i)" , "op": "DB D8+i" , "io": "C0=U C1=W C2=U C3=U PF=R" }, + {"inst": "fcmovu st(i)" , "op": "DA D8+i" , "io": "C0=U C1=W C2=U C3=U PF=R" } + ]}, + + {"category": "FPU", "ext": "FPU SSE3", "data": [ + {"inst": "fisttp W:m16int" , "op": "DF /1" , "io": "C0=U C1=0 C2=U C3=U", "fpuStack": "pop"}, + {"inst": "fisttp W:m32int" , "op": "DB /1" , "io": "C0=U C1=0 C2=U C3=U", "fpuStack": "pop"}, + {"inst": "fisttp W:m64int" , "op": "DD /1" , "io": "C0=U C1=0 C2=U C3=U", "fpuStack": "pop"} + ]}, + {"category": "MMX STATE", "deprecated": true, "volatile": true, "data": [ {"inst": "emms" , "op": "0F 77" , "ext": "MMX"}, {"inst": "femms" , "op": "0F 0E" , "ext": "3DNOW"} @@ -1649,7 +1817,7 @@ {"inst": "movntdqa W:xmm, m128" , "op": "RM: 66 0F 38 2A /r"}, {"inst": "mpsadbw X:xmm, xmm/m128, ib/ub" , "op": "RM: 66 0F 3A 42 /r ib"}, {"inst": "packusdw X:xmm, xmm/m128" , "op": "RM: 66 0F 38 2B /r"}, - {"inst": "pblendvb X:xmm, xmm/m128, " , "op": "RM: 66 0F E0 /r"}, + {"inst": "pblendvb X:xmm, xmm/m128, " , "op": "RM: 66 0F 38 10 /r"}, {"inst": "pblendw X:xmm, xmm/m128, ib/ub" , "op": "RM: 66 0F 3A 0E /r ib"}, {"inst": "pcmpeqq X:~xmm, ~xmm/m128" , "op": "RM: 66 0F 38 29 /r"}, {"inst": "pextrb W:r32[7:0]/m8, xmm, ib/ub" , "op": "MR: 66 0F 3A 14 /r ib"}, @@ -1707,10 +1875,6 @@ {"inst": "insertq X:xmm, xmm, ib/ub, ib/ub" , "op": "RM: F2 0F 78 /r ib ib"} ]}, - {"category": "SSE SIMD", "ext": "PCLMULQDQ", "data": [ - {"inst": "pclmulqdq X:xmm, xmm/m128, ib/ub" , "op": "RM: 66 0F 3A 44 /r ib"} - ]}, - {"category": "SSE SIMD CRYPTO_HASH", "ext": "AESNI", "data": [ {"inst": "aesdec X:xmm, xmm/m128" , "op": "RM: 66 0F 38 DE /r"}, {"inst": "aesdeclast X:xmm, xmm/m128" , "op": "RM: 66 0F 38 DF /r"}, @@ -1720,6 +1884,16 @@ {"inst": "aeskeygenassist W:xmm, xmm/m128, ib/ub" , "op": "RM: 66 0F 3A DF /r ib"} ]}, + {"category": "SSE SIMD", "ext": "GFNI", "data": [ + {"inst": "gf2p8affineinvqb X:xmm, xmm/m128, ib/ub" , "op": "RM: 66 0F 3A CF /r ib"}, + {"inst": "gf2p8affineqb X:xmm, xmm/m128, ib/ub" , "op": "RM: 66 0F 3A CE /r ib"}, + {"inst": "gf2p8mulb X:xmm, xmm/m128" , "op": "RM: 66 0F 38 CF /r"} + ]}, + + {"category": "SSE SIMD", "ext": "PCLMULQDQ", "data": [ + {"inst": "pclmulqdq X:xmm, xmm/m128, ib/ub" , "op": "RM: 66 0F 3A 44 /r ib"} + ]}, + {"category": "SSE SIMD CRYPTO_HASH", "ext": "SHA", "data": [ {"inst": "sha1msg1 xmm, xmm/m128" , "op": "RM: 0F 38 C9 /r"}, {"inst": "sha1msg2 xmm, xmm/m128" , "op": "RM: 0F 38 CA /r"}, @@ -1730,12 +1904,6 @@ {"inst": "sha256rnds2 xmm, xmm/m128, " , "op": "RM: 0F 38 CB /r"} ]}, - {"category": "SSE SIMD", "ext": "GFNI", "data": [ - {"inst": "gf2p8affineinvqb X:xmm, xmm/m128, ib/ub" , "op": "RM: 66 0F 3A CF /r ib"}, - {"inst": "gf2p8affineqb X:xmm, xmm/m128, ib/ub" , "op": "RM: 66 0F 3A CE /r ib"}, - {"inst": "gf2p8mulb X:xmm, xmm/m128" , "op": "RM: 66 0F 38 CF /r"} - ]}, - {"category": "AVX STATE", "ext": "AVX", "data": [ {"inst": "vldmxcsr R:m32" , "op": "VEX.LZ.0F.WIG AE /2", "io": "MXCSR=W"}, {"inst": "vstmxcsr W:m32" , "op": "VEX.LZ.0F.WIG AE /3", "io": "MXCSR=R"}, @@ -2626,7 +2794,7 @@ {"category": "AVX SIMD", "ext": "AVX SM3", "data": [ {"inst": "vsm3msg1 X:xmm, xmm, xmm/m128" , "op": "RVM: VEX.128.NP.0F38.W0 DA /r"}, {"inst": "vsm3msg2 X:xmm, xmm, xmm/m128" , "op": "RVM: VEX.128.66.0F38.W0 DA /r"}, - {"inst": "vsm3rnds2 X:xmm, xmm, xmm/m128, ib/ub" , "op": "RVM: VEX.128.66.0F3A.W0 DE /r /ib"} + {"inst": "vsm3rnds2 X:xmm, xmm, xmm/m128, ib/ub" , "op": "RVM: VEX.128.66.0F3A.W0 DE /r ib"} ]}, {"category": "AVX SIMD", "ext": "AVX SM4", "data": [ diff --git a/deps/asmjit/db/x86.js b/deps/asmjit/db/x86.js index c3fef787..a009a36c 100644 --- a/deps/asmjit/db/x86.js +++ b/deps/asmjit/db/x86.js @@ -1,7 +1,7 @@ // This file is part of AsmJit project // // See asmjit.h or LICENSE.md for license and copyright information -// SPDX-License-Identifier: Zlib +// SPDX-License-Identifier: (Zlib or Unlicense) (function($scope, $as) { "use strict"; diff --git a/deps/asmjit/src/asmjit/a64.h b/deps/asmjit/src/asmjit/a64.h index 71eff85a..e849eb3a 100644 --- a/deps/asmjit/src/asmjit/a64.h +++ b/deps/asmjit/src/asmjit/a64.h @@ -26,16 +26,16 @@ //! //! ### Register Operands //! -//! - \ref arm::Reg - Base class for any AArch32/AArch64 register. -//! - \ref arm::Gp - General purpose register: -//! - \ref arm::GpW - 32-bit register. -//! - \ref arm::GpX - 64-bit register. -//! - \ref arm::Vec - Vector (SIMD) register: -//! - \ref arm::VecB - 8-bit SIMD register. -//! - \ref arm::VecH - 16-bit SIMD register. -//! - \ref arm::VecS - 32-bit SIMD register. -//! - \ref arm::VecD - 64-bit SIMD register. -//! - \ref arm::VecV - 128-bit SIMD register. +//! - \ref arm::Reg - Base class of all AArch32/AArch64 registers. +//! - \ref a64::Gp - General purpose register (AArch64): +//! - \ref a64::GpW - 32-bit general purpose register (AArch64). +//! - \ref a64::GpX - 64-bit general purpose register (AArch64). +//! - \ref a64::Vec - Vector (SIMD) register: +//! - \ref a64::VecB - 8-bit SIMD register. +//! - \ref a64::VecH - 16-bit SIMD register. +//! - \ref a64::VecS - 32-bit SIMD register. +//! - \ref a64::VecD - 64-bit SIMD register. +//! - \ref a64::VecV - 128-bit SIMD register. //! //! ### Memory Operands //! diff --git a/deps/asmjit/src/asmjit/arm.h b/deps/asmjit/src/asmjit/arm.h index 2f2c72b4..e4a3e3d3 100644 --- a/deps/asmjit/src/asmjit/arm.h +++ b/deps/asmjit/src/asmjit/arm.h @@ -18,14 +18,16 @@ //! //! ### Emitters //! -//! - AArch64 +//! - AArch32 //! - \ref a32::Assembler - AArch32 assembler (must read, provides examples). -//! - \ref a64::Assembler - AArch64 assembler (must read, provides examples). //! - \ref a32::Builder - AArch32 builder. -//! - \ref a64::Builder - AArch64 builder. //! - \ref a32::Compiler - AArch32 compiler. -//! - \ref a64::Compiler - AArch64 compiler. //! - \ref a32::Emitter - AArch32 emitter (abstract). +//! +//! - AArch64 +//! - \ref a64::Assembler - AArch64 assembler (must read, provides examples). +//! - \ref a64::Builder - AArch64 builder. +//! - \ref a64::Compiler - AArch64 compiler. //! - \ref a64::Emitter - AArch64 emitter (abstract). //! //! ### Supported Instructions @@ -46,16 +48,22 @@ //! //! ### Register Operands //! -//! - \ref arm::Reg - Base class for any AArch32/AArch64 register. -//! - \ref arm::Gp - General purpose register: -//! - \ref arm::GpW - 32-bit register. -//! - \ref arm::GpX - 64-bit register (AArch64 only). -//! - \ref arm::Vec - Vector (SIMD) register: -//! - \ref arm::VecB - 8-bit SIMD register (AArch64 only). -//! - \ref arm::VecH - 16-bit SIMD register (AArch64 only). -//! - \ref arm::VecS - 32-bit SIMD register. -//! - \ref arm::VecD - 64-bit SIMD register. -//! - \ref arm::VecV - 128-bit SIMD register. +//! - \ref arm::Reg - Base class of all AArch32/AArch64 registers. +//! - \ref a32::Gp - 32-bit general purpose register used by AArch32: +//! - \ref a64::Gp - 32-bit or 64-bit general purpose register used by AArch64: +//! - \ref a64::GpW - 32-bit register (AArch64). +//! - \ref a64::GpX - 64-bit register (AArch64). +//! - \ref arm::BaseVec - Base vector (SIMD) register. +//! - \ref a32::Vec - Vector (SIMD) register (AArch32): +//! - \ref a32::VecS - 32-bit SIMD register (AArch32). +//! - \ref a32::VecD - 64-bit SIMD register (AArch32). +//! - \ref a32::VecV - 128-bit SIMD register (AArch32). +//! - \ref a64::Vec - Vector (SIMD) register (AArch64): +//! - \ref a64::VecB - 8-bit SIMD register (AArch64). +//! - \ref a64::VecH - 16-bit SIMD register (AArch64). +//! - \ref a64::VecS - 32-bit SIMD register (AArch64). +//! - \ref a64::VecD - 64-bit SIMD register (AArch64). +//! - \ref a64::VecV - 128-bit SIMD register (AArch64). //! //! ### Memory Operands //! diff --git a/deps/asmjit/src/asmjit/arm/a64assembler.cpp b/deps/asmjit/src/asmjit/arm/a64assembler.cpp index 444bb1fd..c926766a 100644 --- a/deps/asmjit/src/asmjit/arm/a64assembler.cpp +++ b/deps/asmjit/src/asmjit/arm/a64assembler.cpp @@ -21,12 +21,16 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64) +// a64::Assembler - Utils +// ====================== + +static ASMJIT_FORCE_INLINE constexpr uint32_t diff(RegType a, RegType b) noexcept { return uint32_t(a) - uint32_t(b); } +static ASMJIT_FORCE_INLINE constexpr uint32_t diff(VecElementType elementType, VecElementType baseType) noexcept { return uint32_t(elementType) - uint32_t(baseType); } + // a64::Assembler - Cond // ===================== -static inline uint32_t condCodeToOpcodeCond(uint32_t cond) noexcept { - return (uint32_t(cond) - 2u) & 0xFu; -} +static inline uint32_t condCodeToOpcodeCond(uint32_t cond) noexcept { return (uint32_t(cond) - 2u) & 0xFu; } // a64::Assembler - Bits // ===================== @@ -49,10 +53,6 @@ static constexpr uint32_t kWX = InstDB::kWX; static const uint8_t armShiftOpToLdStOptMap[] = { ASMJIT_LOOKUP_TABLE_16(VALUE, 0) }; #undef VALUE -static inline constexpr uint32_t diff(RegType a, RegType b) noexcept { - return uint32_t(a) - uint32_t(b); -} - // asmjit::a64::Assembler - SizeOp // =============================== @@ -118,25 +118,25 @@ struct SizeOpTable { }; #define VALUE_BIN(x) { \ - x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k00 : \ - x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k00Q : \ - x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB )) ? SizeOp::k00 : \ - x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB )) ? SizeOp::k00Q : SizeOp::kInvalid \ + x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k00 : \ + x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k00Q : \ + x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kB )) ? SizeOp::k00 : \ + x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kB )) ? SizeOp::k00Q : SizeOp::kInvalid \ } #define VALUE_ANY(x) { \ - x == (((uint32_t(RegType::kARM_VecB) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k00S : \ - x == (((uint32_t(RegType::kARM_VecH) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k01S : \ - x == (((uint32_t(RegType::kARM_VecS) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k10S : \ - x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k11S : \ - x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB )) ? SizeOp::k00 : \ - x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB )) ? SizeOp::k00Q : \ - x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeH )) ? SizeOp::k01 : \ - x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeH )) ? SizeOp::k01Q : \ - x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeS )) ? SizeOp::k10 : \ - x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeS )) ? SizeOp::k10Q : \ - x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeD )) ? SizeOp::k11S : \ - x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeD )) ? SizeOp::k11Q : SizeOp::kInvalid \ + x == (((uint32_t(RegType::kARM_VecB) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k00S : \ + x == (((uint32_t(RegType::kARM_VecH) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k01S : \ + x == (((uint32_t(RegType::kARM_VecS) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k10S : \ + x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k11S : \ + x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kB )) ? SizeOp::k00 : \ + x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kB )) ? SizeOp::k00Q : \ + x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kH )) ? SizeOp::k01 : \ + x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kH )) ? SizeOp::k01Q : \ + x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kS )) ? SizeOp::k10 : \ + x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kS )) ? SizeOp::k10Q : \ + x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kD )) ? SizeOp::k11S : \ + x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | uint32_t(VecElementType::kD )) ? SizeOp::k11Q : SizeOp::kInvalid \ } static const SizeOpTable sizeOpTable[SizeOpTable::kCount] = { @@ -254,16 +254,16 @@ static const Operand_& significantSimdOp(const Operand_& o0, const Operand_& o1, return !(instFlags & InstDB::kInstFlagLong) ? o0 : o1; } -static inline SizeOp armElementTypeToSizeOp(uint32_t vecOpType, RegType regType, uint32_t elementType) noexcept { +static inline SizeOp armElementTypeToSizeOp(uint32_t vecOpType, RegType regType, VecElementType elementType) noexcept { // Instruction data or Assembler is wrong if this triggers an assertion failure. ASMJIT_ASSERT(vecOpType < InstDB::kVO_Count); // ElementType uses 3 bits in the operand signature, it should never overflow. - ASMJIT_ASSERT(elementType <= 0x7u); + ASMJIT_ASSERT(uint32_t(elementType) <= 0x7u); const SizeOpMap& map = sizeOpMap[vecOpType]; const SizeOpTable& table = sizeOpTable[map.tableId]; - size_t index = (Support::min(diff(regType, RegType::kARM_VecB), diff(RegType::kARM_VecV, RegType::kARM_VecB) + 1) << 3) | elementType; + size_t index = (Support::min(diff(regType, RegType::kARM_VecB), diff(RegType::kARM_VecV, RegType::kARM_VecB) + 1) << 3) | uint32_t(elementType); SizeOp op = table.array[index]; SizeOp modifiedOp { uint8_t(op.value & map.sizeOpMask) }; @@ -467,7 +467,7 @@ static inline bool matchSignature(const Operand_& o0, const Operand_& o1, const } static inline bool matchSignature(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, uint32_t instFlags) noexcept { - return matchSignature(o0, o1, instFlags) && o1.signature() == o2.signature() && o2.signature() == o3.signature();; + return matchSignature(o0, o1, instFlags) && o1.signature() == o2.signature() && o2.signature() == o3.signature(); } // Memory must be either: @@ -537,7 +537,7 @@ static inline bool pickFpOpcode(const Vec& reg, uint32_t sOp, uint32_t sHf, uint else { // Vector operation [HSD]. uint32_t q = diff(reg.type(), RegType::kARM_VecD); - uint32_t sz = reg.elementType() - Vec::kElementTypeH; + uint32_t sz = diff(reg.elementType(), VecElementType::kH); if (q > 1u || sz > 2u || !Support::bitTest(szBits[vHf].sizeMask, sz)) return false; @@ -716,8 +716,6 @@ static inline bool checkValidRegs(const Operand_& o0, const Operand_& o1, const Assembler::Assembler(CodeHolder* code) noexcept : BaseAssembler() { _archMask = uint64_t(1) << uint32_t(Arch::kAArch64); - assignEmitterFuncs(this); - if (code) code->attach(this); } @@ -803,7 +801,7 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co Operand_ opArray[Globals::kMaxOpCount]; EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); - err = _funcs.validate(arch(), BaseInst(instId, options, _extraReg), opArray, Globals::kMaxOpCount, ValidationFlags::kNone); + err = _funcs.validate(BaseInst(instId, options, _extraReg), opArray, Globals::kMaxOpCount, ValidationFlags::kNone); if (ASMJIT_UNLIKELY(err)) goto Failed; } @@ -2241,6 +2239,86 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co break; } + // ------------------------------------------------------------------------ + // [Base - Prefetch] + // ------------------------------------------------------------------------ + + case InstDB::kEncodingBasePrfm: { + const InstDB::EncodingData::BasePrfm& opData = InstDB::EncodingData::basePrfm[encodingIndex]; + + if (isign4 == ENC_OPS2(Imm, Mem)) { + const Mem& m = o1.as(); + rmRel = &m; + + uint32_t immShift = 3u; + + if (o0.as().valueAs() > 0x1Fu) + goto InvalidImmediate; + + if (!armCheckMemBaseIndexRel(m)) + goto InvalidAddress; + + int64_t offset = m.offset(); + uint32_t prfop = o0.as().valueAs(); + + if (m.hasBaseReg()) { + // [Base {Offset | Index}] + if (m.hasIndex()) { + uint32_t opt = armShiftOpToLdStOptMap[size_t(m.shiftOp())]; + if (opt == 0xFF) + goto InvalidAddress; + + uint32_t shift = m.shift(); + uint32_t s = shift != 0; + + if (s && shift != immShift) + goto InvalidAddressScale; + + opcode.reset(uint32_t(opData.registerOp) << 21); + opcode.addImm(opt, 13); + opcode.addImm(s, 12); + opcode |= B(11); + opcode.addImm(prfop, 0); + goto EmitOp_MemBaseIndex_Rn5_Rm16; + } + + if (!Support::isInt32(offset)) + goto InvalidDisplacement; + + int32_t offset32 = int32_t(offset); + + if (m.isPreOrPost()) + goto InvalidAddress; + + uint32_t imm12 = uint32_t(offset32) >> immShift; + + if (Support::isUInt12(imm12) && (imm12 << immShift) == uint32_t(offset32)) { + opcode.reset(uint32_t(opData.sOffsetOp) << 22); + opcode.addImm(imm12, 10); + opcode.addImm(prfop, 0); + goto EmitOp_MemBase_Rn5; + } + + if (Support::isInt9(offset32)) { + opcode.reset(uint32_t(opData.uOffsetOp) << 21); + opcode.addImm(uint32_t(offset32) & 0x1FFu, 12); + opcode.addImm(prfop, 0); + goto EmitOp_MemBase_Rn5; + } + + goto InvalidAddress; + } + else { + opcode.reset(uint32_t(opData.literalOp) << 24); + opcode.addImm(prfop, 0); + offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 19, 2); + goto EmitOp_Rel; + } + } + + break; + } + // ------------------------------------------------------------------------ // [Base - Load / Store] // ------------------------------------------------------------------------ @@ -2272,7 +2350,7 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co if (m.hasBaseReg()) { // [Base {Offset | Index}] if (m.hasIndex()) { - uint32_t opt = armShiftOpToLdStOptMap[m.predicate()]; + uint32_t opt = armShiftOpToLdStOptMap[size_t(m.shiftOp())]; if (opt == 0xFF) goto InvalidAddress; @@ -2690,7 +2768,7 @@ Case_BaseLdurStur: // hD, vS.{4|8}h (16-bit) // sD, vS.4s (32-bit) uint32_t sz = diff(o0.as().type(), RegType::kARM_VecH); - uint32_t elementSz = o1.as().elementType() - Vec::kElementTypeH; + uint32_t elementSz = diff(o1.as().elementType(), VecElementType::kH); // Size greater than 1 means 64-bit elements, not supported. if ((sz | elementSz) > 1 || sz != elementSz) @@ -2812,7 +2890,7 @@ Case_BaseLdurStur: if (q > 1) goto InvalidInstruction; - uint32_t sz = o0.as().elementType() - Vec::kElementTypeB; + uint32_t sz = diff(o0.as().elementType(), VecElementType::kB); if (sz == 0 || sz > 3) goto InvalidInstruction; @@ -2904,7 +2982,7 @@ Case_BaseLdurStur: if (q > 1) goto InvalidInstruction; - uint32_t sz = o0.as().elementType() - Vec::kElementTypeB; + uint32_t sz = diff(o0.as().elementType(), VecElementType::kB); if (sz == 0 || sz > 3) goto InvalidInstruction; @@ -3086,11 +3164,11 @@ Case_BaseLdurStur: if (uint32_t(opcode.hasQ()) != q) goto InvalidInstruction; - if (rL.isVecS4() && rN.elementType() == Vec::kElementTypeH && !opData.isCvtxn()) { + if (rL.isVecS4() && rN.elementType() == VecElementType::kH && !opData.isCvtxn()) { goto EmitOp_Rd0_Rn5; } - if (rL.isVecD2() && rN.elementType() == Vec::kElementTypeS) { + if (rL.isVecD2() && rN.elementType() == VecElementType::kS) { opcode |= B(22); goto EmitOp_Rd0_Rn5; } @@ -3201,8 +3279,8 @@ Case_BaseLdurStur: } if (uint32_t(o0.as().type()) != uint32_t(o1.as().type()) + qIsOptional || - o0.as().elementType() != opData.tA || - o1.as().elementType() != opData.tB) + uint32_t(o0.as().elementType()) != opData.tA || + uint32_t(o1.as().elementType()) != opData.tB) goto InvalidInstruction; if (!o2.as().hasElementIndex()) { @@ -3214,7 +3292,7 @@ Case_BaseLdurStur: goto EmitOp_Rd0_Rn5_Rm16; } else { - if (o2.as().elementType() != opData.tElement) + if (uint32_t(o2.as().elementType()) != opData.tElement) goto InvalidInstruction; if (o2.as().id() > 15) @@ -3364,7 +3442,7 @@ Case_BaseLdurStur: } else { uint32_t q = diff(o0.as().type(), RegType::kARM_VecD); - uint32_t sz = o0.as().elementType() - Vec::kElementTypeH; + uint32_t sz = diff(o0.as().elementType(), VecElementType::kH); if (q > 1 || sz > 2) goto InvalidInstruction; @@ -3418,7 +3496,7 @@ Case_BaseLdurStur: if (q > 1) goto InvalidInstruction; - uint32_t sz = o0.as().elementType() - Vec::kElementTypeH; + uint32_t sz = diff(o0.as().elementType(), VecElementType::kH); if (sz > 2) goto InvalidInstruction; @@ -3442,7 +3520,7 @@ Case_BaseLdurStur: if (isign4 == ENC_OPS2(Reg, Reg)) { // The first destination operand is scalar, which matches element-type of source vectors. uint32_t L = (instFlags & InstDB::kInstFlagLong) != 0; - if (diff(o0.as().type(), RegType::kARM_VecB) != o1.as().elementType() - Vec::kElementTypeB + L) + if (diff(o0.as().type(), RegType::kARM_VecB) != diff(o1.as().elementType(), VecElementType::kB) + L) goto InvalidInstruction; SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o1.as().type(), o1.as().elementType()); @@ -3542,7 +3620,7 @@ Case_BaseLdurStur: if (!sizeOp.isValid()) goto InvalidInstruction; - if (!checkSignature(o0, o1) || !o0.as().isVecV() || o0.as().elementType() != o2.as().elementType() + 1) + if (!checkSignature(o0, o1) || !o0.as().isVecV() || uint32_t(o0.as().elementType()) != uint32_t(o2.as().elementType()) + 1u) goto InvalidInstruction; opcode.reset(opData.opcode()); @@ -3827,9 +3905,9 @@ Case_BaseLdurStur: if (o0.as().type() != o1.as().type() || o1.as().type() != o2.as().type()) goto InvalidInstruction; - if (o0.as().elementType() != opData.tA || - o1.as().elementType() != opData.tB || - o2.as().elementType() != opData.tB) + if (uint32_t(o0.as().elementType()) != opData.tA || + uint32_t(o1.as().elementType()) != opData.tB || + uint32_t(o2.as().elementType()) != opData.tB) goto InvalidInstruction; opcode.reset(uint32_t(opData.vectorOp) << 10); @@ -3843,9 +3921,9 @@ Case_BaseLdurStur: if (o0.as().type() != o1.as().type() || !o2.as().isVecV()) goto InvalidInstruction; - if (o0.as().elementType() != opData.tA || - o1.as().elementType() != opData.tB || - o2.as().elementType() != opData.tElement) + if (uint32_t(o0.as().elementType()) != opData.tA || + uint32_t(o1.as().elementType()) != opData.tB || + uint32_t(o2.as().elementType()) != opData.tElement) goto InvalidInstruction; uint32_t elementIndex = o2.as().elementIndex(); @@ -3871,13 +3949,13 @@ Case_BaseLdurStur: case InstDB::kEncodingSimdDup: SimdDup: { if (isign4 == ENC_OPS2(Reg, Reg)) { // Truth table of valid encodings of `Q:1|ElementType:3` - uint32_t kValidEncodings = B(Vec::kElementTypeB + 0) | - B(Vec::kElementTypeH + 0) | - B(Vec::kElementTypeS + 0) | - B(Vec::kElementTypeB + 8) | - B(Vec::kElementTypeH + 8) | - B(Vec::kElementTypeS + 8) | - B(Vec::kElementTypeD + 8) ; + uint32_t kValidEncodings = B(uint32_t(VecElementType::kB) + 0) | + B(uint32_t(VecElementType::kH) + 0) | + B(uint32_t(VecElementType::kS) + 0) | + B(uint32_t(VecElementType::kB) + 8) | + B(uint32_t(VecElementType::kH) + 8) | + B(uint32_t(VecElementType::kS) + 8) | + B(uint32_t(VecElementType::kD) + 8) ; uint32_t q = diff(o0.as().type(), RegType::kARM_VecD); @@ -3886,7 +3964,7 @@ Case_BaseLdurStur: // // NOTE: This is only scalar for `dup d, x` case, otherwise the value // would be duplicated across all vector elements (1, 2, 4, 8, or 16). - uint32_t elementType = o0.as().elementType(); + uint32_t elementType = uint32_t(o0.as().elementType()); if (q > 1 || !Support::bitTest(kValidEncodings, (q << 3) | elementType)) goto InvalidInstruction; @@ -3907,7 +3985,7 @@ Case_BaseLdurStur: // DUP - Vec (scalar) <- Vec[N]. uint32_t lsbIndex = diff(o0.as().type(), RegType::kARM_VecB); - if (lsbIndex != o1.as().elementType() - Vec::kElementTypeB || lsbIndex > 3) + if (lsbIndex != diff(o1.as().elementType(), VecElementType::kB) || lsbIndex > 3) goto InvalidInstruction; uint32_t imm5 = ((dstIndex << 1) | 1u) << lsbIndex; @@ -3920,7 +3998,7 @@ Case_BaseLdurStur: } else { // DUP - Vec (all) <- Vec[N]. - uint32_t elementType = o0.as().elementType(); + uint32_t elementType = uint32_t(o0.as().elementType()); if (q > 1 || !Support::bitTest(kValidEncodings, (q << 3) | elementType)) goto InvalidInstruction; @@ -3945,7 +4023,7 @@ Case_BaseLdurStur: if (!o0.as().hasElementIndex()) goto InvalidInstruction; - uint32_t elementType = o0.as().elementType(); + uint32_t elementType = uint32_t(o0.as().elementType()); uint32_t dstIndex = o0.as().elementIndex(); uint32_t lsbIndex = elementType - 1u; @@ -4114,7 +4192,6 @@ Case_BaseLdurStur: if (inverted) { imm8 = ~imm8 & 0xFFu; - inverted = 0; } cmode = B(3) | B(2) | B(1); @@ -4147,7 +4224,6 @@ Case_BaseLdurStur: case 3: if (inverted) { imm8 = ~imm8 & 0xFFu; - inverted = 0; } op = 1; @@ -4435,7 +4511,7 @@ Case_BaseLdurStur: if (m.hasBaseReg()) { // [Base {Offset | Index}] if (m.hasIndex()) { - uint32_t opt = armShiftOpToLdStOptMap[m.predicate()]; + uint32_t opt = armShiftOpToLdStOptMap[size_t(m.shiftOp())]; if (opt == 0xFFu) goto InvalidAddress; @@ -4659,7 +4735,7 @@ Case_SimdLdurStur: uint32_t q = 0; uint32_t rm = 0; uint32_t rn = m.baseId(); - uint32_t sz = v.elementType() - Vec::kElementTypeB; + uint32_t sz = diff(v.elementType(), VecElementType::kB); uint32_t opcSsize = sz; uint32_t offsetPossibility = 0; @@ -5091,6 +5167,10 @@ Error Assembler::align(AlignMode alignMode, uint32_t alignment) { Error Assembler::onAttach(CodeHolder* code) noexcept { ASMJIT_PROPAGATE(Base::onAttach(code)); + + _instructionAlignment = uint8_t(4); + assignEmitterFuncs(this); + return kErrorOk; } diff --git a/deps/asmjit/src/asmjit/arm/a64assembler.h b/deps/asmjit/src/asmjit/arm/a64assembler.h index f9eb9d46..31932157 100644 --- a/deps/asmjit/src/asmjit/arm/a64assembler.h +++ b/deps/asmjit/src/asmjit/arm/a64assembler.h @@ -23,7 +23,7 @@ class ASMJIT_VIRTAPI Assembler public: typedef BaseAssembler Base; - //! \name Construction / Destruction + //! \name Construction & Destruction //! \{ ASMJIT_API Assembler(CodeHolder* code = nullptr) noexcept; @@ -31,17 +31,6 @@ public: //! \} - //! \name Accessors - //! \{ - - //! Gets whether the current ARM mode is THUMB (alternative to 32-bit ARM encoding). - ASMJIT_INLINE_NODEBUG bool isInThumbMode() const noexcept { return _environment.isArchThumb(); } - - //! Gets the current code alignment of the current mode (ARM vs THUMB). - ASMJIT_INLINE_NODEBUG uint32_t codeAlignment() const noexcept { return isInThumbMode() ? 2 : 4; } - - //! \} - //! \name Emit //! \{ diff --git a/deps/asmjit/src/asmjit/arm/a64builder.cpp b/deps/asmjit/src/asmjit/arm/a64builder.cpp index 3a52b2a5..d29b0a49 100644 --- a/deps/asmjit/src/asmjit/arm/a64builder.cpp +++ b/deps/asmjit/src/asmjit/arm/a64builder.cpp @@ -17,8 +17,6 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64) Builder::Builder(CodeHolder* code) noexcept : BaseBuilder() { _archMask = uint64_t(1) << uint32_t(Arch::kAArch64); - assignEmitterFuncs(this); - if (code) code->attach(this); } @@ -28,13 +26,19 @@ Builder::~Builder() noexcept {} // ===================== Error Builder::onAttach(CodeHolder* code) noexcept { - return Base::onAttach(code); + ASMJIT_PROPAGATE(Base::onAttach(code)); + + _instructionAlignment = uint8_t(4); + assignEmitterFuncs(this); + + return kErrorOk; } Error Builder::onDetach(CodeHolder* code) noexcept { return Base::onDetach(code); } + // a64::Builder - Finalize // ======================= diff --git a/deps/asmjit/src/asmjit/arm/a64compiler.cpp b/deps/asmjit/src/asmjit/arm/a64compiler.cpp index d6c4ed28..765fd4b9 100644 --- a/deps/asmjit/src/asmjit/arm/a64compiler.cpp +++ b/deps/asmjit/src/asmjit/arm/a64compiler.cpp @@ -18,8 +18,6 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64) Compiler::Compiler(CodeHolder* code) noexcept : BaseCompiler() { _archMask = uint64_t(1) << uint32_t(Arch::kAArch64); - assignEmitterFuncs(this); - if (code) code->attach(this); } @@ -37,6 +35,9 @@ Error Compiler::onAttach(CodeHolder* code) noexcept { return err; } + _instructionAlignment = uint8_t(4); + assignEmitterFuncs(this); + return kErrorOk; } diff --git a/deps/asmjit/src/asmjit/arm/a64compiler.h b/deps/asmjit/src/asmjit/arm/a64compiler.h index c0b38674..64f82f62 100644 --- a/deps/asmjit/src/asmjit/arm/a64compiler.h +++ b/deps/asmjit/src/asmjit/arm/a64compiler.h @@ -45,20 +45,27 @@ public: return reg; } + template + ASMJIT_INLINE_NODEBUG RegT _newRegInternal(const Type& type, const char* s) { +#ifndef ASMJIT_NO_LOGGING + RegT reg(Globals::NoInit); + _newReg(®, type, s); + return reg; +#else + DebugUtils::unused(s); + return _newRegInternal(type); +#endif + } + template ASMJIT_INLINE_NODEBUG RegT _newRegInternal(const Type& type, const char* s, Args&&... args) { #ifndef ASMJIT_NO_LOGGING RegT reg(Globals::NoInit); - if (sizeof...(Args) == 0) - _newReg(®, type, s); - else - _newRegFmt(®, type, s, std::forward(args)...); + _newRegFmt(®, type, s, std::forward(args)...); return reg; #else DebugUtils::unused(s, std::forward(args)...); - RegT reg(Globals::NoInit); - _newReg(®, type, nullptr); - return reg; + return _newRegInternal(type); #endif } //! \endcond diff --git a/deps/asmjit/src/asmjit/arm/a64emithelper.cpp b/deps/asmjit/src/asmjit/arm/a64emithelper.cpp index 1e8da619..0cf09825 100644 --- a/deps/asmjit/src/asmjit/arm/a64emithelper.cpp +++ b/deps/asmjit/src/asmjit/arm/a64emithelper.cpp @@ -169,7 +169,7 @@ Error EmitHelper::emitArgMove( if (TypeUtils::isInt(dstTypeId)) { if (TypeUtils::isInt(srcTypeId)) { - uint32_t x = dstSize == 8; + uint32_t x = uint32_t(dstSize == 8); dst.setSignature(OperandSignature{x ? uint32_t(GpX::kSignature) : uint32_t(GpW::kSignature)}); _emitter->setInlineComment(comment); @@ -186,7 +186,7 @@ Error EmitHelper::emitArgMove( case TypeId::kInt16: instId = Inst::kIdLdrsh; break; case TypeId::kUInt16: instId = Inst::kIdLdrh; break; case TypeId::kInt32: instId = x ? Inst::kIdLdrsw : Inst::kIdLdr; break; - case TypeId::kUInt32: instId = Inst::kIdLdr; x = 0; break; + case TypeId::kUInt32: instId = Inst::kIdLdr; break; case TypeId::kInt64: instId = Inst::kIdLdr; break; case TypeId::kUInt64: instId = Inst::kIdLdr; break; default: @@ -312,6 +312,12 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitProlog(const FuncFrame& frame) { { Inst::kIdStr_v, Inst::kIdStp_v } }}; + // Emit: 'bti' (indirect branch protection). + if (frame.hasIndirectBranchProtection()) { + // TODO: The instruction is not available at the moment (would be ABI break). + // ASMJIT_PROPAGATE(emitter->bti()); + } + uint32_t adjustInitialOffset = pei.sizeTotal; for (RegGroup group : Support::EnumValues{}) { @@ -339,7 +345,7 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitProlog(const FuncFrame& frame) { else ASMJIT_PROPAGATE(emitter->emit(insts.pairInstId, regs[0], regs[1], mem)); - mem.resetToFixedOffset(); + mem.resetOffsetMode(); if (i == 0 && frame.hasPreservedFP()) { ASMJIT_PROPAGATE(emitter->mov(x29, sp)); @@ -421,7 +427,7 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitEpilog(const FuncFrame& frame) { else ASMJIT_PROPAGATE(emitter->emit(insts.pairInstId, regs[0], regs[1], mem)); - mem.resetToFixedOffset(); + mem.resetOffsetMode(); } } diff --git a/deps/asmjit/src/asmjit/arm/a64emitter.h b/deps/asmjit/src/asmjit/arm/a64emitter.h index 22717d32..15c91e0b 100644 --- a/deps/asmjit/src/asmjit/arm/a64emitter.h +++ b/deps/asmjit/src/asmjit/arm/a64emitter.h @@ -71,7 +71,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64) //! ARM emitter. //! //! NOTE: This class cannot be instantiated, you can only cast to it and use it as emitter that emits to either -//! \ref Assembler, \ref Builder, or \ref Compiler (use withcaution with \ref Compiler as it expects virtual +//! \ref Assembler, \ref Builder, or \ref Compiler (use with caution with \ref Compiler as it expects virtual //! registers to be used). template struct EmitterExplicitT { @@ -79,11 +79,22 @@ struct EmitterExplicitT { // These two are unfortunately reported by the sanitizer. We know what we do, however, the sanitizer doesn't. // I have tried to use reinterpret_cast instead, but that would generate bad code when compiled by MSC. - ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF inline This* _emitter() noexcept { return static_cast(this); } - ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF inline const This* _emitter() const noexcept { return static_cast(this); } + ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF ASMJIT_INLINE_NODEBUG This* _emitter() noexcept { return static_cast(this); } + ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF ASMJIT_INLINE_NODEBUG const This* _emitter() const noexcept { return static_cast(this); } //! \endcond + + //! \name Native Registers + //! \{ + + //! Returns either 32-bit or 64-bit GP register of the given `id` depending on the emitter's architecture. + inline Gp gpz(uint32_t id) const noexcept { return Gp(_emitter()->_gpSignature, id); } + //! Clones the given `reg` to either 32-bit or 64-bit GP register depending on the emitter's architecture. + inline Gp gpz(const Gp& reg) const noexcept { return Gp(_emitter()->_gpSignature, reg.id()); } + + //! \} + //! \name General Purpose Instructions //! \{ @@ -514,6 +525,8 @@ struct EmitterExplicitT { ASMJIT_INST_2x(ldxrb, Ldxrb, Gp, Mem) ASMJIT_INST_2x(ldxrh, Ldxrh, Gp, Mem) + ASMJIT_INST_2x(prfm, Prfm, Imm, Mem) + ASMJIT_INST_2x(stadd, Stadd, Gp, Mem) ASMJIT_INST_2x(staddb, Staddb, Gp, Mem) ASMJIT_INST_2x(staddh, Staddh, Gp, Mem) diff --git a/deps/asmjit/src/asmjit/arm/a64formatter.cpp b/deps/asmjit/src/asmjit/arm/a64formatter.cpp index 8cd4a06e..94ef3ee5 100644 --- a/deps/asmjit/src/asmjit/arm/a64formatter.cpp +++ b/deps/asmjit/src/asmjit/arm/a64formatter.cpp @@ -29,12 +29,10 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatInstruction( Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount) noexcept { - DebugUtils::unused(arch); - // Format instruction options and instruction mnemonic. InstId instId = inst.realId(); - if (instId < Inst::_kIdCount) - ASMJIT_PROPAGATE(InstInternal::instIdToString(arch, instId, sb)); + if (instId != Inst::kIdNone && instId < Inst::_kIdCount) + ASMJIT_PROPAGATE(InstInternal::instIdToString(instId, sb)); else ASMJIT_PROPAGATE(sb.appendFormat("[InstId=#%u]", unsigned(instId))); diff --git a/deps/asmjit/src/asmjit/arm/a64func.cpp b/deps/asmjit/src/asmjit/arm/a64func.cpp index 55e3f2e7..a88c4d88 100644 --- a/deps/asmjit/src/asmjit/arm/a64func.cpp +++ b/deps/asmjit/src/asmjit/arm/a64func.cpp @@ -41,12 +41,13 @@ static RegType regTypeFromFpOrVecTypeId(TypeId typeId) noexcept { ASMJIT_FAVOR_SIZE Error initCallConv(CallConv& cc, CallConvId ccId, const Environment& environment) noexcept { cc.setArch(environment.arch()); + cc.setStrategy(environment.isDarwin() ? CallConvStrategy::kAArch64Apple : CallConvStrategy::kDefault); cc.setSaveRestoreRegSize(RegGroup::kGp, 8); cc.setSaveRestoreRegSize(RegGroup::kVec, 8); cc.setSaveRestoreAlignment(RegGroup::kGp, 16); cc.setSaveRestoreAlignment(RegGroup::kVec, 16); - cc.setSaveRestoreAlignment(RegGroup::kExtraVirt2, 1); + cc.setSaveRestoreAlignment(RegGroup::kMask, 1); cc.setSaveRestoreAlignment(RegGroup::kExtraVirt3, 1); cc.setPassedOrder(RegGroup::kGp, 0, 1, 2, 3, 4, 5, 6, 7); cc.setPassedOrder(RegGroup::kVec, 0, 1, 2, 3, 4, 5, 6, 7); @@ -68,7 +69,7 @@ ASMJIT_FAVOR_SIZE Error initCallConv(CallConv& cc, CallConvId ccId, const Enviro return kErrorOk; } -ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& signature, uint32_t registerSize) noexcept { +ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& signature) noexcept { DebugUtils::unused(signature); const CallConv& cc = func.callConv(); @@ -77,6 +78,13 @@ ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& si uint32_t i; uint32_t argCount = func.argCount(); + // Minimum stack size of a single argument passed via stack. The standard AArch64 calling convention + // specifies 8 bytes, so each function argument would occupy at least 8 bytes even if it needs less. + // However, Apple has decided to not follow this rule and function argument can occupy less, for + // example two consecutive 32-bit arguments would occupy 8 bytes total, instead of 16 as specified + // by ARM. + uint32_t minStackArgSize = cc.strategy() == CallConvStrategy::kAArch64Apple ? 4u : 8u; + if (func.hasRet()) { for (uint32_t valueIndex = 0; valueIndex < Globals::kMaxValuePack; valueIndex++) { TypeId typeId = func._rets[valueIndex].typeId(); @@ -119,7 +127,8 @@ ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& si } switch (cc.strategy()) { - case CallConvStrategy::kDefault: { + case CallConvStrategy::kDefault: + case CallConvStrategy::kAArch64Apple: { uint32_t gpzPos = 0; uint32_t vecPos = 0; @@ -140,7 +149,9 @@ ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& si gpzPos++; } else { - uint32_t size = Support::max(TypeUtils::sizeOf(typeId), registerSize); + uint32_t size = Support::max(TypeUtils::sizeOf(typeId), minStackArgSize); + if (size >= 8) + stackOffset = Support::alignUp(stackOffset, 8); arg.assignStackOffset(int32_t(stackOffset)); stackOffset += size; } @@ -164,7 +175,9 @@ ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& si vecPos++; } else { - uint32_t size = TypeUtils::sizeOf(typeId); + uint32_t size = Support::max(TypeUtils::sizeOf(typeId), minStackArgSize); + if (size >= 8) + stackOffset = Support::alignUp(stackOffset, 8); arg.assignStackOffset(int32_t(stackOffset)); stackOffset += size; } @@ -178,7 +191,7 @@ ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& si return DebugUtils::errored(kErrorInvalidState); } - func._argStackSize = stackOffset; + func._argStackSize = Support::alignUp(stackOffset, 8u); return kErrorOk; } diff --git a/deps/asmjit/src/asmjit/arm/a64func_p.h b/deps/asmjit/src/asmjit/arm/a64func_p.h index 9f531fc5..7f2221c7 100644 --- a/deps/asmjit/src/asmjit/arm/a64func_p.h +++ b/deps/asmjit/src/asmjit/arm/a64func_p.h @@ -21,7 +21,7 @@ namespace FuncInternal { Error initCallConv(CallConv& cc, CallConvId ccId, const Environment& environment) noexcept; //! Initialize `FuncDetail` (AArch64 specific). -Error initFuncDetail(FuncDetail& func, const FuncSignature& signature, uint32_t registerSize) noexcept; +Error initFuncDetail(FuncDetail& func, const FuncSignature& signature) noexcept; } // {FuncInternal} diff --git a/deps/asmjit/src/asmjit/arm/a64globals.h b/deps/asmjit/src/asmjit/arm/a64globals.h index 103414f0..8093885b 100644 --- a/deps/asmjit/src/asmjit/arm/a64globals.h +++ b/deps/asmjit/src/asmjit/arm/a64globals.h @@ -15,9 +15,6 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64) -// a64 uses everything from arm namespace and adds into it. -using namespace arm; - //! \addtogroup asmjit_a64 //! \{ @@ -293,6 +290,7 @@ struct Inst { kIdPacdza, //!< Instruction 'pacdza'. kIdPacdzb, //!< Instruction 'pacdzb'. kIdPacga, //!< Instruction 'pacga'. + kIdPrfm, //!< Instruction 'prfm'. kIdPssbb, //!< Instruction 'pssbb'. kIdRbit, //!< Instruction 'rbit'. kIdRet, //!< Instruction 'ret'. diff --git a/deps/asmjit/src/asmjit/arm/a64instapi.cpp b/deps/asmjit/src/asmjit/arm/a64instapi.cpp index 82bed0e7..97e23fd9 100644 --- a/deps/asmjit/src/asmjit/arm/a64instapi.cpp +++ b/deps/asmjit/src/asmjit/arm/a64instapi.cpp @@ -15,65 +15,22 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64) +namespace InstInternal { + // a64::InstInternal - Text // ======================== #ifndef ASMJIT_NO_TEXT -Error InstInternal::instIdToString(Arch arch, InstId instId, String& output) noexcept { +Error instIdToString(InstId instId, String& output) noexcept { uint32_t realId = instId & uint32_t(InstIdParts::kRealId); - DebugUtils::unused(arch); - if (ASMJIT_UNLIKELY(!Inst::isDefinedId(realId))) return DebugUtils::errored(kErrorInvalidInstruction); - - char nameData[32]; - size_t nameSize = Support::decodeInstName(nameData, InstDB::_instNameIndexTable[realId], InstDB::_instNameStringTable); - - return output.append(nameData, nameSize); + return InstNameUtils::decode(output, InstDB::_instNameIndexTable[realId], InstDB::_instNameStringTable); } -InstId InstInternal::stringToInstId(Arch arch, const char* s, size_t len) noexcept { - DebugUtils::unused(arch); - - if (ASMJIT_UNLIKELY(!s)) - return Inst::kIdNone; - - if (len == SIZE_MAX) - len = strlen(s); - - if (ASMJIT_UNLIKELY(len == 0 || len > InstDB::kMaxNameSize)) - return Inst::kIdNone; - - uint32_t prefix = uint32_t(s[0]) - 'a'; - if (ASMJIT_UNLIKELY(prefix > 'z' - 'a')) - return Inst::kIdNone; - - size_t base = InstDB::instNameIndex[prefix].start; - size_t end = InstDB::instNameIndex[prefix].end; - - if (ASMJIT_UNLIKELY(!base)) - return Inst::kIdNone; - - char nameData[32]; - for (size_t lim = end - base; lim != 0; lim >>= 1) { - size_t instId = base + (lim >> 1); - size_t nameSize = Support::decodeInstName(nameData, InstDB::_instNameIndexTable[instId], InstDB::_instNameStringTable); - - int result = Support::compareStringViews(s, len, nameData, nameSize); - if (result < 0) - continue; - - if (result > 0) { - base = instId + 1; - lim--; - continue; - } - - return InstId(instId); - } - - return Inst::kIdNone; +InstId stringToInstId(const char* s, size_t len) noexcept { + return InstNameUtils::find(s, len, InstDB::instNameIndex, InstDB::_instNameIndexTable, InstDB::_instNameStringTable); } #endif // !ASMJIT_NO_TEXT @@ -81,9 +38,9 @@ InstId InstInternal::stringToInstId(Arch arch, const char* s, size_t len) noexce // ============================ #ifndef ASMJIT_NO_VALIDATION -ASMJIT_FAVOR_SIZE Error InstInternal::validate(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept { +ASMJIT_FAVOR_SIZE Error validate(const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept { // TODO: - DebugUtils::unused(arch, inst, operands, opCount, validationFlags); + DebugUtils::unused(inst, operands, opCount, validationFlags); return kErrorOk; } #endif // !ASMJIT_NO_VALIDATION @@ -127,13 +84,7 @@ static const InstRWInfoData instRWInfoData[] = { static const uint8_t elementTypeSize[8] = { 0, 1, 2, 4, 8, 4, 4, 0 }; -Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept { - // Unused in Release configuration as the assert is not compiled in. - DebugUtils::unused(arch); - - // Only called when `arch` matches X86 family. - ASMJIT_ASSERT(Environment::isFamilyARM(arch)); - +Error queryRWInfo(const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept { // Get the instruction data. uint32_t realId = inst.id() & uint32_t(InstIdParts::kRealId); @@ -223,10 +174,10 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* if (srcOp.isReg()) { if (srcOp.as().hasElementIndex()) { // Only part of the vector is accessed if element index [] is used. - uint32_t elementType = srcOp.as().elementType(); + VecElementType elementType = srcOp.as().elementType(); uint32_t elementIndex = srcOp.as().elementIndex(); - uint32_t elementSize = elementTypeSize[elementType]; + uint32_t elementSize = elementTypeSize[size_t(elementType)]; uint64_t accessMask = uint64_t(Support::lsbMask(elementSize)) << (elementIndex * elementSize); op._readByteMask &= accessMask; @@ -243,8 +194,7 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* } if (memOp.hasIndex()) { - op.addOpFlags(OpRWFlags::kMemIndexRead); - op.addOpFlags(memOp.isPreOrPost() ? OpRWFlags::kMemIndexWrite : OpRWFlags::kNone); + op.addOpFlags(memOp.isPreOrPost() ? OpRWFlags::kMemIndexRW : OpRWFlags::kMemIndexRead); } } } @@ -258,13 +208,15 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* // ================================= #ifndef ASMJIT_NO_INTROSPECTION -Error InstInternal::queryFeatures(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept { +Error queryFeatures(const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept { // TODO: [ARM] QueryFeatures not implemented yet. - DebugUtils::unused(arch, inst, operands, opCount, out); + DebugUtils::unused(inst, operands, opCount, out); return kErrorOk; } #endif // !ASMJIT_NO_INTROSPECTION +} // {InstInternal} + // a64::InstInternal - Unit // ======================== diff --git a/deps/asmjit/src/asmjit/arm/a64instapi_p.h b/deps/asmjit/src/asmjit/arm/a64instapi_p.h index 320a3e88..535e4bd7 100644 --- a/deps/asmjit/src/asmjit/arm/a64instapi_p.h +++ b/deps/asmjit/src/asmjit/arm/a64instapi_p.h @@ -18,17 +18,17 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64) namespace InstInternal { #ifndef ASMJIT_NO_TEXT -Error ASMJIT_CDECL instIdToString(Arch arch, InstId instId, String& output) noexcept; -InstId ASMJIT_CDECL stringToInstId(Arch arch, const char* s, size_t len) noexcept; +Error ASMJIT_CDECL instIdToString(InstId instId, String& output) noexcept; +InstId ASMJIT_CDECL stringToInstId(const char* s, size_t len) noexcept; #endif // !ASMJIT_NO_TEXT #ifndef ASMJIT_NO_VALIDATION -Error ASMJIT_CDECL validate(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept; +Error ASMJIT_CDECL validate(const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept; #endif // !ASMJIT_NO_VALIDATION #ifndef ASMJIT_NO_INTROSPECTION -Error ASMJIT_CDECL queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept; -Error ASMJIT_CDECL queryFeatures(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept; +Error ASMJIT_CDECL queryRWInfo(const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept; +Error ASMJIT_CDECL queryFeatures(const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept; #endif // !ASMJIT_NO_INTROSPECTION } // {InstInternal} diff --git a/deps/asmjit/src/asmjit/arm/a64instdb.cpp b/deps/asmjit/src/asmjit/arm/a64instdb.cpp index 5d04b71f..b19f8808 100644 --- a/deps/asmjit/src/asmjit/arm/a64instdb.cpp +++ b/deps/asmjit/src/asmjit/arm/a64instdb.cpp @@ -323,505 +323,506 @@ const InstInfo _instInfoTable[] = { INST(Pacdza , BaseR , (0b11011010110000010010101111100000, kX, kZR, 0) , kRWI_X , 0 , 4 ), // #262 INST(Pacdzb , BaseR , (0b11011010110000010010111111100000, kX, kZR, 0) , kRWI_X , 0 , 5 ), // #263 INST(Pacga , BaseRRR , (0b1001101011000000001100, kX, kZR, kX, kZR, kX, kSP, false) , kRWI_W , 0 , 13 ), // #264 - INST(Pssbb , BaseOp , (0b11010101000000110011010010011111) , 0 , 0 , 14 ), // #265 - INST(Rbit , BaseRR , (0b01011010110000000000000000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 11 ), // #266 - INST(Ret , BaseBranchReg , (0b11010110010111110000000000000000) , kRWI_R , 0 , 2 ), // #267 - INST(Rev , BaseRev , (_) , kRWI_W , 0 , 0 ), // #268 - INST(Rev16 , BaseRR , (0b01011010110000000000010000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 12 ), // #269 - INST(Rev32 , BaseRR , (0b11011010110000000000100000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 13 ), // #270 - INST(Rev64 , BaseRR , (0b11011010110000000000110000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 14 ), // #271 - INST(Ror , BaseShift , (0b0001101011000000001011, 0b0001001110000000000000, 1) , kRWI_W , 0 , 6 ), // #272 - INST(Rorv , BaseShift , (0b0001101011000000001011, 0b0000000000000000000000, 1) , kRWI_W , 0 , 7 ), // #273 - INST(Sbc , BaseRRR , (0b0101101000000000000000, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 14 ), // #274 - INST(Sbcs , BaseRRR , (0b0111101000000000000000, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 15 ), // #275 - INST(Sbfiz , BaseBfi , (0b00010011000000000000000000000000) , kRWI_W , 0 , 1 ), // #276 - INST(Sbfm , BaseBfm , (0b00010011000000000000000000000000) , kRWI_W , 0 , 1 ), // #277 - INST(Sbfx , BaseBfx , (0b00010011000000000000000000000000) , kRWI_W , 0 , 1 ), // #278 - INST(Sdiv , BaseRRR , (0b0001101011000000000011, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 16 ), // #279 - INST(Setf8 , BaseR , (0b00111010000000000000100000001101, kW, kZR, 5) , 0 , 0 , 6 ), // #280 - INST(Setf16 , BaseR , (0b00111010000000000100100000001101, kW, kZR, 5) , 0 , 0 , 7 ), // #281 - INST(Sev , BaseOp , (0b11010101000000110010000010011111) , 0 , 0 , 15 ), // #282 - INST(Sevl , BaseOp , (0b11010101000000110010000010111111) , 0 , 0 , 16 ), // #283 - INST(Smaddl , BaseRRRR , (0b1001101100100000000000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false) , kRWI_W , 0 , 2 ), // #284 - INST(Smc , BaseOpImm , (0b11010100000000000000000000000011, 16, 5) , 0 , 0 , 11 ), // #285 - INST(Smnegl , BaseRRR , (0b1001101100100000111111, kX , kZR, kW , kZR, kW , kZR, false) , kRWI_W , 0 , 17 ), // #286 - INST(Smsubl , BaseRRRR , (0b1001101100100000100000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false) , kRWI_W , 0 , 3 ), // #287 - INST(Smulh , BaseRRR , (0b1001101101000000011111, kX , kZR, kX , kZR, kX , kZR, true) , kRWI_W , 0 , 18 ), // #288 - INST(Smull , BaseRRR , (0b1001101100100000011111, kX , kZR, kW , kZR, kW , kZR, false) , kRWI_W , 0 , 19 ), // #289 - INST(Ssbb , BaseOp , (0b11010101000000110011000010011111) , 0 , 0 , 17 ), // #290 - INST(St2g , BaseRM_SImm9 , (0b1101100110100000000010, 0b1101100110100000000001, kX, kSP, 0, 4) , kRWI_RW , 0 , 13 ), // #291 - INST(Stadd , BaseAtomicSt , (0b1011100000100000000000, kWX, 30) , kRWI_RX , 0 , 0 ), // #292 - INST(Staddl , BaseAtomicSt , (0b1011100001100000000000, kWX, 30) , kRWI_RX , 0 , 1 ), // #293 - INST(Staddb , BaseAtomicSt , (0b0011100000100000000000, kW , 0 ) , kRWI_RX , 0 , 2 ), // #294 - INST(Staddlb , BaseAtomicSt , (0b0011100001100000000000, kW , 0 ) , kRWI_RX , 0 , 3 ), // #295 - INST(Staddh , BaseAtomicSt , (0b0111100000100000000000, kW , 0 ) , kRWI_RX , 0 , 4 ), // #296 - INST(Staddlh , BaseAtomicSt , (0b0111100001100000000000, kW , 0 ) , kRWI_RX , 0 , 5 ), // #297 - INST(Stclr , BaseAtomicSt , (0b1011100000100000000100, kWX, 30) , kRWI_RX , 0 , 6 ), // #298 - INST(Stclrl , BaseAtomicSt , (0b1011100001100000000100, kWX, 30) , kRWI_RX , 0 , 7 ), // #299 - INST(Stclrb , BaseAtomicSt , (0b0011100000100000000100, kW , 0 ) , kRWI_RX , 0 , 8 ), // #300 - INST(Stclrlb , BaseAtomicSt , (0b0011100001100000000100, kW , 0 ) , kRWI_RX , 0 , 9 ), // #301 - INST(Stclrh , BaseAtomicSt , (0b0111100000100000000100, kW , 0 ) , kRWI_RX , 0 , 10 ), // #302 - INST(Stclrlh , BaseAtomicSt , (0b0111100001100000000100, kW , 0 ) , kRWI_RX , 0 , 11 ), // #303 - INST(Steor , BaseAtomicSt , (0b1011100000100000001000, kWX, 30) , kRWI_RX , 0 , 12 ), // #304 - INST(Steorl , BaseAtomicSt , (0b1011100001100000001000, kWX, 30) , kRWI_RX , 0 , 13 ), // #305 - INST(Steorb , BaseAtomicSt , (0b0011100000100000001000, kW , 0 ) , kRWI_RX , 0 , 14 ), // #306 - INST(Steorlb , BaseAtomicSt , (0b0011100001100000001000, kW , 0 ) , kRWI_RX , 0 , 15 ), // #307 - INST(Steorh , BaseAtomicSt , (0b0111100000100000001000, kW , 0 ) , kRWI_RX , 0 , 16 ), // #308 - INST(Steorlh , BaseAtomicSt , (0b0111100001100000001000, kW , 0 ) , kRWI_RX , 0 , 17 ), // #309 - INST(Stg , BaseRM_SImm9 , (0b1101100100100000000010, 0b1101100100100000000001, kX, kSP, 0, 4) , kRWI_RW , 0 , 14 ), // #310 - INST(Stgm , BaseRM_NoImm , (0b1101100110100000000000, kX , kZR, 0 ) , kRWI_RW , 0 , 13 ), // #311 - INST(Stgp , BaseLdpStp , (0b0110100100, 0b0110100010, kX, 0, 4) , kRWI_RRW , 0 , 3 ), // #312 - INST(Stllr , BaseRM_NoImm , (0b1000100010011111011111, kWX, kZR, 30) , kRWI_RW , 0 , 14 ), // #313 - INST(Stllrb , BaseRM_NoImm , (0b0000100010011111011111, kW , kZR, 0 ) , kRWI_RW , 0 , 15 ), // #314 - INST(Stllrh , BaseRM_NoImm , (0b0100100010011111011111, kW , kZR, 0 ) , kRWI_RW , 0 , 16 ), // #315 - INST(Stlr , BaseRM_NoImm , (0b1000100010011111111111, kWX, kZR, 30) , kRWI_RW , 0 , 17 ), // #316 - INST(Stlrb , BaseRM_NoImm , (0b0000100010011111111111, kW , kZR, 0 ) , kRWI_RW , 0 , 18 ), // #317 - INST(Stlrh , BaseRM_NoImm , (0b0100100010011111111111, kW , kZR, 0 ) , kRWI_RW , 0 , 19 ), // #318 - INST(Stlxp , BaseStxp , (0b1000100000100000100000, kWX, 30) , kRWI_WRRX , 0 , 0 ), // #319 - INST(Stlxr , BaseAtomicOp , (0b1000100000000000111111, kWX, 30, 1) , kRWI_WRX , 0 , 108), // #320 - INST(Stlxrb , BaseAtomicOp , (0b0000100000000000111111, kW , 0 , 1) , kRWI_WRX , 0 , 109), // #321 - INST(Stlxrh , BaseAtomicOp , (0b0100100000000000111111, kW , 0 , 1) , kRWI_WRX , 0 , 110), // #322 - INST(Stnp , BaseLdpStp , (0b0010100000, 0 , kWX, 31, 2) , kRWI_RRW , 0 , 4 ), // #323 - INST(Stp , BaseLdpStp , (0b0010100100, 0b0010100010, kWX, 31, 2) , kRWI_RRW , 0 , 5 ), // #324 - INST(Str , BaseLdSt , (0b1011100100, 0b10111000000, 0b10111000001, 0 , kWX, 30, 2, Inst::kIdStur) , kRWI_RW , 0 , 6 ), // #325 - INST(Strb , BaseLdSt , (0b0011100100, 0b00111000000, 0b00111000001, 0 , kW , 30, 0, Inst::kIdSturb) , kRWI_RW , 0 , 7 ), // #326 - INST(Strh , BaseLdSt , (0b0111100100, 0b01111000000, 0b01111000001, 0 , kWX, 30, 1, Inst::kIdSturh) , kRWI_RW , 0 , 8 ), // #327 - INST(Stset , BaseAtomicSt , (0b1011100000100000001100, kWX, 30) , kRWI_RX , 0 , 18 ), // #328 - INST(Stsetl , BaseAtomicSt , (0b1011100001100000001100, kWX, 30) , kRWI_RX , 0 , 19 ), // #329 - INST(Stsetb , BaseAtomicSt , (0b0011100000100000001100, kW , 0 ) , kRWI_RX , 0 , 20 ), // #330 - INST(Stsetlb , BaseAtomicSt , (0b0011100001100000001100, kW , 0 ) , kRWI_RX , 0 , 21 ), // #331 - INST(Stseth , BaseAtomicSt , (0b0111100000100000001100, kW , 0 ) , kRWI_RX , 0 , 22 ), // #332 - INST(Stsetlh , BaseAtomicSt , (0b0111100001100000001100, kW , 0 ) , kRWI_RX , 0 , 23 ), // #333 - INST(Stsmax , BaseAtomicSt , (0b1011100000100000010000, kWX, 30) , kRWI_RX , 0 , 24 ), // #334 - INST(Stsmaxl , BaseAtomicSt , (0b1011100001100000010000, kWX, 30) , kRWI_RX , 0 , 25 ), // #335 - INST(Stsmaxb , BaseAtomicSt , (0b0011100000100000010000, kW , 0 ) , kRWI_RX , 0 , 26 ), // #336 - INST(Stsmaxlb , BaseAtomicSt , (0b0011100001100000010000, kW , 0 ) , kRWI_RX , 0 , 27 ), // #337 - INST(Stsmaxh , BaseAtomicSt , (0b0111100000100000010000, kW , 0 ) , kRWI_RX , 0 , 28 ), // #338 - INST(Stsmaxlh , BaseAtomicSt , (0b0111100001100000010000, kW , 0 ) , kRWI_RX , 0 , 29 ), // #339 - INST(Stsmin , BaseAtomicSt , (0b1011100000100000010100, kWX, 30) , kRWI_RX , 0 , 30 ), // #340 - INST(Stsminl , BaseAtomicSt , (0b1011100001100000010100, kWX, 30) , kRWI_RX , 0 , 31 ), // #341 - INST(Stsminb , BaseAtomicSt , (0b0011100000100000010100, kW , 0 ) , kRWI_RX , 0 , 32 ), // #342 - INST(Stsminlb , BaseAtomicSt , (0b0011100001100000010100, kW , 0 ) , kRWI_RX , 0 , 33 ), // #343 - INST(Stsminh , BaseAtomicSt , (0b0111100000100000010100, kW , 0 ) , kRWI_RX , 0 , 34 ), // #344 - INST(Stsminlh , BaseAtomicSt , (0b0111100001100000010100, kW , 0 ) , kRWI_RX , 0 , 35 ), // #345 - INST(Sttr , BaseRM_SImm9 , (0b1011100000000000000010, 0b0000000000000000000000, kWX, kZR, 30, 0) , kRWI_RW , 0 , 15 ), // #346 - INST(Sttrb , BaseRM_SImm9 , (0b0011100000000000000010, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_RW , 0 , 16 ), // #347 - INST(Sttrh , BaseRM_SImm9 , (0b0111100000000000000010, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_RW , 0 , 17 ), // #348 - INST(Stumax , BaseAtomicSt , (0b1011100000100000011000, kWX, 30) , kRWI_RX , 0 , 36 ), // #349 - INST(Stumaxl , BaseAtomicSt , (0b1011100001100000011000, kWX, 30) , kRWI_RX , 0 , 37 ), // #350 - INST(Stumaxb , BaseAtomicSt , (0b0011100000100000011000, kW , 0 ) , kRWI_RX , 0 , 38 ), // #351 - INST(Stumaxlb , BaseAtomicSt , (0b0011100001100000011000, kW , 0 ) , kRWI_RX , 0 , 39 ), // #352 - INST(Stumaxh , BaseAtomicSt , (0b0111100000100000011000, kW , 0 ) , kRWI_RX , 0 , 40 ), // #353 - INST(Stumaxlh , BaseAtomicSt , (0b0111100001100000011000, kW , 0 ) , kRWI_RX , 0 , 41 ), // #354 - INST(Stumin , BaseAtomicSt , (0b1011100000100000011100, kWX, 30) , kRWI_RX , 0 , 42 ), // #355 - INST(Stuminl , BaseAtomicSt , (0b1011100001100000011100, kWX, 30) , kRWI_RX , 0 , 43 ), // #356 - INST(Stuminb , BaseAtomicSt , (0b0011100000100000011100, kW , 0 ) , kRWI_RX , 0 , 44 ), // #357 - INST(Stuminlb , BaseAtomicSt , (0b0011100001100000011100, kW , 0 ) , kRWI_RX , 0 , 45 ), // #358 - INST(Stuminh , BaseAtomicSt , (0b0111100000100000011100, kW , 0 ) , kRWI_RX , 0 , 46 ), // #359 - INST(Stuminlh , BaseAtomicSt , (0b0111100001100000011100, kW , 0 ) , kRWI_RX , 0 , 47 ), // #360 - INST(Stur , BaseRM_SImm9 , (0b1011100000000000000000, 0b0000000000000000000000, kWX, kZR, 30, 0) , kRWI_RW , 0 , 18 ), // #361 - INST(Sturb , BaseRM_SImm9 , (0b0011100000000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_RW , 0 , 19 ), // #362 - INST(Sturh , BaseRM_SImm9 , (0b0111100000000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_RW , 0 , 20 ), // #363 - INST(Stxp , BaseStxp , (0b1000100000100000000000, kWX, 30) , kRWI_WRRW , 0 , 1 ), // #364 - INST(Stxr , BaseStx , (0b1000100000000000011111, kWX, 30) , kRWI_WRW , 0 , 0 ), // #365 - INST(Stxrb , BaseStx , (0b0000100000000000011111, kW , 0 ) , kRWI_WRW , 0 , 1 ), // #366 - INST(Stxrh , BaseStx , (0b0100100000000000011111, kW , 0 ) , kRWI_WRW , 0 , 2 ), // #367 - INST(Stz2g , BaseRM_SImm9 , (0b1101100111100000000010, 0b1101100111100000000001, kX , kSP, 0, 4) , kRWI_RW , 0 , 21 ), // #368 - INST(Stzg , BaseRM_SImm9 , (0b1101100101100000000010, 0b1101100101100000000001, kX , kSP, 0, 4) , kRWI_RW , 0 , 22 ), // #369 - INST(Stzgm , BaseRM_NoImm , (0b1101100100100000000000, kX , kZR, 0) , kRWI_RW , 0 , 20 ), // #370 - INST(Sub , BaseAddSub , (0b1001011000, 0b1001011001, 0b1010001) , kRWI_X , 0 , 2 ), // #371 - INST(Subg , BaseRRII , (0b1101000110000000000000, kX, kSP, kX, kSP, 6, 4, 16, 4, 0, 10) , kRWI_W , 0 , 1 ), // #372 - INST(Subp , BaseRRR , (0b1001101011000000000000, kX, kZR, kX, kSP, kX, kSP, false) , kRWI_W , 0 , 20 ), // #373 - INST(Subps , BaseRRR , (0b1011101011000000000000, kX, kZR, kX, kSP, kX, kSP, false) , kRWI_W , 0 , 21 ), // #374 - INST(Subs , BaseAddSub , (0b1101011000, 0b1101011001, 0b1110001) , kRWI_X , 0 , 3 ), // #375 - INST(Svc , BaseOpImm , (0b11010100000000000000000000000001, 16, 5) , 0 , 0 , 12 ), // #376 - INST(Swp , BaseAtomicOp , (0b1011100000100000100000, kWX, 30, 1) , kRWI_RWX , 0 , 111), // #377 - INST(Swpa , BaseAtomicOp , (0b1011100010100000100000, kWX, 30, 1) , kRWI_RWX , 0 , 112), // #378 - INST(Swpab , BaseAtomicOp , (0b0011100010100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 113), // #379 - INST(Swpah , BaseAtomicOp , (0b0111100010100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 114), // #380 - INST(Swpal , BaseAtomicOp , (0b1011100011100000100000, kWX, 30, 1) , kRWI_RWX , 0 , 115), // #381 - INST(Swpalb , BaseAtomicOp , (0b0011100011100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 116), // #382 - INST(Swpalh , BaseAtomicOp , (0b0111100011100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 117), // #383 - INST(Swpb , BaseAtomicOp , (0b0011100000100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 118), // #384 - INST(Swph , BaseAtomicOp , (0b0111100000100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 119), // #385 - INST(Swpl , BaseAtomicOp , (0b1011100001100000100000, kWX, 30, 1) , kRWI_RWX , 0 , 120), // #386 - INST(Swplb , BaseAtomicOp , (0b0011100001100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 121), // #387 - INST(Swplh , BaseAtomicOp , (0b0111100001100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 122), // #388 - INST(Sxtb , BaseExtend , (0b0001001100000000000111, kWX, 0) , kRWI_W , 0 , 0 ), // #389 - INST(Sxth , BaseExtend , (0b0001001100000000001111, kWX, 0) , kRWI_W , 0 , 1 ), // #390 - INST(Sxtw , BaseExtend , (0b1001001101000000011111, kX , 0) , kRWI_W , 0 , 2 ), // #391 - INST(Sys , BaseSys , (_) , kRWI_W , 0 , 0 ), // #392 - INST(Tlbi , BaseAtDcIcTlbi , (0b00011110000000, 0b00010000000000, false) , kRWI_RX , 0 , 3 ), // #393 - INST(Tst , BaseTst , (0b1101010000, 0b111001000) , kRWI_R , 0 , 0 ), // #394 - INST(Tbnz , BaseBranchTst , (0b00110111000000000000000000000000) , kRWI_R , 0 , 0 ), // #395 - INST(Tbz , BaseBranchTst , (0b00110110000000000000000000000000) , kRWI_R , 0 , 1 ), // #396 - INST(Ubfiz , BaseBfi , (0b01010011000000000000000000000000) , kRWI_W , 0 , 2 ), // #397 - INST(Ubfm , BaseBfm , (0b01010011000000000000000000000000) , kRWI_W , 0 , 2 ), // #398 - INST(Ubfx , BaseBfx , (0b01010011000000000000000000000000) , kRWI_W , 0 , 2 ), // #399 - INST(Udf , BaseOpImm , (0b00000000000000000000000000000000, 16, 0) , 0 , 0 , 13 ), // #400 - INST(Udiv , BaseRRR , (0b0001101011000000000010, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 22 ), // #401 - INST(Umaddl , BaseRRRR , (0b1001101110100000000000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false) , kRWI_W , 0 , 4 ), // #402 - INST(Umnegl , BaseRRR , (0b1001101110100000111111, kX , kZR, kW , kZR, kW , kZR, false) , kRWI_W , 0 , 23 ), // #403 - INST(Umull , BaseRRR , (0b1001101110100000011111, kX , kZR, kW , kZR, kW , kZR, false) , kRWI_W , 0 , 24 ), // #404 - INST(Umulh , BaseRRR , (0b1001101111000000011111, kX , kZR, kX , kZR, kX , kZR, false) , kRWI_W , 0 , 25 ), // #405 - INST(Umsubl , BaseRRRR , (0b1001101110100000100000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false) , kRWI_W , 0 , 5 ), // #406 - INST(Uxtb , BaseExtend , (0b0101001100000000000111, kW, 1) , kRWI_W , 0 , 3 ), // #407 - INST(Uxth , BaseExtend , (0b0101001100000000001111, kW, 1) , kRWI_W , 0 , 4 ), // #408 - INST(Wfe , BaseOp , (0b11010101000000110010000001011111) , 0 , 0 , 18 ), // #409 - INST(Wfi , BaseOp , (0b11010101000000110010000001111111) , 0 , 0 , 19 ), // #410 - INST(Xaflag , BaseOp , (0b11010101000000000100000000111111) , 0 , 0 , 20 ), // #411 - INST(Xpacd , BaseR , (0b11011010110000010100011111100000, kX, kZR, 0) , kRWI_X , 0 , 8 ), // #412 - INST(Xpaci , BaseR , (0b11011010110000010100001111100000, kX, kZR, 0) , kRWI_X , 0 , 9 ), // #413 - INST(Xpaclri , BaseOp , (0b11010101000000110010000011111111) , kRWI_X , 0 , 21 ), // #414 - INST(Yield , BaseOp , (0b11010101000000110010000000111111) , 0 , 0 , 22 ), // #415 - INST(Abs_v , ISimdVV , (0b0000111000100000101110, kVO_V_Any) , kRWI_W , 0 , 0 ), // #416 - INST(Add_v , ISimdVVV , (0b0000111000100000100001, kVO_V_Any) , kRWI_W , 0 , 0 ), // #417 - INST(Addhn_v , ISimdVVV , (0b0000111000100000010000, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 1 ), // #418 - INST(Addhn2_v , ISimdVVV , (0b0100111000100000010000, kVO_V_B16H8S4) , kRWI_W , F(Narrow) , 2 ), // #419 - INST(Addp_v , ISimdPair , (0b0101111000110001101110, 0b0000111000100000101111, kVO_V_Any) , kRWI_W , F(Pair) , 0 ), // #420 - INST(Addv_v , ISimdSV , (0b0000111000110001101110, kVO_V_BH_4S) , kRWI_W , 0 , 0 ), // #421 - INST(Aesd_v , ISimdVVx , (0b0100111000101000010110, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 0 ), // #422 - INST(Aese_v , ISimdVVx , (0b0100111000101000010010, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 1 ), // #423 - INST(Aesimc_v , ISimdVVx , (0b0100111000101000011110, kOp_V16B, kOp_V16B) , kRWI_W , 0 , 2 ), // #424 - INST(Aesmc_v , ISimdVVx , (0b0100111000101000011010, kOp_V16B, kOp_V16B) , kRWI_W , 0 , 3 ), // #425 - INST(And_v , ISimdVVV , (0b0000111000100000000111, kVO_V_B) , kRWI_W , 0 , 3 ), // #426 - INST(Bcax_v , ISimdVVVV , (0b1100111000100000000000, kVO_V_B16) , kRWI_W , 0 , 0 ), // #427 - INST(Bfcvt_v , ISimdVVx , (0b0001111001100011010000, kOp_H, kOp_S) , kRWI_W , 0 , 4 ), // #428 - INST(Bfcvtn_v , ISimdVVx , (0b0000111010100001011010, kOp_V4H, kOp_V4S) , kRWI_W , F(Narrow) , 5 ), // #429 - INST(Bfcvtn2_v , ISimdVVx , (0b0100111010100001011010, kOp_V8H, kOp_V4S) , kRWI_W , F(Narrow) , 6 ), // #430 - INST(Bfdot_v , SimdDot , (0b0010111001000000111111, 0b0000111101000000111100, kET_S, kET_H, kET_2H) , kRWI_X , 0 , 0 ), // #431 - INST(Bfmlalb_v , SimdFmlal , (0b0010111011000000111111, 0b0000111111000000111100, 0, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 0 ), // #432 - INST(Bfmlalt_v , SimdFmlal , (0b0110111011000000111111, 0b0100111111000000111100, 0, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 1 ), // #433 - INST(Bfmmla_v , ISimdVVVx , (0b0110111001000000111011, kOp_V4S, kOp_V8H, kOp_V8H) , kRWI_X , F(Long) , 0 ), // #434 - INST(Bic_v , SimdBicOrr , (0b0000111001100000000111, 0b0010111100000000000001) , kRWI_W , 0 , 0 ), // #435 - INST(Bif_v , ISimdVVV , (0b0010111011100000000111, kVO_V_B) , kRWI_X , 0 , 4 ), // #436 - INST(Bit_v , ISimdVVV , (0b0010111010100000000111, kVO_V_B) , kRWI_X , 0 , 5 ), // #437 - INST(Bsl_v , ISimdVVV , (0b0010111001100000000111, kVO_V_B) , kRWI_X , 0 , 6 ), // #438 - INST(Cls_v , ISimdVV , (0b0000111000100000010010, kVO_V_BHS) , kRWI_W , 0 , 1 ), // #439 - INST(Clz_v , ISimdVV , (0b0010111000100000010010, kVO_V_BHS) , kRWI_W , 0 , 2 ), // #440 - INST(Cmeq_v , SimdCmp , (0b0010111000100000100011, 0b0000111000100000100110, kVO_V_Any) , kRWI_W , 0 , 0 ), // #441 - INST(Cmge_v , SimdCmp , (0b0000111000100000001111, 0b0010111000100000100010, kVO_V_Any) , kRWI_W , 0 , 1 ), // #442 - INST(Cmgt_v , SimdCmp , (0b0000111000100000001101, 0b0000111000100000100010, kVO_V_Any) , kRWI_W , 0 , 2 ), // #443 - INST(Cmhi_v , SimdCmp , (0b0010111000100000001101, 0b0000000000000000000000, kVO_V_Any) , kRWI_W , 0 , 3 ), // #444 - INST(Cmhs_v , SimdCmp , (0b0010111000100000001111, 0b0000000000000000000000, kVO_V_Any) , kRWI_W , 0 , 4 ), // #445 - INST(Cmle_v , SimdCmp , (0b0000000000000000000000, 0b0010111000100000100110, kVO_V_Any) , kRWI_W , 0 , 5 ), // #446 - INST(Cmlt_v , SimdCmp , (0b0000000000000000000000, 0b0000111000100000101010, kVO_V_Any) , kRWI_W , 0 , 6 ), // #447 - INST(Cmtst_v , ISimdVVV , (0b0000111000100000100011, kVO_V_Any) , kRWI_W , 0 , 7 ), // #448 - INST(Cnt_v , ISimdVV , (0b0000111000100000010110, kVO_V_B) , kRWI_W , 0 , 3 ), // #449 - INST(Dup_v , SimdDup , (_) , kRWI_W , 0 , 0 ), // #450 - INST(Eor_v , ISimdVVV , (0b0010111000100000000111, kVO_V_B) , kRWI_W , 0 , 8 ), // #451 - INST(Eor3_v , ISimdVVVV , (0b1100111000000000000000, kVO_V_B16) , kRWI_W , 0 , 1 ), // #452 - INST(Ext_v , ISimdVVVI , (0b0010111000000000000000, kVO_V_B, 4, 11, 1) , kRWI_W , 0 , 0 ), // #453 - INST(Fabd_v , FSimdVVV , (0b0111111010100000110101, kHF_C, 0b0010111010100000110101, kHF_C) , kRWI_W , 0 , 0 ), // #454 - INST(Fabs_v , FSimdVV , (0b0001111000100000110000, kHF_A, 0b0000111010100000111110, kHF_B) , kRWI_W , 0 , 0 ), // #455 - INST(Facge_v , FSimdVVV , (0b0111111000100000111011, kHF_C, 0b0010111000100000111011, kHF_C) , kRWI_W , 0 , 1 ), // #456 - INST(Facgt_v , FSimdVVV , (0b0111111010100000111011, kHF_C, 0b0010111010100000111011, kHF_C) , kRWI_W , 0 , 2 ), // #457 - INST(Fadd_v , FSimdVVV , (0b0001111000100000001010, kHF_A, 0b0000111000100000110101, kHF_C) , kRWI_W , 0 , 3 ), // #458 - INST(Faddp_v , FSimdPair , (0b0111111000110000110110, 0b0010111000100000110101) , kRWI_W , 0 , 0 ), // #459 - INST(Fcadd_v , SimdFcadd , (0b0010111000000000111001) , kRWI_W , 0 , 0 ), // #460 - INST(Fccmp_v , SimdFccmpFccmpe , (0b00011110001000000000010000000000) , kRWI_R , 0 , 0 ), // #461 - INST(Fccmpe_v , SimdFccmpFccmpe , (0b00011110001000000000010000010000) , kRWI_R , 0 , 1 ), // #462 - INST(Fcmeq_v , SimdFcm , (0b0000111000100000111001, kHF_C, 0b0000111010100000110110) , kRWI_W , 0 , 0 ), // #463 - INST(Fcmge_v , SimdFcm , (0b0010111000100000111001, kHF_C, 0b0010111010100000110010) , kRWI_W , 0 , 1 ), // #464 - INST(Fcmgt_v , SimdFcm , (0b0010111010100000111001, kHF_C, 0b0000111010100000110010) , kRWI_W , 0 , 2 ), // #465 - INST(Fcmla_v , SimdFcmla , (0b0010111000000000110001, 0b0010111100000000000100) , kRWI_X , 0 , 0 ), // #466 - INST(Fcmle_v , SimdFcm , (0b0000000000000000000000, kHF_C, 0b0010111010100000110110) , kRWI_W , 0 , 3 ), // #467 - INST(Fcmlt_v , SimdFcm , (0b0000000000000000000000, kHF_C, 0b0000111010100000111010) , kRWI_W , 0 , 4 ), // #468 - INST(Fcmp_v , SimdFcmpFcmpe , (0b00011110001000000010000000000000) , kRWI_R , 0 , 0 ), // #469 - INST(Fcmpe_v , SimdFcmpFcmpe , (0b00011110001000000010000000010000) , kRWI_R , 0 , 1 ), // #470 - INST(Fcsel_v , SimdFcsel , (_) , kRWI_W , 0 , 0 ), // #471 - INST(Fcvt_v , SimdFcvt , (_) , kRWI_W , 0 , 0 ), // #472 - INST(Fcvtas_v , SimdFcvtSV , (0b0000111000100001110010, 0b0000000000000000000000, 0b0001111000100100000000, 1) , kRWI_W , 0 , 0 ), // #473 - INST(Fcvtau_v , SimdFcvtSV , (0b0010111000100001110010, 0b0000000000000000000000, 0b0001111000100101000000, 1) , kRWI_W , 0 , 1 ), // #474 - INST(Fcvtl_v , SimdFcvtLN , (0b0000111000100001011110, 0, 0) , kRWI_W , F(Long) , 0 ), // #475 - INST(Fcvtl2_v , SimdFcvtLN , (0b0100111000100001011110, 0, 0) , kRWI_W , F(Long) , 1 ), // #476 - INST(Fcvtms_v , SimdFcvtSV , (0b0000111000100001101110, 0b0000000000000000000000, 0b0001111000110000000000, 1) , kRWI_W , 0 , 2 ), // #477 - INST(Fcvtmu_v , SimdFcvtSV , (0b0010111000100001101110, 0b0000000000000000000000, 0b0001111000110001000000, 1) , kRWI_W , 0 , 3 ), // #478 - INST(Fcvtn_v , SimdFcvtLN , (0b0000111000100001011010, 0, 0) , kRWI_W , F(Narrow) , 2 ), // #479 - INST(Fcvtn2_v , SimdFcvtLN , (0b0100111000100001011010, 0, 0) , kRWI_X , F(Narrow) , 3 ), // #480 - INST(Fcvtns_v , SimdFcvtSV , (0b0000111000100001101010, 0b0000000000000000000000, 0b0001111000100000000000, 1) , kRWI_W , 0 , 4 ), // #481 - INST(Fcvtnu_v , SimdFcvtSV , (0b0010111000100001101010, 0b0000000000000000000000, 0b0001111000100001000000, 1) , kRWI_W , 0 , 5 ), // #482 - INST(Fcvtps_v , SimdFcvtSV , (0b0000111010100001101010, 0b0000000000000000000000, 0b0001111000101000000000, 1) , kRWI_W , 0 , 6 ), // #483 - INST(Fcvtpu_v , SimdFcvtSV , (0b0010111010100001101010, 0b0000000000000000000000, 0b0001111000101001000000, 1) , kRWI_W , 0 , 7 ), // #484 - INST(Fcvtxn_v , SimdFcvtLN , (0b0010111000100001011010, 1, 1) , kRWI_W , F(Narrow) , 4 ), // #485 - INST(Fcvtxn2_v , SimdFcvtLN , (0b0110111000100001011010, 1, 0) , kRWI_X , F(Narrow) , 5 ), // #486 - INST(Fcvtzs_v , SimdFcvtSV , (0b0000111010100001101110, 0b0000111100000000111111, 0b0001111000111000000000, 1) , kRWI_W , 0 , 8 ), // #487 - INST(Fcvtzu_v , SimdFcvtSV , (0b0010111010100001101110, 0b0010111100000000111111, 0b0001111000111001000000, 1) , kRWI_W , 0 , 9 ), // #488 - INST(Fdiv_v , FSimdVVV , (0b0001111000100000000110, kHF_A, 0b0010111000100000111111, kHF_C) , kRWI_W , 0 , 4 ), // #489 - INST(Fjcvtzs_v , ISimdVVx , (0b0001111001111110000000, kOp_GpW, kOp_D) , kRWI_W , 0 , 7 ), // #490 - INST(Fmadd_v , FSimdVVVV , (0b0001111100000000000000, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 0 ), // #491 - INST(Fmax_v , FSimdVVV , (0b0001111000100000010010, kHF_A, 0b0000111000100000111101, kHF_C) , kRWI_W , 0 , 5 ), // #492 - INST(Fmaxnm_v , FSimdVVV , (0b0001111000100000011010, kHF_A, 0b0000111000100000110001, kHF_C) , kRWI_W , 0 , 6 ), // #493 - INST(Fmaxnmp_v , FSimdPair , (0b0111111000110000110010, 0b0010111000100000110001) , kRWI_W , 0 , 1 ), // #494 - INST(Fmaxnmv_v , FSimdSV , (0b0010111000110000110010) , kRWI_W , 0 , 0 ), // #495 - INST(Fmaxp_v , FSimdPair , (0b0111111000110000111110, 0b0010111000100000111101) , kRWI_W , 0 , 2 ), // #496 - INST(Fmaxv_v , FSimdSV , (0b0010111000110000111110) , kRWI_W , 0 , 1 ), // #497 - INST(Fmin_v , FSimdVVV , (0b0001111000100000010110, kHF_A, 0b0000111010100000111101, kHF_C) , kRWI_W , 0 , 7 ), // #498 - INST(Fminnm_v , FSimdVVV , (0b0001111000100000011110, kHF_A, 0b0000111010100000110001, kHF_C) , kRWI_W , 0 , 8 ), // #499 - INST(Fminnmp_v , FSimdPair , (0b0111111010110000110010, 0b0010111010100000110001) , kRWI_W , 0 , 3 ), // #500 - INST(Fminnmv_v , FSimdSV , (0b0010111010110000110010) , kRWI_W , 0 , 2 ), // #501 - INST(Fminp_v , FSimdPair , (0b0111111010110000111110, 0b0010111010100000111101) , kRWI_W , 0 , 4 ), // #502 - INST(Fminv_v , FSimdSV , (0b0010111010110000111110) , kRWI_W , 0 , 3 ), // #503 - INST(Fmla_v , FSimdVVVe , (0b0000000000000000000000, kHF_N, 0b0000111000100000110011, 0b0000111110000000000100) , kRWI_X , F(VH0_15) , 0 ), // #504 - INST(Fmlal_v , SimdFmlal , (0b0000111000100000111011, 0b0000111110000000000000, 1, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 2 ), // #505 - INST(Fmlal2_v , SimdFmlal , (0b0010111000100000110011, 0b0010111110000000100000, 1, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 3 ), // #506 - INST(Fmls_v , FSimdVVVe , (0b0000000000000000000000, kHF_N, 0b0000111010100000110011, 0b0000111110000000010100) , kRWI_X , F(VH0_15) , 1 ), // #507 - INST(Fmlsl_v , SimdFmlal , (0b0000111010100000111011, 0b0000111110000000010000, 1, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 4 ), // #508 - INST(Fmlsl2_v , SimdFmlal , (0b0010111010100000110011, 0b0010111110000000110000, 1, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 5 ), // #509 - INST(Fmov_v , SimdFmov , (_) , kRWI_W , 0 , 0 ), // #510 - INST(Fmsub_v , FSimdVVVV , (0b0001111100000000100000, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 1 ), // #511 - INST(Fmul_v , FSimdVVVe , (0b0001111000100000000010, kHF_A, 0b0010111000100000110111, 0b0000111110000000100100) , kRWI_W , F(VH0_15) , 2 ), // #512 - INST(Fmulx_v , FSimdVVVe , (0b0101111000100000110111, kHF_C, 0b0000111000100000110111, 0b0010111110000000100100) , kRWI_W , F(VH0_15) , 3 ), // #513 - INST(Fneg_v , FSimdVV , (0b0001111000100001010000, kHF_A, 0b0010111010100000111110, kHF_B) , kRWI_W , 0 , 1 ), // #514 - INST(Fnmadd_v , FSimdVVVV , (0b0001111100100000000000, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 2 ), // #515 - INST(Fnmsub_v , FSimdVVVV , (0b0001111100100000100000, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 3 ), // #516 - INST(Fnmul_v , FSimdVVV , (0b0001111000100000100010, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 9 ), // #517 - INST(Frecpe_v , FSimdVV , (0b0101111010100001110110, kHF_B, 0b0000111010100001110110, kHF_B) , kRWI_W , 0 , 2 ), // #518 - INST(Frecps_v , FSimdVVV , (0b0101111000100000111111, kHF_C, 0b0000111000100000111111, kHF_C) , kRWI_W , 0 , 10 ), // #519 - INST(Frecpx_v , FSimdVV , (0b0101111010100001111110, kHF_B, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 3 ), // #520 - INST(Frint32x_v , FSimdVV , (0b0001111000101000110000, kHF_N, 0b0010111000100001111010, kHF_N) , kRWI_W , 0 , 4 ), // #521 - INST(Frint32z_v , FSimdVV , (0b0001111000101000010000, kHF_N, 0b0000111000100001111010, kHF_N) , kRWI_W , 0 , 5 ), // #522 - INST(Frint64x_v , FSimdVV , (0b0001111000101001110000, kHF_N, 0b0010111000100001111110, kHF_N) , kRWI_W , 0 , 6 ), // #523 - INST(Frint64z_v , FSimdVV , (0b0001111000101001010000, kHF_N, 0b0000111000100001111110, kHF_N) , kRWI_W , 0 , 7 ), // #524 - INST(Frinta_v , FSimdVV , (0b0001111000100110010000, kHF_A, 0b0010111000100001100010, kHF_B) , kRWI_W , 0 , 8 ), // #525 - INST(Frinti_v , FSimdVV , (0b0001111000100111110000, kHF_A, 0b0010111010100001100110, kHF_B) , kRWI_W , 0 , 9 ), // #526 - INST(Frintm_v , FSimdVV , (0b0001111000100101010000, kHF_A, 0b0000111000100001100110, kHF_B) , kRWI_W , 0 , 10 ), // #527 - INST(Frintn_v , FSimdVV , (0b0001111000100100010000, kHF_A, 0b0000111000100001100010, kHF_B) , kRWI_W , 0 , 11 ), // #528 - INST(Frintp_v , FSimdVV , (0b0001111000100100110000, kHF_A, 0b0000111010100001100010, kHF_B) , kRWI_W , 0 , 12 ), // #529 - INST(Frintx_v , FSimdVV , (0b0001111000100111010000, kHF_A, 0b0010111000100001100110, kHF_B) , kRWI_W , 0 , 13 ), // #530 - INST(Frintz_v , FSimdVV , (0b0001111000100101110000, kHF_A, 0b0000111010100001100110, kHF_B) , kRWI_W , 0 , 14 ), // #531 - INST(Frsqrte_v , FSimdVV , (0b0111111010100001110110, kHF_B, 0b0010111010100001110110, kHF_B) , kRWI_W , 0 , 15 ), // #532 - INST(Frsqrts_v , FSimdVVV , (0b0101111010100000111111, kHF_C, 0b0000111010100000111111, kHF_C) , kRWI_W , 0 , 11 ), // #533 - INST(Fsqrt_v , FSimdVV , (0b0001111000100001110000, kHF_A, 0b0010111010100001111110, kHF_B) , kRWI_W , 0 , 16 ), // #534 - INST(Fsub_v , FSimdVVV , (0b0001111000100000001110, kHF_A, 0b0000111010100000110101, kHF_C) , kRWI_W , 0 , 12 ), // #535 - INST(Ins_v , SimdIns , (_) , kRWI_X , 0 , 0 ), // #536 - INST(Ld1_v , SimdLdNStN , (0b0000110101000000000000, 0b0000110001000000001000, 1, 0) , kRWI_LDn , F(Consecutive) , 0 ), // #537 - INST(Ld1r_v , SimdLdNStN , (0b0000110101000000110000, 0b0000000000000000000000, 1, 1) , kRWI_LDn , F(Consecutive) , 1 ), // #538 - INST(Ld2_v , SimdLdNStN , (0b0000110101100000000000, 0b0000110001000000100000, 2, 0) , kRWI_LDn , F(Consecutive) , 2 ), // #539 - INST(Ld2r_v , SimdLdNStN , (0b0000110101100000110000, 0b0000000000000000000000, 2, 1) , kRWI_LDn , F(Consecutive) , 3 ), // #540 - INST(Ld3_v , SimdLdNStN , (0b0000110101000000001000, 0b0000110001000000010000, 3, 0) , kRWI_LDn , F(Consecutive) , 4 ), // #541 - INST(Ld3r_v , SimdLdNStN , (0b0000110101000000111000, 0b0000000000000000000000, 3, 1) , kRWI_LDn , F(Consecutive) , 5 ), // #542 - INST(Ld4_v , SimdLdNStN , (0b0000110101100000001000, 0b0000110001000000000000, 4, 0) , kRWI_LDn , F(Consecutive) , 6 ), // #543 - INST(Ld4r_v , SimdLdNStN , (0b0000110101100000111000, 0b0000000000000000000000, 4, 1) , kRWI_LDn , F(Consecutive) , 7 ), // #544 - INST(Ldnp_v , SimdLdpStp , (0b0010110001, 0b0000000000) , kRWI_WW , 0 , 0 ), // #545 - INST(Ldp_v , SimdLdpStp , (0b0010110101, 0b0010110011) , kRWI_WW , 0 , 1 ), // #546 - INST(Ldr_v , SimdLdSt , (0b0011110101, 0b00111100010, 0b00111100011, 0b00011100, Inst::kIdLdur_v) , kRWI_W , 0 , 0 ), // #547 - INST(Ldur_v , SimdLdurStur , (0b0011110001000000000000) , kRWI_W , 0 , 0 ), // #548 - INST(Mla_v , ISimdVVVe , (0b0000111000100000100101, kVO_V_BHS, 0b0010111100000000000000, kVO_V_HS) , kRWI_X , F(VH0_15) , 0 ), // #549 - INST(Mls_v , ISimdVVVe , (0b0010111000100000100101, kVO_V_BHS, 0b0010111100000000010000, kVO_V_HS) , kRWI_X , F(VH0_15) , 1 ), // #550 - INST(Mov_v , SimdMov , (_) , kRWI_W , 0 , 0 ), // #551 - INST(Movi_v , SimdMoviMvni , (0b0000111100000000000001, 0) , kRWI_W , 0 , 0 ), // #552 - INST(Mul_v , ISimdVVVe , (0b0000111000100000100111, kVO_V_BHS, 0b0000111100000000100000, kVO_V_HS) , kRWI_W , F(VH0_15) , 2 ), // #553 - INST(Mvn_v , ISimdVV , (0b0010111000100000010110, kVO_V_B) , kRWI_W , 0 , 4 ), // #554 - INST(Mvni_v , SimdMoviMvni , (0b0000111100000000000001, 1) , kRWI_W , 0 , 1 ), // #555 - INST(Neg_v , ISimdVV , (0b0010111000100000101110, kVO_V_Any) , kRWI_W , 0 , 5 ), // #556 - INST(Not_v , ISimdVV , (0b0010111000100000010110, kVO_V_B) , kRWI_W , 0 , 6 ), // #557 - INST(Orn_v , ISimdVVV , (0b0000111011100000000111, kVO_V_B) , kRWI_W , 0 , 9 ), // #558 - INST(Orr_v , SimdBicOrr , (0b0000111010100000000111, 0b0000111100000000000001) , kRWI_W , 0 , 1 ), // #559 - INST(Pmul_v , ISimdVVV , (0b0010111000100000100111, kVO_V_B) , kRWI_W , 0 , 10 ), // #560 - INST(Pmull_v , ISimdVVV , (0b0000111000100000111000, kVO_V_B8D1) , kRWI_W , F(Long) , 11 ), // #561 - INST(Pmull2_v , ISimdVVV , (0b0100111000100000111000, kVO_V_B16D2) , kRWI_W , F(Long) , 12 ), // #562 - INST(Raddhn_v , ISimdVVV , (0b0010111000100000010000, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 13 ), // #563 - INST(Raddhn2_v , ISimdVVV , (0b0110111000100000010000, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 14 ), // #564 - INST(Rax1_v , ISimdVVV , (0b1100111001100000100011, kVO_V_D2) , kRWI_W , 0 , 15 ), // #565 - INST(Rbit_v , ISimdVV , (0b0010111001100000010110, kVO_V_B) , kRWI_W , 0 , 7 ), // #566 - INST(Rev16_v , ISimdVV , (0b0000111000100000000110, kVO_V_B) , kRWI_W , 0 , 8 ), // #567 - INST(Rev32_v , ISimdVV , (0b0010111000100000000010, kVO_V_BH) , kRWI_W , 0 , 9 ), // #568 - INST(Rev64_v , ISimdVV , (0b0000111000100000000010, kVO_V_BHS) , kRWI_W , 0 , 10 ), // #569 - INST(Rshrn_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000100011, 1, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 0 ), // #570 - INST(Rshrn2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000100011, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 1 ), // #571 - INST(Rsubhn_v , ISimdVVV , (0b0010111000100000011000, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 16 ), // #572 - INST(Rsubhn2_v , ISimdVVV , (0b0110111000100000011000, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 17 ), // #573 - INST(Saba_v , ISimdVVV , (0b0000111000100000011111, kVO_V_BHS) , kRWI_X , 0 , 18 ), // #574 - INST(Sabal_v , ISimdVVV , (0b0000111000100000010100, kVO_V_B8H4S2) , kRWI_X , F(Long) , 19 ), // #575 - INST(Sabal2_v , ISimdVVV , (0b0100111000100000010100, kVO_V_B16H8S4) , kRWI_X , F(Long) , 20 ), // #576 - INST(Sabd_v , ISimdVVV , (0b0000111000100000011101, kVO_V_BHS) , kRWI_W , 0 , 21 ), // #577 - INST(Sabdl_v , ISimdVVV , (0b0000111000100000011100, kVO_V_B8H4S2) , kRWI_W , F(Long) , 22 ), // #578 - INST(Sabdl2_v , ISimdVVV , (0b0100111000100000011100, kVO_V_B16H8S4) , kRWI_W , F(Long) , 23 ), // #579 - INST(Sadalp_v , ISimdVV , (0b0000111000100000011010, kVO_V_BHS) , kRWI_X , F(Long) | F(Pair) , 11 ), // #580 - INST(Saddl_v , ISimdVVV , (0b0000111000100000000000, kVO_V_B8H4S2) , kRWI_W , F(Long) , 24 ), // #581 - INST(Saddl2_v , ISimdVVV , (0b0100111000100000000000, kVO_V_B16H8S4) , kRWI_W , F(Long) , 25 ), // #582 - INST(Saddlp_v , ISimdVV , (0b0000111000100000001010, kVO_V_BHS) , kRWI_W , F(Long) | F(Pair) , 12 ), // #583 - INST(Saddlv_v , ISimdSV , (0b0000111000110000001110, kVO_V_BH_4S) , kRWI_W , F(Long) , 1 ), // #584 - INST(Saddw_v , ISimdWWV , (0b0000111000100000000100, kVO_V_B8H4S2) , kRWI_W , 0 , 0 ), // #585 - INST(Saddw2_v , ISimdWWV , (0b0000111000100000000100, kVO_V_B16H8S4) , kRWI_W , 0 , 1 ), // #586 - INST(Scvtf_v , SimdFcvtSV , (0b0000111000100001110110, 0b0000111100000000111001, 0b0001111000100010000000, 0) , kRWI_W , 0 , 10 ), // #587 - INST(Sdot_v , SimdDot , (0b0000111010000000100101, 0b0000111110000000111000, kET_S, kET_B, kET_4B) , kRWI_X , 0 , 1 ), // #588 - INST(Sha1c_v , ISimdVVVx , (0b0101111000000000000000, kOp_Q, kOp_S, kOp_V4S) , kRWI_X , 0 , 1 ), // #589 - INST(Sha1h_v , ISimdVVx , (0b0101111000101000000010, kOp_S, kOp_S) , kRWI_W , 0 , 8 ), // #590 - INST(Sha1m_v , ISimdVVVx , (0b0101111000000000001000, kOp_Q, kOp_S, kOp_V4S) , kRWI_X , 0 , 2 ), // #591 - INST(Sha1p_v , ISimdVVVx , (0b0101111000000000000100, kOp_Q, kOp_S, kOp_V4S) , kRWI_X , 0 , 3 ), // #592 - INST(Sha1su0_v , ISimdVVVx , (0b0101111000000000001100, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 4 ), // #593 - INST(Sha1su1_v , ISimdVVx , (0b0101111000101000000110, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 9 ), // #594 - INST(Sha256h_v , ISimdVVVx , (0b0101111000000000010000, kOp_Q, kOp_Q, kOp_V4S) , kRWI_X , 0 , 5 ), // #595 - INST(Sha256h2_v , ISimdVVVx , (0b0101111000000000010100, kOp_Q, kOp_Q, kOp_V4S) , kRWI_X , 0 , 6 ), // #596 - INST(Sha256su0_v , ISimdVVx , (0b0101111000101000001010, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 10 ), // #597 - INST(Sha256su1_v , ISimdVVVx , (0b0101111000000000011000, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 7 ), // #598 - INST(Sha512h_v , ISimdVVVx , (0b1100111001100000100000, kOp_Q, kOp_Q, kOp_V2D) , kRWI_X , 0 , 8 ), // #599 - INST(Sha512h2_v , ISimdVVVx , (0b1100111001100000100001, kOp_Q, kOp_Q, kOp_V2D) , kRWI_X , 0 , 9 ), // #600 - INST(Sha512su0_v , ISimdVVx , (0b1100111011000000100000, kOp_V2D, kOp_V2D) , kRWI_X , 0 , 11 ), // #601 - INST(Sha512su1_v , ISimdVVVx , (0b1100111001100000100010, kOp_V2D, kOp_V2D, kOp_V2D) , kRWI_X , 0 , 10 ), // #602 - INST(Shadd_v , ISimdVVV , (0b0000111000100000000001, kVO_V_BHS) , kRWI_W , 0 , 26 ), // #603 - INST(Shl_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000010101, 0, kVO_V_Any) , kRWI_W , 0 , 2 ), // #604 - INST(Shll_v , SimdShiftES , (0b0010111000100001001110, kVO_V_B8H4S2) , kRWI_W , F(Long) , 0 ), // #605 - INST(Shll2_v , SimdShiftES , (0b0110111000100001001110, kVO_V_B16H8S4) , kRWI_W , F(Long) , 1 ), // #606 - INST(Shrn_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000100001, 1, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 3 ), // #607 - INST(Shrn2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000100001, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 4 ), // #608 - INST(Shsub_v , ISimdVVV , (0b0000111000100000001001, kVO_V_BHS) , kRWI_W , 0 , 27 ), // #609 - INST(Sli_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000010101, 0, kVO_V_Any) , kRWI_X , 0 , 5 ), // #610 - INST(Sm3partw1_v , ISimdVVVx , (0b1100111001100000110000, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 11 ), // #611 - INST(Sm3partw2_v , ISimdVVVx , (0b1100111001100000110001, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 12 ), // #612 - INST(Sm3ss1_v , ISimdVVVVx , (0b1100111001000000000000, kOp_V4S, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_W , 0 , 0 ), // #613 - INST(Sm3tt1a_v , SimdSm3tt , (0b1100111001000000100000) , kRWI_X , 0 , 0 ), // #614 - INST(Sm3tt1b_v , SimdSm3tt , (0b1100111001000000100001) , kRWI_X , 0 , 1 ), // #615 - INST(Sm3tt2a_v , SimdSm3tt , (0b1100111001000000100010) , kRWI_X , 0 , 2 ), // #616 - INST(Sm3tt2b_v , SimdSm3tt , (0b1100111001000000100011) , kRWI_X , 0 , 3 ), // #617 - INST(Sm4e_v , ISimdVVx , (0b1100111011000000100001, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 12 ), // #618 - INST(Sm4ekey_v , ISimdVVVx , (0b1100111001100000110010, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 13 ), // #619 - INST(Smax_v , ISimdVVV , (0b0000111000100000011001, kVO_V_BHS) , kRWI_W , 0 , 28 ), // #620 - INST(Smaxp_v , ISimdVVV , (0b0000111000100000101001, kVO_V_BHS) , kRWI_W , 0 , 29 ), // #621 - INST(Smaxv_v , ISimdSV , (0b0000111000110000101010, kVO_V_BH_4S) , kRWI_W , 0 , 2 ), // #622 - INST(Smin_v , ISimdVVV , (0b0000111000100000011011, kVO_V_BHS) , kRWI_W , 0 , 30 ), // #623 - INST(Sminp_v , ISimdVVV , (0b0000111000100000101011, kVO_V_BHS) , kRWI_W , 0 , 31 ), // #624 - INST(Sminv_v , ISimdSV , (0b0000111000110001101010, kVO_V_BH_4S) , kRWI_W , 0 , 3 ), // #625 - INST(Smlal_v , ISimdVVVe , (0b0000111000100000100000, kVO_V_B8H4S2, 0b0000111100000000001000, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 3 ), // #626 - INST(Smlal2_v , ISimdVVVe , (0b0100111000100000100000, kVO_V_B16H8S4, 0b0100111100000000001000, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 4 ), // #627 - INST(Smlsl_v , ISimdVVVe , (0b0000111000100000101000, kVO_V_B8H4S2, 0b0000111100000000011000, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 5 ), // #628 - INST(Smlsl2_v , ISimdVVVe , (0b0100111000100000101000, kVO_V_B16H8S4, 0b0100111100000000011000, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 6 ), // #629 - INST(Smmla_v , ISimdVVVx , (0b0100111010000000101001, kOp_V4S, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 14 ), // #630 - INST(Smov_v , SimdSmovUmov , (0b0000111000000000001011, kVO_V_BHS, 1) , kRWI_W , 0 , 0 ), // #631 - INST(Smull_v , ISimdVVVe , (0b0000111000100000110000, kVO_V_B8H4S2, 0b0000111100000000101000, kVO_V_H4S2) , kRWI_W , F(Long) | F(VH0_15) , 7 ), // #632 - INST(Smull2_v , ISimdVVVe , (0b0100111000100000110000, kVO_V_B16H8S4, 0b0100111100000000101000, kVO_V_H8S4) , kRWI_W , F(Long) | F(VH0_15) , 8 ), // #633 - INST(Sqabs_v , ISimdVV , (0b0000111000100000011110, kVO_SV_Any) , kRWI_W , 0 , 13 ), // #634 - INST(Sqadd_v , ISimdVVV , (0b0000111000100000000011, kVO_SV_Any) , kRWI_W , 0 , 32 ), // #635 - INST(Sqdmlal_v , ISimdVVVe , (0b0000111000100000100100, kVO_SV_BHS, 0b0000111100000000001100, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 9 ), // #636 - INST(Sqdmlal2_v , ISimdVVVe , (0b0100111000100000100100, kVO_V_B16H8S4, 0b0100111100000000001100, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 10 ), // #637 - INST(Sqdmlsl_v , ISimdVVVe , (0b0000111000100000101100, kVO_SV_BHS, 0b0000111100000000011100, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 11 ), // #638 - INST(Sqdmlsl2_v , ISimdVVVe , (0b0100111000100000101100, kVO_V_B16H8S4, 0b0100111100000000011100, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 12 ), // #639 - INST(Sqdmulh_v , ISimdVVVe , (0b0000111000100000101101, kVO_SV_HS, 0b0000111100000000110000, kVO_SV_HS) , kRWI_W , F(VH0_15) , 13 ), // #640 - INST(Sqdmull_v , ISimdVVVe , (0b0000111000100000110100, kVO_SV_BHS, 0b0000111100000000101100, kVO_V_H4S2) , kRWI_W , F(Long) | F(VH0_15) , 14 ), // #641 - INST(Sqdmull2_v , ISimdVVVe , (0b0100111000100000110100, kVO_V_B16H8S4, 0b0100111100000000101100, kVO_V_H8S4) , kRWI_W , F(Long) | F(VH0_15) , 15 ), // #642 - INST(Sqneg_v , ISimdVV , (0b0010111000100000011110, kVO_SV_Any) , kRWI_W , 0 , 14 ), // #643 - INST(Sqrdmlah_v , ISimdVVVe , (0b0010111000000000100001, kVO_SV_HS, 0b0010111100000000110100, kVO_SV_HS) , kRWI_X , F(VH0_15) , 16 ), // #644 - INST(Sqrdmlsh_v , ISimdVVVe , (0b0010111000000000100011, kVO_SV_HS, 0b0010111100000000111100, kVO_SV_HS) , kRWI_X , F(VH0_15) , 17 ), // #645 - INST(Sqrdmulh_v , ISimdVVVe , (0b0010111000100000101101, kVO_SV_HS, 0b0000111100000000110100, kVO_SV_HS) , kRWI_W , F(VH0_15) , 18 ), // #646 - INST(Sqrshl_v , SimdShift , (0b0000111000100000010111, 0b0000000000000000000000, 1, kVO_SV_Any) , kRWI_W , 0 , 6 ), // #647 - INST(Sqrshrn_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000100111, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 7 ), // #648 - INST(Sqrshrn2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000100111, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 8 ), // #649 - INST(Sqrshrun_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000100011, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 9 ), // #650 - INST(Sqrshrun2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000100011, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 10 ), // #651 - INST(Sqshl_v , SimdShift , (0b0000111000100000010011, 0b0000111100000000011101, 0, kVO_SV_Any) , kRWI_W , 0 , 11 ), // #652 - INST(Sqshlu_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000011001, 0, kVO_SV_Any) , kRWI_W , 0 , 12 ), // #653 - INST(Sqshrn_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000100101, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 13 ), // #654 - INST(Sqshrn2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000100101, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 14 ), // #655 - INST(Sqshrun_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000100001, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 15 ), // #656 - INST(Sqshrun2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000100001, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 16 ), // #657 - INST(Sqsub_v , ISimdVVV , (0b0000111000100000001011, kVO_SV_Any) , kRWI_W , 0 , 33 ), // #658 - INST(Sqxtn_v , ISimdVV , (0b0000111000100001010010, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 15 ), // #659 - INST(Sqxtn2_v , ISimdVV , (0b0100111000100001010010, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 16 ), // #660 - INST(Sqxtun_v , ISimdVV , (0b0010111000100001001010, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 17 ), // #661 - INST(Sqxtun2_v , ISimdVV , (0b0110111000100001001010, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 18 ), // #662 - INST(Srhadd_v , ISimdVVV , (0b0000111000100000000101, kVO_V_BHS) , kRWI_W , 0 , 34 ), // #663 - INST(Sri_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000010001, 1, kVO_V_Any) , kRWI_W , 0 , 17 ), // #664 - INST(Srshl_v , SimdShift , (0b0000111000100000010101, 0b0000000000000000000000, 0, kVO_V_Any) , kRWI_W , 0 , 18 ), // #665 - INST(Srshr_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000001001, 1, kVO_V_Any) , kRWI_W , 0 , 19 ), // #666 - INST(Srsra_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000001101, 1, kVO_V_Any) , kRWI_X , 0 , 20 ), // #667 - INST(Sshl_v , SimdShift , (0b0000111000100000010001, 0b0000000000000000000000, 0, kVO_V_Any) , kRWI_W , 0 , 21 ), // #668 - INST(Sshll_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000101001, 0, kVO_V_B8H4S2) , kRWI_W , F(Long) , 22 ), // #669 - INST(Sshll2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000101001, 0, kVO_V_B16H8S4) , kRWI_W , F(Long) , 23 ), // #670 - INST(Sshr_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000000001, 1, kVO_V_Any) , kRWI_W , 0 , 24 ), // #671 - INST(Ssra_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000000101, 1, kVO_V_Any) , kRWI_X , 0 , 25 ), // #672 - INST(Ssubl_v , ISimdVVV , (0b0000111000100000001000, kVO_V_B8H4S2) , kRWI_W , F(Long) , 35 ), // #673 - INST(Ssubl2_v , ISimdVVV , (0b0100111000100000001000, kVO_V_B16H8S4) , kRWI_W , F(Long) , 36 ), // #674 - INST(Ssubw_v , ISimdWWV , (0b0000111000100000001100, kVO_V_B8H4S2) , kRWI_W , 0 , 2 ), // #675 - INST(Ssubw2_v , ISimdWWV , (0b0000111000100000001100, kVO_V_B16H8S4) , kRWI_X , 0 , 3 ), // #676 - INST(St1_v , SimdLdNStN , (0b0000110100000000000000, 0b0000110000000000001000, 1, 0) , kRWI_STn , F(Consecutive) , 8 ), // #677 - INST(St2_v , SimdLdNStN , (0b0000110100100000000000, 0b0000110000000000100000, 2, 0) , kRWI_STn , F(Consecutive) , 9 ), // #678 - INST(St3_v , SimdLdNStN , (0b0000110100000000001000, 0b0000110000000000010000, 3, 0) , kRWI_STn , F(Consecutive) , 10 ), // #679 - INST(St4_v , SimdLdNStN , (0b0000110100100000001000, 0b0000110000000000000000, 4, 0) , kRWI_STn , F(Consecutive) , 11 ), // #680 - INST(Stnp_v , SimdLdpStp , (0b0010110000, 0b0000000000) , kRWI_RRW , 0 , 2 ), // #681 - INST(Stp_v , SimdLdpStp , (0b0010110100, 0b0010110010) , kRWI_RRW , 0 , 3 ), // #682 - INST(Str_v , SimdLdSt , (0b0011110100, 0b00111100000, 0b00111100001, 0b00000000, Inst::kIdStur_v) , kRWI_RW , 0 , 1 ), // #683 - INST(Stur_v , SimdLdurStur , (0b0011110000000000000000) , kRWI_RW , 0 , 1 ), // #684 - INST(Sub_v , ISimdVVV , (0b0010111000100000100001, kVO_V_Any) , kRWI_W , 0 , 37 ), // #685 - INST(Subhn_v , ISimdVVV , (0b0000111000100000011000, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 38 ), // #686 - INST(Subhn2_v , ISimdVVV , (0b0000111000100000011000, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 39 ), // #687 - INST(Sudot_v , SimdDot , (0b0000000000000000000000, 0b0000111100000000111100, kET_S, kET_B, kET_4B) , kRWI_X , 0 , 2 ), // #688 - INST(Suqadd_v , ISimdVV , (0b0000111000100000001110, kVO_SV_Any) , kRWI_X , 0 , 19 ), // #689 - INST(Sxtl_v , SimdSxtlUxtl , (0b0000111100000000101001, kVO_V_B8H4S2) , kRWI_W , F(Long) , 0 ), // #690 - INST(Sxtl2_v , SimdSxtlUxtl , (0b0100111100000000101001, kVO_V_B16H8S4) , kRWI_W , F(Long) , 1 ), // #691 - INST(Tbl_v , SimdTblTbx , (0b0000111000000000000000) , kRWI_W , 0 , 0 ), // #692 - INST(Tbx_v , SimdTblTbx , (0b0000111000000000000100) , kRWI_W , 0 , 1 ), // #693 - INST(Trn1_v , ISimdVVV , (0b0000111000000000001010, kVO_V_BHS_D2) , kRWI_W , 0 , 40 ), // #694 - INST(Trn2_v , ISimdVVV , (0b0000111000000000011010, kVO_V_BHS_D2) , kRWI_W , 0 , 41 ), // #695 - INST(Uaba_v , ISimdVVV , (0b0010111000100000011111, kVO_V_BHS) , kRWI_X , 0 , 42 ), // #696 - INST(Uabal_v , ISimdVVV , (0b0010111000100000010100, kVO_V_B8H4S2) , kRWI_X , F(Long) , 43 ), // #697 - INST(Uabal2_v , ISimdVVV , (0b0110111000100000010100, kVO_V_B16H8S4) , kRWI_X , F(Long) , 44 ), // #698 - INST(Uabd_v , ISimdVVV , (0b0010111000100000011101, kVO_V_BHS) , kRWI_W , 0 , 45 ), // #699 - INST(Uabdl_v , ISimdVVV , (0b0010111000100000011100, kVO_V_B8H4S2) , kRWI_W , F(Long) , 46 ), // #700 - INST(Uabdl2_v , ISimdVVV , (0b0110111000100000011100, kVO_V_B16H8S4) , kRWI_W , F(Long) , 47 ), // #701 - INST(Uadalp_v , ISimdVV , (0b0010111000100000011010, kVO_V_BHS) , kRWI_X , F(Long) | F(Pair) , 20 ), // #702 - INST(Uaddl_v , ISimdVVV , (0b0010111000100000000000, kVO_V_B8H4S2) , kRWI_W , F(Long) , 48 ), // #703 - INST(Uaddl2_v , ISimdVVV , (0b0110111000100000000000, kVO_V_B16H8S4) , kRWI_W , F(Long) , 49 ), // #704 - INST(Uaddlp_v , ISimdVV , (0b0010111000100000001010, kVO_V_BHS) , kRWI_W , F(Long) | F(Pair) , 21 ), // #705 - INST(Uaddlv_v , ISimdSV , (0b0010111000110000001110, kVO_V_BH_4S) , kRWI_W , F(Long) , 4 ), // #706 - INST(Uaddw_v , ISimdWWV , (0b0010111000100000000100, kVO_V_B8H4S2) , kRWI_W , 0 , 4 ), // #707 - INST(Uaddw2_v , ISimdWWV , (0b0010111000100000000100, kVO_V_B16H8S4) , kRWI_W , 0 , 5 ), // #708 - INST(Ucvtf_v , SimdFcvtSV , (0b0010111000100001110110, 0b0010111100000000111001, 0b0001111000100011000000, 0) , kRWI_W , 0 , 11 ), // #709 - INST(Udot_v , SimdDot , (0b0010111010000000100101, 0b0010111110000000111000, kET_S, kET_B, kET_4B) , kRWI_X , 0 , 3 ), // #710 - INST(Uhadd_v , ISimdVVV , (0b0010111000100000000001, kVO_V_BHS) , kRWI_W , 0 , 50 ), // #711 - INST(Uhsub_v , ISimdVVV , (0b0010111000100000001001, kVO_V_BHS) , kRWI_W , 0 , 51 ), // #712 - INST(Umax_v , ISimdVVV , (0b0010111000100000011001, kVO_V_BHS) , kRWI_W , 0 , 52 ), // #713 - INST(Umaxp_v , ISimdVVV , (0b0010111000100000101001, kVO_V_BHS) , kRWI_W , 0 , 53 ), // #714 - INST(Umaxv_v , ISimdSV , (0b0010111000110000101010, kVO_V_BH_4S) , kRWI_W , 0 , 5 ), // #715 - INST(Umin_v , ISimdVVV , (0b0010111000100000011011, kVO_V_BHS) , kRWI_W , 0 , 54 ), // #716 - INST(Uminp_v , ISimdVVV , (0b0010111000100000101011, kVO_V_BHS) , kRWI_W , 0 , 55 ), // #717 - INST(Uminv_v , ISimdSV , (0b0010111000110001101010, kVO_V_BH_4S) , kRWI_W , 0 , 6 ), // #718 - INST(Umlal_v , ISimdVVVe , (0b0010111000100000100000, kVO_V_B8H4S2, 0b0010111100000000001000, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 19 ), // #719 - INST(Umlal2_v , ISimdVVVe , (0b0110111000100000100000, kVO_V_B16H8S4, 0b0010111100000000001000, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 20 ), // #720 - INST(Umlsl_v , ISimdVVVe , (0b0010111000100000101000, kVO_V_B8H4S2, 0b0010111100000000011000, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 21 ), // #721 - INST(Umlsl2_v , ISimdVVVe , (0b0110111000100000101000, kVO_V_B16H8S4, 0b0110111100000000011000, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 22 ), // #722 - INST(Ummla_v , ISimdVVVx , (0b0110111010000000101001, kOp_V4S, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 15 ), // #723 - INST(Umov_v , SimdSmovUmov , (0b0000111000000000001111, kVO_V_Any, 0) , kRWI_W , 0 , 1 ), // #724 - INST(Umull_v , ISimdVVVe , (0b0010111000100000110000, kVO_V_B8H4S2, 0b0010111100000000101000, kVO_V_H4S2) , kRWI_W , F(Long) | F(VH0_15) , 23 ), // #725 - INST(Umull2_v , ISimdVVVe , (0b0110111000100000110000, kVO_V_B16H8S4, 0b0110111100000000101000, kVO_V_H8S4) , kRWI_W , F(Long) | F(VH0_15) , 24 ), // #726 - INST(Uqadd_v , ISimdVVV , (0b0010111000100000000011, kVO_SV_Any) , kRWI_W , 0 , 56 ), // #727 - INST(Uqrshl_v , SimdShift , (0b0010111000100000010111, 0b0000000000000000000000, 0, kVO_SV_Any) , kRWI_W , 0 , 26 ), // #728 - INST(Uqrshrn_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000100111, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 27 ), // #729 - INST(Uqrshrn2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000100111, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 28 ), // #730 - INST(Uqshl_v , SimdShift , (0b0010111000100000010011, 0b0010111100000000011101, 0, kVO_SV_Any) , kRWI_W , 0 , 29 ), // #731 - INST(Uqshrn_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000100101, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 30 ), // #732 - INST(Uqshrn2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000100101, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 31 ), // #733 - INST(Uqsub_v , ISimdVVV , (0b0010111000100000001011, kVO_SV_Any) , kRWI_W , 0 , 57 ), // #734 - INST(Uqxtn_v , ISimdVV , (0b0010111000100001010010, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 22 ), // #735 - INST(Uqxtn2_v , ISimdVV , (0b0110111000100001010010, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 23 ), // #736 - INST(Urecpe_v , ISimdVV , (0b0000111010100001110010, kVO_V_S) , kRWI_W , 0 , 24 ), // #737 - INST(Urhadd_v , ISimdVVV , (0b0010111000100000000101, kVO_V_BHS) , kRWI_W , 0 , 58 ), // #738 - INST(Urshl_v , SimdShift , (0b0010111000100000010101, 0b0000000000000000000000, 0, kVO_V_Any) , kRWI_W , 0 , 32 ), // #739 - INST(Urshr_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000001001, 1, kVO_V_Any) , kRWI_W , 0 , 33 ), // #740 - INST(Ursqrte_v , ISimdVV , (0b0010111010100001110010, kVO_V_S) , kRWI_W , 0 , 25 ), // #741 - INST(Ursra_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000001101, 1, kVO_V_Any) , kRWI_X , 0 , 34 ), // #742 - INST(Usdot_v , SimdDot , (0b0000111010000000100111, 0b0000111110000000111100, kET_S, kET_B, kET_4B) , kRWI_X , 0 , 4 ), // #743 - INST(Ushl_v , SimdShift , (0b0010111000100000010001, 0b0000000000000000000000, 0, kVO_V_Any) , kRWI_W , 0 , 35 ), // #744 - INST(Ushll_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000101001, 0, kVO_V_B8H4S2) , kRWI_W , F(Long) , 36 ), // #745 - INST(Ushll2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000101001, 0, kVO_V_B16H8S4) , kRWI_W , F(Long) , 37 ), // #746 - INST(Ushr_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000000001, 1, kVO_V_Any) , kRWI_W , 0 , 38 ), // #747 - INST(Usmmla_v , ISimdVVVx , (0b0100111010000000101011, kOp_V4S, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 16 ), // #748 - INST(Usqadd_v , ISimdVV , (0b0010111000100000001110, kVO_SV_Any) , kRWI_X , 0 , 26 ), // #749 - INST(Usra_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000000101, 1, kVO_V_Any) , kRWI_X , 0 , 39 ), // #750 - INST(Usubl_v , ISimdVVV , (0b0010111000100000001000, kVO_V_B8H4S2) , kRWI_W , F(Long) , 59 ), // #751 - INST(Usubl2_v , ISimdVVV , (0b0110111000100000001000, kVO_V_B16H8S4) , kRWI_W , F(Long) , 60 ), // #752 - INST(Usubw_v , ISimdWWV , (0b0010111000100000001100, kVO_V_B8H4S2) , kRWI_W , 0 , 6 ), // #753 - INST(Usubw2_v , ISimdWWV , (0b0010111000100000001100, kVO_V_B16H8S4) , kRWI_W , 0 , 7 ), // #754 - INST(Uxtl_v , SimdSxtlUxtl , (0b0010111100000000101001, kVO_V_B8H4S2) , kRWI_W , F(Long) , 2 ), // #755 - INST(Uxtl2_v , SimdSxtlUxtl , (0b0110111100000000101001, kVO_V_B16H8S4) , kRWI_W , F(Long) , 3 ), // #756 - INST(Uzp1_v , ISimdVVV , (0b0000111000000000000110, kVO_V_BHS_D2) , kRWI_W , 0 , 61 ), // #757 - INST(Uzp2_v , ISimdVVV , (0b0000111000000000010110, kVO_V_BHS_D2) , kRWI_W , 0 , 62 ), // #758 - INST(Xar_v , ISimdVVVI , (0b1100111001100000100011, kVO_V_D2, 6, 10, 0) , kRWI_W , 0 , 1 ), // #759 - INST(Xtn_v , ISimdVV , (0b0000111000100001001010, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 27 ), // #760 - INST(Xtn2_v , ISimdVV , (0b0100111000100001001010, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 28 ), // #761 - INST(Zip1_v , ISimdVVV , (0b0000111000000000001110, kVO_V_BHS_D2) , kRWI_W , 0 , 63 ), // #762 - INST(Zip2_v , ISimdVVV , (0b0000111000000000011110, kVO_V_BHS_D2) , kRWI_W , 0 , 64 ) // #763 + INST(Prfm , BasePrfm , (0b11111000101, 0b1111100110, 0b11111000100, 0b11011000) , kRWI_R , 0 , 0 ), // #265 + INST(Pssbb , BaseOp , (0b11010101000000110011010010011111) , 0 , 0 , 14 ), // #266 + INST(Rbit , BaseRR , (0b01011010110000000000000000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 11 ), // #267 + INST(Ret , BaseBranchReg , (0b11010110010111110000000000000000) , kRWI_R , 0 , 2 ), // #268 + INST(Rev , BaseRev , (_) , kRWI_W , 0 , 0 ), // #269 + INST(Rev16 , BaseRR , (0b01011010110000000000010000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 12 ), // #270 + INST(Rev32 , BaseRR , (0b11011010110000000000100000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 13 ), // #271 + INST(Rev64 , BaseRR , (0b11011010110000000000110000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 14 ), // #272 + INST(Ror , BaseShift , (0b0001101011000000001011, 0b0001001110000000000000, 1) , kRWI_W , 0 , 6 ), // #273 + INST(Rorv , BaseShift , (0b0001101011000000001011, 0b0000000000000000000000, 1) , kRWI_W , 0 , 7 ), // #274 + INST(Sbc , BaseRRR , (0b0101101000000000000000, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 14 ), // #275 + INST(Sbcs , BaseRRR , (0b0111101000000000000000, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 15 ), // #276 + INST(Sbfiz , BaseBfi , (0b00010011000000000000000000000000) , kRWI_W , 0 , 1 ), // #277 + INST(Sbfm , BaseBfm , (0b00010011000000000000000000000000) , kRWI_W , 0 , 1 ), // #278 + INST(Sbfx , BaseBfx , (0b00010011000000000000000000000000) , kRWI_W , 0 , 1 ), // #279 + INST(Sdiv , BaseRRR , (0b0001101011000000000011, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 16 ), // #280 + INST(Setf8 , BaseR , (0b00111010000000000000100000001101, kW, kZR, 5) , 0 , 0 , 6 ), // #281 + INST(Setf16 , BaseR , (0b00111010000000000100100000001101, kW, kZR, 5) , 0 , 0 , 7 ), // #282 + INST(Sev , BaseOp , (0b11010101000000110010000010011111) , 0 , 0 , 15 ), // #283 + INST(Sevl , BaseOp , (0b11010101000000110010000010111111) , 0 , 0 , 16 ), // #284 + INST(Smaddl , BaseRRRR , (0b1001101100100000000000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false) , kRWI_W , 0 , 2 ), // #285 + INST(Smc , BaseOpImm , (0b11010100000000000000000000000011, 16, 5) , 0 , 0 , 11 ), // #286 + INST(Smnegl , BaseRRR , (0b1001101100100000111111, kX , kZR, kW , kZR, kW , kZR, false) , kRWI_W , 0 , 17 ), // #287 + INST(Smsubl , BaseRRRR , (0b1001101100100000100000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false) , kRWI_W , 0 , 3 ), // #288 + INST(Smulh , BaseRRR , (0b1001101101000000011111, kX , kZR, kX , kZR, kX , kZR, true) , kRWI_W , 0 , 18 ), // #289 + INST(Smull , BaseRRR , (0b1001101100100000011111, kX , kZR, kW , kZR, kW , kZR, false) , kRWI_W , 0 , 19 ), // #290 + INST(Ssbb , BaseOp , (0b11010101000000110011000010011111) , 0 , 0 , 17 ), // #291 + INST(St2g , BaseRM_SImm9 , (0b1101100110100000000010, 0b1101100110100000000001, kX, kSP, 0, 4) , kRWI_RW , 0 , 13 ), // #292 + INST(Stadd , BaseAtomicSt , (0b1011100000100000000000, kWX, 30) , kRWI_RX , 0 , 0 ), // #293 + INST(Staddl , BaseAtomicSt , (0b1011100001100000000000, kWX, 30) , kRWI_RX , 0 , 1 ), // #294 + INST(Staddb , BaseAtomicSt , (0b0011100000100000000000, kW , 0 ) , kRWI_RX , 0 , 2 ), // #295 + INST(Staddlb , BaseAtomicSt , (0b0011100001100000000000, kW , 0 ) , kRWI_RX , 0 , 3 ), // #296 + INST(Staddh , BaseAtomicSt , (0b0111100000100000000000, kW , 0 ) , kRWI_RX , 0 , 4 ), // #297 + INST(Staddlh , BaseAtomicSt , (0b0111100001100000000000, kW , 0 ) , kRWI_RX , 0 , 5 ), // #298 + INST(Stclr , BaseAtomicSt , (0b1011100000100000000100, kWX, 30) , kRWI_RX , 0 , 6 ), // #299 + INST(Stclrl , BaseAtomicSt , (0b1011100001100000000100, kWX, 30) , kRWI_RX , 0 , 7 ), // #300 + INST(Stclrb , BaseAtomicSt , (0b0011100000100000000100, kW , 0 ) , kRWI_RX , 0 , 8 ), // #301 + INST(Stclrlb , BaseAtomicSt , (0b0011100001100000000100, kW , 0 ) , kRWI_RX , 0 , 9 ), // #302 + INST(Stclrh , BaseAtomicSt , (0b0111100000100000000100, kW , 0 ) , kRWI_RX , 0 , 10 ), // #303 + INST(Stclrlh , BaseAtomicSt , (0b0111100001100000000100, kW , 0 ) , kRWI_RX , 0 , 11 ), // #304 + INST(Steor , BaseAtomicSt , (0b1011100000100000001000, kWX, 30) , kRWI_RX , 0 , 12 ), // #305 + INST(Steorl , BaseAtomicSt , (0b1011100001100000001000, kWX, 30) , kRWI_RX , 0 , 13 ), // #306 + INST(Steorb , BaseAtomicSt , (0b0011100000100000001000, kW , 0 ) , kRWI_RX , 0 , 14 ), // #307 + INST(Steorlb , BaseAtomicSt , (0b0011100001100000001000, kW , 0 ) , kRWI_RX , 0 , 15 ), // #308 + INST(Steorh , BaseAtomicSt , (0b0111100000100000001000, kW , 0 ) , kRWI_RX , 0 , 16 ), // #309 + INST(Steorlh , BaseAtomicSt , (0b0111100001100000001000, kW , 0 ) , kRWI_RX , 0 , 17 ), // #310 + INST(Stg , BaseRM_SImm9 , (0b1101100100100000000010, 0b1101100100100000000001, kX, kSP, 0, 4) , kRWI_RW , 0 , 14 ), // #311 + INST(Stgm , BaseRM_NoImm , (0b1101100110100000000000, kX , kZR, 0 ) , kRWI_RW , 0 , 13 ), // #312 + INST(Stgp , BaseLdpStp , (0b0110100100, 0b0110100010, kX, 0, 4) , kRWI_RRW , 0 , 3 ), // #313 + INST(Stllr , BaseRM_NoImm , (0b1000100010011111011111, kWX, kZR, 30) , kRWI_RW , 0 , 14 ), // #314 + INST(Stllrb , BaseRM_NoImm , (0b0000100010011111011111, kW , kZR, 0 ) , kRWI_RW , 0 , 15 ), // #315 + INST(Stllrh , BaseRM_NoImm , (0b0100100010011111011111, kW , kZR, 0 ) , kRWI_RW , 0 , 16 ), // #316 + INST(Stlr , BaseRM_NoImm , (0b1000100010011111111111, kWX, kZR, 30) , kRWI_RW , 0 , 17 ), // #317 + INST(Stlrb , BaseRM_NoImm , (0b0000100010011111111111, kW , kZR, 0 ) , kRWI_RW , 0 , 18 ), // #318 + INST(Stlrh , BaseRM_NoImm , (0b0100100010011111111111, kW , kZR, 0 ) , kRWI_RW , 0 , 19 ), // #319 + INST(Stlxp , BaseStxp , (0b1000100000100000100000, kWX, 30) , kRWI_WRRX , 0 , 0 ), // #320 + INST(Stlxr , BaseAtomicOp , (0b1000100000000000111111, kWX, 30, 1) , kRWI_WRX , 0 , 108), // #321 + INST(Stlxrb , BaseAtomicOp , (0b0000100000000000111111, kW , 0 , 1) , kRWI_WRX , 0 , 109), // #322 + INST(Stlxrh , BaseAtomicOp , (0b0100100000000000111111, kW , 0 , 1) , kRWI_WRX , 0 , 110), // #323 + INST(Stnp , BaseLdpStp , (0b0010100000, 0 , kWX, 31, 2) , kRWI_RRW , 0 , 4 ), // #324 + INST(Stp , BaseLdpStp , (0b0010100100, 0b0010100010, kWX, 31, 2) , kRWI_RRW , 0 , 5 ), // #325 + INST(Str , BaseLdSt , (0b1011100100, 0b10111000000, 0b10111000001, 0 , kWX, 30, 2, Inst::kIdStur) , kRWI_RW , 0 , 6 ), // #326 + INST(Strb , BaseLdSt , (0b0011100100, 0b00111000000, 0b00111000001, 0 , kW , 30, 0, Inst::kIdSturb) , kRWI_RW , 0 , 7 ), // #327 + INST(Strh , BaseLdSt , (0b0111100100, 0b01111000000, 0b01111000001, 0 , kWX, 30, 1, Inst::kIdSturh) , kRWI_RW , 0 , 8 ), // #328 + INST(Stset , BaseAtomicSt , (0b1011100000100000001100, kWX, 30) , kRWI_RX , 0 , 18 ), // #329 + INST(Stsetl , BaseAtomicSt , (0b1011100001100000001100, kWX, 30) , kRWI_RX , 0 , 19 ), // #330 + INST(Stsetb , BaseAtomicSt , (0b0011100000100000001100, kW , 0 ) , kRWI_RX , 0 , 20 ), // #331 + INST(Stsetlb , BaseAtomicSt , (0b0011100001100000001100, kW , 0 ) , kRWI_RX , 0 , 21 ), // #332 + INST(Stseth , BaseAtomicSt , (0b0111100000100000001100, kW , 0 ) , kRWI_RX , 0 , 22 ), // #333 + INST(Stsetlh , BaseAtomicSt , (0b0111100001100000001100, kW , 0 ) , kRWI_RX , 0 , 23 ), // #334 + INST(Stsmax , BaseAtomicSt , (0b1011100000100000010000, kWX, 30) , kRWI_RX , 0 , 24 ), // #335 + INST(Stsmaxl , BaseAtomicSt , (0b1011100001100000010000, kWX, 30) , kRWI_RX , 0 , 25 ), // #336 + INST(Stsmaxb , BaseAtomicSt , (0b0011100000100000010000, kW , 0 ) , kRWI_RX , 0 , 26 ), // #337 + INST(Stsmaxlb , BaseAtomicSt , (0b0011100001100000010000, kW , 0 ) , kRWI_RX , 0 , 27 ), // #338 + INST(Stsmaxh , BaseAtomicSt , (0b0111100000100000010000, kW , 0 ) , kRWI_RX , 0 , 28 ), // #339 + INST(Stsmaxlh , BaseAtomicSt , (0b0111100001100000010000, kW , 0 ) , kRWI_RX , 0 , 29 ), // #340 + INST(Stsmin , BaseAtomicSt , (0b1011100000100000010100, kWX, 30) , kRWI_RX , 0 , 30 ), // #341 + INST(Stsminl , BaseAtomicSt , (0b1011100001100000010100, kWX, 30) , kRWI_RX , 0 , 31 ), // #342 + INST(Stsminb , BaseAtomicSt , (0b0011100000100000010100, kW , 0 ) , kRWI_RX , 0 , 32 ), // #343 + INST(Stsminlb , BaseAtomicSt , (0b0011100001100000010100, kW , 0 ) , kRWI_RX , 0 , 33 ), // #344 + INST(Stsminh , BaseAtomicSt , (0b0111100000100000010100, kW , 0 ) , kRWI_RX , 0 , 34 ), // #345 + INST(Stsminlh , BaseAtomicSt , (0b0111100001100000010100, kW , 0 ) , kRWI_RX , 0 , 35 ), // #346 + INST(Sttr , BaseRM_SImm9 , (0b1011100000000000000010, 0b0000000000000000000000, kWX, kZR, 30, 0) , kRWI_RW , 0 , 15 ), // #347 + INST(Sttrb , BaseRM_SImm9 , (0b0011100000000000000010, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_RW , 0 , 16 ), // #348 + INST(Sttrh , BaseRM_SImm9 , (0b0111100000000000000010, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_RW , 0 , 17 ), // #349 + INST(Stumax , BaseAtomicSt , (0b1011100000100000011000, kWX, 30) , kRWI_RX , 0 , 36 ), // #350 + INST(Stumaxl , BaseAtomicSt , (0b1011100001100000011000, kWX, 30) , kRWI_RX , 0 , 37 ), // #351 + INST(Stumaxb , BaseAtomicSt , (0b0011100000100000011000, kW , 0 ) , kRWI_RX , 0 , 38 ), // #352 + INST(Stumaxlb , BaseAtomicSt , (0b0011100001100000011000, kW , 0 ) , kRWI_RX , 0 , 39 ), // #353 + INST(Stumaxh , BaseAtomicSt , (0b0111100000100000011000, kW , 0 ) , kRWI_RX , 0 , 40 ), // #354 + INST(Stumaxlh , BaseAtomicSt , (0b0111100001100000011000, kW , 0 ) , kRWI_RX , 0 , 41 ), // #355 + INST(Stumin , BaseAtomicSt , (0b1011100000100000011100, kWX, 30) , kRWI_RX , 0 , 42 ), // #356 + INST(Stuminl , BaseAtomicSt , (0b1011100001100000011100, kWX, 30) , kRWI_RX , 0 , 43 ), // #357 + INST(Stuminb , BaseAtomicSt , (0b0011100000100000011100, kW , 0 ) , kRWI_RX , 0 , 44 ), // #358 + INST(Stuminlb , BaseAtomicSt , (0b0011100001100000011100, kW , 0 ) , kRWI_RX , 0 , 45 ), // #359 + INST(Stuminh , BaseAtomicSt , (0b0111100000100000011100, kW , 0 ) , kRWI_RX , 0 , 46 ), // #360 + INST(Stuminlh , BaseAtomicSt , (0b0111100001100000011100, kW , 0 ) , kRWI_RX , 0 , 47 ), // #361 + INST(Stur , BaseRM_SImm9 , (0b1011100000000000000000, 0b0000000000000000000000, kWX, kZR, 30, 0) , kRWI_RW , 0 , 18 ), // #362 + INST(Sturb , BaseRM_SImm9 , (0b0011100000000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_RW , 0 , 19 ), // #363 + INST(Sturh , BaseRM_SImm9 , (0b0111100000000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_RW , 0 , 20 ), // #364 + INST(Stxp , BaseStxp , (0b1000100000100000000000, kWX, 30) , kRWI_WRRW , 0 , 1 ), // #365 + INST(Stxr , BaseStx , (0b1000100000000000011111, kWX, 30) , kRWI_WRW , 0 , 0 ), // #366 + INST(Stxrb , BaseStx , (0b0000100000000000011111, kW , 0 ) , kRWI_WRW , 0 , 1 ), // #367 + INST(Stxrh , BaseStx , (0b0100100000000000011111, kW , 0 ) , kRWI_WRW , 0 , 2 ), // #368 + INST(Stz2g , BaseRM_SImm9 , (0b1101100111100000000010, 0b1101100111100000000001, kX , kSP, 0, 4) , kRWI_RW , 0 , 21 ), // #369 + INST(Stzg , BaseRM_SImm9 , (0b1101100101100000000010, 0b1101100101100000000001, kX , kSP, 0, 4) , kRWI_RW , 0 , 22 ), // #370 + INST(Stzgm , BaseRM_NoImm , (0b1101100100100000000000, kX , kZR, 0) , kRWI_RW , 0 , 20 ), // #371 + INST(Sub , BaseAddSub , (0b1001011000, 0b1001011001, 0b1010001) , kRWI_W , 0 , 2 ), // #372 + INST(Subg , BaseRRII , (0b1101000110000000000000, kX, kSP, kX, kSP, 6, 4, 16, 4, 0, 10) , kRWI_W , 0 , 1 ), // #373 + INST(Subp , BaseRRR , (0b1001101011000000000000, kX, kZR, kX, kSP, kX, kSP, false) , kRWI_W , 0 , 20 ), // #374 + INST(Subps , BaseRRR , (0b1011101011000000000000, kX, kZR, kX, kSP, kX, kSP, false) , kRWI_W , 0 , 21 ), // #375 + INST(Subs , BaseAddSub , (0b1101011000, 0b1101011001, 0b1110001) , kRWI_W , 0 , 3 ), // #376 + INST(Svc , BaseOpImm , (0b11010100000000000000000000000001, 16, 5) , 0 , 0 , 12 ), // #377 + INST(Swp , BaseAtomicOp , (0b1011100000100000100000, kWX, 30, 1) , kRWI_RWX , 0 , 111), // #378 + INST(Swpa , BaseAtomicOp , (0b1011100010100000100000, kWX, 30, 1) , kRWI_RWX , 0 , 112), // #379 + INST(Swpab , BaseAtomicOp , (0b0011100010100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 113), // #380 + INST(Swpah , BaseAtomicOp , (0b0111100010100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 114), // #381 + INST(Swpal , BaseAtomicOp , (0b1011100011100000100000, kWX, 30, 1) , kRWI_RWX , 0 , 115), // #382 + INST(Swpalb , BaseAtomicOp , (0b0011100011100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 116), // #383 + INST(Swpalh , BaseAtomicOp , (0b0111100011100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 117), // #384 + INST(Swpb , BaseAtomicOp , (0b0011100000100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 118), // #385 + INST(Swph , BaseAtomicOp , (0b0111100000100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 119), // #386 + INST(Swpl , BaseAtomicOp , (0b1011100001100000100000, kWX, 30, 1) , kRWI_RWX , 0 , 120), // #387 + INST(Swplb , BaseAtomicOp , (0b0011100001100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 121), // #388 + INST(Swplh , BaseAtomicOp , (0b0111100001100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 122), // #389 + INST(Sxtb , BaseExtend , (0b0001001100000000000111, kWX, 0) , kRWI_W , 0 , 0 ), // #390 + INST(Sxth , BaseExtend , (0b0001001100000000001111, kWX, 0) , kRWI_W , 0 , 1 ), // #391 + INST(Sxtw , BaseExtend , (0b1001001101000000011111, kX , 0) , kRWI_W , 0 , 2 ), // #392 + INST(Sys , BaseSys , (_) , kRWI_W , 0 , 0 ), // #393 + INST(Tlbi , BaseAtDcIcTlbi , (0b00011110000000, 0b00010000000000, false) , kRWI_RX , 0 , 3 ), // #394 + INST(Tst , BaseTst , (0b1101010000, 0b111001000) , kRWI_R , 0 , 0 ), // #395 + INST(Tbnz , BaseBranchTst , (0b00110111000000000000000000000000) , kRWI_R , 0 , 0 ), // #396 + INST(Tbz , BaseBranchTst , (0b00110110000000000000000000000000) , kRWI_R , 0 , 1 ), // #397 + INST(Ubfiz , BaseBfi , (0b01010011000000000000000000000000) , kRWI_W , 0 , 2 ), // #398 + INST(Ubfm , BaseBfm , (0b01010011000000000000000000000000) , kRWI_W , 0 , 2 ), // #399 + INST(Ubfx , BaseBfx , (0b01010011000000000000000000000000) , kRWI_W , 0 , 2 ), // #400 + INST(Udf , BaseOpImm , (0b00000000000000000000000000000000, 16, 0) , 0 , 0 , 13 ), // #401 + INST(Udiv , BaseRRR , (0b0001101011000000000010, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 22 ), // #402 + INST(Umaddl , BaseRRRR , (0b1001101110100000000000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false) , kRWI_W , 0 , 4 ), // #403 + INST(Umnegl , BaseRRR , (0b1001101110100000111111, kX , kZR, kW , kZR, kW , kZR, false) , kRWI_W , 0 , 23 ), // #404 + INST(Umull , BaseRRR , (0b1001101110100000011111, kX , kZR, kW , kZR, kW , kZR, false) , kRWI_W , 0 , 24 ), // #405 + INST(Umulh , BaseRRR , (0b1001101111000000011111, kX , kZR, kX , kZR, kX , kZR, false) , kRWI_W , 0 , 25 ), // #406 + INST(Umsubl , BaseRRRR , (0b1001101110100000100000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false) , kRWI_W , 0 , 5 ), // #407 + INST(Uxtb , BaseExtend , (0b0101001100000000000111, kW, 1) , kRWI_W , 0 , 3 ), // #408 + INST(Uxth , BaseExtend , (0b0101001100000000001111, kW, 1) , kRWI_W , 0 , 4 ), // #409 + INST(Wfe , BaseOp , (0b11010101000000110010000001011111) , 0 , 0 , 18 ), // #410 + INST(Wfi , BaseOp , (0b11010101000000110010000001111111) , 0 , 0 , 19 ), // #411 + INST(Xaflag , BaseOp , (0b11010101000000000100000000111111) , 0 , 0 , 20 ), // #412 + INST(Xpacd , BaseR , (0b11011010110000010100011111100000, kX, kZR, 0) , kRWI_X , 0 , 8 ), // #413 + INST(Xpaci , BaseR , (0b11011010110000010100001111100000, kX, kZR, 0) , kRWI_X , 0 , 9 ), // #414 + INST(Xpaclri , BaseOp , (0b11010101000000110010000011111111) , kRWI_X , 0 , 21 ), // #415 + INST(Yield , BaseOp , (0b11010101000000110010000000111111) , 0 , 0 , 22 ), // #416 + INST(Abs_v , ISimdVV , (0b0000111000100000101110, kVO_V_Any) , kRWI_W , 0 , 0 ), // #417 + INST(Add_v , ISimdVVV , (0b0000111000100000100001, kVO_V_Any) , kRWI_W , 0 , 0 ), // #418 + INST(Addhn_v , ISimdVVV , (0b0000111000100000010000, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 1 ), // #419 + INST(Addhn2_v , ISimdVVV , (0b0100111000100000010000, kVO_V_B16H8S4) , kRWI_W , F(Narrow) , 2 ), // #420 + INST(Addp_v , ISimdPair , (0b0101111000110001101110, 0b0000111000100000101111, kVO_V_Any) , kRWI_W , F(Pair) , 0 ), // #421 + INST(Addv_v , ISimdSV , (0b0000111000110001101110, kVO_V_BH_4S) , kRWI_W , 0 , 0 ), // #422 + INST(Aesd_v , ISimdVVx , (0b0100111000101000010110, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 0 ), // #423 + INST(Aese_v , ISimdVVx , (0b0100111000101000010010, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 1 ), // #424 + INST(Aesimc_v , ISimdVVx , (0b0100111000101000011110, kOp_V16B, kOp_V16B) , kRWI_W , 0 , 2 ), // #425 + INST(Aesmc_v , ISimdVVx , (0b0100111000101000011010, kOp_V16B, kOp_V16B) , kRWI_W , 0 , 3 ), // #426 + INST(And_v , ISimdVVV , (0b0000111000100000000111, kVO_V_B) , kRWI_W , 0 , 3 ), // #427 + INST(Bcax_v , ISimdVVVV , (0b1100111000100000000000, kVO_V_B16) , kRWI_W , 0 , 0 ), // #428 + INST(Bfcvt_v , ISimdVVx , (0b0001111001100011010000, kOp_H, kOp_S) , kRWI_W , 0 , 4 ), // #429 + INST(Bfcvtn_v , ISimdVVx , (0b0000111010100001011010, kOp_V4H, kOp_V4S) , kRWI_W , F(Narrow) , 5 ), // #430 + INST(Bfcvtn2_v , ISimdVVx , (0b0100111010100001011010, kOp_V8H, kOp_V4S) , kRWI_W , F(Narrow) , 6 ), // #431 + INST(Bfdot_v , SimdDot , (0b0010111001000000111111, 0b0000111101000000111100, kET_S, kET_H, kET_2H) , kRWI_X , 0 , 0 ), // #432 + INST(Bfmlalb_v , SimdFmlal , (0b0010111011000000111111, 0b0000111111000000111100, 0, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 0 ), // #433 + INST(Bfmlalt_v , SimdFmlal , (0b0110111011000000111111, 0b0100111111000000111100, 0, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 1 ), // #434 + INST(Bfmmla_v , ISimdVVVx , (0b0110111001000000111011, kOp_V4S, kOp_V8H, kOp_V8H) , kRWI_X , F(Long) , 0 ), // #435 + INST(Bic_v , SimdBicOrr , (0b0000111001100000000111, 0b0010111100000000000001) , kRWI_W , 0 , 0 ), // #436 + INST(Bif_v , ISimdVVV , (0b0010111011100000000111, kVO_V_B) , kRWI_X , 0 , 4 ), // #437 + INST(Bit_v , ISimdVVV , (0b0010111010100000000111, kVO_V_B) , kRWI_X , 0 , 5 ), // #438 + INST(Bsl_v , ISimdVVV , (0b0010111001100000000111, kVO_V_B) , kRWI_X , 0 , 6 ), // #439 + INST(Cls_v , ISimdVV , (0b0000111000100000010010, kVO_V_BHS) , kRWI_W , 0 , 1 ), // #440 + INST(Clz_v , ISimdVV , (0b0010111000100000010010, kVO_V_BHS) , kRWI_W , 0 , 2 ), // #441 + INST(Cmeq_v , SimdCmp , (0b0010111000100000100011, 0b0000111000100000100110, kVO_V_Any) , kRWI_W , 0 , 0 ), // #442 + INST(Cmge_v , SimdCmp , (0b0000111000100000001111, 0b0010111000100000100010, kVO_V_Any) , kRWI_W , 0 , 1 ), // #443 + INST(Cmgt_v , SimdCmp , (0b0000111000100000001101, 0b0000111000100000100010, kVO_V_Any) , kRWI_W , 0 , 2 ), // #444 + INST(Cmhi_v , SimdCmp , (0b0010111000100000001101, 0b0000000000000000000000, kVO_V_Any) , kRWI_W , 0 , 3 ), // #445 + INST(Cmhs_v , SimdCmp , (0b0010111000100000001111, 0b0000000000000000000000, kVO_V_Any) , kRWI_W , 0 , 4 ), // #446 + INST(Cmle_v , SimdCmp , (0b0000000000000000000000, 0b0010111000100000100110, kVO_V_Any) , kRWI_W , 0 , 5 ), // #447 + INST(Cmlt_v , SimdCmp , (0b0000000000000000000000, 0b0000111000100000101010, kVO_V_Any) , kRWI_W , 0 , 6 ), // #448 + INST(Cmtst_v , ISimdVVV , (0b0000111000100000100011, kVO_V_Any) , kRWI_W , 0 , 7 ), // #449 + INST(Cnt_v , ISimdVV , (0b0000111000100000010110, kVO_V_B) , kRWI_W , 0 , 3 ), // #450 + INST(Dup_v , SimdDup , (_) , kRWI_W , 0 , 0 ), // #451 + INST(Eor_v , ISimdVVV , (0b0010111000100000000111, kVO_V_B) , kRWI_W , 0 , 8 ), // #452 + INST(Eor3_v , ISimdVVVV , (0b1100111000000000000000, kVO_V_B16) , kRWI_W , 0 , 1 ), // #453 + INST(Ext_v , ISimdVVVI , (0b0010111000000000000000, kVO_V_B, 4, 11, 1) , kRWI_W , 0 , 0 ), // #454 + INST(Fabd_v , FSimdVVV , (0b0111111010100000110101, kHF_C, 0b0010111010100000110101, kHF_C) , kRWI_W , 0 , 0 ), // #455 + INST(Fabs_v , FSimdVV , (0b0001111000100000110000, kHF_A, 0b0000111010100000111110, kHF_B) , kRWI_W , 0 , 0 ), // #456 + INST(Facge_v , FSimdVVV , (0b0111111000100000111011, kHF_C, 0b0010111000100000111011, kHF_C) , kRWI_W , 0 , 1 ), // #457 + INST(Facgt_v , FSimdVVV , (0b0111111010100000111011, kHF_C, 0b0010111010100000111011, kHF_C) , kRWI_W , 0 , 2 ), // #458 + INST(Fadd_v , FSimdVVV , (0b0001111000100000001010, kHF_A, 0b0000111000100000110101, kHF_C) , kRWI_W , 0 , 3 ), // #459 + INST(Faddp_v , FSimdPair , (0b0111111000110000110110, 0b0010111000100000110101) , kRWI_W , 0 , 0 ), // #460 + INST(Fcadd_v , SimdFcadd , (0b0010111000000000111001) , kRWI_W , 0 , 0 ), // #461 + INST(Fccmp_v , SimdFccmpFccmpe , (0b00011110001000000000010000000000) , kRWI_R , 0 , 0 ), // #462 + INST(Fccmpe_v , SimdFccmpFccmpe , (0b00011110001000000000010000010000) , kRWI_R , 0 , 1 ), // #463 + INST(Fcmeq_v , SimdFcm , (0b0000111000100000111001, kHF_C, 0b0000111010100000110110) , kRWI_W , 0 , 0 ), // #464 + INST(Fcmge_v , SimdFcm , (0b0010111000100000111001, kHF_C, 0b0010111010100000110010) , kRWI_W , 0 , 1 ), // #465 + INST(Fcmgt_v , SimdFcm , (0b0010111010100000111001, kHF_C, 0b0000111010100000110010) , kRWI_W , 0 , 2 ), // #466 + INST(Fcmla_v , SimdFcmla , (0b0010111000000000110001, 0b0010111100000000000100) , kRWI_X , 0 , 0 ), // #467 + INST(Fcmle_v , SimdFcm , (0b0000000000000000000000, kHF_C, 0b0010111010100000110110) , kRWI_W , 0 , 3 ), // #468 + INST(Fcmlt_v , SimdFcm , (0b0000000000000000000000, kHF_C, 0b0000111010100000111010) , kRWI_W , 0 , 4 ), // #469 + INST(Fcmp_v , SimdFcmpFcmpe , (0b00011110001000000010000000000000) , kRWI_R , 0 , 0 ), // #470 + INST(Fcmpe_v , SimdFcmpFcmpe , (0b00011110001000000010000000010000) , kRWI_R , 0 , 1 ), // #471 + INST(Fcsel_v , SimdFcsel , (_) , kRWI_W , 0 , 0 ), // #472 + INST(Fcvt_v , SimdFcvt , (_) , kRWI_W , 0 , 0 ), // #473 + INST(Fcvtas_v , SimdFcvtSV , (0b0000111000100001110010, 0b0000000000000000000000, 0b0001111000100100000000, 1) , kRWI_W , 0 , 0 ), // #474 + INST(Fcvtau_v , SimdFcvtSV , (0b0010111000100001110010, 0b0000000000000000000000, 0b0001111000100101000000, 1) , kRWI_W , 0 , 1 ), // #475 + INST(Fcvtl_v , SimdFcvtLN , (0b0000111000100001011110, 0, 0) , kRWI_W , F(Long) , 0 ), // #476 + INST(Fcvtl2_v , SimdFcvtLN , (0b0100111000100001011110, 0, 0) , kRWI_W , F(Long) , 1 ), // #477 + INST(Fcvtms_v , SimdFcvtSV , (0b0000111000100001101110, 0b0000000000000000000000, 0b0001111000110000000000, 1) , kRWI_W , 0 , 2 ), // #478 + INST(Fcvtmu_v , SimdFcvtSV , (0b0010111000100001101110, 0b0000000000000000000000, 0b0001111000110001000000, 1) , kRWI_W , 0 , 3 ), // #479 + INST(Fcvtn_v , SimdFcvtLN , (0b0000111000100001011010, 0, 0) , kRWI_W , F(Narrow) , 2 ), // #480 + INST(Fcvtn2_v , SimdFcvtLN , (0b0100111000100001011010, 0, 0) , kRWI_X , F(Narrow) , 3 ), // #481 + INST(Fcvtns_v , SimdFcvtSV , (0b0000111000100001101010, 0b0000000000000000000000, 0b0001111000100000000000, 1) , kRWI_W , 0 , 4 ), // #482 + INST(Fcvtnu_v , SimdFcvtSV , (0b0010111000100001101010, 0b0000000000000000000000, 0b0001111000100001000000, 1) , kRWI_W , 0 , 5 ), // #483 + INST(Fcvtps_v , SimdFcvtSV , (0b0000111010100001101010, 0b0000000000000000000000, 0b0001111000101000000000, 1) , kRWI_W , 0 , 6 ), // #484 + INST(Fcvtpu_v , SimdFcvtSV , (0b0010111010100001101010, 0b0000000000000000000000, 0b0001111000101001000000, 1) , kRWI_W , 0 , 7 ), // #485 + INST(Fcvtxn_v , SimdFcvtLN , (0b0010111000100001011010, 1, 1) , kRWI_W , F(Narrow) , 4 ), // #486 + INST(Fcvtxn2_v , SimdFcvtLN , (0b0110111000100001011010, 1, 0) , kRWI_X , F(Narrow) , 5 ), // #487 + INST(Fcvtzs_v , SimdFcvtSV , (0b0000111010100001101110, 0b0000111100000000111111, 0b0001111000111000000000, 1) , kRWI_W , 0 , 8 ), // #488 + INST(Fcvtzu_v , SimdFcvtSV , (0b0010111010100001101110, 0b0010111100000000111111, 0b0001111000111001000000, 1) , kRWI_W , 0 , 9 ), // #489 + INST(Fdiv_v , FSimdVVV , (0b0001111000100000000110, kHF_A, 0b0010111000100000111111, kHF_C) , kRWI_W , 0 , 4 ), // #490 + INST(Fjcvtzs_v , ISimdVVx , (0b0001111001111110000000, kOp_GpW, kOp_D) , kRWI_W , 0 , 7 ), // #491 + INST(Fmadd_v , FSimdVVVV , (0b0001111100000000000000, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 0 ), // #492 + INST(Fmax_v , FSimdVVV , (0b0001111000100000010010, kHF_A, 0b0000111000100000111101, kHF_C) , kRWI_W , 0 , 5 ), // #493 + INST(Fmaxnm_v , FSimdVVV , (0b0001111000100000011010, kHF_A, 0b0000111000100000110001, kHF_C) , kRWI_W , 0 , 6 ), // #494 + INST(Fmaxnmp_v , FSimdPair , (0b0111111000110000110010, 0b0010111000100000110001) , kRWI_W , 0 , 1 ), // #495 + INST(Fmaxnmv_v , FSimdSV , (0b0010111000110000110010) , kRWI_W , 0 , 0 ), // #496 + INST(Fmaxp_v , FSimdPair , (0b0111111000110000111110, 0b0010111000100000111101) , kRWI_W , 0 , 2 ), // #497 + INST(Fmaxv_v , FSimdSV , (0b0010111000110000111110) , kRWI_W , 0 , 1 ), // #498 + INST(Fmin_v , FSimdVVV , (0b0001111000100000010110, kHF_A, 0b0000111010100000111101, kHF_C) , kRWI_W , 0 , 7 ), // #499 + INST(Fminnm_v , FSimdVVV , (0b0001111000100000011110, kHF_A, 0b0000111010100000110001, kHF_C) , kRWI_W , 0 , 8 ), // #500 + INST(Fminnmp_v , FSimdPair , (0b0111111010110000110010, 0b0010111010100000110001) , kRWI_W , 0 , 3 ), // #501 + INST(Fminnmv_v , FSimdSV , (0b0010111010110000110010) , kRWI_W , 0 , 2 ), // #502 + INST(Fminp_v , FSimdPair , (0b0111111010110000111110, 0b0010111010100000111101) , kRWI_W , 0 , 4 ), // #503 + INST(Fminv_v , FSimdSV , (0b0010111010110000111110) , kRWI_W , 0 , 3 ), // #504 + INST(Fmla_v , FSimdVVVe , (0b0000000000000000000000, kHF_N, 0b0000111000100000110011, 0b0000111110000000000100) , kRWI_X , F(VH0_15) , 0 ), // #505 + INST(Fmlal_v , SimdFmlal , (0b0000111000100000111011, 0b0000111110000000000000, 1, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 2 ), // #506 + INST(Fmlal2_v , SimdFmlal , (0b0010111000100000110011, 0b0010111110000000100000, 1, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 3 ), // #507 + INST(Fmls_v , FSimdVVVe , (0b0000000000000000000000, kHF_N, 0b0000111010100000110011, 0b0000111110000000010100) , kRWI_X , F(VH0_15) , 1 ), // #508 + INST(Fmlsl_v , SimdFmlal , (0b0000111010100000111011, 0b0000111110000000010000, 1, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 4 ), // #509 + INST(Fmlsl2_v , SimdFmlal , (0b0010111010100000110011, 0b0010111110000000110000, 1, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 5 ), // #510 + INST(Fmov_v , SimdFmov , (_) , kRWI_W , 0 , 0 ), // #511 + INST(Fmsub_v , FSimdVVVV , (0b0001111100000000100000, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 1 ), // #512 + INST(Fmul_v , FSimdVVVe , (0b0001111000100000000010, kHF_A, 0b0010111000100000110111, 0b0000111110000000100100) , kRWI_W , F(VH0_15) , 2 ), // #513 + INST(Fmulx_v , FSimdVVVe , (0b0101111000100000110111, kHF_C, 0b0000111000100000110111, 0b0010111110000000100100) , kRWI_W , F(VH0_15) , 3 ), // #514 + INST(Fneg_v , FSimdVV , (0b0001111000100001010000, kHF_A, 0b0010111010100000111110, kHF_B) , kRWI_W , 0 , 1 ), // #515 + INST(Fnmadd_v , FSimdVVVV , (0b0001111100100000000000, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 2 ), // #516 + INST(Fnmsub_v , FSimdVVVV , (0b0001111100100000100000, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 3 ), // #517 + INST(Fnmul_v , FSimdVVV , (0b0001111000100000100010, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 9 ), // #518 + INST(Frecpe_v , FSimdVV , (0b0101111010100001110110, kHF_B, 0b0000111010100001110110, kHF_B) , kRWI_W , 0 , 2 ), // #519 + INST(Frecps_v , FSimdVVV , (0b0101111000100000111111, kHF_C, 0b0000111000100000111111, kHF_C) , kRWI_W , 0 , 10 ), // #520 + INST(Frecpx_v , FSimdVV , (0b0101111010100001111110, kHF_B, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 3 ), // #521 + INST(Frint32x_v , FSimdVV , (0b0001111000101000110000, kHF_N, 0b0010111000100001111010, kHF_N) , kRWI_W , 0 , 4 ), // #522 + INST(Frint32z_v , FSimdVV , (0b0001111000101000010000, kHF_N, 0b0000111000100001111010, kHF_N) , kRWI_W , 0 , 5 ), // #523 + INST(Frint64x_v , FSimdVV , (0b0001111000101001110000, kHF_N, 0b0010111000100001111110, kHF_N) , kRWI_W , 0 , 6 ), // #524 + INST(Frint64z_v , FSimdVV , (0b0001111000101001010000, kHF_N, 0b0000111000100001111110, kHF_N) , kRWI_W , 0 , 7 ), // #525 + INST(Frinta_v , FSimdVV , (0b0001111000100110010000, kHF_A, 0b0010111000100001100010, kHF_B) , kRWI_W , 0 , 8 ), // #526 + INST(Frinti_v , FSimdVV , (0b0001111000100111110000, kHF_A, 0b0010111010100001100110, kHF_B) , kRWI_W , 0 , 9 ), // #527 + INST(Frintm_v , FSimdVV , (0b0001111000100101010000, kHF_A, 0b0000111000100001100110, kHF_B) , kRWI_W , 0 , 10 ), // #528 + INST(Frintn_v , FSimdVV , (0b0001111000100100010000, kHF_A, 0b0000111000100001100010, kHF_B) , kRWI_W , 0 , 11 ), // #529 + INST(Frintp_v , FSimdVV , (0b0001111000100100110000, kHF_A, 0b0000111010100001100010, kHF_B) , kRWI_W , 0 , 12 ), // #530 + INST(Frintx_v , FSimdVV , (0b0001111000100111010000, kHF_A, 0b0010111000100001100110, kHF_B) , kRWI_W , 0 , 13 ), // #531 + INST(Frintz_v , FSimdVV , (0b0001111000100101110000, kHF_A, 0b0000111010100001100110, kHF_B) , kRWI_W , 0 , 14 ), // #532 + INST(Frsqrte_v , FSimdVV , (0b0111111010100001110110, kHF_B, 0b0010111010100001110110, kHF_B) , kRWI_W , 0 , 15 ), // #533 + INST(Frsqrts_v , FSimdVVV , (0b0101111010100000111111, kHF_C, 0b0000111010100000111111, kHF_C) , kRWI_W , 0 , 11 ), // #534 + INST(Fsqrt_v , FSimdVV , (0b0001111000100001110000, kHF_A, 0b0010111010100001111110, kHF_B) , kRWI_W , 0 , 16 ), // #535 + INST(Fsub_v , FSimdVVV , (0b0001111000100000001110, kHF_A, 0b0000111010100000110101, kHF_C) , kRWI_W , 0 , 12 ), // #536 + INST(Ins_v , SimdIns , (_) , kRWI_X , 0 , 0 ), // #537 + INST(Ld1_v , SimdLdNStN , (0b0000110101000000000000, 0b0000110001000000001000, 1, 0) , kRWI_LDn , F(Consecutive) , 0 ), // #538 + INST(Ld1r_v , SimdLdNStN , (0b0000110101000000110000, 0b0000000000000000000000, 1, 1) , kRWI_LDn , F(Consecutive) , 1 ), // #539 + INST(Ld2_v , SimdLdNStN , (0b0000110101100000000000, 0b0000110001000000100000, 2, 0) , kRWI_LDn , F(Consecutive) , 2 ), // #540 + INST(Ld2r_v , SimdLdNStN , (0b0000110101100000110000, 0b0000000000000000000000, 2, 1) , kRWI_LDn , F(Consecutive) , 3 ), // #541 + INST(Ld3_v , SimdLdNStN , (0b0000110101000000001000, 0b0000110001000000010000, 3, 0) , kRWI_LDn , F(Consecutive) , 4 ), // #542 + INST(Ld3r_v , SimdLdNStN , (0b0000110101000000111000, 0b0000000000000000000000, 3, 1) , kRWI_LDn , F(Consecutive) , 5 ), // #543 + INST(Ld4_v , SimdLdNStN , (0b0000110101100000001000, 0b0000110001000000000000, 4, 0) , kRWI_LDn , F(Consecutive) , 6 ), // #544 + INST(Ld4r_v , SimdLdNStN , (0b0000110101100000111000, 0b0000000000000000000000, 4, 1) , kRWI_LDn , F(Consecutive) , 7 ), // #545 + INST(Ldnp_v , SimdLdpStp , (0b0010110001, 0b0000000000) , kRWI_WW , 0 , 0 ), // #546 + INST(Ldp_v , SimdLdpStp , (0b0010110101, 0b0010110011) , kRWI_WW , 0 , 1 ), // #547 + INST(Ldr_v , SimdLdSt , (0b0011110101, 0b00111100010, 0b00111100011, 0b00011100, Inst::kIdLdur_v) , kRWI_W , 0 , 0 ), // #548 + INST(Ldur_v , SimdLdurStur , (0b0011110001000000000000) , kRWI_W , 0 , 0 ), // #549 + INST(Mla_v , ISimdVVVe , (0b0000111000100000100101, kVO_V_BHS, 0b0010111100000000000000, kVO_V_HS) , kRWI_X , F(VH0_15) , 0 ), // #550 + INST(Mls_v , ISimdVVVe , (0b0010111000100000100101, kVO_V_BHS, 0b0010111100000000010000, kVO_V_HS) , kRWI_X , F(VH0_15) , 1 ), // #551 + INST(Mov_v , SimdMov , (_) , kRWI_W , 0 , 0 ), // #552 + INST(Movi_v , SimdMoviMvni , (0b0000111100000000000001, 0) , kRWI_W , 0 , 0 ), // #553 + INST(Mul_v , ISimdVVVe , (0b0000111000100000100111, kVO_V_BHS, 0b0000111100000000100000, kVO_V_HS) , kRWI_W , F(VH0_15) , 2 ), // #554 + INST(Mvn_v , ISimdVV , (0b0010111000100000010110, kVO_V_B) , kRWI_W , 0 , 4 ), // #555 + INST(Mvni_v , SimdMoviMvni , (0b0000111100000000000001, 1) , kRWI_W , 0 , 1 ), // #556 + INST(Neg_v , ISimdVV , (0b0010111000100000101110, kVO_V_Any) , kRWI_W , 0 , 5 ), // #557 + INST(Not_v , ISimdVV , (0b0010111000100000010110, kVO_V_B) , kRWI_W , 0 , 6 ), // #558 + INST(Orn_v , ISimdVVV , (0b0000111011100000000111, kVO_V_B) , kRWI_W , 0 , 9 ), // #559 + INST(Orr_v , SimdBicOrr , (0b0000111010100000000111, 0b0000111100000000000001) , kRWI_W , 0 , 1 ), // #560 + INST(Pmul_v , ISimdVVV , (0b0010111000100000100111, kVO_V_B) , kRWI_W , 0 , 10 ), // #561 + INST(Pmull_v , ISimdVVV , (0b0000111000100000111000, kVO_V_B8D1) , kRWI_W , F(Long) , 11 ), // #562 + INST(Pmull2_v , ISimdVVV , (0b0100111000100000111000, kVO_V_B16D2) , kRWI_W , F(Long) , 12 ), // #563 + INST(Raddhn_v , ISimdVVV , (0b0010111000100000010000, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 13 ), // #564 + INST(Raddhn2_v , ISimdVVV , (0b0110111000100000010000, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 14 ), // #565 + INST(Rax1_v , ISimdVVV , (0b1100111001100000100011, kVO_V_D2) , kRWI_W , 0 , 15 ), // #566 + INST(Rbit_v , ISimdVV , (0b0010111001100000010110, kVO_V_B) , kRWI_W , 0 , 7 ), // #567 + INST(Rev16_v , ISimdVV , (0b0000111000100000000110, kVO_V_B) , kRWI_W , 0 , 8 ), // #568 + INST(Rev32_v , ISimdVV , (0b0010111000100000000010, kVO_V_BH) , kRWI_W , 0 , 9 ), // #569 + INST(Rev64_v , ISimdVV , (0b0000111000100000000010, kVO_V_BHS) , kRWI_W , 0 , 10 ), // #570 + INST(Rshrn_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000100011, 1, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 0 ), // #571 + INST(Rshrn2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000100011, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 1 ), // #572 + INST(Rsubhn_v , ISimdVVV , (0b0010111000100000011000, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 16 ), // #573 + INST(Rsubhn2_v , ISimdVVV , (0b0110111000100000011000, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 17 ), // #574 + INST(Saba_v , ISimdVVV , (0b0000111000100000011111, kVO_V_BHS) , kRWI_X , 0 , 18 ), // #575 + INST(Sabal_v , ISimdVVV , (0b0000111000100000010100, kVO_V_B8H4S2) , kRWI_X , F(Long) , 19 ), // #576 + INST(Sabal2_v , ISimdVVV , (0b0100111000100000010100, kVO_V_B16H8S4) , kRWI_X , F(Long) , 20 ), // #577 + INST(Sabd_v , ISimdVVV , (0b0000111000100000011101, kVO_V_BHS) , kRWI_W , 0 , 21 ), // #578 + INST(Sabdl_v , ISimdVVV , (0b0000111000100000011100, kVO_V_B8H4S2) , kRWI_W , F(Long) , 22 ), // #579 + INST(Sabdl2_v , ISimdVVV , (0b0100111000100000011100, kVO_V_B16H8S4) , kRWI_W , F(Long) , 23 ), // #580 + INST(Sadalp_v , ISimdVV , (0b0000111000100000011010, kVO_V_BHS) , kRWI_X , F(Long) | F(Pair) , 11 ), // #581 + INST(Saddl_v , ISimdVVV , (0b0000111000100000000000, kVO_V_B8H4S2) , kRWI_W , F(Long) , 24 ), // #582 + INST(Saddl2_v , ISimdVVV , (0b0100111000100000000000, kVO_V_B16H8S4) , kRWI_W , F(Long) , 25 ), // #583 + INST(Saddlp_v , ISimdVV , (0b0000111000100000001010, kVO_V_BHS) , kRWI_W , F(Long) | F(Pair) , 12 ), // #584 + INST(Saddlv_v , ISimdSV , (0b0000111000110000001110, kVO_V_BH_4S) , kRWI_W , F(Long) , 1 ), // #585 + INST(Saddw_v , ISimdWWV , (0b0000111000100000000100, kVO_V_B8H4S2) , kRWI_W , 0 , 0 ), // #586 + INST(Saddw2_v , ISimdWWV , (0b0000111000100000000100, kVO_V_B16H8S4) , kRWI_W , 0 , 1 ), // #587 + INST(Scvtf_v , SimdFcvtSV , (0b0000111000100001110110, 0b0000111100000000111001, 0b0001111000100010000000, 0) , kRWI_W , 0 , 10 ), // #588 + INST(Sdot_v , SimdDot , (0b0000111010000000100101, 0b0000111110000000111000, kET_S, kET_B, kET_4B) , kRWI_X , 0 , 1 ), // #589 + INST(Sha1c_v , ISimdVVVx , (0b0101111000000000000000, kOp_Q, kOp_S, kOp_V4S) , kRWI_X , 0 , 1 ), // #590 + INST(Sha1h_v , ISimdVVx , (0b0101111000101000000010, kOp_S, kOp_S) , kRWI_W , 0 , 8 ), // #591 + INST(Sha1m_v , ISimdVVVx , (0b0101111000000000001000, kOp_Q, kOp_S, kOp_V4S) , kRWI_X , 0 , 2 ), // #592 + INST(Sha1p_v , ISimdVVVx , (0b0101111000000000000100, kOp_Q, kOp_S, kOp_V4S) , kRWI_X , 0 , 3 ), // #593 + INST(Sha1su0_v , ISimdVVVx , (0b0101111000000000001100, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 4 ), // #594 + INST(Sha1su1_v , ISimdVVx , (0b0101111000101000000110, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 9 ), // #595 + INST(Sha256h_v , ISimdVVVx , (0b0101111000000000010000, kOp_Q, kOp_Q, kOp_V4S) , kRWI_X , 0 , 5 ), // #596 + INST(Sha256h2_v , ISimdVVVx , (0b0101111000000000010100, kOp_Q, kOp_Q, kOp_V4S) , kRWI_X , 0 , 6 ), // #597 + INST(Sha256su0_v , ISimdVVx , (0b0101111000101000001010, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 10 ), // #598 + INST(Sha256su1_v , ISimdVVVx , (0b0101111000000000011000, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 7 ), // #599 + INST(Sha512h_v , ISimdVVVx , (0b1100111001100000100000, kOp_Q, kOp_Q, kOp_V2D) , kRWI_X , 0 , 8 ), // #600 + INST(Sha512h2_v , ISimdVVVx , (0b1100111001100000100001, kOp_Q, kOp_Q, kOp_V2D) , kRWI_X , 0 , 9 ), // #601 + INST(Sha512su0_v , ISimdVVx , (0b1100111011000000100000, kOp_V2D, kOp_V2D) , kRWI_X , 0 , 11 ), // #602 + INST(Sha512su1_v , ISimdVVVx , (0b1100111001100000100010, kOp_V2D, kOp_V2D, kOp_V2D) , kRWI_X , 0 , 10 ), // #603 + INST(Shadd_v , ISimdVVV , (0b0000111000100000000001, kVO_V_BHS) , kRWI_W , 0 , 26 ), // #604 + INST(Shl_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000010101, 0, kVO_V_Any) , kRWI_W , 0 , 2 ), // #605 + INST(Shll_v , SimdShiftES , (0b0010111000100001001110, kVO_V_B8H4S2) , kRWI_W , F(Long) , 0 ), // #606 + INST(Shll2_v , SimdShiftES , (0b0110111000100001001110, kVO_V_B16H8S4) , kRWI_W , F(Long) , 1 ), // #607 + INST(Shrn_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000100001, 1, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 3 ), // #608 + INST(Shrn2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000100001, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 4 ), // #609 + INST(Shsub_v , ISimdVVV , (0b0000111000100000001001, kVO_V_BHS) , kRWI_W , 0 , 27 ), // #610 + INST(Sli_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000010101, 0, kVO_V_Any) , kRWI_X , 0 , 5 ), // #611 + INST(Sm3partw1_v , ISimdVVVx , (0b1100111001100000110000, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 11 ), // #612 + INST(Sm3partw2_v , ISimdVVVx , (0b1100111001100000110001, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 12 ), // #613 + INST(Sm3ss1_v , ISimdVVVVx , (0b1100111001000000000000, kOp_V4S, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_W , 0 , 0 ), // #614 + INST(Sm3tt1a_v , SimdSm3tt , (0b1100111001000000100000) , kRWI_X , 0 , 0 ), // #615 + INST(Sm3tt1b_v , SimdSm3tt , (0b1100111001000000100001) , kRWI_X , 0 , 1 ), // #616 + INST(Sm3tt2a_v , SimdSm3tt , (0b1100111001000000100010) , kRWI_X , 0 , 2 ), // #617 + INST(Sm3tt2b_v , SimdSm3tt , (0b1100111001000000100011) , kRWI_X , 0 , 3 ), // #618 + INST(Sm4e_v , ISimdVVx , (0b1100111011000000100001, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 12 ), // #619 + INST(Sm4ekey_v , ISimdVVVx , (0b1100111001100000110010, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 13 ), // #620 + INST(Smax_v , ISimdVVV , (0b0000111000100000011001, kVO_V_BHS) , kRWI_W , 0 , 28 ), // #621 + INST(Smaxp_v , ISimdVVV , (0b0000111000100000101001, kVO_V_BHS) , kRWI_W , 0 , 29 ), // #622 + INST(Smaxv_v , ISimdSV , (0b0000111000110000101010, kVO_V_BH_4S) , kRWI_W , 0 , 2 ), // #623 + INST(Smin_v , ISimdVVV , (0b0000111000100000011011, kVO_V_BHS) , kRWI_W , 0 , 30 ), // #624 + INST(Sminp_v , ISimdVVV , (0b0000111000100000101011, kVO_V_BHS) , kRWI_W , 0 , 31 ), // #625 + INST(Sminv_v , ISimdSV , (0b0000111000110001101010, kVO_V_BH_4S) , kRWI_W , 0 , 3 ), // #626 + INST(Smlal_v , ISimdVVVe , (0b0000111000100000100000, kVO_V_B8H4S2, 0b0000111100000000001000, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 3 ), // #627 + INST(Smlal2_v , ISimdVVVe , (0b0100111000100000100000, kVO_V_B16H8S4, 0b0100111100000000001000, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 4 ), // #628 + INST(Smlsl_v , ISimdVVVe , (0b0000111000100000101000, kVO_V_B8H4S2, 0b0000111100000000011000, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 5 ), // #629 + INST(Smlsl2_v , ISimdVVVe , (0b0100111000100000101000, kVO_V_B16H8S4, 0b0100111100000000011000, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 6 ), // #630 + INST(Smmla_v , ISimdVVVx , (0b0100111010000000101001, kOp_V4S, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 14 ), // #631 + INST(Smov_v , SimdSmovUmov , (0b0000111000000000001011, kVO_V_BHS, 1) , kRWI_W , 0 , 0 ), // #632 + INST(Smull_v , ISimdVVVe , (0b0000111000100000110000, kVO_V_B8H4S2, 0b0000111100000000101000, kVO_V_H4S2) , kRWI_W , F(Long) | F(VH0_15) , 7 ), // #633 + INST(Smull2_v , ISimdVVVe , (0b0100111000100000110000, kVO_V_B16H8S4, 0b0100111100000000101000, kVO_V_H8S4) , kRWI_W , F(Long) | F(VH0_15) , 8 ), // #634 + INST(Sqabs_v , ISimdVV , (0b0000111000100000011110, kVO_SV_Any) , kRWI_W , 0 , 13 ), // #635 + INST(Sqadd_v , ISimdVVV , (0b0000111000100000000011, kVO_SV_Any) , kRWI_W , 0 , 32 ), // #636 + INST(Sqdmlal_v , ISimdVVVe , (0b0000111000100000100100, kVO_SV_BHS, 0b0000111100000000001100, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 9 ), // #637 + INST(Sqdmlal2_v , ISimdVVVe , (0b0100111000100000100100, kVO_V_B16H8S4, 0b0100111100000000001100, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 10 ), // #638 + INST(Sqdmlsl_v , ISimdVVVe , (0b0000111000100000101100, kVO_SV_BHS, 0b0000111100000000011100, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 11 ), // #639 + INST(Sqdmlsl2_v , ISimdVVVe , (0b0100111000100000101100, kVO_V_B16H8S4, 0b0100111100000000011100, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 12 ), // #640 + INST(Sqdmulh_v , ISimdVVVe , (0b0000111000100000101101, kVO_SV_HS, 0b0000111100000000110000, kVO_SV_HS) , kRWI_W , F(VH0_15) , 13 ), // #641 + INST(Sqdmull_v , ISimdVVVe , (0b0000111000100000110100, kVO_SV_BHS, 0b0000111100000000101100, kVO_V_H4S2) , kRWI_W , F(Long) | F(VH0_15) , 14 ), // #642 + INST(Sqdmull2_v , ISimdVVVe , (0b0100111000100000110100, kVO_V_B16H8S4, 0b0100111100000000101100, kVO_V_H8S4) , kRWI_W , F(Long) | F(VH0_15) , 15 ), // #643 + INST(Sqneg_v , ISimdVV , (0b0010111000100000011110, kVO_SV_Any) , kRWI_W , 0 , 14 ), // #644 + INST(Sqrdmlah_v , ISimdVVVe , (0b0010111000000000100001, kVO_SV_HS, 0b0010111100000000110100, kVO_SV_HS) , kRWI_X , F(VH0_15) , 16 ), // #645 + INST(Sqrdmlsh_v , ISimdVVVe , (0b0010111000000000100011, kVO_SV_HS, 0b0010111100000000111100, kVO_SV_HS) , kRWI_X , F(VH0_15) , 17 ), // #646 + INST(Sqrdmulh_v , ISimdVVVe , (0b0010111000100000101101, kVO_SV_HS, 0b0000111100000000110100, kVO_SV_HS) , kRWI_W , F(VH0_15) , 18 ), // #647 + INST(Sqrshl_v , SimdShift , (0b0000111000100000010111, 0b0000000000000000000000, 1, kVO_SV_Any) , kRWI_W , 0 , 6 ), // #648 + INST(Sqrshrn_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000100111, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 7 ), // #649 + INST(Sqrshrn2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000100111, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 8 ), // #650 + INST(Sqrshrun_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000100011, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 9 ), // #651 + INST(Sqrshrun2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000100011, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 10 ), // #652 + INST(Sqshl_v , SimdShift , (0b0000111000100000010011, 0b0000111100000000011101, 0, kVO_SV_Any) , kRWI_W , 0 , 11 ), // #653 + INST(Sqshlu_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000011001, 0, kVO_SV_Any) , kRWI_W , 0 , 12 ), // #654 + INST(Sqshrn_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000100101, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 13 ), // #655 + INST(Sqshrn2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000100101, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 14 ), // #656 + INST(Sqshrun_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000100001, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 15 ), // #657 + INST(Sqshrun2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000100001, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 16 ), // #658 + INST(Sqsub_v , ISimdVVV , (0b0000111000100000001011, kVO_SV_Any) , kRWI_W , 0 , 33 ), // #659 + INST(Sqxtn_v , ISimdVV , (0b0000111000100001010010, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 15 ), // #660 + INST(Sqxtn2_v , ISimdVV , (0b0100111000100001010010, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 16 ), // #661 + INST(Sqxtun_v , ISimdVV , (0b0010111000100001001010, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 17 ), // #662 + INST(Sqxtun2_v , ISimdVV , (0b0110111000100001001010, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 18 ), // #663 + INST(Srhadd_v , ISimdVVV , (0b0000111000100000000101, kVO_V_BHS) , kRWI_W , 0 , 34 ), // #664 + INST(Sri_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000010001, 1, kVO_V_Any) , kRWI_W , 0 , 17 ), // #665 + INST(Srshl_v , SimdShift , (0b0000111000100000010101, 0b0000000000000000000000, 0, kVO_V_Any) , kRWI_W , 0 , 18 ), // #666 + INST(Srshr_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000001001, 1, kVO_V_Any) , kRWI_W , 0 , 19 ), // #667 + INST(Srsra_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000001101, 1, kVO_V_Any) , kRWI_X , 0 , 20 ), // #668 + INST(Sshl_v , SimdShift , (0b0000111000100000010001, 0b0000000000000000000000, 0, kVO_V_Any) , kRWI_W , 0 , 21 ), // #669 + INST(Sshll_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000101001, 0, kVO_V_B8H4S2) , kRWI_W , F(Long) , 22 ), // #670 + INST(Sshll2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000101001, 0, kVO_V_B16H8S4) , kRWI_W , F(Long) , 23 ), // #671 + INST(Sshr_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000000001, 1, kVO_V_Any) , kRWI_W , 0 , 24 ), // #672 + INST(Ssra_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000000101, 1, kVO_V_Any) , kRWI_X , 0 , 25 ), // #673 + INST(Ssubl_v , ISimdVVV , (0b0000111000100000001000, kVO_V_B8H4S2) , kRWI_W , F(Long) , 35 ), // #674 + INST(Ssubl2_v , ISimdVVV , (0b0100111000100000001000, kVO_V_B16H8S4) , kRWI_W , F(Long) , 36 ), // #675 + INST(Ssubw_v , ISimdWWV , (0b0000111000100000001100, kVO_V_B8H4S2) , kRWI_W , 0 , 2 ), // #676 + INST(Ssubw2_v , ISimdWWV , (0b0000111000100000001100, kVO_V_B16H8S4) , kRWI_X , 0 , 3 ), // #677 + INST(St1_v , SimdLdNStN , (0b0000110100000000000000, 0b0000110000000000001000, 1, 0) , kRWI_STn , F(Consecutive) , 8 ), // #678 + INST(St2_v , SimdLdNStN , (0b0000110100100000000000, 0b0000110000000000100000, 2, 0) , kRWI_STn , F(Consecutive) , 9 ), // #679 + INST(St3_v , SimdLdNStN , (0b0000110100000000001000, 0b0000110000000000010000, 3, 0) , kRWI_STn , F(Consecutive) , 10 ), // #680 + INST(St4_v , SimdLdNStN , (0b0000110100100000001000, 0b0000110000000000000000, 4, 0) , kRWI_STn , F(Consecutive) , 11 ), // #681 + INST(Stnp_v , SimdLdpStp , (0b0010110000, 0b0000000000) , kRWI_RRW , 0 , 2 ), // #682 + INST(Stp_v , SimdLdpStp , (0b0010110100, 0b0010110010) , kRWI_RRW , 0 , 3 ), // #683 + INST(Str_v , SimdLdSt , (0b0011110100, 0b00111100000, 0b00111100001, 0b00000000, Inst::kIdStur_v) , kRWI_RW , 0 , 1 ), // #684 + INST(Stur_v , SimdLdurStur , (0b0011110000000000000000) , kRWI_RW , 0 , 1 ), // #685 + INST(Sub_v , ISimdVVV , (0b0010111000100000100001, kVO_V_Any) , kRWI_W , 0 , 37 ), // #686 + INST(Subhn_v , ISimdVVV , (0b0000111000100000011000, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 38 ), // #687 + INST(Subhn2_v , ISimdVVV , (0b0000111000100000011000, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 39 ), // #688 + INST(Sudot_v , SimdDot , (0b0000000000000000000000, 0b0000111100000000111100, kET_S, kET_B, kET_4B) , kRWI_X , 0 , 2 ), // #689 + INST(Suqadd_v , ISimdVV , (0b0000111000100000001110, kVO_SV_Any) , kRWI_X , 0 , 19 ), // #690 + INST(Sxtl_v , SimdSxtlUxtl , (0b0000111100000000101001, kVO_V_B8H4S2) , kRWI_W , F(Long) , 0 ), // #691 + INST(Sxtl2_v , SimdSxtlUxtl , (0b0100111100000000101001, kVO_V_B16H8S4) , kRWI_W , F(Long) , 1 ), // #692 + INST(Tbl_v , SimdTblTbx , (0b0000111000000000000000) , kRWI_W , 0 , 0 ), // #693 + INST(Tbx_v , SimdTblTbx , (0b0000111000000000000100) , kRWI_W , 0 , 1 ), // #694 + INST(Trn1_v , ISimdVVV , (0b0000111000000000001010, kVO_V_BHS_D2) , kRWI_W , 0 , 40 ), // #695 + INST(Trn2_v , ISimdVVV , (0b0000111000000000011010, kVO_V_BHS_D2) , kRWI_W , 0 , 41 ), // #696 + INST(Uaba_v , ISimdVVV , (0b0010111000100000011111, kVO_V_BHS) , kRWI_X , 0 , 42 ), // #697 + INST(Uabal_v , ISimdVVV , (0b0010111000100000010100, kVO_V_B8H4S2) , kRWI_X , F(Long) , 43 ), // #698 + INST(Uabal2_v , ISimdVVV , (0b0110111000100000010100, kVO_V_B16H8S4) , kRWI_X , F(Long) , 44 ), // #699 + INST(Uabd_v , ISimdVVV , (0b0010111000100000011101, kVO_V_BHS) , kRWI_W , 0 , 45 ), // #700 + INST(Uabdl_v , ISimdVVV , (0b0010111000100000011100, kVO_V_B8H4S2) , kRWI_W , F(Long) , 46 ), // #701 + INST(Uabdl2_v , ISimdVVV , (0b0110111000100000011100, kVO_V_B16H8S4) , kRWI_W , F(Long) , 47 ), // #702 + INST(Uadalp_v , ISimdVV , (0b0010111000100000011010, kVO_V_BHS) , kRWI_X , F(Long) | F(Pair) , 20 ), // #703 + INST(Uaddl_v , ISimdVVV , (0b0010111000100000000000, kVO_V_B8H4S2) , kRWI_W , F(Long) , 48 ), // #704 + INST(Uaddl2_v , ISimdVVV , (0b0110111000100000000000, kVO_V_B16H8S4) , kRWI_W , F(Long) , 49 ), // #705 + INST(Uaddlp_v , ISimdVV , (0b0010111000100000001010, kVO_V_BHS) , kRWI_W , F(Long) | F(Pair) , 21 ), // #706 + INST(Uaddlv_v , ISimdSV , (0b0010111000110000001110, kVO_V_BH_4S) , kRWI_W , F(Long) , 4 ), // #707 + INST(Uaddw_v , ISimdWWV , (0b0010111000100000000100, kVO_V_B8H4S2) , kRWI_W , 0 , 4 ), // #708 + INST(Uaddw2_v , ISimdWWV , (0b0010111000100000000100, kVO_V_B16H8S4) , kRWI_W , 0 , 5 ), // #709 + INST(Ucvtf_v , SimdFcvtSV , (0b0010111000100001110110, 0b0010111100000000111001, 0b0001111000100011000000, 0) , kRWI_W , 0 , 11 ), // #710 + INST(Udot_v , SimdDot , (0b0010111010000000100101, 0b0010111110000000111000, kET_S, kET_B, kET_4B) , kRWI_X , 0 , 3 ), // #711 + INST(Uhadd_v , ISimdVVV , (0b0010111000100000000001, kVO_V_BHS) , kRWI_W , 0 , 50 ), // #712 + INST(Uhsub_v , ISimdVVV , (0b0010111000100000001001, kVO_V_BHS) , kRWI_W , 0 , 51 ), // #713 + INST(Umax_v , ISimdVVV , (0b0010111000100000011001, kVO_V_BHS) , kRWI_W , 0 , 52 ), // #714 + INST(Umaxp_v , ISimdVVV , (0b0010111000100000101001, kVO_V_BHS) , kRWI_W , 0 , 53 ), // #715 + INST(Umaxv_v , ISimdSV , (0b0010111000110000101010, kVO_V_BH_4S) , kRWI_W , 0 , 5 ), // #716 + INST(Umin_v , ISimdVVV , (0b0010111000100000011011, kVO_V_BHS) , kRWI_W , 0 , 54 ), // #717 + INST(Uminp_v , ISimdVVV , (0b0010111000100000101011, kVO_V_BHS) , kRWI_W , 0 , 55 ), // #718 + INST(Uminv_v , ISimdSV , (0b0010111000110001101010, kVO_V_BH_4S) , kRWI_W , 0 , 6 ), // #719 + INST(Umlal_v , ISimdVVVe , (0b0010111000100000100000, kVO_V_B8H4S2, 0b0010111100000000001000, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 19 ), // #720 + INST(Umlal2_v , ISimdVVVe , (0b0110111000100000100000, kVO_V_B16H8S4, 0b0010111100000000001000, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 20 ), // #721 + INST(Umlsl_v , ISimdVVVe , (0b0010111000100000101000, kVO_V_B8H4S2, 0b0010111100000000011000, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 21 ), // #722 + INST(Umlsl2_v , ISimdVVVe , (0b0110111000100000101000, kVO_V_B16H8S4, 0b0110111100000000011000, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 22 ), // #723 + INST(Ummla_v , ISimdVVVx , (0b0110111010000000101001, kOp_V4S, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 15 ), // #724 + INST(Umov_v , SimdSmovUmov , (0b0000111000000000001111, kVO_V_Any, 0) , kRWI_W , 0 , 1 ), // #725 + INST(Umull_v , ISimdVVVe , (0b0010111000100000110000, kVO_V_B8H4S2, 0b0010111100000000101000, kVO_V_H4S2) , kRWI_W , F(Long) | F(VH0_15) , 23 ), // #726 + INST(Umull2_v , ISimdVVVe , (0b0110111000100000110000, kVO_V_B16H8S4, 0b0110111100000000101000, kVO_V_H8S4) , kRWI_W , F(Long) | F(VH0_15) , 24 ), // #727 + INST(Uqadd_v , ISimdVVV , (0b0010111000100000000011, kVO_SV_Any) , kRWI_W , 0 , 56 ), // #728 + INST(Uqrshl_v , SimdShift , (0b0010111000100000010111, 0b0000000000000000000000, 0, kVO_SV_Any) , kRWI_W , 0 , 26 ), // #729 + INST(Uqrshrn_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000100111, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 27 ), // #730 + INST(Uqrshrn2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000100111, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 28 ), // #731 + INST(Uqshl_v , SimdShift , (0b0010111000100000010011, 0b0010111100000000011101, 0, kVO_SV_Any) , kRWI_W , 0 , 29 ), // #732 + INST(Uqshrn_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000100101, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 30 ), // #733 + INST(Uqshrn2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000100101, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 31 ), // #734 + INST(Uqsub_v , ISimdVVV , (0b0010111000100000001011, kVO_SV_Any) , kRWI_W , 0 , 57 ), // #735 + INST(Uqxtn_v , ISimdVV , (0b0010111000100001010010, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 22 ), // #736 + INST(Uqxtn2_v , ISimdVV , (0b0110111000100001010010, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 23 ), // #737 + INST(Urecpe_v , ISimdVV , (0b0000111010100001110010, kVO_V_S) , kRWI_W , 0 , 24 ), // #738 + INST(Urhadd_v , ISimdVVV , (0b0010111000100000000101, kVO_V_BHS) , kRWI_W , 0 , 58 ), // #739 + INST(Urshl_v , SimdShift , (0b0010111000100000010101, 0b0000000000000000000000, 0, kVO_V_Any) , kRWI_W , 0 , 32 ), // #740 + INST(Urshr_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000001001, 1, kVO_V_Any) , kRWI_W , 0 , 33 ), // #741 + INST(Ursqrte_v , ISimdVV , (0b0010111010100001110010, kVO_V_S) , kRWI_W , 0 , 25 ), // #742 + INST(Ursra_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000001101, 1, kVO_V_Any) , kRWI_X , 0 , 34 ), // #743 + INST(Usdot_v , SimdDot , (0b0000111010000000100111, 0b0000111110000000111100, kET_S, kET_B, kET_4B) , kRWI_X , 0 , 4 ), // #744 + INST(Ushl_v , SimdShift , (0b0010111000100000010001, 0b0000000000000000000000, 0, kVO_V_Any) , kRWI_W , 0 , 35 ), // #745 + INST(Ushll_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000101001, 0, kVO_V_B8H4S2) , kRWI_W , F(Long) , 36 ), // #746 + INST(Ushll2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000101001, 0, kVO_V_B16H8S4) , kRWI_W , F(Long) , 37 ), // #747 + INST(Ushr_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000000001, 1, kVO_V_Any) , kRWI_W , 0 , 38 ), // #748 + INST(Usmmla_v , ISimdVVVx , (0b0100111010000000101011, kOp_V4S, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 16 ), // #749 + INST(Usqadd_v , ISimdVV , (0b0010111000100000001110, kVO_SV_Any) , kRWI_X , 0 , 26 ), // #750 + INST(Usra_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000000101, 1, kVO_V_Any) , kRWI_X , 0 , 39 ), // #751 + INST(Usubl_v , ISimdVVV , (0b0010111000100000001000, kVO_V_B8H4S2) , kRWI_W , F(Long) , 59 ), // #752 + INST(Usubl2_v , ISimdVVV , (0b0110111000100000001000, kVO_V_B16H8S4) , kRWI_W , F(Long) , 60 ), // #753 + INST(Usubw_v , ISimdWWV , (0b0010111000100000001100, kVO_V_B8H4S2) , kRWI_W , 0 , 6 ), // #754 + INST(Usubw2_v , ISimdWWV , (0b0010111000100000001100, kVO_V_B16H8S4) , kRWI_W , 0 , 7 ), // #755 + INST(Uxtl_v , SimdSxtlUxtl , (0b0010111100000000101001, kVO_V_B8H4S2) , kRWI_W , F(Long) , 2 ), // #756 + INST(Uxtl2_v , SimdSxtlUxtl , (0b0110111100000000101001, kVO_V_B16H8S4) , kRWI_W , F(Long) , 3 ), // #757 + INST(Uzp1_v , ISimdVVV , (0b0000111000000000000110, kVO_V_BHS_D2) , kRWI_W , 0 , 61 ), // #758 + INST(Uzp2_v , ISimdVVV , (0b0000111000000000010110, kVO_V_BHS_D2) , kRWI_W , 0 , 62 ), // #759 + INST(Xar_v , ISimdVVVI , (0b1100111001100000100011, kVO_V_D2, 6, 10, 0) , kRWI_W , 0 , 1 ), // #760 + INST(Xtn_v , ISimdVV , (0b0000111000100001001010, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 27 ), // #761 + INST(Xtn2_v , ISimdVV , (0b0100111000100001001010, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 28 ), // #762 + INST(Zip1_v , ISimdVVV , (0b0000111000000000001110, kVO_V_BHS_D2) , kRWI_W , 0 , 63 ), // #763 + INST(Zip2_v , ISimdVVV , (0b0000111000000000011110, kVO_V_BHS_D2) , kRWI_W , 0 , 64 ) // #764 // ${InstInfo:End} }; @@ -1211,6 +1212,10 @@ const BaseOpImm baseOpImm[14] = { { 0b00000000000000000000000000000000, 16, 0 } // udf }; +const BasePrfm basePrfm[1] = { + { 0b11111000101, 0b1111100110, 0b11111000100, 0b11011000 } // prfm +}; + const BaseR baseR[10] = { { 0b11011010110000010011101111100000, kX, kZR, 0 }, // autdza { 0b11011010110000010011111111100000, kX, kZR, 0 }, // autdzb @@ -1266,7 +1271,7 @@ const BaseRM_SImm9 baseRM_SImm9[23] = { { 0b0111100001000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0 }, // ldurh { 0b0011100011000000000000, 0b0000000000000000000000, kWX, kZR, 22, 0 }, // ldursb { 0b0111100011000000000000, 0b0000000000000000000000, kWX, kZR, 22, 0 }, // ldursh - { 0b1011100010000000000000, 0b0000000000000000000000, kX, kZR, 0 , 0 }, // ldursw + { 0b1011100010000000000000, 0b0000000000000000000000, kX , kZR, 0 , 0 }, // ldursw { 0b1101100110100000000010, 0b1101100110100000000001, kX, kSP, 0, 4 }, // st2g { 0b1101100100100000000010, 0b1101100100100000000001, kX, kSP, 0, 4 }, // stg { 0b1011100000000000000010, 0b0000000000000000000000, kWX, kZR, 30, 0 }, // sttr @@ -1846,6 +1851,42 @@ const InstDB::CommonInfo InstDB::commonData[] = { #ifndef ASMJIT_NO_TEXT // ${NameData:Begin} // ------------------- Automatically generated, do not edit ------------------- +const InstNameIndex InstDB::instNameIndex = {{ + { Inst::kIdAdc , Inst::kIdAnd_v + 1 }, + { Inst::kIdB , Inst::kIdBsl_v + 1 }, + { Inst::kIdCas , Inst::kIdCnt_v + 1 }, + { Inst::kIdDc , Inst::kIdDup_v + 1 }, + { Inst::kIdEon , Inst::kIdExt_v + 1 }, + { Inst::kIdFabd_v , Inst::kIdFsub_v + 1 }, + { Inst::kIdGmi , Inst::kIdGmi + 1 }, + { Inst::kIdHint , Inst::kIdHvc + 1 }, + { Inst::kIdIc , Inst::kIdIns_v + 1 }, + { Inst::kIdNone , Inst::kIdNone + 1 }, + { Inst::kIdNone , Inst::kIdNone + 1 }, + { Inst::kIdLdadd , Inst::kIdLdur_v + 1 }, + { Inst::kIdMadd , Inst::kIdMvni_v + 1 }, + { Inst::kIdNeg , Inst::kIdNot_v + 1 }, + { Inst::kIdOrn , Inst::kIdOrr_v + 1 }, + { Inst::kIdPacda , Inst::kIdPmull2_v + 1 }, + { Inst::kIdNone , Inst::kIdNone + 1 }, + { Inst::kIdRbit , Inst::kIdRsubhn2_v + 1 }, + { Inst::kIdSbc , Inst::kIdSxtl2_v + 1 }, + { Inst::kIdTlbi , Inst::kIdTrn2_v + 1 }, + { Inst::kIdUbfiz , Inst::kIdUzp2_v + 1 }, + { Inst::kIdNone , Inst::kIdNone + 1 }, + { Inst::kIdWfe , Inst::kIdWfi + 1 }, + { Inst::kIdXaflag , Inst::kIdXtn2_v + 1 }, + { Inst::kIdYield , Inst::kIdYield + 1 }, + { Inst::kIdZip1_v , Inst::kIdZip2_v + 1 } +}, uint16_t(9)}; + +const char InstDB::_instNameStringTable[] = + "autia1716autibldsmaxalhldsminalldumaxallduminalsha256su0sha512su1sm3partwsqrshru" + "nldaddalldclralldeoralldsetallbstsmaxstsminstumaxstuminfrint32z64x64zh2sqdmlalsl" + "2sqdmulsqrdmlaulhn2sqshruuqrshrspcrc32cstaddstclrsteorstsetxpaclbfcvtbfmlaltfcvt" + "xfjcvtzfmaxnmfminnmfrsqrraddrsubsha1sm3tt12a2bsm4ekeysqxtuuqshrursqrsetfrev8"; + + const uint32_t InstDB::_instNameIndexTable[] = { 0x80000000, // Small ''. 0x80000C81, // Small 'adc'. @@ -2112,6 +2153,7 @@ const uint32_t InstDB::_instNameIndexTable[] = { 0x83A20C30, // Small 'pacdza'. 0x85A20C30, // Small 'pacdzb'. 0x80138C30, // Small 'pacga'. + 0x80069A50, // Small 'prfm'. 0x80214E70, // Small 'pssbb'. 0x800A2452, // Small 'rbit'. 0x800050B2, // Small 'ret'. @@ -2612,42 +2654,6 @@ const uint32_t InstDB::_instNameIndexTable[] = { 0x800E413A, // Small 'zip1'. 0x800EC13A // Small 'zip2'. }; - -const char InstDB::_instNameStringTable[] = - "autia1716autibldsmaxalhldsminalldumaxallduminalsha256su0sha512su1sm3partwsqrshru" - "nldaddalldclralldeoralldsetallbstsmaxstsminstumaxstuminfrint32z64x64zh2sqdmlalsl" - "2sqdmulsqrdmlaulhn2sqshruuqrshrspcrc32cstaddstclrsteorstsetxpaclbfcvtbfmlaltfcvt" - "xfjcvtzfmaxnmfminnmfrsqrraddrsubsha1sm3tt12a2bsm4ekeysqxtuuqshrursqrsetfrev8"; - - -const InstDB::InstNameIndex InstDB::instNameIndex[26] = { - { Inst::kIdAdc , Inst::kIdAnd_v + 1 }, - { Inst::kIdB , Inst::kIdBsl_v + 1 }, - { Inst::kIdCas , Inst::kIdCnt_v + 1 }, - { Inst::kIdDc , Inst::kIdDup_v + 1 }, - { Inst::kIdEon , Inst::kIdExt_v + 1 }, - { Inst::kIdFabd_v , Inst::kIdFsub_v + 1 }, - { Inst::kIdGmi , Inst::kIdGmi + 1 }, - { Inst::kIdHint , Inst::kIdHvc + 1 }, - { Inst::kIdIc , Inst::kIdIns_v + 1 }, - { Inst::kIdNone , Inst::kIdNone + 1 }, - { Inst::kIdNone , Inst::kIdNone + 1 }, - { Inst::kIdLdadd , Inst::kIdLdur_v + 1 }, - { Inst::kIdMadd , Inst::kIdMvni_v + 1 }, - { Inst::kIdNeg , Inst::kIdNot_v + 1 }, - { Inst::kIdOrn , Inst::kIdOrr_v + 1 }, - { Inst::kIdPacda , Inst::kIdPmull2_v + 1 }, - { Inst::kIdNone , Inst::kIdNone + 1 }, - { Inst::kIdRbit , Inst::kIdRsubhn2_v + 1 }, - { Inst::kIdSbc , Inst::kIdSxtl2_v + 1 }, - { Inst::kIdTlbi , Inst::kIdTrn2_v + 1 }, - { Inst::kIdUbfiz , Inst::kIdUzp2_v + 1 }, - { Inst::kIdNone , Inst::kIdNone + 1 }, - { Inst::kIdWfe , Inst::kIdWfi + 1 }, - { Inst::kIdXaflag , Inst::kIdXtn2_v + 1 }, - { Inst::kIdYield , Inst::kIdYield + 1 }, - { Inst::kIdZip1_v , Inst::kIdZip2_v + 1 } -}; // ---------------------------------------------------------------------------- // ${NameData:End} #endif // !ASMJIT_NO_TEXT diff --git a/deps/asmjit/src/asmjit/arm/a64instdb.h b/deps/asmjit/src/asmjit/arm/a64instdb.h index d0be3ca1..a0312540 100644 --- a/deps/asmjit/src/asmjit/arm/a64instdb.h +++ b/deps/asmjit/src/asmjit/arm/a64instdb.h @@ -29,7 +29,7 @@ enum InstFlags : uint32_t { //! SIMD element access of half-words can only be used with v0..15. kInstFlagVH0_15 = 0x00000010u, - //! Instruction may consecutive registers if the number of operands is greater than 2. + //! Instruction uses consecutive registers if the number of operands is greater than 2. kInstFlagConsecutive = 0x00000080u }; diff --git a/deps/asmjit/src/asmjit/arm/a64instdb_p.h b/deps/asmjit/src/asmjit/arm/a64instdb_p.h index 9a6edf1d..5c3da7e1 100644 --- a/deps/asmjit/src/asmjit/arm/a64instdb_p.h +++ b/deps/asmjit/src/asmjit/arm/a64instdb_p.h @@ -7,6 +7,7 @@ #define ASMJIT_ARM_A64INSTDB_H_P_INCLUDED #include "../core/codeholder.h" +#include "../core/instdb_p.h" #include "../arm/a64instdb.h" #include "../arm/a64operand.h" @@ -58,14 +59,14 @@ enum RWInfoType : uint32_t { // a64::InstDB - ElementType // ========================= -enum ElementType : uint8_t { - kET_None = Vec::kElementTypeNone, - kET_B = Vec::kElementTypeB, - kET_H = Vec::kElementTypeH, - kET_S = Vec::kElementTypeS, - kET_D = Vec::kElementTypeD, - kET_2H = Vec::kElementTypeH2, - kET_4B = Vec::kElementTypeB4 +enum InstElementType : uint8_t { + kET_None = uint8_t(VecElementType::kNone), + kET_B = uint8_t(VecElementType::kB), + kET_H = uint8_t(VecElementType::kH), + kET_S = uint8_t(VecElementType::kS), + kET_D = uint8_t(VecElementType::kD), + kET_2H = uint8_t(VecElementType::kH2), + kET_4B = uint8_t(VecElementType::kB4) }; // a64::InstDB - GpType @@ -192,6 +193,7 @@ enum EncodingId : uint32_t { kEncodingBaseMvnNeg, kEncodingBaseOp, kEncodingBaseOpImm, + kEncodingBasePrfm, kEncodingBaseR, kEncodingBaseRM_NoImm, kEncodingBaseRM_SImm10, @@ -412,6 +414,13 @@ struct BaseRM_SImm10 { uint32_t immShift : 4; }; +struct BasePrfm { + uint32_t registerOp : 11; + uint32_t sOffsetOp : 10; + uint32_t uOffsetOp : 11; + uint32_t literalOp; +}; + struct BaseLdSt { uint32_t uOffsetOp : 10; uint32_t prePostOp : 11; @@ -787,6 +796,7 @@ extern const BaseMovKNZ baseMovKNZ[3]; extern const BaseMvnNeg baseMvnNeg[3]; extern const BaseOp baseOp[23]; extern const BaseOpImm baseOpImm[14]; +extern const BasePrfm basePrfm[1]; extern const BaseR baseR[10]; extern const BaseRM_NoImm baseRM_NoImm[21]; extern const BaseRM_SImm10 baseRM_SImm10[2]; @@ -843,27 +853,13 @@ extern const SimdTblTbx simdTblTbx[2]; } // {EncodingData} -// a64::InstDB - InstNameIndex -// =========================== - -// ${NameLimits:Begin} -// ------------------- Automatically generated, do not edit ------------------- -enum : uint32_t { kMaxNameSize = 9 }; -// ---------------------------------------------------------------------------- -// ${NameLimits:End} - -struct InstNameIndex { - uint16_t start; - uint16_t end; -}; - // a64::InstDB - Tables // ==================== #ifndef ASMJIT_NO_TEXT -extern const uint32_t _instNameIndexTable[]; +extern const InstNameIndex instNameIndex; extern const char _instNameStringTable[]; -extern const InstNameIndex instNameIndex[26]; +extern const uint32_t _instNameIndexTable[]; #endif // !ASMJIT_NO_TEXT } // {InstDB} diff --git a/deps/asmjit/src/asmjit/arm/a64operand.cpp b/deps/asmjit/src/asmjit/arm/a64operand.cpp index 3dba96de..e8c6100f 100644 --- a/deps/asmjit/src/asmjit/arm/a64operand.cpp +++ b/deps/asmjit/src/asmjit/arm/a64operand.cpp @@ -56,7 +56,7 @@ UNIT(a64_operand) { EXPECT_EQ(vd_1.group(), RegGroup::kVec); EXPECT_EQ(vd_1.id(), 15u); EXPECT_TRUE(vd_1.isVecD2()); - EXPECT_EQ(vd_1.elementType(), Vec::kElementTypeD); + EXPECT_EQ(vd_1.elementType(), VecElementType::kD); EXPECT_TRUE(vd_1.hasElementIndex()); EXPECT_EQ(vd_1.elementIndex(), 1u); @@ -65,7 +65,7 @@ UNIT(a64_operand) { EXPECT_EQ(vs_3.group(), RegGroup::kVec); EXPECT_EQ(vs_3.id(), 15u); EXPECT_TRUE(vs_3.isVecS4()); - EXPECT_EQ(vs_3.elementType(), Vec::kElementTypeS); + EXPECT_EQ(vs_3.elementType(), VecElementType::kS); EXPECT_TRUE(vs_3.hasElementIndex()); EXPECT_EQ(vs_3.elementIndex(), 3u); @@ -74,7 +74,7 @@ UNIT(a64_operand) { EXPECT_EQ(vb_4.group(), RegGroup::kVec); EXPECT_EQ(vb_4.id(), 15u); EXPECT_TRUE(vb_4.isVecB4x4()); - EXPECT_EQ(vb_4.elementType(), Vec::kElementTypeB4); + EXPECT_EQ(vb_4.elementType(), VecElementType::kB4); EXPECT_TRUE(vb_4.hasElementIndex()); EXPECT_EQ(vb_4.elementIndex(), 3u); } diff --git a/deps/asmjit/src/asmjit/arm/a64operand.h b/deps/asmjit/src/asmjit/arm/a64operand.h index c2d3c179..c64f20eb 100644 --- a/deps/asmjit/src/asmjit/arm/a64operand.h +++ b/deps/asmjit/src/asmjit/arm/a64operand.h @@ -13,24 +13,276 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64) //! \addtogroup asmjit_a64 //! \{ -using arm::Reg; -using arm::Mem; -using arm::Gp; -using arm::GpW; -using arm::GpX; +class GpW; +class GpX; -using arm::Vec; -using arm::VecB; -using arm::VecH; -using arm::VecS; -using arm::VecD; -using arm::VecV; +class VecB; +class VecH; +class VecS; +class VecD; +class VecV; + +//! General purpose register (AArch64). +class Gp : public Reg { +public: + ASMJIT_DEFINE_ABSTRACT_REG(Gp, Reg) + + //! Special register id. + enum Id : uint32_t { + //! Register that depends on OS, could be used as TLS offset. + kIdOs = 18, + //! Frame pointer register id. + kIdFp = 29, + //! Link register id. + kIdLr = 30, + //! Stack register id. + kIdSp = 31, + //! Zero register id. + //! + //! Although zero register has the same id as stack register it has a special treatment, because we need to be + //! able to distinguish between these two at API level. Some instructions were designed to be used with SP and + //! some other with ZR - so we need a way to distinguish these two to make sure we emit the right thing. + //! + //! The number 63 is not random, when you perform `id & 31` you would always get 31 for both SP and ZR inputs, + //! which is the identifier used by AArch64 ISA to encode either SP or ZR depending on the instruction. + kIdZr = 63 + }; + + //! Test whether this register is ZR register. + ASMJIT_INLINE_NODEBUG constexpr bool isZR() const noexcept { return id() == kIdZr; } + //! Test whether this register is SP register. + ASMJIT_INLINE_NODEBUG constexpr bool isSP() const noexcept { return id() == kIdSp; } + + //! Cast this register to a 32-bit W register (returns a new operand). + ASMJIT_INLINE_NODEBUG GpW w() const noexcept; + //! \overload + ASMJIT_INLINE_NODEBUG GpW r32() const noexcept; + //! Cast this register to a 64-bit X register (returns a new operand). + ASMJIT_INLINE_NODEBUG GpX x() const noexcept; + //! \overload + ASMJIT_INLINE_NODEBUG GpX r64() const noexcept; +}; + +//! 32-bit general purpose W register (AArch64). +class GpW : public Gp { ASMJIT_DEFINE_FINAL_REG(GpW, Gp, RegTraits); }; +//! 64-bit general purpose X register (AArch64). +class GpX : public Gp { ASMJIT_DEFINE_FINAL_REG(GpX, Gp, RegTraits); }; + +#ifndef _DOXYGEN +ASMJIT_INLINE_NODEBUG GpW Gp::w() const noexcept { return GpW(id()); } +ASMJIT_INLINE_NODEBUG GpX Gp::x() const noexcept { return GpX(id()); } +ASMJIT_INLINE_NODEBUG GpW Gp::r32() const noexcept { return GpW(id()); } +ASMJIT_INLINE_NODEBUG GpX Gp::r64() const noexcept { return GpX(id()); } +#endif + +//! Vector element type (AArch64). +enum class VecElementType : uint32_t { + //! No element type specified. + kNone = 0, + //! Byte elements (B8 or B16). + kB, + //! Halfword elements (H4 or H8). + kH, + //! Singleword elements (S2 or S4). + kS, + //! Doubleword elements (D2). + kD, + //! Byte elements grouped by 4 bytes (B4). + //! + //! \note This element-type is only used by few instructions. + kB4, + //! Halfword elements grouped by 2 halfwords (H2). + //! + //! \note This element-type is only used by few instructions. + kH2, + + //! Maximum value of \ref VecElementType + kMaxValue = kH2 +}; + +//! Vector register (AArch64). +class Vec : public BaseVec { +public: + ASMJIT_DEFINE_ABSTRACT_REG(Vec, BaseVec) + + //! \cond + //! Shortcuts. + enum SignatureReg : uint32_t { + kSignatureElementB = uint32_t(VecElementType::kB) << kSignatureRegElementTypeShift, + kSignatureElementH = uint32_t(VecElementType::kH) << kSignatureRegElementTypeShift, + kSignatureElementS = uint32_t(VecElementType::kS) << kSignatureRegElementTypeShift, + kSignatureElementD = uint32_t(VecElementType::kD) << kSignatureRegElementTypeShift, + kSignatureElementB4 = uint32_t(VecElementType::kB4) << kSignatureRegElementTypeShift, + kSignatureElementH2 = uint32_t(VecElementType::kH2) << kSignatureRegElementTypeShift + }; + //! \endcond + + //! Returns whether the register has element type or element index (or both). + ASMJIT_INLINE_NODEBUG constexpr bool hasElementTypeOrIndex() const noexcept { return _signature.hasField(); } + + //! Returns whether the vector register has associated a vector element type. + ASMJIT_INLINE_NODEBUG constexpr bool hasElementType() const noexcept { return _signature.hasField(); } + //! Returns vector element type of the register. + ASMJIT_INLINE_NODEBUG constexpr VecElementType elementType() const noexcept { return VecElementType(_signature.getField()); } + //! Sets vector element type of the register to `elementType`. + ASMJIT_INLINE_NODEBUG void setElementType(VecElementType elementType) noexcept { _signature.setField(uint32_t(elementType)); } + //! Resets vector element type to none. + ASMJIT_INLINE_NODEBUG void resetElementType() noexcept { _signature.setField(0); } + + ASMJIT_INLINE_NODEBUG constexpr bool isVecB8() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementB); } + ASMJIT_INLINE_NODEBUG constexpr bool isVecH4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementH); } + ASMJIT_INLINE_NODEBUG constexpr bool isVecS2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementS); } + ASMJIT_INLINE_NODEBUG constexpr bool isVecD1() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature); } + + ASMJIT_INLINE_NODEBUG constexpr bool isVecB16() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementB); } + ASMJIT_INLINE_NODEBUG constexpr bool isVecH8() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementH); } + ASMJIT_INLINE_NODEBUG constexpr bool isVecS4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementS); } + ASMJIT_INLINE_NODEBUG constexpr bool isVecD2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementD); } + ASMJIT_INLINE_NODEBUG constexpr bool isVecB4x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementB4); } + ASMJIT_INLINE_NODEBUG constexpr bool isVecH2x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementH2); } + + //! Creates a cloned register with element access. + ASMJIT_INLINE_NODEBUG Vec at(uint32_t elementIndex) const noexcept { + return Vec((signature() & ~kSignatureRegElementIndexMask) | (elementIndex << kSignatureRegElementIndexShift) | kSignatureRegElementFlagMask, id()); + } + + //! Cast this register to an 8-bit B register (AArch64 only). + ASMJIT_INLINE_NODEBUG VecB b() const noexcept; + //! Cast this register to a 16-bit H register (AArch64 only). + ASMJIT_INLINE_NODEBUG VecH h() const noexcept; + //! Cast this register to a 32-bit S register. + ASMJIT_INLINE_NODEBUG VecS s() const noexcept; + //! Cast this register to a 64-bit D register. + ASMJIT_INLINE_NODEBUG VecD d() const noexcept; + //! Cast this register to a 128-bit Q register. + ASMJIT_INLINE_NODEBUG VecV q() const noexcept; + //! Cast this register to a 128-bit V register. + ASMJIT_INLINE_NODEBUG VecV v() const noexcept; + + //! Casts this register to b (clone). + ASMJIT_INLINE_NODEBUG Vec v8() const noexcept; + //! Casts this register to h (clone). + ASMJIT_INLINE_NODEBUG Vec v16() const noexcept; + //! Casts this register to s (clone). + ASMJIT_INLINE_NODEBUG Vec v32() const noexcept; + //! Casts this register to d (clone). + ASMJIT_INLINE_NODEBUG Vec v64() const noexcept; + //! Casts this register to q (clone). + ASMJIT_INLINE_NODEBUG Vec v128() const noexcept; + + //! Cast this register to a 128-bit V.B[elementIndex] register. + ASMJIT_INLINE_NODEBUG VecV b(uint32_t elementIndex) const noexcept; + //! Cast this register to a 128-bit V.H[elementIndex] register. + ASMJIT_INLINE_NODEBUG VecV h(uint32_t elementIndex) const noexcept; + //! Cast this register to a 128-bit V.S[elementIndex] register. + ASMJIT_INLINE_NODEBUG VecV s(uint32_t elementIndex) const noexcept; + //! Cast this register to a 128-bit V.D[elementIndex] register. + ASMJIT_INLINE_NODEBUG VecV d(uint32_t elementIndex) const noexcept; + //! Cast this register to a 128-bit V.H2[elementIndex] register. + ASMJIT_INLINE_NODEBUG VecV h2(uint32_t elementIndex) const noexcept; + //! Cast this register to a 128-bit V.B4[elementIndex] register. + ASMJIT_INLINE_NODEBUG VecV b4(uint32_t elementIndex) const noexcept; + + //! Cast this register to V.8B. + ASMJIT_INLINE_NODEBUG VecD b8() const noexcept; + //! Cast this register to V.16B. + ASMJIT_INLINE_NODEBUG VecV b16() const noexcept; + //! Cast this register to V.2H. + ASMJIT_INLINE_NODEBUG VecS h2() const noexcept; + //! Cast this register to V.4H. + ASMJIT_INLINE_NODEBUG VecD h4() const noexcept; + //! Cast this register to V.8H. + ASMJIT_INLINE_NODEBUG VecV h8() const noexcept; + //! Cast this register to V.2S. + ASMJIT_INLINE_NODEBUG VecD s2() const noexcept; + //! Cast this register to V.4S. + ASMJIT_INLINE_NODEBUG VecV s4() const noexcept; + //! Cast this register to V.2D. + ASMJIT_INLINE_NODEBUG VecV d2() const noexcept; + + static ASMJIT_INLINE_NODEBUG constexpr OperandSignature _makeElementAccessSignature(VecElementType elementType, uint32_t elementIndex) noexcept { + return OperandSignature{ + uint32_t(RegTraits::kSignature) | + uint32_t(kSignatureRegElementFlagMask) | + (uint32_t(elementType) << kSignatureRegElementTypeShift) | + (uint32_t(elementIndex << kSignatureRegElementIndexShift))}; + } +}; + +//! 8-bit view (S) of VFP/SIMD register. +class VecB : public Vec { +public: + ASMJIT_DEFINE_FINAL_REG(VecB, Vec, RegTraits) +}; + +//! 16-bit view (S) of VFP/SIMD register. +class VecH : public Vec { +public: + ASMJIT_DEFINE_FINAL_REG(VecH, Vec, RegTraits) +}; + +//! 32-bit view (S) of VFP/SIMD register. +class VecS : public Vec { +public: + ASMJIT_DEFINE_FINAL_REG(VecS, Vec, RegTraits) +}; + +//! 64-bit view (D) of VFP/SIMD register. +class VecD : public Vec { +public: + ASMJIT_DEFINE_FINAL_REG(VecD, Vec, RegTraits) +}; + +//! 128-bit vector register (Q or V). +class VecV : public Vec { +public: + ASMJIT_DEFINE_FINAL_REG(VecV, Vec, RegTraits) +}; + +ASMJIT_INLINE_NODEBUG VecB Vec::b() const noexcept { return VecB(id()); } +ASMJIT_INLINE_NODEBUG VecH Vec::h() const noexcept { return VecH(id()); } +ASMJIT_INLINE_NODEBUG VecS Vec::s() const noexcept { return VecS(id()); } +ASMJIT_INLINE_NODEBUG VecD Vec::d() const noexcept { return VecD(id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::q() const noexcept { return VecV(id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::v() const noexcept { return VecV(id()); } + +ASMJIT_INLINE_NODEBUG Vec Vec::v8() const noexcept { return VecB(id()); } +ASMJIT_INLINE_NODEBUG Vec Vec::v16() const noexcept { return VecH(id()); } +ASMJIT_INLINE_NODEBUG Vec Vec::v32() const noexcept { return VecS(id()); } +ASMJIT_INLINE_NODEBUG Vec Vec::v64() const noexcept { return VecD(id()); } +ASMJIT_INLINE_NODEBUG Vec Vec::v128() const noexcept { return VecV(id()); } + +ASMJIT_INLINE_NODEBUG VecV Vec::b(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kB, elementIndex), id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::h(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kH, elementIndex), id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::s(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kS, elementIndex), id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::d(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kD, elementIndex), id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::h2(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kH2, elementIndex), id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::b4(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kB4, elementIndex), id()); } + +ASMJIT_INLINE_NODEBUG VecD Vec::b8() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementB}, id()); } +ASMJIT_INLINE_NODEBUG VecS Vec::h2() const noexcept { return VecS(OperandSignature{VecS::kSignature | kSignatureElementH}, id()); } +ASMJIT_INLINE_NODEBUG VecD Vec::h4() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementH}, id()); } +ASMJIT_INLINE_NODEBUG VecD Vec::s2() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementS}, id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::b16() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementB}, id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::h8() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementH}, id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::s4() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementS}, id()); } +ASMJIT_INLINE_NODEBUG VecV Vec::d2() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementD}, id()); } #ifndef _DOXYGEN namespace regs { #endif -using namespace ::asmjit::arm::regs; +//! Creates a 32-bit W register operand. +static ASMJIT_INLINE_NODEBUG constexpr GpW w(uint32_t id) noexcept { return GpW(id); } +//! Creates a 64-bit X register operand. +static ASMJIT_INLINE_NODEBUG constexpr GpX x(uint32_t id) noexcept { return GpX(id); } + +//! Creates a 32-bit S register operand. +static ASMJIT_INLINE_NODEBUG constexpr VecS s(uint32_t id) noexcept { return VecS(id); } +//! Creates a 64-bit D register operand. +static ASMJIT_INLINE_NODEBUG constexpr VecD d(uint32_t id) noexcept { return VecD(id); } +//! Creates a 1282-bit V register operand. +static ASMJIT_INLINE_NODEBUG constexpr VecV v(uint32_t id) noexcept { return VecV(id); } static constexpr GpW w0 = GpW(0); static constexpr GpW w1 = GpW(1); @@ -305,8 +557,94 @@ static constexpr VecV v31 = VecV(31); using namespace regs; #endif +//! \name Shift Operation Construction +//! \{ + +//! Constructs a `UXTB #value` extend and shift (unsigned byte extend) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Shift uxtb(uint32_t value) noexcept { return Shift(ShiftOp::kUXTB, value); } +//! Constructs a `UXTH #value` extend and shift (unsigned hword extend) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Shift uxth(uint32_t value) noexcept { return Shift(ShiftOp::kUXTH, value); } +//! Constructs a `UXTW #value` extend and shift (unsigned word extend) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Shift uxtw(uint32_t value) noexcept { return Shift(ShiftOp::kUXTW, value); } +//! Constructs a `UXTX #value` extend and shift (unsigned dword extend) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Shift uxtx(uint32_t value) noexcept { return Shift(ShiftOp::kUXTX, value); } + +//! Constructs a `SXTB #value` extend and shift (signed byte extend) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Shift sxtb(uint32_t value) noexcept { return Shift(ShiftOp::kSXTB, value); } +//! Constructs a `SXTH #value` extend and shift (signed hword extend) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Shift sxth(uint32_t value) noexcept { return Shift(ShiftOp::kSXTH, value); } +//! Constructs a `SXTW #value` extend and shift (signed word extend) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Shift sxtw(uint32_t value) noexcept { return Shift(ShiftOp::kSXTW, value); } +//! Constructs a `SXTX #value` extend and shift (signed dword extend) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Shift sxtx(uint32_t value) noexcept { return Shift(ShiftOp::kSXTX, value); } + +//! \} + +//! \name Memory Operand Construction +//! \{ + +//! Creates `[base, offset]` memory operand (offset mode) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Gp& base, int32_t offset = 0) noexcept { + return Mem(base, offset); +} + +//! Creates `[base, offset]!` memory operand (pre-index mode) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_pre(const Gp& base, int32_t offset = 0) noexcept { + return Mem(base, offset, OperandSignature::fromValue(OffsetMode::kPreIndex)); +} + +//! Creates `[base], offset` memory operand (post-index mode) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_post(const Gp& base, int32_t offset = 0) noexcept { + return Mem(base, offset, OperandSignature::fromValue(OffsetMode::kPostIndex)); +} + +//! Creates `[base, index]` memory operand (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Gp& base, const Gp& index) noexcept { + return Mem(base, index); +} + +//! Creates `[base, index]!` memory operand (pre-index mode) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_pre(const Gp& base, const Gp& index) noexcept { + return Mem(base, index, OperandSignature::fromValue(OffsetMode::kPreIndex)); +} + +//! Creates `[base], index` memory operand (post-index mode) (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_post(const Gp& base, const Gp& index) noexcept { + return Mem(base, index, OperandSignature::fromValue(OffsetMode::kPostIndex)); +} + +//! Creates `[base, index, SHIFT_OP #shift]` memory operand (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Gp& base, const Gp& index, const Shift& shift) noexcept { + return Mem(base, index, shift); +} + +//! Creates `[base, offset]` memory operand (AArch64). +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Label& base, int32_t offset = 0) noexcept { + return Mem(base, offset); +} + +// TODO: [ARM] PC + offset address. +#if 0 +//! Creates `[PC + offset]` (relative) memory operand. +static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const PC& pc, int32_t offset = 0) noexcept { + return Mem(pc, offset); +} +#endif + +//! \} + //! \} ASMJIT_END_SUB_NAMESPACE +//! \cond INTERNAL +ASMJIT_BEGIN_NAMESPACE +ASMJIT_DEFINE_TYPE_ID(a64::GpW, TypeId::kInt32); +ASMJIT_DEFINE_TYPE_ID(a64::GpX, TypeId::kInt64); +ASMJIT_DEFINE_TYPE_ID(a64::VecS, TypeId::kFloat32x1); +ASMJIT_DEFINE_TYPE_ID(a64::VecD, TypeId::kFloat64x1); +ASMJIT_DEFINE_TYPE_ID(a64::VecV, TypeId::kInt32x4); +ASMJIT_END_NAMESPACE +//! \endcond + #endif // ASMJIT_ARM_A64OPERAND_H_INCLUDED diff --git a/deps/asmjit/src/asmjit/arm/a64rapass.cpp b/deps/asmjit/src/asmjit/arm/a64rapass.cpp index aaec1c90..b97f259e 100644 --- a/deps/asmjit/src/asmjit/arm/a64rapass.cpp +++ b/deps/asmjit/src/asmjit/arm/a64rapass.cpp @@ -131,7 +131,7 @@ Error RACFGBuilder::onInst(InstNode* inst, InstControlFlow& controlType, RAInstB InstId instId = inst->id(); uint32_t opCount = inst->opCount(); const Operand* opArray = inst->operands(); - ASMJIT_PROPAGATE(InstInternal::queryRWInfo(_arch, inst->baseInst(), opArray, opCount, &rwInfo)); + ASMJIT_PROPAGATE(InstInternal::queryRWInfo(inst->baseInst(), opArray, opCount, &rwInfo)); const InstDB::InstInfo& instInfo = InstDB::infoById(instId); uint32_t singleRegOps = 0; @@ -230,7 +230,7 @@ Error RACFGBuilder::onInst(InstNode* inst, InstControlFlow& controlType, RAInstB if (reg.as().hasElementIndex()) { // Only the first 0..15 registers can be used if the register uses // element accessor that accesses half-words (h[0..7] elements). - if (instInfo.hasFlag(InstDB::kInstFlagVH0_15) && reg.as().elementType() == Vec::kElementTypeH) { + if (instInfo.hasFlag(InstDB::kInstFlagVH0_15) && reg.as().elementType() == VecElementType::kH) { if (Support::test(flags, RATiedFlags::kUse)) useId &= 0x0000FFFFu; else @@ -595,14 +595,14 @@ void ARMRAPass::onInit() noexcept { _archTraits = &ArchTraits::byArch(arch); _physRegCount.set(RegGroup::kGp, 32); _physRegCount.set(RegGroup::kVec, 32); - _physRegCount.set(RegGroup::kExtraVirt2, 0); + _physRegCount.set(RegGroup::kMask, 0); _physRegCount.set(RegGroup::kExtraVirt3, 0); _buildPhysIndex(); _availableRegCount = _physRegCount; _availableRegs[RegGroup::kGp] = Support::lsbMask(_physRegCount.get(RegGroup::kGp)); _availableRegs[RegGroup::kVec] = Support::lsbMask(_physRegCount.get(RegGroup::kVec)); - _availableRegs[RegGroup::kExtraVirt3] = Support::lsbMask(_physRegCount.get(RegGroup::kExtraVirt2)); + _availableRegs[RegGroup::kMask] = Support::lsbMask(_physRegCount.get(RegGroup::kMask)); _availableRegs[RegGroup::kExtraVirt3] = Support::lsbMask(_physRegCount.get(RegGroup::kExtraVirt3)); _scratchRegIndexes[0] = uint8_t(27); @@ -612,7 +612,9 @@ void ARMRAPass::onInit() noexcept { // make unavailable all registers that are special and cannot be used in general. bool hasFP = _func->frame().hasPreservedFP(); - if (hasFP) + // Apple ABI requires that the frame-pointer register is not changed by leaf functions and properly updated + // by non-leaf functions. So, let's make this register unavailable as it's just not safe to update it. + if (hasFP || cc()->environment().isDarwin()) makeUnavailable(RegGroup::kGp, Gp::kIdFp); makeUnavailable(RegGroup::kGp, Gp::kIdSp); diff --git a/deps/asmjit/src/asmjit/arm/armformatter.cpp b/deps/asmjit/src/asmjit/arm/armformatter.cpp index 86eb24b9..3fe2c6b9 100644 --- a/deps/asmjit/src/asmjit/arm/armformatter.cpp +++ b/deps/asmjit/src/asmjit/arm/armformatter.cpp @@ -9,7 +9,7 @@ #include "../core/misc_p.h" #include "../core/support.h" #include "../arm/armformatter_p.h" -#include "../arm/armoperand.h" +#include "../arm/a64operand.h" #include "../arm/a64instapi_p.h" #include "../arm/a64instdb_p.h" @@ -31,26 +31,45 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "ARMv8a\0" "THUMB\0" "THUMBv2\0" + "ABLE\0" + "ADERR\0" "AES\0" "AFP\0" + "AIE\0" + "AMU1\0" + "AMU1_1\0" + "ANERR\0" "ASIMD\0" "BF16\0" + "BRBE\0" "BTI\0" + "BWE\0" "CCIDX\0" "CHK\0" "CLRBHB\0" + "CMOW\0" + "CONSTPACFIELD\0" + "CPA\0" + "CPA2\0" "CPUID\0" "CRC32\0" "CSSC\0" + "CSV2\0" + "CSV2_3\0" + "CSV3\0" "D128\0" "DGH\0" "DIT\0" "DOTPROD\0" "DPB\0" "DPB2\0" + "EBEP\0" "EBF16\0" + "ECBHB\0" "ECV\0" + "EDHSR\0" "EDSP\0" + "FAMINMAX\0" "FCMA\0" "FGT\0" "FGT2\0" @@ -61,13 +80,25 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "FP\0" "FP16\0" "FP16CONV\0" + "FP8\0" + "FP8DOT2\0" + "FP8DOT4\0" + "FP8FMA\0" + "FPMR\0" "FRINTTS\0" "GCS\0" + "HACDBS\0" + "HAFDBS\0" + "HAFT\0" + "HDBSS\0" "HBC\0" "HCX\0" + "HPDS\0" + "HPDS2\0" "I8MM\0" "IDIVA\0" "IDIVT\0" + "ITE\0" "JSCVT\0" "LOR\0" "LRCPC\0" @@ -79,12 +110,24 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "LSE\0" "LSE128\0" "LSE2\0" + "LUT\0" + "LVA\0" + "LVA3\0" + "MEC\0" "MOPS\0" "MPAM\0" "MTE\0" "MTE2\0" "MTE3\0" "MTE4\0" + "MTE_ASYM_FAULT\0" + "MTE_ASYNC\0" + "MTE_CANONICAL_TAGS\0" + "MTE_NO_ADDRESS_TAGS\0" + "MTE_PERM_S1\0" + "MTE_STORE_ONLY\0" + "MTE_TAGGED_FAR\0" + "MTPMU\0" "NMI\0" "NV\0" "NV2\0" @@ -92,19 +135,28 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "PAN2\0" "PAN3\0" "PAUTH\0" + "PFAR\0" "PMU\0" "PMULL\0" "PRFMSLC\0" "RAS\0" "RAS1_1\0" "RAS2\0" + "RASSA2\0" "RDM\0" "RME\0" "RNG\0" "RNG_TRAP\0" "RPRES\0" "RPRFM\0" + "S1PIE\0" + "S1POE\0" + "S2PIE\0" + "S2POE\0" "SB\0" + "SCTLR2\0" + "SEBEP\0" + "SEL2\0" "SHA1\0" "SHA256\0" "SHA3\0" @@ -121,14 +173,32 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "SME_F16F32\0" "SME_F32F32\0" "SME_F64F64\0" + "SME_F8F16\0" + "SME_F8F32\0" "SME_FA64\0" "SME_I16I32\0" "SME_I16I64\0" "SME_I8I32\0" + "SME_LUTv2\0" + "SPE\0" + "SPE1_1\0" + "SPE1_2\0" + "SPE1_3\0" + "SPE1_4\0" + "SPE_ALTCLK\0" + "SPE_CRR\0" + "SPE_EFT\0" + "SPE_FDS\0" + "SPE_FPF\0" + "SPE_SME\0" "SPECRES\0" "SPECRES2\0" + "SPMU\0" "SSBS\0" "SSBS2\0" + "SSVE_FP8DOT2\0" + "SSVE_FP8DOT4\0" + "SSVE_FP8FMA\0" "SVE\0" "SVE2\0" "SVE2_1\0" @@ -146,25 +216,35 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "SYSINSTR128\0" "SYSREG128\0" "THE\0" + "TLBIOS\0" + "TLBIRANGE\0" + "TLBIW\0" "TME\0" "TRF\0" "UAO\0" "VFP_D32\0" "VHE\0" + "VMID16\0" "WFXT\0" + "XNX\0" "XS\0" "\0"; static const uint16_t sFeatureIndex[] = { - 0, 5, 11, 17, 24, 30, 38, 42, 46, 52, 57, 61, 67, 71, 78, 84, 90, 95, 100, - 104, 108, 116, 120, 125, 131, 135, 140, 145, 149, 154, 158, 164, 171, 176, - 179, 184, 193, 201, 205, 209, 213, 218, 224, 230, 236, 240, 246, 253, 260, - 265, 278, 285, 289, 296, 301, 306, 311, 315, 320, 325, 330, 334, 337, 341, - 345, 350, 355, 361, 365, 371, 379, 383, 390, 395, 399, 403, 407, 416, 422, - 428, 431, 436, 443, 448, 455, 459, 463, 467, 472, 479, 490, 501, 513, 524, - 535, 546, 557, 566, 577, 588, 598, 606, 615, 620, 626, 630, 635, 642, 650, - 661, 670, 682, 692, 702, 712, 721, 734, 743, 751, 763, 773, 777, 781, 785, - 789, 797, 801, 806, 809 + 0, 5, 11, 17, 24, 30, 38, 43, 49, 53, 57, 61, 66, 73, 79, 85, 90, 95, 99, + 103, 109, 113, 120, 125, 139, 143, 148, 154, 160, 165, 170, 177, 182, 187, + 191, 195, 203, 207, 212, 217, 223, 229, 233, 239, 244, 253, 258, 262, 267, + 271, 277, 284, 289, 292, 297, 306, 310, 318, 326, 333, 338, 346, 350, 357, + 364, 369, 375, 379, 383, 388, 394, 399, 405, 411, 415, 421, 425, 431, 438, + 445, 450, 463, 470, 474, 481, 486, 490, 494, 499, 503, 508, 513, 517, 522, + 527, 532, 547, 557, 576, 596, 608, 623, 638, 644, 648, 651, 655, 659, 664, + 669, 675, 680, 684, 690, 698, 702, 709, 714, 721, 725, 729, 733, 742, 748, + 754, 760, 766, 772, 778, 781, 788, 794, 799, 804, 811, 816, 823, 827, 831, + 835, 840, 847, 858, 869, 881, 892, 903, 914, 925, 935, 945, 954, 965, 976, + 986, 996, 1000, 1007, 1014, 1021, 1028, 1039, 1047, 1055, 1063, 1071, 1079, + 1087, 1096, 1101, 1106, 1112, 1125, 1138, 1150, 1154, 1159, 1166, 1174, 1185, + 1194, 1206, 1216, 1226, 1236, 1245, 1258, 1267, 1275, 1287, 1297, 1301, 1308, + 1318, 1324, 1328, 1332, 1336, 1344, 1348, 1355, 1360, 1364, 1367 }; // @EnumStringEnd@ @@ -178,14 +258,14 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatCondCode(String& sb, CondCode c static const char condCodeData[] = "al\0" "na\0" "eq\0" "ne\0" - "cs\0" "cc\0" "mi\0" "pl\0" "vs\0" "vc\0" + "hs\0" "lo\0" "mi\0" "pl\0" "vs\0" "vc\0" "hi\0" "ls\0" "ge\0" "lt\0" "gt\0" "le\0" ""; return sb.append(condCodeData + Support::min(uint32_t(cc), 16u) * 3); } ASMJIT_FAVOR_SIZE Error FormatterInternal::formatShiftOp(String& sb, ShiftOp shiftOp) noexcept { - const char* str = ""; + const char* str = nullptr; switch (shiftOp) { case ShiftOp::kLSL: str = "lsl"; break; case ShiftOp::kLSR: str = "lsr"; break; @@ -201,6 +281,7 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatShiftOp(String& sb, ShiftOp shi case ShiftOp::kSXTH: str = "sxth"; break; case ShiftOp::kSXTW: str = "sxtw"; break; case ShiftOp::kSXTX: str = "sxtx"; break; + default: str = ""; break; } return sb.append(str); } @@ -208,6 +289,25 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatShiftOp(String& sb, ShiftOp shi // arm::FormatterInternal - Format Register // ======================================== +struct FormatElementData { + char letter; + uint8_t elementCount; + uint8_t onlyIndex; + uint8_t reserved; +}; + +static constexpr FormatElementData formatElementDataTable[9] = { + { '?' , 0 , 0, 0 }, // None + { 'b' , 16, 0, 0 }, // bX or b[index] + { 'h' , 8 , 0, 0 }, // hX or h[index] + { 's' , 4 , 0, 0 }, // sX or s[index] + { 'd' , 2 , 0, 0 }, // dX or d[index] + { 'b' , 4 , 1, 0 }, // ?? or b4[index] + { 'h' , 2 , 1, 0 }, // ?? or h2[index] + { '?' , 0 , 0, 0 }, // invalid (possibly stored in Operand) + { '?' , 0 , 0, 0 } // invalid (never stored in Operand, bug...) +}; + ASMJIT_FAVOR_SIZE Error FormatterInternal::formatRegister( String& sb, FormatFlags flags, @@ -264,31 +364,22 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatRegister( if (Environment::is64Bit(arch)) { letter = 'w'; - if (rId == Gp::kIdZr) + if (rId == a64::Gp::kIdZr) return sb.append("wzr", 3); - if (rId == Gp::kIdSp) + if (rId == a64::Gp::kIdSp) return sb.append("wsp", 3); } else { letter = 'r'; - - if (rId == 13) - return sb.append("sp", 2); - - if (rId == 14) - return sb.append("lr", 2); - - if (rId == 15) - return sb.append("pc", 2); } break; case RegType::kARM_GpX: if (Environment::is64Bit(arch)) { - if (rId == Gp::kIdZr) + if (rId == a64::Gp::kIdZr) return sb.append("xzr", 3); - if (rId == Gp::kIdSp) + if (rId == a64::Gp::kIdSp) return sb.append("sp", 2); letter = 'x'; @@ -299,7 +390,7 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatRegister( ASMJIT_FALLTHROUGH; default: - ASMJIT_PROPAGATE(sb.appendFormat("?$u", uint32_t(regType), rId)); + ASMJIT_PROPAGATE(sb.appendFormat("?%u", uint32_t(regType), rId)); break; } @@ -307,54 +398,69 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatRegister( ASMJIT_PROPAGATE(sb.appendFormat("%c%u", letter, rId)); } + constexpr uint32_t kElementTypeCount = uint32_t(a64::VecElementType::kMaxValue) + 1; if (elementType) { - char elementLetter = '\0'; - uint32_t elementCount = 0; + elementType = Support::min(elementType, kElementTypeCount); - switch (elementType) { - case Vec::kElementTypeB: - elementLetter = 'b'; - elementCount = 16; - break; + FormatElementData elementData = formatElementDataTable[elementType]; + uint32_t elementCount = elementData.elementCount; - case Vec::kElementTypeH: - elementLetter = 'h'; - elementCount = 8; - break; - - case Vec::kElementTypeS: - elementLetter = 's'; - elementCount = 4; - break; - - case Vec::kElementTypeD: - elementLetter = 'd'; - elementCount = 2; - break; - - default: - return sb.append("."); + if (regType == RegType::kARM_VecD) { + elementCount /= 2u; } - if (elementLetter) { - if (elementIndex == 0xFFFFFFFFu) { - if (regType == RegType::kARM_VecD) - elementCount /= 2u; - ASMJIT_PROPAGATE(sb.appendFormat(".%u%c", elementCount, elementLetter)); - } - else { - ASMJIT_PROPAGATE(sb.appendFormat(".%c[%u]", elementLetter, elementIndex)); - } + ASMJIT_PROPAGATE(sb.append('.')); + if (elementCount) { + ASMJIT_PROPAGATE(sb.appendUInt(elementCount)); } + ASMJIT_PROPAGATE(sb.append(elementData.letter)); } - else if (elementIndex != 0xFFFFFFFFu) { - // This should only be used by AArch32 - AArch64 requires an additional elementType in index[]. + + if (elementIndex != 0xFFFFFFFFu) { ASMJIT_PROPAGATE(sb.appendFormat("[%u]", elementIndex)); } return kErrorOk; } +ASMJIT_FAVOR_SIZE Error FormatterInternal::formatRegisterList( + String& sb, + FormatFlags flags, + const BaseEmitter* emitter, + Arch arch, + RegType regType, + uint32_t rMask) noexcept { + + bool first = true; + + ASMJIT_PROPAGATE(sb.append('{')); + while (rMask != 0u) { + uint32_t start = Support::ctz(rMask); + uint32_t count = 0u; + + uint32_t mask = 1u << start; + do { + rMask &= ~mask; + mask <<= 1u; + count++; + } while (rMask & mask); + + if (!first) + ASMJIT_PROPAGATE(sb.append(", ")); + + ASMJIT_PROPAGATE(formatRegister(sb, flags, emitter, arch, regType, start, 0, 0xFFFFFFFFu)); + if (count >= 2u) { + ASMJIT_PROPAGATE(sb.append('-')); + ASMJIT_PROPAGATE(formatRegister(sb, flags, emitter, arch, regType, start + count - 1, 0, 0xFFFFFFFFu)); + } + + first = false; + } + ASMJIT_PROPAGATE(sb.append('}')); + + return kErrorOk; +} + // a64::FormatterInternal - Format Operand // ======================================= @@ -368,10 +474,10 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( if (op.isReg()) { const BaseReg& reg = op.as(); - uint32_t elementType = op.as().elementType(); - uint32_t elementIndex = op.as().elementIndex(); + uint32_t elementType = op._signature.getField(); + uint32_t elementIndex = op.as().elementIndex(); - if (!op.as().hasElementIndex()) + if (!op.as().hasElementIndex()) elementIndex = 0xFFFFFFFFu; return formatRegister(sb, flags, emitter, arch, reg.type(), reg.id(), elementType, elementIndex); @@ -433,7 +539,7 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( if (m.hasShift()) { ASMJIT_PROPAGATE(sb.append(' ')); if (!m.isPreOrPost()) - ASMJIT_PROPAGATE(formatShiftOp(sb, (ShiftOp)m.predicate())); + ASMJIT_PROPAGATE(formatShiftOp(sb, m.shiftOp())); ASMJIT_PROPAGATE(sb.appendFormat(" %u", m.shift())); } @@ -449,6 +555,12 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( if (op.isImm()) { const Imm& i = op.as(); int64_t val = i.value(); + uint32_t predicate = i.predicate(); + + if (predicate) { + ASMJIT_PROPAGATE(formatShiftOp(sb, ShiftOp(predicate))); + ASMJIT_PROPAGATE(sb.append(' ')); + } if (Support::test(flags, FormatFlags::kHexImms) && uint64_t(val) > 9) { ASMJIT_PROPAGATE(sb.append("0x")); @@ -463,6 +575,11 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( return Formatter::formatLabel(sb, flags, emitter, op.id()); } + if (op.isRegList()) { + const BaseRegList& regList = op.as(); + return formatRegisterList(sb, flags, emitter, arch, regList.type(), regList.list()); + } + return sb.append(""); } diff --git a/deps/asmjit/src/asmjit/arm/armformatter_p.h b/deps/asmjit/src/asmjit/arm/armformatter_p.h index ccd2bd67..20b4812e 100644 --- a/deps/asmjit/src/asmjit/arm/armformatter_p.h +++ b/deps/asmjit/src/asmjit/arm/armformatter_p.h @@ -43,6 +43,14 @@ Error ASMJIT_CDECL formatRegister( uint32_t elementType = 0, uint32_t elementIndex = 0xFFFFFFFF) noexcept; +Error ASMJIT_CDECL formatRegisterList( + String& sb, + FormatFlags flags, + const BaseEmitter* emitter, + Arch arch, + RegType regType, + uint32_t rMask) noexcept; + Error ASMJIT_CDECL formatOperand( String& sb, FormatFlags flags, diff --git a/deps/asmjit/src/asmjit/arm/armglobals.h b/deps/asmjit/src/asmjit/arm/armglobals.h index 506646f8..851f6708 100644 --- a/deps/asmjit/src/asmjit/arm/armglobals.h +++ b/deps/asmjit/src/asmjit/arm/armglobals.h @@ -14,8 +14,4 @@ //! //! API shared between AArch32 & AArch64 backends. -ASMJIT_BEGIN_SUB_NAMESPACE(arm) - -ASMJIT_END_SUB_NAMESPACE - #endif // ASMJIT_ARM_ARMGLOBALS_H_INCLUDED diff --git a/deps/asmjit/src/asmjit/arm/armoperand.h b/deps/asmjit/src/asmjit/arm/armoperand.h index 5e03e649..583a3d8c 100644 --- a/deps/asmjit/src/asmjit/arm/armoperand.h +++ b/deps/asmjit/src/asmjit/arm/armoperand.h @@ -19,18 +19,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(arm) class Reg; class Mem; -class Gp; -class GpW; -class GpX; - -class Vec; -class VecB; -class VecH; -class VecS; -class VecD; -class VecV; - -//! Register traits (ARM/AArch64). +//! Register traits (AArch32/AArch64). //! //! Register traits contains information about a particular register type. It's used by asmjit to setup register //! information on-the-fly and to populate tables that contain register information (this way it's possible to @@ -39,27 +28,31 @@ template struct RegTraits : public BaseRegTraits {}; //! \cond -// <--------------------+-----+-------------------------+------------------------+---+---+------------------+ -// | Reg | Reg-Type | Reg-Group |Sz |Cnt| TypeId | -// <--------------------+-----+-------------------------+------------------------+---+---+------------------+ -ASMJIT_DEFINE_REG_TRAITS(GpW , RegType::kARM_GpW , RegGroup::kGp , 4 , 32, TypeId::kInt32 ); -ASMJIT_DEFINE_REG_TRAITS(GpX , RegType::kARM_GpX , RegGroup::kGp , 8 , 32, TypeId::kInt64 ); -ASMJIT_DEFINE_REG_TRAITS(VecB , RegType::kARM_VecB , RegGroup::kVec , 1 , 32, TypeId::kVoid ); -ASMJIT_DEFINE_REG_TRAITS(VecH , RegType::kARM_VecH , RegGroup::kVec , 2 , 32, TypeId::kVoid ); -ASMJIT_DEFINE_REG_TRAITS(VecS , RegType::kARM_VecS , RegGroup::kVec , 4 , 32, TypeId::kInt32x1 ); -ASMJIT_DEFINE_REG_TRAITS(VecD , RegType::kARM_VecD , RegGroup::kVec , 8 , 32, TypeId::kInt32x2 ); -ASMJIT_DEFINE_REG_TRAITS(VecV , RegType::kARM_VecV , RegGroup::kVec , 16, 32, TypeId::kInt32x4 ); +// <--------------------+------------------------+------------------------+---+------------------+ +// | Reg-Type | Reg-Group |Sz | TypeId | +// <--------------------+------------------------+------------------------+---+------------------+ +ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_GpW , RegGroup::kGp , 4 , TypeId::kInt32 ); // AArch32 & AArch64 +ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_GpX , RegGroup::kGp , 8 , TypeId::kInt64 ); // AArch64 +ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_VecB , RegGroup::kVec , 1 , TypeId::kVoid ); // AArch64 +ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_VecH , RegGroup::kVec , 2 , TypeId::kVoid ); // AArch64 +ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_VecS , RegGroup::kVec , 4 , TypeId::kInt32x1 ); // AArch32 & AArch64 +ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_VecD , RegGroup::kVec , 8 , TypeId::kInt32x2 ); // AArch32 & AArch64 +ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_VecQ , RegGroup::kVec , 16, TypeId::kInt32x4 ); // AArch32 & AArch64 +ASMJIT_DEFINE_REG_TRAITS(RegType::kARM_PC , RegGroup::kPC , 8 , TypeId::kInt64 ); // AArch64 //! \endcond -//! Register (ARM). +//! Register operand that can represent AArch32 and AArch64 registers. class Reg : public BaseReg { public: ASMJIT_DEFINE_ABSTRACT_REG(Reg, BaseReg) - //! Gets whether the register is a `R|W` register (32-bit). + //! Gets whether the register is either `R` or `W` register (32-bit). + ASMJIT_INLINE_NODEBUG constexpr bool isGpR() const noexcept { return baseSignature() == RegTraits::kSignature; } + //! Gets whether the register is either `R` or `W` register (32-bit). ASMJIT_INLINE_NODEBUG constexpr bool isGpW() const noexcept { return baseSignature() == RegTraits::kSignature; } //! Gets whether the register is an `X` register (64-bit). ASMJIT_INLINE_NODEBUG constexpr bool isGpX() const noexcept { return baseSignature() == RegTraits::kSignature; } + //! Gets whether the register is a VEC-B register (8-bit). ASMJIT_INLINE_NODEBUG constexpr bool isVecB() const noexcept { return baseSignature() == RegTraits::kSignature; } //! Gets whether the register is a VEC-H register (16-bit). @@ -70,13 +63,22 @@ public: ASMJIT_INLINE_NODEBUG constexpr bool isVecD() const noexcept { return baseSignature() == RegTraits::kSignature; } //! Gets whether the register is a VEC-Q register (128-bit). ASMJIT_INLINE_NODEBUG constexpr bool isVecQ() const noexcept { return baseSignature() == RegTraits::kSignature; } - //! Gets whether the register is either VEC-D (64-bit) or VEC-Q (128-bit). ASMJIT_INLINE_NODEBUG constexpr bool isVecDOrQ() const noexcept { return uint32_t(type()) - uint32_t(RegType::kARM_VecD) <= 1u; } - //! Gets whether the register is a VEC-V register (128-bit). ASMJIT_INLINE_NODEBUG constexpr bool isVecV() const noexcept { return baseSignature() == RegTraits::kSignature; } + //! Gets whether the register is an 8-bit vector register or view, alias if \ref isVecB(). + ASMJIT_INLINE_NODEBUG constexpr bool isVec8() const noexcept { return baseSignature() == RegTraits::kSignature; } + //! Gets whether the register is a 16-bit vector register or view, alias if \ref isVecH(). + ASMJIT_INLINE_NODEBUG constexpr bool isVec16() const noexcept { return baseSignature() == RegTraits::kSignature; } + //! Gets whether the register is a 32-bit vector register or view, alias if \ref isVecS(). + ASMJIT_INLINE_NODEBUG constexpr bool isVec32() const noexcept { return baseSignature() == RegTraits::kSignature; } + //! Gets whether the register is a 64-bit vector register or view, alias if \ref isVecD(). + ASMJIT_INLINE_NODEBUG constexpr bool isVec64() const noexcept { return baseSignature() == RegTraits::kSignature; } + //! Gets whether the register is a 128-bit vector register or view, alias if \ref isVecQ(). + ASMJIT_INLINE_NODEBUG constexpr bool isVec128() const noexcept { return baseSignature() == RegTraits::kSignature; } + template ASMJIT_INLINE_NODEBUG void setRegT(uint32_t id) noexcept { setSignature(RegTraits::kSignature); @@ -99,7 +101,7 @@ public: static ASMJIT_INLINE_NODEBUG TypeId typeIdOfT() noexcept { return RegTraits::kTypeId; } template - static ASMJIT_INLINE_NODEBUG OperandSignature signatureOfT() noexcept { return RegTraits::kSignature; } + static ASMJIT_INLINE_NODEBUG OperandSignature signatureOfT() noexcept { return OperandSignature{RegTraits::kSignature}; } static ASMJIT_INLINE_NODEBUG bool isGpW(const Operand_& op) noexcept { return op.as().isGpW(); } static ASMJIT_INLINE_NODEBUG bool isGpX(const Operand_& op) noexcept { return op.as().isGpX(); } @@ -120,47 +122,12 @@ public: static ASMJIT_INLINE_NODEBUG bool isVecV(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isVecV(op)) & unsigned(op.id() == id)); } }; -//! General purpose register (ARM). -class Gp : public Reg { +//! Vector register base - a common base for both AArch32 & AArch64 vector register. +class BaseVec : public Reg { public: - ASMJIT_DEFINE_ABSTRACT_REG(Gp, Reg) + ASMJIT_DEFINE_ABSTRACT_REG(BaseVec, Reg) - //! Special register id. - enum Id : uint32_t { - //! Register that depends on OS, could be used as TLS offset. - kIdOs = 18, - //! Frame pointer. - kIdFp = 29, - //! Link register. - kIdLr = 30, - //! Stack register id. - kIdSp = 31, - //! Zero register id. - //! - //! Although zero register has the same id as stack register it has a special treatment, because we need to be - //! able to distinguish between these two at API level. Some intructions were designed to be used with SP and - //! some other with ZR - so we need a way to distinguish these two to make sure we emit the right thing. - //! - //! The number 63 is not random, when you perform `id & 31` you would always get 31 for both SP and ZR inputs, - //! which is the identifier used by AArch64 ISA to encode either SP or ZR depending on the instruction. - kIdZr = 63 - }; - - ASMJIT_INLINE_NODEBUG constexpr bool isZR() const noexcept { return id() == kIdZr; } - ASMJIT_INLINE_NODEBUG constexpr bool isSP() const noexcept { return id() == kIdSp; } - - //! Cast this register to a 32-bit R|W. - ASMJIT_INLINE_NODEBUG GpW w() const noexcept; - //! Cast this register to a 64-bit X. - ASMJIT_INLINE_NODEBUG GpX x() const noexcept; -}; - -//! Vector register (ARM). -class Vec : public Reg { -public: - ASMJIT_DEFINE_ABSTRACT_REG(Vec, Reg) - - //! Additional signature bits used by arm::Vec. + //! Additional signature bits used by a vector register. enum AdditionalBits : uint32_t { // Register element type (3 bits). // |........|........|.XXX....|........| @@ -178,57 +145,8 @@ public: kSignatureRegElementIndexMask = 0x0F << kSignatureRegElementIndexShift }; - //! Element type (AArch64 only). - enum ElementType : uint32_t { - //! No element type specified. - kElementTypeNone = 0, - //! Byte elements (B8 or B16). - kElementTypeB, - //! Halfword elements (H4 or H8). - kElementTypeH, - //! Singleword elements (S2 or S4). - kElementTypeS, - //! Doubleword elements (D2). - kElementTypeD, - //! Byte elements grouped by 4 bytes (B4). - //! - //! \note This element-type is only used by few instructions. - kElementTypeB4, - //! Halfword elements grouped by 2 halfwords (H2). - //! - //! \note This element-type is only used by few instructions. - kElementTypeH2, - - //! Count of element types. - kElementTypeCount - }; - - //! \cond - //! Shortcuts. - enum SignatureReg : uint32_t { - kSignatureElementB = kElementTypeB << kSignatureRegElementTypeShift, - kSignatureElementH = kElementTypeH << kSignatureRegElementTypeShift, - kSignatureElementS = kElementTypeS << kSignatureRegElementTypeShift, - kSignatureElementD = kElementTypeD << kSignatureRegElementTypeShift, - kSignatureElementB4 = kElementTypeB4 << kSignatureRegElementTypeShift, - kSignatureElementH2 = kElementTypeH2 << kSignatureRegElementTypeShift - }; - //! \endcond - - //! Returns whether the register has associated an element type. - ASMJIT_INLINE_NODEBUG constexpr bool hasElementType() const noexcept { return _signature.hasField(); } //! Returns whether the register has element index (it's an element index access). ASMJIT_INLINE_NODEBUG constexpr bool hasElementIndex() const noexcept { return _signature.hasField(); } - //! Returns whether the reggister has element type or element index (or both). - ASMJIT_INLINE_NODEBUG constexpr bool hasElementTypeOrIndex() const noexcept { return _signature.hasField(); } - - //! Returns element type of the register. - ASMJIT_INLINE_NODEBUG constexpr uint32_t elementType() const noexcept { return _signature.getField(); } - //! Sets element type of the register to `elementType`. - ASMJIT_INLINE_NODEBUG void setElementType(uint32_t elementType) noexcept { _signature.setField(elementType); } - //! Resets element type to none. - ASMJIT_INLINE_NODEBUG void resetElementType() noexcept { _signature.setField(0); } - //! Returns element index of the register. ASMJIT_INLINE_NODEBUG constexpr uint32_t elementIndex() const noexcept { return _signature.getField(); } //! Sets element index of the register to `elementType`. @@ -240,140 +158,8 @@ public: ASMJIT_INLINE_NODEBUG void resetElementIndex() noexcept { _signature &= ~(kSignatureRegElementFlagMask | kSignatureRegElementIndexMask); } - - ASMJIT_INLINE_NODEBUG constexpr bool isVecB8() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementB); } - ASMJIT_INLINE_NODEBUG constexpr bool isVecH4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementH); } - ASMJIT_INLINE_NODEBUG constexpr bool isVecS2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementS); } - ASMJIT_INLINE_NODEBUG constexpr bool isVecD1() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature); } - - ASMJIT_INLINE_NODEBUG constexpr bool isVecB16() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementB); } - ASMJIT_INLINE_NODEBUG constexpr bool isVecH8() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementH); } - ASMJIT_INLINE_NODEBUG constexpr bool isVecS4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementS); } - ASMJIT_INLINE_NODEBUG constexpr bool isVecD2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementD); } - ASMJIT_INLINE_NODEBUG constexpr bool isVecB4x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementB4); } - ASMJIT_INLINE_NODEBUG constexpr bool isVecH2x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits::kSignature | kSignatureElementH2); } - - //! Creates a cloned register with element access. - ASMJIT_INLINE_NODEBUG Vec at(uint32_t elementIndex) const noexcept { - return Vec((signature() & ~kSignatureRegElementIndexMask) | (elementIndex << kSignatureRegElementIndexShift) | kSignatureRegElementFlagMask, id()); - } - - //! Cast this register to an 8-bit B register (AArch64 only). - ASMJIT_INLINE_NODEBUG VecB b() const noexcept; - //! Cast this register to a 16-bit H register (AArch64 only). - ASMJIT_INLINE_NODEBUG VecH h() const noexcept; - //! Cast this register to a 32-bit S register. - ASMJIT_INLINE_NODEBUG VecS s() const noexcept; - //! Cast this register to a 64-bit D register. - ASMJIT_INLINE_NODEBUG VecD d() const noexcept; - //! Cast this register to a 128-bit Q register. - ASMJIT_INLINE_NODEBUG VecV q() const noexcept; - //! Cast this register to a 128-bit V register. - ASMJIT_INLINE_NODEBUG VecV v() const noexcept; - - //! Cast this register to a 128-bit V.B[elementIndex] register. - ASMJIT_INLINE_NODEBUG VecV b(uint32_t elementIndex) const noexcept; - //! Cast this register to a 128-bit V.H[elementIndex] register. - ASMJIT_INLINE_NODEBUG VecV h(uint32_t elementIndex) const noexcept; - //! Cast this register to a 128-bit V.S[elementIndex] register. - ASMJIT_INLINE_NODEBUG VecV s(uint32_t elementIndex) const noexcept; - //! Cast this register to a 128-bit V.D[elementIndex] register. - ASMJIT_INLINE_NODEBUG VecV d(uint32_t elementIndex) const noexcept; - //! Cast this register to a 128-bit V.H2[elementIndex] register. - ASMJIT_INLINE_NODEBUG VecV h2(uint32_t elementIndex) const noexcept; - //! Cast this register to a 128-bit V.B4[elementIndex] register. - ASMJIT_INLINE_NODEBUG VecV b4(uint32_t elementIndex) const noexcept; - - //! Cast this register to V.8B. - ASMJIT_INLINE_NODEBUG VecD b8() const noexcept; - //! Cast this register to V.16B. - ASMJIT_INLINE_NODEBUG VecV b16() const noexcept; - //! Cast this register to V.2H. - ASMJIT_INLINE_NODEBUG VecS h2() const noexcept; - //! Cast this register to V.4H. - ASMJIT_INLINE_NODEBUG VecD h4() const noexcept; - //! Cast this register to V.8H. - ASMJIT_INLINE_NODEBUG VecV h8() const noexcept; - //! Cast this register to V.2S. - ASMJIT_INLINE_NODEBUG VecD s2() const noexcept; - //! Cast this register to V.4S. - ASMJIT_INLINE_NODEBUG VecV s4() const noexcept; - //! Cast this register to V.2D. - ASMJIT_INLINE_NODEBUG VecV d2() const noexcept; - - static ASMJIT_INLINE_NODEBUG constexpr OperandSignature _makeElementAccessSignature(uint32_t elementType, uint32_t elementIndex) noexcept { - return OperandSignature{ - uint32_t(RegTraits::kSignature) | - uint32_t(kSignatureRegElementFlagMask) | - uint32_t(elementType << kSignatureRegElementTypeShift) | - uint32_t(elementIndex << kSignatureRegElementIndexShift)}; - } }; -//! 32-bit GPW (AArch64) and/or GPR (ARM/AArch32) register. -class GpW : public Gp { ASMJIT_DEFINE_FINAL_REG(GpW, Gp, RegTraits) }; -//! 64-bit GPX (AArch64) register. -class GpX : public Gp { ASMJIT_DEFINE_FINAL_REG(GpX, Gp, RegTraits) }; - -//! 8-bit view (S) of VFP/SIMD register. -class VecB : public Vec { ASMJIT_DEFINE_FINAL_REG(VecB, Vec, RegTraits) }; -//! 16-bit view (S) of VFP/SIMD register. -class VecH : public Vec { ASMJIT_DEFINE_FINAL_REG(VecH, Vec, RegTraits) }; -//! 32-bit view (S) of VFP/SIMD register. -class VecS : public Vec { ASMJIT_DEFINE_FINAL_REG(VecS, Vec, RegTraits) }; -//! 64-bit view (D) of VFP/SIMD register. -class VecD : public Vec { ASMJIT_DEFINE_FINAL_REG(VecD, Vec, RegTraits) }; -//! 128-bit vector register (Q or V). -class VecV : public Vec { ASMJIT_DEFINE_FINAL_REG(VecV, Vec, RegTraits) }; - -ASMJIT_INLINE_NODEBUG GpW Gp::w() const noexcept { return GpW(id()); } -ASMJIT_INLINE_NODEBUG GpX Gp::x() const noexcept { return GpX(id()); } - -ASMJIT_INLINE_NODEBUG VecB Vec::b() const noexcept { return VecB(id()); } -ASMJIT_INLINE_NODEBUG VecH Vec::h() const noexcept { return VecH(id()); } -ASMJIT_INLINE_NODEBUG VecS Vec::s() const noexcept { return VecS(id()); } -ASMJIT_INLINE_NODEBUG VecD Vec::d() const noexcept { return VecD(id()); } -ASMJIT_INLINE_NODEBUG VecV Vec::q() const noexcept { return VecV(id()); } -ASMJIT_INLINE_NODEBUG VecV Vec::v() const noexcept { return VecV(id()); } - -ASMJIT_INLINE_NODEBUG VecV Vec::b(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeB, elementIndex), id()); } -ASMJIT_INLINE_NODEBUG VecV Vec::h(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeH, elementIndex), id()); } -ASMJIT_INLINE_NODEBUG VecV Vec::s(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeS, elementIndex), id()); } -ASMJIT_INLINE_NODEBUG VecV Vec::d(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeD, elementIndex), id()); } -ASMJIT_INLINE_NODEBUG VecV Vec::h2(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeH2, elementIndex), id()); } -ASMJIT_INLINE_NODEBUG VecV Vec::b4(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeB4, elementIndex), id()); } - -ASMJIT_INLINE_NODEBUG VecD Vec::b8() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementB}, id()); } -ASMJIT_INLINE_NODEBUG VecS Vec::h2() const noexcept { return VecS(OperandSignature{VecS::kSignature | kSignatureElementH}, id()); } -ASMJIT_INLINE_NODEBUG VecD Vec::h4() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementH}, id()); } -ASMJIT_INLINE_NODEBUG VecD Vec::s2() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementS}, id()); } -ASMJIT_INLINE_NODEBUG VecV Vec::b16() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementB}, id()); } -ASMJIT_INLINE_NODEBUG VecV Vec::h8() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementH}, id()); } -ASMJIT_INLINE_NODEBUG VecV Vec::s4() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementS}, id()); } -ASMJIT_INLINE_NODEBUG VecV Vec::d2() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementD}, id()); } - -#ifndef _DOXYGEN -namespace regs { -#endif - -//! Creates a 32-bit W register operand (ARM/AArch64). -static ASMJIT_INLINE_NODEBUG constexpr GpW w(uint32_t id) noexcept { return GpW(id); } -//! Creates a 64-bit X register operand (AArch64). -static ASMJIT_INLINE_NODEBUG constexpr GpX x(uint32_t id) noexcept { return GpX(id); } -//! Creates a 32-bit S register operand (ARM/AArch64). -static ASMJIT_INLINE_NODEBUG constexpr VecS s(uint32_t id) noexcept { return VecS(id); } -//! Creates a 64-bit D register operand (ARM/AArch64). -static ASMJIT_INLINE_NODEBUG constexpr VecD d(uint32_t id) noexcept { return VecD(id); } -//! Creates a 1282-bit V register operand (ARM/AArch64). -static ASMJIT_INLINE_NODEBUG constexpr VecV v(uint32_t id) noexcept { return VecV(id); } - -#ifndef _DOXYGEN -} // {regs} - -// Make `arm::regs` accessible through `arm` namespace as well. -using namespace regs; -#endif - //! Memory operand (ARM). class Mem : public BaseMem { public: @@ -385,23 +171,18 @@ public: kSignatureMemShiftValueShift = 14, kSignatureMemShiftValueMask = 0x1Fu << kSignatureMemShiftValueShift, - // Shift operation type (4 bits). + // Index shift operation (4 bits). // |........|XXXX....|........|........| - kSignatureMemPredicateShift = 20, - kSignatureMemPredicateMask = 0x0Fu << kSignatureMemPredicateShift + kSignatureMemShiftOpShift = 20, + kSignatureMemShiftOpMask = 0x0Fu << kSignatureMemShiftOpShift, + + // Offset mode type (2 bits). + // |......XX|........|........|........| + kSignatureMemOffsetModeShift = 24, + kSignatureMemOffsetModeMask = 0x03u << kSignatureMemOffsetModeShift }; //! \endcond - //! Memory offset mode. - //! - //! Additional constants that can be used with the `predicate`. - enum OffsetMode : uint32_t { - //! Pre-index "[BASE, #Offset {, }]!" with write-back. - kOffsetPreIndex = 0xE, - //! Post-index "[BASE], #Offset {, }" with write-back. - kOffsetPostIndex = 0xF - }; - //! \name Construction & Destruction //! \{ @@ -438,11 +219,11 @@ public: : BaseMem(Signature::fromOpType(OperandType::kMem) | Signature::fromMemBaseType(base.type()) | Signature::fromMemIndexType(index.type()) | - Signature::fromValue(uint32_t(shift.op())) | + Signature::fromValue(uint32_t(shift.op())) | Signature::fromValue(shift.value()) | signature, base.id(), index.id(), 0) {} - ASMJIT_INLINE_NODEBUG constexpr Mem(uint64_t base, Signature signature = Signature{0}) noexcept + ASMJIT_INLINE_NODEBUG constexpr explicit Mem(uint64_t base, Signature signature = Signature{0}) noexcept : BaseMem(Signature::fromOpType(OperandType::kMem) | signature, uint32_t(base >> 32), 0, int32_t(uint32_t(base & 0xFFFFFFFFu))) {} @@ -471,14 +252,14 @@ public: //! Clones the memory operand and makes it pre-index. ASMJIT_INLINE_NODEBUG Mem pre() const noexcept { Mem result(*this); - result.setPredicate(kOffsetPreIndex); + result.setOffsetMode(OffsetMode::kPreIndex); return result; } //! Clones the memory operand, applies a given offset `off` and makes it pre-index. ASMJIT_INLINE_NODEBUG Mem pre(int64_t off) const noexcept { Mem result(*this); - result.setPredicate(kOffsetPreIndex); + result.setOffsetMode(OffsetMode::kPreIndex); result.addOffset(off); return result; } @@ -486,14 +267,14 @@ public: //! Clones the memory operand and makes it post-index. ASMJIT_INLINE_NODEBUG Mem post() const noexcept { Mem result(*this); - result.setPredicate(kOffsetPostIndex); + result.setOffsetMode(OffsetMode::kPostIndex); return result; } //! Clones the memory operand, applies a given offset `off` and makes it post-index. ASMJIT_INLINE_NODEBUG Mem post(int64_t off) const noexcept { Mem result(*this); - result.setPredicate(kOffsetPostIndex); + result.setOffsetMode(OffsetMode::kPostIndex); result.addOffset(off); return result; } @@ -520,88 +301,85 @@ public: setShift(shift); } + ASMJIT_INLINE_NODEBUG void setIndex(const BaseReg& index, Shift shift) noexcept { + setIndex(index); + setShift(shift); + } + //! \} //! \name ARM Specific Features //! \{ + //! Gets offset mode. + ASMJIT_INLINE_NODEBUG constexpr OffsetMode offsetMode() const noexcept { return OffsetMode(_signature.getField()); } + //! Sets offset mode to `mode`. + ASMJIT_INLINE_NODEBUG void setOffsetMode(OffsetMode mode) noexcept { _signature.setField(uint32_t(mode)); } + //! Resets offset mode to default (fixed offset, without write-back). + ASMJIT_INLINE_NODEBUG void resetOffsetMode() noexcept { _signature.setField(uint32_t(OffsetMode::kFixed)); } + + //! Tests whether the current memory offset mode is fixed (see \ref OffsetMode::kFixed). + ASMJIT_INLINE_NODEBUG constexpr bool isFixedOffset() const noexcept { return offsetMode() == OffsetMode::kFixed; } + //! Tests whether the current memory offset mode is either pre-index or post-index (write-back is used). + ASMJIT_INLINE_NODEBUG constexpr bool isPreOrPost() const noexcept { return offsetMode() != OffsetMode::kFixed; } + //! Tests whether the current memory offset mode is pre-index (write-back is used). + ASMJIT_INLINE_NODEBUG constexpr bool isPreIndex() const noexcept { return offsetMode() == OffsetMode::kPreIndex; } + //! Tests whether the current memory offset mode is post-index (write-back is used). + ASMJIT_INLINE_NODEBUG constexpr bool isPostIndex() const noexcept { return offsetMode() == OffsetMode::kPostIndex; } + + //! Sets offset mode of this memory operand to pre-index (write-back is used). + ASMJIT_INLINE_NODEBUG void makePreIndex() noexcept { setOffsetMode(OffsetMode::kPreIndex); } + //! Sets offset mode of this memory operand to post-index (write-back is used). + ASMJIT_INLINE_NODEBUG void makePostIndex() noexcept { setOffsetMode(OffsetMode::kPostIndex); } + + //! Gets shift operation that is used by index register. + ASMJIT_INLINE_NODEBUG constexpr ShiftOp shiftOp() const noexcept { return ShiftOp(_signature.getField()); } + //! Sets shift operation that is used by index register. + ASMJIT_INLINE_NODEBUG void setShiftOp(ShiftOp sop) noexcept { _signature.setField(uint32_t(sop)); } + //! Resets shift operation that is used by index register to LSL (default value). + ASMJIT_INLINE_NODEBUG void resetShiftOp() noexcept { _signature.setField(uint32_t(ShiftOp::kLSL)); } + //! Gets whether the memory operand has shift (aka scale) constant. ASMJIT_INLINE_NODEBUG constexpr bool hasShift() const noexcept { return _signature.hasField(); } //! Gets the memory operand's shift (aka scale) constant. ASMJIT_INLINE_NODEBUG constexpr uint32_t shift() const noexcept { return _signature.getField(); } //! Sets the memory operand's shift (aka scale) constant. ASMJIT_INLINE_NODEBUG void setShift(uint32_t shift) noexcept { _signature.setField(shift); } + + //! Sets the memory operand's shift and shift operation. + ASMJIT_INLINE_NODEBUG void setShift(Shift shift) noexcept { + _signature.setField(uint32_t(shift.op())); + _signature.setField(shift.value()); + } + //! Resets the memory operand's shift (aka scale) constant to zero. ASMJIT_INLINE_NODEBUG void resetShift() noexcept { _signature.setField(0); } - //! Gets memory predicate (shift mode or offset mode), see \ref ShiftOp and \ref OffsetMode. - ASMJIT_INLINE_NODEBUG constexpr uint32_t predicate() const noexcept { return _signature.getField(); } - //! Sets memory predicate to `predicate`, see `Mem::ShiftOp`. - ASMJIT_INLINE_NODEBUG void setPredicate(uint32_t predicate) noexcept { _signature.setField(predicate); } - //! Resets shift mode to LSL (default). - ASMJIT_INLINE_NODEBUG void resetPredicate() noexcept { _signature.setField(0); } - - ASMJIT_INLINE_NODEBUG constexpr bool isFixedOffset() const noexcept { return predicate() < kOffsetPreIndex; } - ASMJIT_INLINE_NODEBUG constexpr bool isPreOrPost() const noexcept { return predicate() >= kOffsetPreIndex; } - ASMJIT_INLINE_NODEBUG constexpr bool isPreIndex() const noexcept { return predicate() == kOffsetPreIndex; } - ASMJIT_INLINE_NODEBUG constexpr bool isPostIndex() const noexcept { return predicate() == kOffsetPostIndex; } - - ASMJIT_INLINE_NODEBUG void resetToFixedOffset() noexcept { resetPredicate(); } - ASMJIT_INLINE_NODEBUG void makePreIndex() noexcept { setPredicate(kOffsetPreIndex); } - ASMJIT_INLINE_NODEBUG void makePostIndex() noexcept { setPredicate(kOffsetPostIndex); } - //! \} }; -//! Creates `[base, offset]` memory operand (offset mode). -static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Gp& base, int32_t offset = 0) noexcept { - return Mem(base, offset); -} +//! \name Shift Operation Construction +//! \{ -//! Creates `[base, offset]!` memory operand (pre-index mode). -static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_pre(const Gp& base, int32_t offset = 0) noexcept { - return Mem(base, offset, OperandSignature::fromValue(Mem::kOffsetPreIndex)); -} +//! Constructs a `LSL #value` shift (logical shift left). +static ASMJIT_INLINE_NODEBUG constexpr Shift lsl(uint32_t value) noexcept { return Shift(ShiftOp::kLSL, value); } +//! Constructs a `LSR #value` shift (logical shift right). +static ASMJIT_INLINE_NODEBUG constexpr Shift lsr(uint32_t value) noexcept { return Shift(ShiftOp::kLSR, value); } +//! Constructs a `ASR #value` shift (arithmetic shift right). +static ASMJIT_INLINE_NODEBUG constexpr Shift asr(uint32_t value) noexcept { return Shift(ShiftOp::kASR, value); } +//! Constructs a `ROR #value` shift (rotate right). +static ASMJIT_INLINE_NODEBUG constexpr Shift ror(uint32_t value) noexcept { return Shift(ShiftOp::kROR, value); } +//! Constructs a `RRX` shift (rotate with carry by 1). +static ASMJIT_INLINE_NODEBUG constexpr Shift rrx() noexcept { return Shift(ShiftOp::kRRX, 0); } +//! Constructs a `MSL #value` shift (logical shift left filling ones). +static ASMJIT_INLINE_NODEBUG constexpr Shift msl(uint32_t value) noexcept { return Shift(ShiftOp::kMSL, value); } -//! Creates `[base], offset` memory operand (post-index mode). -static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_post(const Gp& base, int32_t offset = 0) noexcept { - return Mem(base, offset, OperandSignature::fromValue(Mem::kOffsetPostIndex)); -} +//! \} -//! Creates `[base, index]` memory operand. -static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Gp& base, const Gp& index) noexcept { - return Mem(base, index); -} +//! \name Memory Operand Construction +//! \{ -//! Creates `[base, index]!` memory operand (pre-index mode). -static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_pre(const Gp& base, const Gp& index) noexcept { - return Mem(base, index, OperandSignature::fromValue(Mem::kOffsetPreIndex)); -} - -//! Creates `[base], index` memory operand (post-index mode). -static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_post(const Gp& base, const Gp& index) noexcept { - return Mem(base, index, OperandSignature::fromValue(Mem::kOffsetPostIndex)); -} - -//! Creates `[base, index, SHIFT_OP #shift]` memory operand. -static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Gp& base, const Gp& index, const Shift& shift) noexcept { - return Mem(base, index, shift); -} - -//! Creates `[base, offset]` memory operand. -static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Label& base, int32_t offset = 0) noexcept { - return Mem(base, offset); -} - -// TODO: [ARM] PC + offset address. -#if 0 -//! Creates `[PC + offset]` (relative) memory operand. -static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const PC& pc, int32_t offset = 0) noexcept { - return Mem(pc, offset); -} -#endif - -//! Creates `[base]` absolute memory operand. +//! Creates `[base]` absolute memory operand (AArch32 or AArch64). //! //! \note The concept of absolute memory operands doesn't exist on ARM, the ISA only provides PC relative addressing. //! Absolute memory operands can only be used if it's known that the PC relative offset is encodable and that it @@ -611,16 +389,8 @@ static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(uint64_t base) noexcept { return //! \} +//! \} + ASMJIT_END_SUB_NAMESPACE -//! \cond INTERNAL -ASMJIT_BEGIN_NAMESPACE -ASMJIT_DEFINE_TYPE_ID(arm::GpW, TypeId::kInt32); -ASMJIT_DEFINE_TYPE_ID(arm::GpX, TypeId::kInt64); -ASMJIT_DEFINE_TYPE_ID(arm::VecS, TypeId::kFloat32x1); -ASMJIT_DEFINE_TYPE_ID(arm::VecD, TypeId::kFloat64x1); -ASMJIT_DEFINE_TYPE_ID(arm::VecV, TypeId::kInt32x4); -ASMJIT_END_NAMESPACE -//! \endcond - #endif // ASMJIT_ARM_ARMOPERAND_H_INCLUDED diff --git a/deps/asmjit/src/asmjit/arm/armutils.h b/deps/asmjit/src/asmjit/arm/armutils.h index a32256ce..8241eda0 100644 --- a/deps/asmjit/src/asmjit/arm/armutils.h +++ b/deps/asmjit/src/asmjit/arm/armutils.h @@ -6,6 +6,7 @@ #ifndef ASMJIT_ARM_ARMUTILS_H_INCLUDED #define ASMJIT_ARM_ARMUTILS_H_INCLUDED +#include "../core/support.h" #include "../arm/armglobals.h" ASMJIT_BEGIN_SUB_NAMESPACE(arm) @@ -16,6 +17,38 @@ ASMJIT_BEGIN_SUB_NAMESPACE(arm) //! Public utilities and helpers for targeting AArch32 and AArch64 architectures. namespace Utils { +//! Encodes a 12-bit immediate part of opcode that ise used by a standard 32-bit ARM encoding. +ASMJIT_MAYBE_UNUSED +static inline bool encodeAArch32Imm(uint64_t imm, uint32_t* encodedImmOut) noexcept { + if (imm & 0xFFFFFFFF00000000u) + return false; + + uint32_t v = uint32_t(imm); + uint32_t r = 0; + + if (v <= 0xFFu) { + *encodedImmOut = v; + return true; + } + + // Rotate if there are bits on both ends (LSB and MSB) + // (otherwise we would not be able to calculate the rotation with ctz). + if (v & 0xFF0000FFu) { + v = Support::ror(v, 16); + r = 16u; + } + + uint32_t n = Support::ctz(v) & ~0x1u; + r = (r - n) & 0x1Eu; + v = Support::ror(v, n); + + if (v > 0xFFu) + return false; + + *encodedImmOut = v | (r << 7); + return true; +} + //! Decomposed fields of a logical immediate value. struct LogicalImm { uint32_t n; @@ -94,6 +127,13 @@ static ASMJIT_INLINE_NODEBUG bool isLogicalImm(uint64_t imm, uint32_t width) noe return encodeLogicalImm(imm, width, &dummy); } +//! Returns true if the given `imm` value is encodable as an immediate with `add` and `sub` instructions on AArch64. +//! These two instructions can encode 12-bit immediate value optionally shifted left by 12 bits. +ASMJIT_MAYBE_UNUSED +static ASMJIT_INLINE_NODEBUG bool isAddSubImm(uint64_t imm) noexcept { + return imm <= 0xFFFu || (imm & ~uint64_t(0xFFFu << 12)) == 0; +} + //! Returns true if the given `imm` value is a byte mask. Byte mask has each byte part of the value set to either //! 0x00 or 0xFF. Some ARM instructions accept immediates that form a byte-mask and this function can be used to //! verify that the immediate is encodable before using the value. diff --git a/deps/asmjit/src/asmjit/asmjit.h b/deps/asmjit/src/asmjit/asmjit.h index 1cd0651f..f5184eb5 100644 --- a/deps/asmjit/src/asmjit/asmjit.h +++ b/deps/asmjit/src/asmjit/asmjit.h @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Zlib // Official GitHub Repository: https://github.com/asmjit/asmjit // -// Copyright (c) 2008-2021 The AsmJit Authors +// Copyright (c) 2008-2024 The AsmJit Authors // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/deps/asmjit/src/asmjit/core.h b/deps/asmjit/src/asmjit/core.h index ce39b867..66cbce64 100644 --- a/deps/asmjit/src/asmjit/core.h +++ b/deps/asmjit/src/asmjit/core.h @@ -179,38 +179,47 @@ namespace asmjit { //! AsmJit currently supports only X86/X64 backend, but the plan is to add more backends in the future. By default //! AsmJit builds only the host backend, which is auto-detected at compile-time, but this can be overridden. //! -//! - \ref ASMJIT_NO_X86 - Disable X86/X64 backends. -//! - \ref ASMJIT_NO_FOREIGN - Disables the support for foreign architectures. +//! - \ref ASMJIT_NO_X86 - Disables both X86 and X86_64 backends. +//! - \ref ASMJIT_NO_AARCH64 - Disables AArch64 backend. +//! - \ref ASMJIT_NO_FOREIGN - Disables the support for foreign architecture backends, only keeps a native backend. +//! +//! ### AsmJit Compilation Options +//! +//! - \ref ASMJIT_NO_DEPRECATED - Disables deprecated API at compile time so it won't be available and the +//! compilation will fail if there is attempt to use such API. This includes deprecated classes, namespaces, +//! enumerations, and functions. +//! +//! - \ref ASMJIT_NO_SHM_OPEN - Disables functionality that uses `shm_open()`. +//! +//! - \ref ASMJIT_NO_ABI_NAMESPACE - Disables inline ABI namespace within `asmjit` namespace. This is only provided +//! for users that control all the dependencies (even transitive ones) and that make sure that no two AsmJit +//! versions are used at the same time. This option can be debugging a little simpler as there would not be ABI +//! tag after `asmjit::` namespace. Otherwise asmjit would look like `asmjit::_abi_1_13::`, for example. //! //! ### Features Selection //! //! AsmJit builds by defaults all supported features, which includes all emitters, logging, instruction validation and //! introspection, and JIT memory allocation. Features can be disabled at compile time by using `ASMJIT_NO_...` //! definitions. -//! -//! - \ref ASMJIT_NO_DEPRECATED - Disables deprecated API at compile time so it won't be available and the -//! compilation will fail if there is attempt to use such API. This includes deprecated classes, namespaces, -//! enumerations, and functions. -//! -//! - \ref ASMJIT_NO_BUILDER - Disables \ref asmjit_builder functionality completely. This implies \ref -//! ASMJIT_NO_COMPILER as \ref asmjit_compiler cannot be used without \ref asmjit_builder. -//! -//! - \ref ASMJIT_NO_COMPILER - Disables \ref asmjit_compiler functionality completely. -//! //! - \ref ASMJIT_NO_JIT - Disables JIT memory management and \ref JitRuntime. //! -//! - \ref ASMJIT_NO_LOGGING - Disables \ref Logger and \ref Formatter. -//! //! - \ref ASMJIT_NO_TEXT - Disables everything that contains string representation of AsmJit constants, should //! be used together with \ref ASMJIT_NO_LOGGING as logging doesn't make sense without the ability to query //! instruction names, register names, etc... //! +//! - \ref ASMJIT_NO_LOGGING - Disables \ref Logger and \ref Formatter. +//! //! - \ref ASMJIT_NO_VALIDATION - Disables validation API. //! //! - \ref ASMJIT_NO_INTROSPECTION - Disables instruction introspection API, must be used together with \ref //! ASMJIT_NO_COMPILER as \ref asmjit_compiler requires introspection for its liveness analysis and register //! allocation. //! +//! - \ref ASMJIT_NO_BUILDER - Disables \ref asmjit_builder functionality completely. This implies \ref +//! ASMJIT_NO_COMPILER as \ref asmjit_compiler cannot be used without \ref asmjit_builder. +//! +//! - \ref ASMJIT_NO_COMPILER - Disables \ref asmjit_compiler functionality completely. +//! //! \note It's not recommended to disable features if you plan to build AsmJit as a shared library that will be //! used by multiple projects that you don't control how AsmJit was built (for example AsmJit in a Linux distribution). //! The possibility to disable certain features exists mainly for customized AsmJit builds. @@ -231,7 +240,7 @@ namespace asmjit { //! //! Useful tips before you start: //! -//! - Visit our [Public Gitter Channel](https://gitter.im/asmjit/asmjit) if you need a quick help. +//! - Visit our [Public Gitter Chat](https://app.gitter.im/#/room/#asmjit:gitter.im) if you need a quick help. //! //! - Build AsmJit with `ASMJIT_NO_DEPRECATED` macro defined to make sure that you are not using deprecated //! functionality at all. Deprecated functions are decorated with `ASMJIT_DEPRECATED()` macro, but sometimes @@ -239,6 +248,47 @@ namespace asmjit { //! because some compilers would warn about that. If your project compiles fine with `ASMJIT_NO_DEPRECATED` //! it's not using anything, which was deprecated. //! +//! ### Changes committed at 2024-01-01 +//! +//! Core changes: +//! +//! - Renamed equality functions `eq()` to `equals()` - Only related to `String`, `ZoneVector`, and `CpuFeatures`. +//! Old function names were deprecated. +//! +//! - Removed `CallConvId::kNone` in favor of `CallConvId::kCDecl`, which is now the default calling convention. +//! +//! - Deprecated `CallConvId::kHost` in favor of `CallConvId::kCDecl` - host calling convention is now not part +//! of CallConvId, it can be calculated from CallConvId and Environment instead. +//! +//! ### Changes committed at 2023-12-27 +//! +//! Core changes: +//! +//! - Renamed `a64::Vec::ElementType` to `a64::VecElementType` and made it a typed enum. This enum was used mostly +//! internally, but there is a public API using it, so it's a breaking change. +//! +//! - Refactored `FuncSignature`, `FuncSignatureT`, and `FuncSignatureBuilder`. There is only `FuncSignature` now, +//! which acts as a function signature holder and builder. Replace `FuncSignatureBuilder` with `FuncSignature` +//! and use `FuncSignature::build` instead of `FuncSignatureT`. The old API has been deprecated. +//! +//! - The maximum number of function arguments was raised from 16 to 32. +//! +//! ### Changes committed at 2023-12-26 +//! +//! Core changes: +//! +//! - Reworked InstNode and InstExNode to be friendlier to static analysis and to not cause undefined behavior. +//! InstNode has no operands visually embedded within the struct so there is no _opArray (which was internal). +//! This means that sizeof(InstNode) changed, but since it's allocated by AsmJit this should be fine. Moreover, +//! there is no longer InstExNode as that was more a hack, instead there is now InstNodeWithOperands, which is +//! a template and specifies the number of operands embedded (InstNode accesses these). All nodes that inherited +//! InstExNode now just inherit InstNodeWithOperands, which would provide the same +//! number of nodes as InstNode. +//! +//! - Moved GP and Vec registers from asmjit::arm namespace to asmjit::a64 namespace. At this time there was +//! no prior deprecation as having arm::Vec would collide with a64::Vec as arm namespace is used within a64 +//! namespace. Just change `arm::Gp` to `a64::Gp` and `arm::Vec` to `a64::Vec`. +//! //! ### Changes committed at 2023-09-10 //! //! Core changes: @@ -419,7 +469,7 @@ namespace asmjit { //! // Calling a function (Compiler) changed - use invoke() instead of call(). //! void functionInvocation(x86::Compiler& cc) { //! InvokeNode* invokeNode; -//! cc.invoke(&invokeNode, targetOperand, FuncSignatureT<...>(...)); +//! cc.invoke(&invokeNode, targetOperand, FuncSignature::build<...>(...)); //! } //! ``` @@ -916,12 +966,15 @@ namespace asmjit { //! with assembler requires the knowledge of the following: //! //! - \ref BaseAssembler and architecture-specific assemblers: -//! - \ref x86::Assembler - Assembler specific to X86 architecture +//! - \ref x86::Assembler - Assembler implementation targeting X86 and X86_64 architectures. +//! - \ref a64::Assembler - Assembler implementation targeting AArch64 architecture. //! - \ref Operand and its variations: //! - \ref BaseReg - Base class for a register operand, inherited by: -//! - \ref x86::Reg - Register operand specific to X86 architecture. +//! - \ref x86::Reg - Register operand specific to X86 and X86_64 architectures. +//! - \ref arm::Reg - Register operand specific to AArch64 architecture. //! - \ref BaseMem - Base class for a memory operand, inherited by: //! - \ref x86::Mem - Memory operand specific to X86 architecture. +//! - \ref arm::Mem - Memory operand specific to AArch64 architecture. //! - \ref Imm - Immediate (value) operand. //! - \ref Label - Label operand. //! @@ -1029,7 +1082,7 @@ namespace asmjit { //! //! // Type-unsafe, but possible. //! a.emit(x86::Inst::kIdMov, dst, m); -//! // Also possible, `emit()` is typeless and can be used with raw Operand. +//! // Also possible, `emit()` is type-less and can be used with raw Operand. //! a.emit(x86::Inst::kIdMov, dst, op); //! } //! ``` @@ -1100,10 +1153,10 @@ namespace asmjit { //! //! void testX86Mem() { //! // The same as: dword ptr [rax + rbx]. -//! x86::Mem a = x86::dword_ptr(rax, rbx); +//! x86::Mem a = x86::dword_ptr(x86::rax, x86::rbx); //! //! // The same as: qword ptr [rdx + rsi << 0 + 1]. -//! x86::Mem b = x86::qword_ptr(rdx, rsi, 0, 1); +//! x86::Mem b = x86::qword_ptr(x86::rdx, x86::rsi, 0, 1); //! } //! ``` //! @@ -1116,18 +1169,18 @@ namespace asmjit { //! //! void testX86Mem() { //! // The same as: dword ptr [rax + 12]. -//! x86::Mem mem = x86::dword_ptr(rax, 12); +//! x86::Mem mem = x86::dword_ptr(x86::rax, 12); //! //! mem.hasBase(); // true. //! mem.hasIndex(); // false. //! mem.size(); // 4. //! mem.offset(); // 12. //! -//! mem.setSize(0); // Sets the size to 0 (makes it sizeless). +//! mem.setSize(0); // Sets the size to 0 (makes it size-less). //! mem.addOffset(-1); // Adds -1 to the offset and makes it 11. //! mem.setOffset(0); // Sets the offset to 0. -//! mem.setBase(rcx); // Changes BASE to RCX. -//! mem.setIndex(rax); // Changes INDEX to RAX. +//! mem.setBase(x86::rcx); // Changes BASE to RCX. +//! mem.setIndex(x86::rax); // Changes INDEX to RAX. //! mem.hasIndex(); // true. //! } //! // ... @@ -1219,7 +1272,8 @@ namespace asmjit { //! //! ### Builder Examples //! -//! - \ref x86::Builder provides many X86/X64 examples. +//! - \ref x86::Builder - Builder implementation targeting X86 and X86_64 architectures. +//! - \ref a64::Builder - Builder implementation targeting AArch64 architecture. //! \defgroup asmjit_compiler Compiler @@ -1256,7 +1310,8 @@ namespace asmjit { //! //! ### Compiler Examples //! -//! - \ref x86::Compiler provides many X86/X64 examples. +//! - \ref x86::Compiler - Compiler implementation targeting X86 and X86_64 architectures. +//! - \ref a64::Compiler - Compiler implementation targeting AArch64 architecture. //! //! ### Compiler Tips //! @@ -1428,7 +1483,7 @@ namespace asmjit { //! The first example illustrates how to format operands: //! //! ``` -//! #include +//! #include //! #include //! //! using namespace asmjit; @@ -1453,17 +1508,17 @@ namespace asmjit { //! // compatible with what AsmJit normally does. //! Arch arch = Arch::kX64; //! -//! log(arch, rax); // Prints 'rax'. -//! log(arch, ptr(rax, rbx, 2)); // Prints '[rax + rbx * 4]`. -//! log(arch, dword_ptr(rax, rbx, 2)); // Prints 'dword [rax + rbx * 4]`. -//! log(arch, imm(42)); // Prints '42'. +//! logOperand(arch, rax); // Prints 'rax'. +//! logOperand(arch, ptr(rax, rbx, 2)); // Prints '[rax + rbx * 4]`. +//! logOperand(arch, dword_ptr(rax, rbx, 2)); // Prints 'dword [rax + rbx * 4]`. +//! logOperand(arch, imm(42)); // Prints '42'. //! } //! ``` //! //! Next example illustrates how to format whole instructions: //! //! ``` -//! #include +//! #include //! #include //! #include //! @@ -1478,7 +1533,7 @@ namespace asmjit { //! FormatFlags formatFlags = FormatFlags::kNone; //! //! // The formatter expects operands in an array. -//! Operand_ operands { std::forward(args)... }; +//! Operand_ operands[] { std::forward(args)... }; //! //! StringTmp<128> sb; //! Formatter::formatInstruction( @@ -1500,13 +1555,13 @@ namespace asmjit { //! // Prints 'vaddpd zmm0, zmm1, [rax] {1to8}'. //! logInstruction(arch, //! BaseInst(Inst::kIdVaddpd), -//! zmm0, zmm1, ptr(rax)._1toN()); +//! zmm0, zmm1, ptr(rax)._1to8()); //! //! // BaseInst abstracts instruction id, instruction options, and extraReg. //! // Prints 'lock add [rax], rcx'. //! logInstruction(arch, //! BaseInst(Inst::kIdAdd, InstOptions::kX86_Lock), -//! x86::ptr(rax), rcx); +//! ptr(rax), rcx); //! //! // Similarly an extra register (like AVX-512 selector) can be used. //! // Prints 'vaddpd zmm0 {k2} {z}, zmm1, [rax]'. @@ -1624,7 +1679,7 @@ namespace asmjit { //! //! Each instruction can be then queried for the following information: //! -//! - \ref InstRWInfo - Read/write information of instruction and its oprands (includes \ref OpRWInfo). +//! - \ref InstRWInfo - Read/write information of instruction and its operands (includes \ref OpRWInfo). //! //! - \ref CpuFeatures - CPU features required to execute the instruction. //! diff --git a/deps/asmjit/src/asmjit/core/api-config.h b/deps/asmjit/src/asmjit/core/api-config.h index dd504750..bbc35067 100644 --- a/deps/asmjit/src/asmjit/core/api-config.h +++ b/deps/asmjit/src/asmjit/core/api-config.h @@ -16,7 +16,7 @@ #define ASMJIT_LIBRARY_MAKE_VERSION(major, minor, patch) ((major << 16) | (minor << 8) | (patch)) //! AsmJit library version, see \ref ASMJIT_LIBRARY_MAKE_VERSION for a version format reference. -#define ASMJIT_LIBRARY_VERSION ASMJIT_LIBRARY_MAKE_VERSION(1, 11, 0) +#define ASMJIT_LIBRARY_VERSION ASMJIT_LIBRARY_MAKE_VERSION(1, 13, 0) //! \def ASMJIT_ABI_NAMESPACE //! @@ -27,7 +27,7 @@ //! AsmJit default, which makes it possible to use multiple AsmJit libraries within a single project, totally //! controlled by users. This is useful especially in cases in which some of such library comes from third party. #if !defined(ASMJIT_ABI_NAMESPACE) - #define ASMJIT_ABI_NAMESPACE _abi_1_11 + #define ASMJIT_ABI_NAMESPACE _abi_1_13 #endif // !ASMJIT_ABI_NAMESPACE //! \} @@ -42,7 +42,7 @@ #include #include -#include +#include #include #include #include @@ -112,7 +112,7 @@ namespace asmjit { #define ASMJIT_NO_INTROSPECTION // Avoid doxygen preprocessor using feature-selection definitions. -#undef ASMJIT_BUILD_EMBNED +#undef ASMJIT_BUILD_EMBED #undef ASMJIT_BUILD_STATIC #undef ASMJIT_BUILD_DEBUG #undef ASMJIT_BUILD_RELEASE @@ -163,6 +163,41 @@ namespace asmjit { // Target Architecture Detection // ============================= +//! \addtogroup asmjit_core +//! \{ + +//! \def ASMJIT_ARCH_X86 +//! +//! Defined to either 0, 32, or 64 depending on whether the target CPU is X86 (32) or X86_64 (64). + +//! \def ASMJIT_ARCH_ARM +//! +//! Defined to either 0, 32, or 64 depending on whether the target CPU is ARM (32) or AArch64 (64). + +//! \def ASMJIT_ARCH_MIPS +//! +//! Defined to either 0, 32, or 64 depending on whether the target CPU is MIPS (32) or MISP64 (64). + +//! \def ASMJIT_ARCH_RISCV +//! +//! Defined to either 0, 32, or 64 depending on whether the target CPU is RV32 (32) or RV64 (64). + +//! \def ASMJIT_ARCH_BITS +//! +//! Defined to either 32 or 64 depending on the target. + +//! \def ASMJIT_ARCH_LE +//! +//! Defined to 1 if the target architecture is little endian. + +//! \def ASMJIT_ARCH_BE +//! +//! Defined to 1 if the target architecture is big endian. + +//! \} + +//! \cond NONE + #if defined(_M_X64) || defined(__x86_64__) #define ASMJIT_ARCH_X86 64 #elif defined(_M_IX86) || defined(__X86__) || defined(__i386__) @@ -187,10 +222,17 @@ namespace asmjit { #define ASMJIT_ARCH_MIPS 0 #endif -#define ASMJIT_ARCH_BITS (ASMJIT_ARCH_X86 | ASMJIT_ARCH_ARM | ASMJIT_ARCH_MIPS) +// NOTE `__riscv` is the correct macro in this case as specified by "RISC-V Toolchain Conventions". +#if (defined(__riscv) || defined(__riscv__)) && defined(__riscv_xlen) + #define ASMJIT_ARCH_RISCV __riscv_xlen +#else + #define ASMJIT_ARCH_RISCV 0 +#endif + +#define ASMJIT_ARCH_BITS (ASMJIT_ARCH_X86 | ASMJIT_ARCH_ARM | ASMJIT_ARCH_MIPS | ASMJIT_ARCH_RISCV) #if ASMJIT_ARCH_BITS == 0 #undef ASMJIT_ARCH_BITS - #if defined (__LP64__) || defined(_LP64) + #if defined(__LP64__) || defined(_LP64) #define ASMJIT_ARCH_BITS 64 #else #define ASMJIT_ARCH_BITS 32 @@ -212,62 +254,88 @@ namespace asmjit { #define ASMJIT_NO_X86 #endif - #if !ASMJIT_ARCH_ARM && !defined(ASMJIT_NO_AARCH64) + #if ASMJIT_ARCH_ARM != 64 && !defined(ASMJIT_NO_AARCH64) #define ASMJIT_NO_AARCH64 #endif #endif +//! \endcond // C++ Compiler and Features Detection // =================================== -#define ASMJIT_CXX_GNU 0 -#define ASMJIT_CXX_MAKE_VER(MAJOR, MINOR) ((MAJOR) * 1000 + (MINOR)) - -// Intel Compiler [pretends to be GNU or MSC, so it must be checked first]: -// - https://software.intel.com/en-us/articles/c0x-features-supported-by-intel-c-compiler -// - https://software.intel.com/en-us/articles/c14-features-supported-by-intel-c-compiler -// - https://software.intel.com/en-us/articles/c17-features-supported-by-intel-c-compiler -#if defined(__INTEL_COMPILER) - -// MSC Compiler: -// - https://msdn.microsoft.com/en-us/library/hh567368.aspx -// -// Version List: -// - 16.00.0 == VS2010 -// - 17.00.0 == VS2012 -// - 18.00.0 == VS2013 -// - 19.00.0 == VS2015 -// - 19.10.0 == VS2017 -#elif defined(_MSC_VER) && defined(_MSC_FULL_VER) - -// Clang Compiler [Pretends to be GNU, so it must be checked before]: -// - https://clang.llvm.org/cxx_status.html -#elif defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) - -// GNU Compiler: -// - https://gcc.gnu.org/projects/cxx-status.html -#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) - - #undef ASMJIT_CXX_GNU - #define ASMJIT_CXX_GNU ASMJIT_CXX_MAKE_VER(__GNUC__, __GNUC_MINOR__) - -#endif - -// Compiler features detection macros. -#if defined(__clang__) && defined(__has_attribute) +#if defined(__GNUC__) && defined(__has_attribute) #define ASMJIT_CXX_HAS_ATTRIBUTE(NAME, CHECK) (__has_attribute(NAME)) #else #define ASMJIT_CXX_HAS_ATTRIBUTE(NAME, CHECK) (!(!(CHECK))) -#endif +#endif // !ASMJIT_CXX_HAS_ATTRIBUTE // API Decorators & C++ Extensions // =============================== +//! \addtogroup asmjit_core +//! \{ + //! \def ASMJIT_API //! //! A decorator that is used to decorate API that AsmJit exports when built as a shared library. +//! \def ASMJIT_VIRTAPI +//! +//! This is basically a workaround. When using MSVC and marking class as DLL export everything gets exported, which +//! is unwanted in most projects. MSVC automatically exports typeinfo and vtable if at least one symbol of the class +//! is exported. However, GCC has some strange behavior that even if one or more symbol is exported it doesn't export +//! typeinfo unless the class itself is decorated with "visibility(default)" (i.e. ASMJIT_API). + +//! \def ASMJIT_FORCE_INLINE +//! +//! Decorator to force inlining of functions, uses either `__attribute__((__always_inline__))` or __forceinline, +//! depending on C++ compiler. + +//! \def ASMJIT_INLINE_NODEBUG +//! +//! Like \ref ASMJIT_FORCE_INLINE, but uses additionally `__nodebug__` or `__artificial__` attribute to make the +//! debugging of some AsmJit functions easier, especially getters and one-line abstractions where usually you don't +//! want to step in. + +//! \def ASMJIT_NOINLINE +//! +//! Decorator to avoid inlining of functions, uses either `__attribute__((__noinline__))` or `__declspec(noinline)` +//! depending on C++ compiler. + +//! \def ASMJIT_NORETURN +//! +//! Decorator that marks functions that should never return. Typically used to implement assertion handlers that +//! terminate, so the function never returns. + +//! \def ASMJIT_CDECL +//! +//! CDECL function attribute - either `__attribute__((__cdecl__))` or `__cdecl`. + +//! \def ASMJIT_STDCALL +//! +//! STDCALL function attribute - either `__attribute__((__stdcall__))` or `__stdcall`. +//! +//! \note This expands to nothing on non-x86 targets as STDCALL is X86 specific. + +//! \def ASMJIT_FASTCALL +//! +//! FASTCALL function attribute - either `__attribute__((__fastcall__))` or `__fastcall`. +//! +//! \note Expands to nothing on non-x86 targets as FASTCALL is X86 specific. + +//! \def ASMJIT_REGPARM(N) +//! +//! Expands to `__attribute__((__regparm__(N)))` when compiled by GCC or clang, nothing otherwise. + +//! \def ASMJIT_VECTORCALL +//! +//! VECTORCALL function attribute - either `__attribute__((__vectorcall__))` or `__vectorcall`. +//! +//! \note Expands to nothing on non-x86 targets as VECTORCALL is X86 specific. + +//! \} + // API (Export / Import). #if !defined(ASMJIT_STATIC) #if defined(_WIN32) && (defined(_MSC_VER) || defined(__MINGW32__)) @@ -295,13 +363,7 @@ namespace asmjit { #define ASMJIT_VARAPI extern ASMJIT_API #endif -//! \def ASMJIT_VIRTAPI -//! -//! This is basically a workaround. When using MSVC and marking class as DLL export everything gets exported, which -//! is unwanted in most projects. MSVC automatically exports typeinfo and vtable if at least one symbol of the class -//! is exported. However, GCC has some strange behavior that even if one or more symbol is exported it doesn't export -//! typeinfo unless the class itself is decorated with "visibility(default)" (i.e. ASMJIT_API). -#if !defined(_WIN32) && defined(__GNUC__) +#if defined(__GNUC__) && !defined(_WIN32) #define ASMJIT_VIRTAPI ASMJIT_API #else #define ASMJIT_VIRTAPI @@ -458,17 +520,10 @@ namespace asmjit { //! Marks function, class, struct, enum, or anything else as deprecated. #if defined(__GNUC__) #define ASMJIT_DEPRECATED(MESSAGE) __attribute__((__deprecated__(MESSAGE))) - #if defined(__clang__) - #define ASMJIT_DEPRECATED_STRUCT(MESSAGE) __attribute__((__deprecated__(MESSAGE))) - #else - #define ASMJIT_DEPRECATED_STRUCT(MESSAGE) /* not usable if a deprecated function uses it */ - #endif #elif defined(_MSC_VER) #define ASMJIT_DEPRECATED(MESSAGE) __declspec(deprecated(MESSAGE)) - #define ASMJIT_DEPRECATED_STRUCT(MESSAGE) /* not usable if a deprecated function uses it */ #else #define ASMJIT_DEPRECATED(MESSAGE) - #define ASMJIT_DEPRECATED_STRUCT(MESSAGE) #endif // Utilities. @@ -477,66 +532,60 @@ namespace asmjit { #if ASMJIT_CXX_HAS_ATTRIBUTE(no_sanitize, 0) #define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF __attribute__((__no_sanitize__("undefined"))) -#elif ASMJIT_CXX_GNU >= ASMJIT_CXX_MAKE_VER(4, 9) +#elif defined(__GNUC__) && __GNUC__ >= 5 #define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF __attribute__((__no_sanitize_undefined__)) #else #define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF #endif -// Begin-Namespace & End-Namespace Macros +// Diagnostic Macros // ====================================== -#if defined _DOXYGEN - #define ASMJIT_BEGIN_NAMESPACE namespace asmjit { - #define ASMJIT_END_NAMESPACE } -#elif defined(__clang__) - #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wconstant-logical-operand\"") \ - _Pragma("clang diagnostic ignored \"-Wunnamed-type-template-args\"") - #define ASMJIT_END_NAMESPACE \ - _Pragma("clang diagnostic pop") \ - }} -#elif defined(__GNUC__) && __GNUC__ == 4 - #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { \ +#if !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(_DOXYGEN) + #if defined(__GNUC__) && __GNUC__ == 4 + // There is a bug in GCC 4.X that has been fixed in GCC 5+, so just silence the warning. + #define ASMJIT_BEGIN_DIAGNOSTIC_SCOPE \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") - #define ASMJIT_END_NAMESPACE \ - _Pragma("GCC diagnostic pop") \ - }} -#elif defined(__GNUC__) && __GNUC__ >= 8 - #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { \ - _Pragma("GCC diagnostic push") \ - _Pragma("GCC diagnostic ignored \"-Wclass-memaccess\"") - #define ASMJIT_END_NAMESPACE \ - _Pragma("GCC diagnostic pop") \ - }} -#elif defined(_MSC_VER) && !defined(__INTEL_COMPILER) - #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { \ + #define ASMJIT_END_DIAGNOSTIC_SCOPE \ + _Pragma("GCC diagnostic pop") + #elif defined(_MSC_VER) + #define ASMJIT_BEGIN_DIAGNOSTIC_SCOPE \ __pragma(warning(push)) \ __pragma(warning(disable: 4127)) /* conditional expression is const */ \ __pragma(warning(disable: 4201)) /* nameless struct/union */ + #define ASMJIT_END_DIAGNOSTIC_SCOPE \ + __pragma(warning(pop)) + #endif +#endif + +#if !defined(ASMJIT_BEGIN_DIAGNOSTIC_SCOPE) && !defined(ASMJIT_END_DIAGNOSTIC_SCOPE) + #define ASMJIT_BEGIN_DIAGNOSTIC_SCOPE + #define ASMJIT_END_DIAGNOSTIC_SCOPE +#endif + +// Begin-Namespace & End-Namespace Macros +// ====================================== + +#if !defined(ASMJIT_NO_ABI_NAMESPACE) && !defined(_DOXYGEN) + #define ASMJIT_BEGIN_NAMESPACE \ + ASMJIT_BEGIN_DIAGNOSTIC_SCOPE \ + namespace asmjit { \ + inline namespace ASMJIT_ABI_NAMESPACE { #define ASMJIT_END_NAMESPACE \ - __pragma(warning(pop)) \ - }} + }} \ + ASMJIT_END_DIAGNOSTIC_SCOPE +#else + #define ASMJIT_BEGIN_NAMESPACE \ + ASMJIT_BEGIN_DIAGNOSTIC_SCOPE \ + namespace asmjit { + #define ASMJIT_END_NAMESPACE \ + } \ + ASMJIT_END_DIAGNOSTIC_SCOPE #endif -#if !defined(ASMJIT_BEGIN_NAMESPACE) && !defined(ASMJIT_END_NAMESPACE) - #define ASMJIT_BEGIN_NAMESPACE namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { - #define ASMJIT_END_NAMESPACE }} -#endif - -#define ASMJIT_BEGIN_SUB_NAMESPACE(NAMESPACE) \ - ASMJIT_BEGIN_NAMESPACE \ - namespace NAMESPACE { - -#define ASMJIT_END_SUB_NAMESPACE \ - } \ - ASMJIT_END_NAMESPACE +#define ASMJIT_BEGIN_SUB_NAMESPACE(NAMESPACE) ASMJIT_BEGIN_NAMESPACE namespace NAMESPACE { +#define ASMJIT_END_SUB_NAMESPACE } ASMJIT_END_NAMESPACE // C++ Utilities // ============= @@ -612,10 +661,4 @@ namespace asmjit { } #endif -// Cleanup Api-Config Specific Macros -// ================================== - -#undef ASMJIT_CXX_GNU -#undef ASMJIT_CXX_MAKE_VER - #endif // ASMJIT_CORE_API_CONFIG_H_INCLUDED diff --git a/deps/asmjit/src/asmjit/core/archcommons.h b/deps/asmjit/src/asmjit/core/archcommons.h index 7321c128..2b47d17c 100644 --- a/deps/asmjit/src/asmjit/core/archcommons.h +++ b/deps/asmjit/src/asmjit/core/archcommons.h @@ -29,8 +29,8 @@ enum class CondCode : uint8_t { kNE = 0x03u, //!< Z==0 (any_sign !=) kCS = 0x04u, //!< C==1 (unsigned >=) kHS = 0x04u, //!< C==1 (unsigned >=) - kCC = 0x05u, //!< C==0 (unsigned < ) kLO = 0x05u, //!< C==0 (unsigned < ) + kCC = 0x05u, //!< C==0 (unsigned < ) kMI = 0x06u, //!< N==1 (is negative) kPL = 0x07u, //!< N==0 (is positive or zero) kVS = 0x08u, //!< V==1 (is overflow) @@ -42,21 +42,24 @@ enum class CondCode : uint8_t { kGT = 0x0Eu, //!< Z==0 & N==V (signed > ) kLE = 0x0Fu, //!< Z==1 | N!=V (signed <=) - kSign = kMI, //!< Sign. - kNotSign = kPL, //!< Not sign. - - kOverflow = kVS, //!< Signed overflow. - kNotOverflow = kVC, //!< Not signed overflow. + kZero = kEQ, //!< Zero flag (alias to equal). + kNotZero = kNE, //!< Not zero (alias to Not Equal). kEqual = kEQ, //!< Equal `a == b`. kNotEqual = kNE, //!< Not Equal `a != b`. - kZero = kEQ, //!< Zero (alias to equal). - kNotZero = kNE, //!< Not Zero (alias to Not Equal). + kCarry = kCS, //!< Carry flag. + kNotCarry = kCC, //!< Not carry. + + kSign = kMI, //!< Sign flag. + kNotSign = kPL, //!< Not sign. kNegative = kMI, //!< Negative. kPositive = kPL, //!< Positive or zero. + kOverflow = kVS, //!< Signed overflow. + kNotOverflow = kVC, //!< Not signed overflow. + kSignedLT = kLT, //!< Signed `a < b`. kSignedLE = kLE, //!< Signed `a <= b`. kSignedGT = kGT, //!< Signed `a > b`. @@ -67,49 +70,51 @@ enum class CondCode : uint8_t { kUnsignedGT = kHI, //!< Unsigned `a > b`. kUnsignedGE = kHS, //!< Unsigned `a >= b`. + kBTZero = kZero, //!< Tested bit is zero. + kBTNotZero = kNotZero, //!< Tested bit is not zero. + kAlways = kAL, //!< No condition code (always). kMaxValue = 0x0Fu //!< Maximum value of `CondCode`. }; + +//! \cond +static constexpr CondCode _reverseCondTable[] = { + CondCode::kAL, // AL <- AL + CondCode::kNA, // NA <- NA + CondCode::kEQ, // EQ <- EQ + CondCode::kNE, // NE <- NE + CondCode::kLS, // LS <- CS + CondCode::kHI, // HI <- LO + CondCode::kMI, // MI <- MI + CondCode::kPL, // PL <- PL + CondCode::kVS, // VS <- VS + CondCode::kVC, // VC <- VC + CondCode::kLO, // LO <- HI + CondCode::kCS, // CS <- LS + CondCode::kLE, // LE <- GE + CondCode::kGT, // GT <- LT + CondCode::kLT, // LT <- GT + CondCode::kGE // GE <- LE +}; +//! \endcond + +//! Reverses a condition code (reverses the corresponding operands of a comparison). +static ASMJIT_INLINE_NODEBUG constexpr CondCode reverseCond(CondCode cond) noexcept { return _reverseCondTable[uint8_t(cond)]; } //! Negates a condition code. static ASMJIT_INLINE_NODEBUG constexpr CondCode negateCond(CondCode cond) noexcept { return CondCode(uint8_t(cond) ^ uint8_t(1)); } -//! Data type that can be encoded with the instruction (AArch32 only). -enum class DataType : uint32_t { - //! No data type specified (default for all general purpose instructions). - kNone = 0, - //! 8-bit signed integer, specified as `.s8` in assembly. - kS8 = 1, - //! 16-bit signed integer, specified as `.s16` in assembly. - kS16 = 2, - //! 32-bit signed integer, specified as `.s32` in assembly. - kS32 = 3, - //! 64-bit signed integer, specified as `.s64` in assembly. - kS64 = 4, - //! 8-bit unsigned integer, specified as `.u8` in assembly. - kU8 = 5, - //! 16-bit unsigned integer, specified as `.u16` in assembly. - kU16 = 6, - //! 32-bit unsigned integer, specified as `.u32` in assembly. - kU32 = 7, - //! 64-bit unsigned integer, specified as `.u64` in assembly. - kU64 = 8, - //! 16-bit floating point (half precision), specified as `.f16` in assembly. - kF16 = 10, - //! 32-bit floating point (single precision), specified as `.f32` in assembly. - kF32 = 11, - //! 64-bit floating point (double precision), specified as `.f64` in assembly. - kF64 = 12, - //! 8-bit polynomial. - kP8 = 13, - //! 16-bit BF16 floating point. - kBF16 = 14, - //! 64-bit polynomial. - kP64 = 15, - - //! Maximum value of `DataType`. - kMaxValue = 15 +//! Memory offset mode. +//! +//! Describes either fixed, pre-index, or post-index offset modes. +enum class OffsetMode : uint32_t { + //! Fixed offset mode (either no index at all or a regular index without a write-back). + kFixed = 0u, + //! Pre-index "[BASE, #Offset {, }]!" with write-back. + kPreIndex = 1u, + //! Post-index "[BASE], #Offset {, }" with write-back. + kPostIndex = 2u }; //! Shift operation predicate (ARM) describes either SHIFT or EXTEND operation. @@ -187,45 +192,70 @@ public: //! Sets shift operation to `op`. ASMJIT_INLINE_NODEBUG void setOp(ShiftOp op) noexcept { _op = op; } - //! Returns the shift smount. + //! Returns the shift amount. ASMJIT_INLINE_NODEBUG constexpr uint32_t value() const noexcept { return _value; } //! Sets shift amount to `value`. ASMJIT_INLINE_NODEBUG void setValue(uint32_t value) noexcept { _value = value; } }; -//! Constructs a `LSL #value` shift (logical shift left). -static ASMJIT_INLINE_NODEBUG constexpr Shift lsl(uint32_t value) noexcept { return Shift(ShiftOp::kLSL, value); } -//! Constructs a `LSR #value` shift (logical shift right). -static ASMJIT_INLINE_NODEBUG constexpr Shift lsr(uint32_t value) noexcept { return Shift(ShiftOp::kLSR, value); } -//! Constructs a `ASR #value` shift (arithmetic shift right). -static ASMJIT_INLINE_NODEBUG constexpr Shift asr(uint32_t value) noexcept { return Shift(ShiftOp::kASR, value); } -//! Constructs a `ROR #value` shift (rotate right). -static ASMJIT_INLINE_NODEBUG constexpr Shift ror(uint32_t value) noexcept { return Shift(ShiftOp::kROR, value); } -//! Constructs a `RRX` shift (rotate with carry by 1). -static ASMJIT_INLINE_NODEBUG constexpr Shift rrx() noexcept { return Shift(ShiftOp::kRRX, 0); } -//! Constructs a `MSL #value` shift (logical shift left filling ones). -static ASMJIT_INLINE_NODEBUG constexpr Shift msl(uint32_t value) noexcept { return Shift(ShiftOp::kMSL, value); } - -//! Constructs a `UXTB #value` extend and shift (unsigned byte extend). -static ASMJIT_INLINE_NODEBUG constexpr Shift uxtb(uint32_t value) noexcept { return Shift(ShiftOp::kUXTB, value); } -//! Constructs a `UXTH #value` extend and shift (unsigned hword extend). -static ASMJIT_INLINE_NODEBUG constexpr Shift uxth(uint32_t value) noexcept { return Shift(ShiftOp::kUXTH, value); } -//! Constructs a `UXTW #value` extend and shift (unsigned word extend). -static ASMJIT_INLINE_NODEBUG constexpr Shift uxtw(uint32_t value) noexcept { return Shift(ShiftOp::kUXTW, value); } -//! Constructs a `UXTX #value` extend and shift (unsigned dword extend). -static ASMJIT_INLINE_NODEBUG constexpr Shift uxtx(uint32_t value) noexcept { return Shift(ShiftOp::kUXTX, value); } - -//! Constructs a `SXTB #value` extend and shift (signed byte extend). -static ASMJIT_INLINE_NODEBUG constexpr Shift sxtb(uint32_t value) noexcept { return Shift(ShiftOp::kSXTB, value); } -//! Constructs a `SXTH #value` extend and shift (signed hword extend). -static ASMJIT_INLINE_NODEBUG constexpr Shift sxth(uint32_t value) noexcept { return Shift(ShiftOp::kSXTH, value); } -//! Constructs a `SXTW #value` extend and shift (signed word extend). -static ASMJIT_INLINE_NODEBUG constexpr Shift sxtw(uint32_t value) noexcept { return Shift(ShiftOp::kSXTW, value); } -//! Constructs a `SXTX #value` extend and shift (signed dword extend). -static ASMJIT_INLINE_NODEBUG constexpr Shift sxtx(uint32_t value) noexcept { return Shift(ShiftOp::kSXTX, value); } - //! \} ASMJIT_END_SUB_NAMESPACE +ASMJIT_BEGIN_SUB_NAMESPACE(a32) + +using namespace arm; + +//! Data type that can be encoded with AArch32 instruction identifier. +//! +//! \note Data types are frequently used with AArch32 SIMD instructions. For example `VMAX` instruction can +//! use almost all datatypes in a form `VMAX.F32`, `VMAX.S16`, `VMAX.U32`, etc... Emitter automatically adds +//! the required data type at emit level. +enum class DataType : uint32_t { + //! No data type specified (default for all general purpose instructions). + kNone = 0, + //! 8-bit signed integer, specified as `.s8` in assembly. + kS8 = 1, + //! 16-bit signed integer, specified as `.s16` in assembly. + kS16 = 2, + //! 32-bit signed integer, specified as `.s32` in assembly. + kS32 = 3, + //! 64-bit signed integer, specified as `.s64` in assembly. + kS64 = 4, + //! 8-bit unsigned integer, specified as `.u8` in assembly. + kU8 = 5, + //! 16-bit unsigned integer, specified as `.u16` in assembly. + kU16 = 6, + //! 32-bit unsigned integer, specified as `.u32` in assembly. + kU32 = 7, + //! 64-bit unsigned integer, specified as `.u64` in assembly. + kU64 = 8, + //! 16-bit floating point (half precision), specified as `.f16` in assembly. + kF16 = 10, + //! 32-bit floating point (single precision), specified as `.f32` in assembly. + kF32 = 11, + //! 64-bit floating point (double precision), specified as `.f64` in assembly. + kF64 = 12, + //! 8-bit polynomial. + kP8 = 13, + //! 16-bit BF16 floating point. + kBF16 = 14, + //! 64-bit polynomial. + kP64 = 15, + + //! Maximum value of `DataType`. + kMaxValue = 15 +}; + +static ASMJIT_INLINE_NODEBUG uint32_t dataTypeSize(DataType dt) noexcept { + static constexpr uint8_t table[] = { 0, 1, 2, 4, 8, 1, 2, 4, 8, 2, 4, 8, 1, 2, 8 }; + return table[size_t(dt)]; +} + +ASMJIT_END_SUB_NAMESPACE + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) +using namespace arm; +ASMJIT_END_SUB_NAMESPACE + #endif // ASMJIT_CORE_ARCHCOMMONS_H_INCLUDED diff --git a/deps/asmjit/src/asmjit/core/archtraits.h b/deps/asmjit/src/asmjit/core/archtraits.h index df87412e..9f08dea5 100644 --- a/deps/asmjit/src/asmjit/core/archtraits.h +++ b/deps/asmjit/src/asmjit/core/archtraits.h @@ -74,6 +74,9 @@ enum class Arch : uint8_t { ASMJIT_ARCH_X86 == 32 ? kX86 : ASMJIT_ARCH_X86 == 64 ? kX64 : + ASMJIT_ARCH_RISCV == 32 ? kRISCV32 : + ASMJIT_ARCH_RISCV == 64 ? kRISCV64 : + ASMJIT_ARCH_ARM == 32 && ASMJIT_ARCH_LE ? kARM : ASMJIT_ARCH_ARM == 32 && ASMJIT_ARCH_BE ? kARM_BE : ASMJIT_ARCH_ARM == 64 && ASMJIT_ARCH_LE ? kAArch64 : diff --git a/deps/asmjit/src/asmjit/core/assembler.h b/deps/asmjit/src/asmjit/core/assembler.h index aac72e0a..d53d9e53 100644 --- a/deps/asmjit/src/asmjit/core/assembler.h +++ b/deps/asmjit/src/asmjit/core/assembler.h @@ -25,6 +25,7 @@ ASMJIT_BEGIN_NAMESPACE //! Check out architecture specific assemblers for more details and examples: //! //! - \ref x86::Assembler - X86/X64 assembler implementation. +//! - \ref a64::Assembler - AArch64 assembler implementation. class ASMJIT_VIRTAPI BaseAssembler : public BaseEmitter { public: ASMJIT_NONCOPYABLE(BaseAssembler) diff --git a/deps/asmjit/src/asmjit/core/builder.cpp b/deps/asmjit/src/asmjit/core/builder.cpp index 4b761226..25433b9a 100644 --- a/deps/asmjit/src/asmjit/core/builder.cpp +++ b/deps/asmjit/src/asmjit/core/builder.cpp @@ -590,7 +590,7 @@ Error BaseBuilder::_emit(InstId instId, const Operand_& o0, const Operand_& o1, EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); ValidationFlags validationFlags = isCompiler() ? ValidationFlags::kEnableVirtRegs : ValidationFlags::kNone; - Error err = _funcs.validate(arch(), BaseInst(instId, options, _extraReg), opArray, opCount, validationFlags); + Error err = _funcs.validate(BaseInst(instId, options, _extraReg), opArray, opCount, validationFlags); if (ASMJIT_UNLIKELY(err)) { #ifndef ASMJIT_NO_LOGGING diff --git a/deps/asmjit/src/asmjit/core/builder.h b/deps/asmjit/src/asmjit/core/builder.h index c7aca961..0de19234 100644 --- a/deps/asmjit/src/asmjit/core/builder.h +++ b/deps/asmjit/src/asmjit/core/builder.h @@ -48,7 +48,7 @@ enum class NodeType : uint8_t { // [BaseBuilder] - //! Node is \ref InstNode or \ref InstExNode. + //! Node is \ref InstNode. kInst = 1, //! Node is \ref SectionNode. kSection = 2, @@ -181,6 +181,7 @@ public: //! Check out architecture specific builders for more details and examples: //! //! - \ref x86::Builder - X86/X64 builder implementation. +//! - \ref a64::Builder - AArch64 builder implementation. class ASMJIT_VIRTAPI BaseBuilder : public BaseEmitter { public: ASMJIT_NONCOPYABLE(BaseBuilder) @@ -546,7 +547,7 @@ public: uint8_t _reserved1; }; - //! Data that can have different meaning dependning on \ref NodeType. + //! Data that can have different meaning depending on \ref NodeType. union { //! Data useful by any node type. AnyData _any; @@ -694,8 +695,9 @@ public: //! Returns user data casted to `T*`. //! - //! User data is decicated to be used only by AsmJit users and not touched by the library. The data has a pointer - //! size so you can either store a pointer or `intptr_t` value through `setUserDataAsIntPtr()`. + //! User data is dedicated to be used only by AsmJit users and not touched by the library. The data is of a pointer + //! size so you can either store a pointer or `int64_t` value through `setUserDataAsPtr()`, `setUserDataAsInt64()` + //! and `setUserDataAsUInt64()`. template ASMJIT_INLINE_NODEBUG T* userDataAsPtr() const noexcept { return static_cast(_userDataPtr); } //! Returns user data casted to `int64_t`. @@ -747,12 +749,15 @@ public: //! \name Constants //! \{ - enum : uint32_t { - //! Count of embedded operands per `InstNode` that are always allocated as a part of the instruction. Minimum - //! embedded operands is 4, but in 32-bit more pointers are smaller and we can embed 5. The rest (up to 6 operands) - //! is always stored in `InstExNode`. - kBaseOpCapacity = uint32_t((128 - sizeof(BaseNode) - sizeof(BaseInst)) / sizeof(Operand_)) - }; + //! The number of embedded operands for a default \ref InstNode instance that are always allocated as a part of + //! the instruction itself. Minimum embedded operands is 4, but in 32-bit more pointers are smaller and we can + //! embed 5. The rest (up to 6 operands) is considered extended. + //! + //! The number of operands InstNode holds is decided when \ref InstNode is created. + static constexpr uint32_t kBaseOpCapacity = uint32_t((128 - sizeof(BaseNode) - sizeof(BaseInst)) / sizeof(Operand_)); + + //! Count of maximum number of operands \ref InstNode can hold. + static constexpr uint32_t kFullOpCapacity = Globals::kMaxOpCount; //! \} @@ -761,8 +766,6 @@ public: //! Base instruction data. BaseInst _baseInst; - //! First 4 or 5 operands (indexed from 0). - Operand_ _opArray[kBaseOpCapacity]; //! \} @@ -811,11 +814,17 @@ public: //! \name Instruction Options //! \{ + //! Returns instruction options, see \ref InstOptions for more details. ASMJIT_INLINE_NODEBUG InstOptions options() const noexcept { return _baseInst.options(); } + //! Tests whether instruction has the given \option` set/enabled. ASMJIT_INLINE_NODEBUG bool hasOption(InstOptions option) const noexcept { return _baseInst.hasOption(option); } + //! Sets instruction `options` to the provided value, resetting all others. ASMJIT_INLINE_NODEBUG void setOptions(InstOptions options) noexcept { _baseInst.setOptions(options); } + //! Adds instruction `options` to the instruction. ASMJIT_INLINE_NODEBUG void addOptions(InstOptions options) noexcept { _baseInst.addOptions(options); } + //! Clears instruction `options` of the instruction (disables the given options). ASMJIT_INLINE_NODEBUG void clearOptions(InstOptions options) noexcept { _baseInst.clearOptions(options); } + //! Resets instruction options to none - disabling all instruction options. ASMJIT_INLINE_NODEBUG void resetOptions() noexcept { _baseInst.resetOptions(); } //! \} @@ -850,38 +859,52 @@ public: ASMJIT_INLINE_NODEBUG void setOpCount(uint32_t opCount) noexcept { _inst._opCount = uint8_t(opCount); } //! Returns operands array. - ASMJIT_INLINE_NODEBUG Operand* operands() noexcept { return (Operand*)_opArray; } + ASMJIT_INLINE_NODEBUG Operand* operands() noexcept { + return reinterpret_cast(reinterpret_cast(this) + sizeof(InstNode)); + } + //! Returns operands array (const). - ASMJIT_INLINE_NODEBUG const Operand* operands() const noexcept { return (const Operand*)_opArray; } + ASMJIT_INLINE_NODEBUG const Operand* operands() const noexcept { + return reinterpret_cast(reinterpret_cast(this) + sizeof(InstNode)); + } //! Returns operand at the given `index`. inline Operand& op(uint32_t index) noexcept { ASMJIT_ASSERT(index < opCapacity()); - return _opArray[index].as(); + + Operand* ops = operands(); + return ops[index].as(); } //! Returns operand at the given `index` (const). inline const Operand& op(uint32_t index) const noexcept { ASMJIT_ASSERT(index < opCapacity()); - return _opArray[index].as(); + + const Operand* ops = operands(); + return ops[index].as(); } //! Sets operand at the given `index` to `op`. inline void setOp(uint32_t index, const Operand_& op) noexcept { ASMJIT_ASSERT(index < opCapacity()); - _opArray[index].copyFrom(op); + + Operand* ops = operands(); + ops[index].copyFrom(op); } //! Resets operand at the given `index` to none. inline void resetOp(uint32_t index) noexcept { ASMJIT_ASSERT(index < opCapacity()); - _opArray[index].reset(); + + Operand* ops = operands(); + ops[index].reset(); } //! Resets operands at `[start, end)` range. inline void resetOpRange(uint32_t start, uint32_t end) noexcept { + Operand* ops = operands(); for (uint32_t i = start; i < end; i++) - _opArray[i].reset(); + ops[i].reset(); } //! \} @@ -889,33 +912,47 @@ public: //! \name Utilities //! \{ + //! Tests whether the given operand type `opType` is used by the instruction. inline bool hasOpType(OperandType opType) const noexcept { + const Operand* ops = operands(); for (uint32_t i = 0, count = opCount(); i < count; i++) - if (_opArray[i].opType() == opType) + if (ops[i].opType() == opType) return true; return false; } + //! Tests whether the instruction uses at least one register operand. inline bool hasRegOp() const noexcept { return hasOpType(OperandType::kReg); } + //! Tests whether the instruction uses at least one memory operand. inline bool hasMemOp() const noexcept { return hasOpType(OperandType::kMem); } + //! Tests whether the instruction uses at least one immediate operand. inline bool hasImmOp() const noexcept { return hasOpType(OperandType::kImm); } + //! Tests whether the instruction uses at least one label operand. inline bool hasLabelOp() const noexcept { return hasOpType(OperandType::kLabel); } + //! Returns the index of the given operand type `opType`. + //! + //! \note If the operand type wa found, the value returned represents its index in \ref operands() + //! array, otherwise \ref Globals::kNotFound is returned to signalize that the operand was not found. inline uint32_t indexOfOpType(OperandType opType) const noexcept { uint32_t i = 0; uint32_t count = opCount(); + const Operand* ops = operands(); while (i < count) { - if (_opArray[i].opType() == opType) - break; + if (ops[i].opType() == opType) + return i; i++; } - return i; + return Globals::kNotFound; } + //! A shortcut that calls `indexOfOpType(OperandType::kMem)`. inline uint32_t indexOfMemOp() const noexcept { return indexOfOpType(OperandType::kMem); } + //! A shortcut that calls `indexOfOpType(OperandType::kImm)`. inline uint32_t indexOfImmOp() const noexcept { return indexOfOpType(OperandType::kImm); } + //! A shortcut that calls `indexOfOpType(OperandType::kLabel)`. inline uint32_t indexOfLabelOp() const noexcept { return indexOfOpType(OperandType::kLabel); } //! \} @@ -924,20 +961,40 @@ public: //! \{ //! \cond INTERNAL + + //! Returns uint32_t[] view that represents BaseInst::RegOnly and instruction operands. ASMJIT_INLINE_NODEBUG uint32_t* _getRewriteArray() noexcept { return &_baseInst._extraReg._id; } + //! \overload ASMJIT_INLINE_NODEBUG const uint32_t* _getRewriteArray() const noexcept { return &_baseInst._extraReg._id; } + //! Maximum value of rewrite id - 6 operands each having 4 slots is 24, one RegOnly having 2 slots => 26. + static constexpr uint32_t kMaxRewriteId = 26 - 1; + + //! Returns a rewrite index of the given pointer to `id`. + //! + //! This function returns a value that can be then passed to `\ref rewriteIdAtIndex() function. It can address + //! any id from any operand that is used by the instruction in addition to \ref BaseInst::regOnly field, which + //! can also be used by the register allocator. inline uint32_t getRewriteIndex(const uint32_t* id) const noexcept { const uint32_t* array = _getRewriteArray(); ASMJIT_ASSERT(array <= id); size_t index = (size_t)(id - array); - ASMJIT_ASSERT(index < 32); + ASMJIT_ASSERT(index <= kMaxRewriteId); return uint32_t(index); } + //! Rewrites the given `index` to the provided identifier `id`. + //! + //! \note This is an internal function that is used by a \ref BaseCompiler implementation to rewrite virtual + //! registers to physical registers. The rewriter in this case sees all operands as array of uint32 values + //! and the given `index` describes a position in this array. For example a single \ref Operand would be + //! decomposed to 4 uint32_t values, where the first at index 0 would be operand signature, next would be + //! base id, etc... This is a comfortable way of patching operands without having to check for their types. inline void rewriteIdAtIndex(uint32_t index, uint32_t id) noexcept { + ASMJIT_ASSERT(index <= kMaxRewriteId); + uint32_t* array = _getRewriteArray(); array[index] = id; } @@ -949,43 +1006,40 @@ public: //! \{ //! \cond INTERNAL - static ASMJIT_INLINE_NODEBUG uint32_t capacityOfOpCount(uint32_t opCount) noexcept { - return opCount <= kBaseOpCapacity ? kBaseOpCapacity : Globals::kMaxOpCount; + + //! Returns the capacity required for the given operands count `opCount`. + //! + //! There are only two capacities used - \ref kBaseOpCapacity and \ref kFullOpCapacity, so this function + //! is used to decide between these two. The general rule is that instructions that can be represented with + //! \ref kBaseOpCapacity would use this value, and all others would take \ref kFullOpCapacity. + static ASMJIT_INLINE_NODEBUG constexpr uint32_t capacityOfOpCount(uint32_t opCount) noexcept { + return opCount <= kBaseOpCapacity ? kBaseOpCapacity : kFullOpCapacity; } - static ASMJIT_INLINE_NODEBUG size_t nodeSizeOfOpCapacity(uint32_t opCapacity) noexcept { - size_t base = sizeof(InstNode) - kBaseOpCapacity * sizeof(Operand); - return base + opCapacity * sizeof(Operand); + //! Calculates the size of \ref InstNode required to hold at most `opCapacity` operands. + //! + //! This function is used internally to allocate \ref InstNode. + static ASMJIT_INLINE_NODEBUG constexpr size_t nodeSizeOfOpCapacity(uint32_t opCapacity) noexcept { + return sizeof(InstNode) + opCapacity * sizeof(Operand); } //! \endcond //! \} }; -//! Instruction node with maximum number of operands. +//! Instruction node with embedded operands following \ref InstNode layout. //! -//! This node is created automatically by Builder/Compiler in case that the required number of operands exceeds -//! the default capacity of `InstNode`. -class InstExNode : public InstNode { +//! \note This is used to make tools such as static analysis and compilers happy about the layout. There were two +//! instruction nodes in the past, having the second extend the operand array of the first, but that has caused +//! undefined behavior and made recent tools unhappy about that. +template +class InstNodeWithOperands : public InstNode { public: - ASMJIT_NONCOPYABLE(InstExNode) + Operand_ _operands[kN]; - //! \name Members - //! \{ - - //! Continued `_opArray[]` to hold up to `kMaxOpCount` operands. - Operand_ _opArrayEx[Globals::kMaxOpCount - kBaseOpCapacity]; - - //! \} - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `InstExNode` instance. - ASMJIT_INLINE_NODEBUG InstExNode(BaseBuilder* cb, InstId instId, InstOptions options, uint32_t opCapacity = Globals::kMaxOpCount) noexcept - : InstNode(cb, instId, options, opCapacity) {} - - //! \} + //! Creates a new `InstNodeWithOperands` instance. + ASMJIT_INLINE_NODEBUG InstNodeWithOperands(BaseBuilder* cb, InstId instId, InstOptions options, uint32_t opCount) noexcept + : InstNode(cb, instId, options, opCount, kN) {} }; //! Section node. @@ -1012,9 +1066,9 @@ public: //! \{ //! Creates a new `SectionNode` instance. - ASMJIT_INLINE_NODEBUG SectionNode(BaseBuilder* cb, uint32_t secionId = 0) noexcept + ASMJIT_INLINE_NODEBUG SectionNode(BaseBuilder* cb, uint32_t sectionId = 0) noexcept : BaseNode(cb, NodeType::kSection, NodeFlags::kHasNoEffect), - _id(secionId), + _id(sectionId), _nextSection(nullptr) {} //! \} diff --git a/deps/asmjit/src/asmjit/core/builder_p.h b/deps/asmjit/src/asmjit/core/builder_p.h index 303358fc..98790fdf 100644 --- a/deps/asmjit/src/asmjit/core/builder_p.h +++ b/deps/asmjit/src/asmjit/core/builder_p.h @@ -13,6 +13,7 @@ ASMJIT_BEGIN_NAMESPACE +//! \cond INTERNAL //! \addtogroup asmjit_builder //! \{ @@ -28,6 +29,7 @@ static inline void BaseBuilder_assignInstState(BaseBuilder* self, InstNode* node } //! \} +//! \endcond ASMJIT_END_NAMESPACE diff --git a/deps/asmjit/src/asmjit/core/codeholder.cpp b/deps/asmjit/src/asmjit/core/codeholder.cpp index 6c2b7629..63b15a3a 100644 --- a/deps/asmjit/src/asmjit/core/codeholder.cpp +++ b/deps/asmjit/src/asmjit/core/codeholder.cpp @@ -132,8 +132,8 @@ CodeHolder::~CodeHolder() noexcept { CodeHolder_resetInternal(this, ResetPolicy::kHard); } -// CodeHolder - Init & Reset -// ========================= +// CodeHolder - Initialization & Reset +// =================================== inline void CodeHolder_setSectionDefaultName( Section* section, @@ -908,7 +908,7 @@ size_t CodeHolder::codeSize() const noexcept { } } - if ((sizeof(uint64_t) > sizeof(size_t) && offset > SIZE_MAX) || of) + if ((sizeof(uint64_t) > sizeof(size_t) && offset > uint64_t(SIZE_MAX)) || of) return SIZE_MAX; return size_t(offset); diff --git a/deps/asmjit/src/asmjit/core/codeholder.h b/deps/asmjit/src/asmjit/core/codeholder.h index da661bec..3f2d1d70 100644 --- a/deps/asmjit/src/asmjit/core/codeholder.h +++ b/deps/asmjit/src/asmjit/core/codeholder.h @@ -45,7 +45,7 @@ enum class ExpressionOpType : uint8_t { kSra = 5 }; -//! Value tyoe that can be used within an \ref Expression. +//! Value type that can be used within an \ref Expression. enum class ExpressionValueType : uint8_t { //! No value or invalid. kNone = 0, @@ -272,6 +272,9 @@ public: //! Offset format type, used by \ref OffsetFormat. enum class OffsetType : uint8_t { + // Common Offset Formats + // --------------------- + //! A value having `_immBitCount` bits and shifted by `_immBitShift`. //! //! This offset type is sufficient for many targets that store offset as a continuous set bits within an @@ -284,14 +287,82 @@ enum class OffsetType : uint8_t { // AArch64 Specific Offset Formats // ------------------------------- - //! AARCH64 ADR format of `[.|immlo:2|.....|immhi:19|.....]`. + //! AArch64 ADR format of `[.|immlo:2|.....|immhi:19|.....]`. kAArch64_ADR, - //! AARCH64 ADRP format of `[.|immlo:2|.....|immhi:19|.....]` (4kB pages). + //! AArch64 ADRP format of `[.|immlo:2|.....|immhi:19|.....]` (4kB pages). kAArch64_ADRP, + // AArch32 Specific Offset Formats (T16 & T32) + // ------------------------------------------- + + //! AArch32 THUMBv2 immediate encoding of 'ADR' instruction (12-bit payload and sign bit): + //! + //! `|.....|imm:1|..N.N|......|imm:3|....|imm:8|` + //! + //! Where `N` is one if the offset is negative. The immediate is encoded as absolute value of the offset if negative. + kThumb32_ADR, + + //! AArch32 THUMBv2 immediate encoding of 'BLX' instruction (23-bit immediate payload, multiplied by 4): + //! + //! `|.....|imm[22]|imm[19:10]|..|ja|1|jb|imm[9:0]|0` + //! + //! Where: + //! + //! - `ja` is calculated as imm[22] ^ imm[21] ^ 1. + //! - `jb` is calculated as imm[22] ^ imm[20] ^ 1. + kThumb32_BLX, + + //! AArch32 THUMBv2 immediate encoding of 'B' instruction without `` (24-bit immediate payload, multiplied by 2): + //! + //! `|.....|imm[23]|imm[20:11]|..|ja|1|jb|imm[10:0]` + //! + //! Where: + //! + //! - `ja` is calculated as imm[23] ^ imm[22] ^ 1. + //! - `jb` is calculated as imm[23] ^ imm[21] ^ 1. + kThumb32_B, + + //! AArch32 THUMBv2 immediate encoding of 'B' instruction with `` (20-bit immediate payload, multiplied by 2). + //! + //! `|.....|imm[19]|....|imm[16:11]|..|ja|1|jb|imm[10:0]` + //! + //! Where: + //! + //! - `ja` is calculated as imm[19] ^ imm[18] ^ 1. + //! - `jb` is calculated as imm[19] ^ imm[17] ^ 1. + kThumb32_BCond, + + // AArch32 Specific Offset Formats (A32) + // ------------------------------------- + + //! AArch32 ADR instruction, which uses a standard 12-bit immediate encoding that is used by other ARM instructions. + kAArch32_ADR, + + //! AArch32 signed offset that is similar to `kSignedOffset`, however it uses absolute value of the offset and its + //! sign is encoded in 23rd bit of the opcode. + //! + //! `|........|U.......|........|........|` + //! + kAArch32_U23_SignedOffset, + + //! AArch32 offset format that encodes 8-bit offset as: + //! + //! `|........|U.......|....|imm[7:4]|....|imm[3:0]|` + //! + //! in a 32-bit word, where U is a sign of the displacement and the displacement itself is encoded as its absolute + //! value. + kAArch32_U23_0To3At0_4To7At8, + + //! AArch32 offset format that encodes a signed 25-bit offset as: + //! + //! `|.......|imm[0]|imm[24:1]|` + //! + //! in a 32-bit word. + kAArch32_1To24At0_0At24, + //! Maximum value of `OffsetFormatType`. - kMaxValue = kAArch64_ADRP + kMaxValue = kAArch32_1To24At0_0At24 }; //! Provides information about formatting offsets, absolute addresses, or their parts. Offset format is used by both @@ -350,15 +421,24 @@ struct OffsetFormat { //! Returns the type of the offset. ASMJIT_INLINE_NODEBUG OffsetType type() const noexcept { return _type; } + //! Returns whether the offset is encoded as an absolute value of the offset with additional field(s) that represent + //! the sign (AArch32 U/N fields in the opcode). + //! + //! If true, the offset itself is always positive and a separate U/N field is used to indicate the sign of the offset + //! (usually `U==1` means ADD, but sometimes `N==1` means negative offset, which implies SUB). + ASMJIT_INLINE_NODEBUG bool hasSignBit() const noexcept { + return _type == OffsetType::kThumb32_ADR || + _type == OffsetType::kAArch32_ADR || + _type == OffsetType::kAArch32_U23_SignedOffset || + _type == OffsetType::kAArch32_U23_0To3At0_4To7At8; + } + //! Returns flags. ASMJIT_INLINE_NODEBUG uint32_t flags() const noexcept { return _flags; } - //! Returns the size of the region/instruction where the offset is encoded. ASMJIT_INLINE_NODEBUG uint32_t regionSize() const noexcept { return _regionSize; } - //! Returns the offset of the word relative to the start of the region where the offset is. ASMJIT_INLINE_NODEBUG uint32_t valueOffset() const noexcept { return _valueOffset; } - //! Returns the size of the data-type (word) that contains the offset, in bytes. ASMJIT_INLINE_NODEBUG uint32_t valueSize() const noexcept { return _valueSize; } //! Returns the count of bits of the offset value in the data it's stored in. @@ -850,7 +930,7 @@ public: //! use the same slot. //! //! This function should be considered internal as it's used by assemblers to insert an absolute address into the - //! address table. Inserting address into address table without creating a particula relocation entry makes no sense. + //! address table. Inserting address into address table without creating a particular relocation entry makes no sense. ASMJIT_API Error addAddressToAddressTable(uint64_t address) noexcept; //! \} @@ -1018,7 +1098,8 @@ public: //! Relocates the code to the given `baseAddress`. //! //! \param baseAddress Absolute base address where the code will be relocated to. Please note that nothing is - //! copied to such base address, it's just an absolute value used by the relocator to resolve all stored relocations. + //! copied to such base address, it's just an absolute value used by the relocation code to resolve all stored + //! relocations. //! //! \note This should never be called more than once. ASMJIT_API Error relocateToBase(uint64_t baseAddress) noexcept; diff --git a/deps/asmjit/src/asmjit/core/codewriter.cpp b/deps/asmjit/src/asmjit/core/codewriter.cpp index 1babc5f1..2ee5b38c 100644 --- a/deps/asmjit/src/asmjit/core/codewriter.cpp +++ b/deps/asmjit/src/asmjit/core/codewriter.cpp @@ -6,6 +6,7 @@ #include "../core/api-build_p.h" #include "../core/codeholder.h" #include "../core/codewriter_p.h" +#include "../arm/armutils.h" ASMJIT_BEGIN_NAMESPACE @@ -19,9 +20,20 @@ bool CodeWriterUtils::encodeOffset32(uint32_t* dst, int64_t offset64, const Offs return false; uint32_t value; + uint32_t u = 0; + bool unsignedLogic = format.type() == OffsetType::kUnsignedOffset; + + // First handle all offsets that use additional field for their sign and the offset is encoded as its + // absolute value. + if (format.hasSignBit()) { + u = uint32_t(offset64 >= 0); + if (u == 0) + offset64 = -offset64; + unsignedLogic = true; + } // First handle all unsigned offset types. - if (format.type() == OffsetType::kUnsignedOffset) { + if (unsignedLogic) { if (discardLsb) { ASMJIT_ASSERT(discardLsb <= 32); if ((offset64 & Support::lsbMask(discardLsb)) != 0) @@ -57,6 +69,97 @@ bool CodeWriterUtils::encodeOffset32(uint32_t* dst, int64_t offset64, const Offs return true; } + // Opcode: {.....|imm:1|..N.N|......|imm:3|....|imm:8} + case OffsetType::kThumb32_ADR: { + // Sanity checks. + if (format.valueSize() != 4 || bitCount != 12 || bitShift != 0) + return false; + + uint32_t imm8 = (value & 0x00FFu); + uint32_t imm3 = (value & 0x0700u) << (12 - 8); + uint32_t imm1 = (value & 0x0800u) << (26 - 11); + uint32_t n = u ^ 1u; + + *dst = imm8 | imm3 | imm1 | (n << 21) | (n << 23); + return true; + } + + // Opcode: {....|.|imm[22]|imm[19:10]|..|ja|.|jb|imm[9:0]|.} + case OffsetType::kThumb32_BLX: + // The calculation is the same as `B`, but the first LSB bit must be zero, so account for that. + value <<= 1; + ASMJIT_FALLTHROUGH; + + // Opcode: {....|.|imm[23]|imm[20:11]|..|ja|.|jb|imm[10:0]} + case OffsetType::kThumb32_B: { + // Sanity checks. + if (format.valueSize() != 4) + return false; + + uint32_t ia = (value & 0x0007FFu); + uint32_t ib = (value & 0x1FF800u) << (16 - 11); + uint32_t ic = (value & 0x800000u) << (26 - 23); + uint32_t ja = ((~value >> 23) ^ (value >> 22)) & 1u; + uint32_t jb = ((~value >> 23) ^ (value >> 21)) & 1u; + + *dst = ia | ib | ic | (ja << 14) | (jb << 11); + return true; + } + + // Opcode: {....|.|imm[19]|....|imm[16:11]|..|ja|.|jb|imm[10:0]} + case OffsetType::kThumb32_BCond: { + // Sanity checks. + if (format.valueSize() != 4 || bitCount != 20 || bitShift != 0) + return false; + + uint32_t ia = (value & 0x0007FFu); + uint32_t ib = (value & 0x01F800u) << (16 - 11); + uint32_t ic = (value & 0x080000u) << (26 - 19); + uint32_t ja = ((~value >> 19) ^ (value >> 22)) & 1u; + uint32_t jb = ((~value >> 19) ^ (value >> 21)) & 1u; + + *dst = ia | ib | ic | (ja << 14) | (jb << 11); + return true; + } + + case OffsetType::kAArch32_ADR: { + uint32_t encodedImm; + if (!arm::Utils::encodeAArch32Imm(value, &encodedImm)) + return false; + + *dst = (Support::bitMask(22) << u) | (encodedImm << bitShift); + return true; + } + + case OffsetType::kAArch32_U23_SignedOffset: { + *dst = (value << bitShift) | (u << 23); + return true; + } + + case OffsetType::kAArch32_U23_0To3At0_4To7At8: { + // Sanity checks. + if (format.valueSize() != 4 || bitCount != 8 || bitShift != 0) + return false; + + uint32_t immLo = (value & 0x0Fu); + uint32_t immHi = (value & 0xF0u) << (8 - 4); + + *dst = immLo | immHi | (u << 23); + return true; + } + + case OffsetType::kAArch32_1To24At0_0At24: { + // Sanity checks. + if (format.valueSize() != 4 || bitCount != 25 || bitShift != 0) + return false; + + uint32_t immLo = (value & 0x0000001u) << 24; + uint32_t immHi = (value & 0x1FFFFFEu) >> 1; + + *dst = immLo | immHi; + return true; + } + case OffsetType::kAArch64_ADR: case OffsetType::kAArch64_ADRP: { // Sanity checks. diff --git a/deps/asmjit/src/asmjit/core/compiler.h b/deps/asmjit/src/asmjit/core/compiler.h index 5897a1b2..7d4b47c4 100644 --- a/deps/asmjit/src/asmjit/core/compiler.h +++ b/deps/asmjit/src/asmjit/core/compiler.h @@ -47,6 +47,7 @@ class InvokeNode; //! Check out architecture specific compilers for more details and examples: //! //! - \ref x86::Compiler - X86/X64 compiler implementation. +//! - \ref a64::Compiler - AArch64 compiler implementation. class ASMJIT_VIRTAPI BaseCompiler : public BaseBuilder { public: ASMJIT_NONCOPYABLE(BaseCompiler) @@ -162,6 +163,8 @@ public: //! //! \note This version accepts a snprintf() format `fmt` followed by a variadic arguments. ASMJIT_API Error _newRegFmt(BaseReg* ASMJIT_NONNULL(out), TypeId typeId, const char* fmt, ...); + //! \overload + inline Error _newRegFmt(BaseReg* ASMJIT_NONNULL(out), TypeId typeId) { return _newRegFmt(out, typeId, nullptr); } //! Creates a new virtual register compatible with the provided reference register `ref`. ASMJIT_API Error _newReg(BaseReg* ASMJIT_NONNULL(out), const BaseReg& ref, const char* name = nullptr); @@ -325,7 +328,7 @@ public: //! \note This node should be only used to represent jump where the jump target cannot be deduced by examining //! instruction operands. For example if the jump target is register or memory location. This pattern is often //! used to perform indirect jumps that use jump table, e.g. to implement `switch{}` statement. -class JumpNode : public InstNode { +class JumpNode : public InstNodeWithOperands { public: ASMJIT_NONCOPYABLE(JumpNode) @@ -340,7 +343,7 @@ public: //! \{ inline JumpNode(BaseCompiler* ASMJIT_NONNULL(cc), InstId instId, InstOptions options, uint32_t opCount, JumpAnnotation* annotation) noexcept - : InstNode(cc, instId, options, opCount, kBaseOpCapacity), + : InstNodeWithOperands(cc, instId, options, opCount), _annotation(annotation) { setType(NodeType::kJump); } @@ -531,7 +534,7 @@ public: }; //! Function return, used by \ref BaseCompiler. -class FuncRetNode : public InstNode { +class FuncRetNode : public InstNodeWithOperands { public: ASMJIT_NONCOPYABLE(FuncRetNode) @@ -539,7 +542,8 @@ public: //! \{ //! Creates a new `FuncRetNode` instance. - inline FuncRetNode(BaseBuilder* ASMJIT_NONNULL(cb)) noexcept : InstNode(cb, BaseInst::kIdAbstract, InstOptions::kNone, 0) { + inline FuncRetNode(BaseBuilder* ASMJIT_NONNULL(cb)) noexcept + : InstNodeWithOperands(cb, BaseInst::kIdAbstract, InstOptions::kNone, 0) { _any._nodeType = NodeType::kFuncRet; } @@ -547,12 +551,12 @@ public: }; //! Function invocation, used by \ref BaseCompiler. -class InvokeNode : public InstNode { +class InvokeNode : public InstNodeWithOperands { public: ASMJIT_NONCOPYABLE(InvokeNode) //! Operand pack provides multiple operands that can be associated with a single return value of function - //! argument. Sometims this is necessary to express an argument or return value that requires multiple + //! argument. Sometimes this is necessary to express an argument or return value that requires multiple //! registers, for example 64-bit value in 32-bit mode or passing / returning homogeneous data structures. struct OperandPack { //! Operands. @@ -594,7 +598,7 @@ public: //! Creates a new `InvokeNode` instance. inline InvokeNode(BaseBuilder* ASMJIT_NONNULL(cb), InstId instId, InstOptions options) noexcept - : InstNode(cb, instId, options, kBaseOpCapacity), + : InstNodeWithOperands(cb, instId, options, 0), _funcDetail(), _args(nullptr) { setType(NodeType::kInvoke); @@ -619,9 +623,9 @@ public: ASMJIT_INLINE_NODEBUG const FuncDetail& detail() const noexcept { return _funcDetail; } //! Returns the target operand. - ASMJIT_INLINE_NODEBUG Operand& target() noexcept { return _opArray[0].as(); } + ASMJIT_INLINE_NODEBUG Operand& target() noexcept { return op(0); } //! \overload - ASMJIT_INLINE_NODEBUG const Operand& target() const noexcept { return _opArray[0].as(); } + ASMJIT_INLINE_NODEBUG const Operand& target() const noexcept { return op(0); } //! Returns the number of function return values. ASMJIT_INLINE_NODEBUG bool hasRet() const noexcept { return _funcDetail.hasRet(); } diff --git a/deps/asmjit/src/asmjit/core/constpool.h b/deps/asmjit/src/asmjit/core/constpool.h index 067c73d2..673c11d6 100644 --- a/deps/asmjit/src/asmjit/core/constpool.h +++ b/deps/asmjit/src/asmjit/core/constpool.h @@ -27,6 +27,9 @@ enum class ConstPoolScope : uint32_t { }; //! Constant pool. +//! +//! Constant pool is designed to hold 1, 2, 4, 8, 16, 32, and 64 byte constants. It's not designed to hold constants +//! having arbitrary length like strings and arrays. class ConstPool { public: ASMJIT_NONCOPYABLE(ConstPool) @@ -199,9 +202,17 @@ public: //! \name Construction & Destruction //! \{ - ASMJIT_API ConstPool(Zone* zone) noexcept; + //! Creates a new constant pool that would use `zone` as a memory allocator. + ASMJIT_API explicit ConstPool(Zone* zone) noexcept; + //! Destroys this constant pool. ASMJIT_API ~ConstPool() noexcept; + //! \} + + //! \name Reset + //! \{ + + //! Resets this constant pool and its allocator to `zone`. ASMJIT_API void reset(Zone* zone) noexcept; //! \} diff --git a/deps/asmjit/src/asmjit/core/cpuinfo.cpp b/deps/asmjit/src/asmjit/core/cpuinfo.cpp index fd831e17..c6d35459 100644 --- a/deps/asmjit/src/asmjit/core/cpuinfo.cpp +++ b/deps/asmjit/src/asmjit/core/cpuinfo.cpp @@ -7,6 +7,8 @@ #include "../core/cpuinfo.h" #include "../core/support.h" +#include + // Required by `__cpuidex()` and `_xgetbv()`. #if ASMJIT_ARCH_X86 #if defined(_MSC_VER) @@ -14,12 +16,15 @@ #endif #endif // ASMJIT_ARCH_X86 +#if !defined(_WIN32) + #include +#endif + #if ASMJIT_ARCH_ARM // Required by various utilities that are required by features detection. #if !defined(_WIN32) #include #include - #include #endif //! Required to detect CPU and features on Apple platforms. @@ -566,6 +571,7 @@ static ASMJIT_FAVOR_SIZE void detectX86Cpu(CpuInfo& cpu) noexcept { // Other resources: // https://en.wikipedia.org/wiki/AArch64 // https://en.wikipedia.org/wiki/Apple_silicon#List_of_Apple_processors +// https://developer.arm.com/downloads/-/exploration-tools/feature-names-for-a-profile // https://developer.arm.com/architectures/learn-the-architecture/understanding-the-armv8-x-extensions/single-page #if ASMJIT_ARCH_ARM @@ -659,8 +665,8 @@ static inline void populateBaseARMFeatures(CpuInfo& cpu) noexcept { #endif } -// CpuInfo - Detect - ARM - Madatory Features of ARM Architectures -// =============================================================== +// CpuInfo - Detect - ARM - Mandatory Features of ARM Architectures +// ================================================================ // Populates mandatory ARMv8.[v]A features. ASMJIT_MAYBE_UNUSED @@ -678,22 +684,21 @@ static ASMJIT_FAVOR_SIZE void populateARMv8AFeatures(CpuFeatures::ARM& features, features.add(Ext::kHCX, Ext::kPAN3, Ext::kWFXT, Ext::kXS); ASMJIT_FALLTHROUGH; case 6: // ARMv8.6 - // Missing: AMUv1p1. - features.add(Ext::kBF16, Ext::kECV, Ext::kFGT, Ext::kI8MM); + features.add(Ext::kAMU1_1, Ext::kBF16, Ext::kECV, Ext::kFGT, Ext::kI8MM); ASMJIT_FALLTHROUGH; case 5: // ARMv8.5 - // Missing: CSV2_2. - features.add(Ext::kBTI, Ext::kDPB2, Ext::kFLAGM2, Ext::kFRINTTS, Ext::kSB, Ext::kSPECRES, Ext::kSSBS); + features.add(Ext::kBTI, Ext::kCSV2, Ext::kDPB2, Ext::kFLAGM2, Ext::kFRINTTS, Ext::kSB, Ext::kSPECRES, Ext::kSSBS); ASMJIT_FALLTHROUGH; case 4: // ARMv8.4 - // Missing: AMUv1, SEL2, TLBIOS, TLBIRANGE. - features.add(Ext::kDIT, Ext::kDOTPROD, Ext::kFLAGM, Ext::kLRCPC2, Ext::kLSE2, Ext::kMPAM, Ext::kNV, Ext::kTRF); + features.add(Ext::kAMU1, Ext::kDIT, Ext::kDOTPROD, Ext::kFLAGM, + Ext::kLRCPC2, Ext::kLSE2, Ext::kMPAM, Ext::kNV, + Ext::kSEL2, Ext::kTLBIOS, Ext::kTLBIRANGE, Ext::kTRF); ASMJIT_FALLTHROUGH; case 3: // ARMv8.3 features.add(Ext::kCCIDX, Ext::kFCMA, Ext::kJSCVT, Ext::kLRCPC, Ext::kPAUTH); ASMJIT_FALLTHROUGH; case 2: // ARMv8.2 - features.add(Ext::kCRC32, Ext::kDPB, Ext::kPAN2, Ext::kRAS, Ext::kUAO); + features.add(Ext::kDPB, Ext::kPAN2, Ext::kRAS, Ext::kUAO); ASMJIT_FALLTHROUGH; case 1: // ARMv8.1 features.add(Ext::kCRC32, Ext::kLOR, Ext::kLSE, Ext::kPAN, Ext::kRDM, Ext::kVHE); @@ -752,9 +757,25 @@ static ASMJIT_FORCE_INLINE void mergeAArch64CPUIDFeatureNA(CpuFeatures::ARM& fea if (f3 != Ext::kNone) features.addIf(val >= 3, f3); } -// Merges a feature that contains 0b0000 when it doesn't exist and starts at 0b0001 when it does. +// Merges a feature identified by a single bit at `offset`. ASMJIT_MAYBE_UNUSED -static ASMJIT_FORCE_INLINE void mergeAArch64CPUIDFeatureExt(CpuFeatures::ARM& features, uint64_t regBits, uint32_t offset, +static ASMJIT_FORCE_INLINE void mergeAArch64CPUIDFeature1B(CpuFeatures::ARM& features, uint64_t regBits, uint32_t offset, Ext::Id f1) noexcept { + features.addIf((regBits & (uint64_t(1) << offset)) != 0, f1); +} + +// Merges a feature-list starting from 0b01 when it does (0b00 means feature not supported). +ASMJIT_MAYBE_UNUSED +static ASMJIT_FORCE_INLINE void mergeAArch64CPUIDFeature2B(CpuFeatures::ARM& features, uint64_t regBits, uint32_t offset, Ext::Id f1, Ext::Id f2, Ext::Id f3) noexcept { + uint32_t val = uint32_t((regBits >> offset) & 0x3u); + + if (f1 != Ext::kNone) features.addIf(val >= 1, f1); + if (f2 != Ext::kNone) features.addIf(val >= 2, f2); + if (f3 != Ext::kNone) features.addIf(val == 3, f3); +} + +// Merges a feature-list starting from 0b0001 when it does (0b0000 means feature not supported). +ASMJIT_MAYBE_UNUSED +static ASMJIT_FORCE_INLINE void mergeAArch64CPUIDFeature4B(CpuFeatures::ARM& features, uint64_t regBits, uint32_t offset, Ext::Id f1, Ext::Id f2 = Ext::kNone, Ext::Id f3 = Ext::kNone, @@ -770,65 +791,70 @@ static ASMJIT_FORCE_INLINE void mergeAArch64CPUIDFeatureExt(CpuFeatures::ARM& fe if (f4 != Ext::kNone) features.addIf(val >= 4, f4); } -#define MERGE_FEATURE_N_A(identifier, reg, offset, ...) mergeAArch64CPUIDFeatureNA(cpu.features().arm(), reg, offset, __VA_ARGS__) -#define MERGE_FEATURE_EXT(identifier, reg, offset, ...) mergeAArch64CPUIDFeatureExt(cpu.features().arm(), reg, offset, __VA_ARGS__) +// Merges a feature that is identified by an exact bit-combination of 4 bits. +ASMJIT_MAYBE_UNUSED +static ASMJIT_FORCE_INLINE void mergeAArch64CPUIDFeature4S(CpuFeatures::ARM& features, uint64_t regBits, uint32_t offset, uint32_t value, Ext::Id f1) noexcept { + features.addIf(uint32_t((regBits >> offset) & 0xFu) == value, f1); +} + +#define MERGE_FEATURE_NA(identifier, reg, offset, ...) mergeAArch64CPUIDFeatureNA(cpu.features().arm(), reg, offset, __VA_ARGS__) +#define MERGE_FEATURE_1B(identifier, reg, offset, ...) mergeAArch64CPUIDFeature1B(cpu.features().arm(), reg, offset, __VA_ARGS__) +#define MERGE_FEATURE_2B(identifier, reg, offset, ...) mergeAArch64CPUIDFeature2B(cpu.features().arm(), reg, offset, __VA_ARGS__) +#define MERGE_FEATURE_4B(identifier, reg, offset, ...) mergeAArch64CPUIDFeature4B(cpu.features().arm(), reg, offset, __VA_ARGS__) +#define MERGE_FEATURE_4S(identifier, reg, offset, ...) mergeAArch64CPUIDFeature4S(cpu.features().arm(), reg, offset, __VA_ARGS__) // Detects features based on the content of ID_AA64PFR0_EL1 and ID_AA64PFR1_EL1 registers. ASMJIT_MAYBE_UNUSED -static ASMJIT_FAVOR_SIZE void detectAArch64FeaturesViaCPUID_AA64PFR0_AA64PFR1(CpuInfo& cpu, uint64_t fpr0, uint64_t fpr1) noexcept { +static inline void detectAArch64FeaturesViaCPUID_AA64PFR0_AA64PFR1(CpuInfo& cpu, uint64_t fpr0, uint64_t fpr1) noexcept { // ID_AA64PFR0_EL1 // =============== // FP and AdvSIMD bits should match (i.e. if FP features FP16, ASIMD must feature it too). - MERGE_FEATURE_N_A("FP bits [19:16]" , fpr0, 16, Ext::kFP, Ext::kFP16); - MERGE_FEATURE_N_A("AdvSIMD bits [23:20]" , fpr0, 20, Ext::kASIMD, Ext::kFP16); + MERGE_FEATURE_NA("FP bits [19:16]" , fpr0, 16, Ext::kFP, Ext::kFP16); + MERGE_FEATURE_NA("AdvSIMD bits [23:20]" , fpr0, 20, Ext::kASIMD, Ext::kFP16); /* - MERGE_FEATURE_EXT("GIC bits [27:24]" , fpr0, 24, ...); - */ - MERGE_FEATURE_EXT("RAS bits [31:28]" , fpr0, 28, Ext::kRAS, Ext::kRAS1_1, Ext::kRAS2); - MERGE_FEATURE_EXT("SVE bits [35:32]" , fpr0, 32, Ext::kSVE); - /* - MERGE_FEATURE_EXT("SEL2 bits [39:36]" , fpr0, 36, ...); - MERGE_FEATURE_EXT("MPAM bits [43:40]" , fpr0, 40, ...); - MERGE_FEATURE_EXT("AMU bits [47:44]" , fpr0, 44, ...); - */ - MERGE_FEATURE_EXT("DIT bits [51:48]" , fpr0, 48, Ext::kDIT); - MERGE_FEATURE_EXT("RME bits [55:52]" , fpr0, 52, Ext::kRME); - /* - MERGE_FEATURE_EXT("CSV2 bits [59:56]" , fpr0, 56, ...); - MERGE_FEATURE_EXT("CSV3 bits [63:60]" , fpr0, 60, ...); + MERGE_FEATURE_4B("GIC bits [27:24]" , fpr0, 24, ...); */ + MERGE_FEATURE_4B("RAS bits [31:28]" , fpr0, 28, Ext::kRAS, Ext::kRAS1_1, Ext::kRAS2); + MERGE_FEATURE_4B("SVE bits [35:32]" , fpr0, 32, Ext::kSVE); + MERGE_FEATURE_4B("SEL2 bits [39:36]" , fpr0, 36, Ext::kSEL2); + MERGE_FEATURE_4B("MPAM bits [43:40]" , fpr0, 40, Ext::kMPAM); + MERGE_FEATURE_4B("AMU bits [47:44]" , fpr0, 44, Ext::kAMU1, Ext::kAMU1_1); + MERGE_FEATURE_4B("DIT bits [51:48]" , fpr0, 48, Ext::kDIT); + MERGE_FEATURE_4B("RME bits [55:52]" , fpr0, 52, Ext::kRME); + MERGE_FEATURE_4B("CSV2 bits [59:56]" , fpr0, 56, Ext::kCSV2, Ext::kCSV2, Ext::kCSV2, Ext::kCSV2_3); + MERGE_FEATURE_4B("CSV3 bits [63:60]" , fpr0, 60, Ext::kCSV3); // ID_AA64PFR1_EL1 // =============== - MERGE_FEATURE_EXT("BT bits [3:0]" , fpr1, 0, Ext::kBTI); - MERGE_FEATURE_EXT("SSBS bits [7:4]" , fpr1, 4, Ext::kSSBS, Ext::kSSBS2); - MERGE_FEATURE_EXT("MTE bits [11:8]" , fpr1, 8, Ext::kMTE, Ext::kMTE2, Ext::kMTE3); + MERGE_FEATURE_4B("BT bits [3:0]" , fpr1, 0, Ext::kBTI); + MERGE_FEATURE_4B("SSBS bits [7:4]" , fpr1, 4, Ext::kSSBS, Ext::kSSBS2); + MERGE_FEATURE_4B("MTE bits [11:8]" , fpr1, 8, Ext::kMTE, Ext::kMTE2, Ext::kMTE3); /* - MERGE_FEATURE_EXT("RAS_frac bits [15:12]" , fpr1, 12, ...); - MERGE_FEATURE_EXT("MPAM_frac bits [19:16]" , fpr1, 16, ...); + MERGE_FEATURE_4B("RAS_frac bits [15:12]" , fpr1, 12, ...); + MERGE_FEATURE_4B("MPAM_frac bits [19:16]" , fpr1, 16, ...); */ - MERGE_FEATURE_EXT("SME bits [27:24]" , fpr1, 24, Ext::kSME, Ext::kSME2); - MERGE_FEATURE_EXT("RNDR_trap bits [31:28]" , fpr1, 28, Ext::kRNG_TRAP); + MERGE_FEATURE_4B("SME bits [27:24]" , fpr1, 24, Ext::kSME, Ext::kSME2); + MERGE_FEATURE_4B("RNDR_trap bits [31:28]" , fpr1, 28, Ext::kRNG_TRAP); /* - MERGE_FEATURE_EXT("CSV2_frac bits [35:32]" , fpr1, 32, ...); + MERGE_FEATURE_4B("CSV2_frac bits [35:32]" , fpr1, 32, ...); */ - MERGE_FEATURE_EXT("NMI bits [39:36]" , fpr1, 36, Ext::kNMI); + MERGE_FEATURE_4B("NMI bits [39:36]" , fpr1, 36, Ext::kNMI); /* - MERGE_FEATURE_EXT("MTE_frac bits [43:40]" , fpr1, 40, ...); - MERGE_FEATURE_EXT("GCS bits [47:44]" , fpr1, 44, ...); + MERGE_FEATURE_4B("MTE_frac bits [43:40]" , fpr1, 40, ...); */ - MERGE_FEATURE_EXT("THE bits [51:48]" , fpr1, 48, Ext::kTHE); + MERGE_FEATURE_4B("GCS bits [47:44]" , fpr1, 44, Ext::kGCS); + MERGE_FEATURE_4B("THE bits [51:48]" , fpr1, 48, Ext::kTHE); // MTEX extensions are only available when MTE3 is available. if (cpu.features().arm().hasMTE3()) - MERGE_FEATURE_EXT("MTEX bits [55:52]" , fpr1, 52, Ext::kMTE4); + MERGE_FEATURE_4B("MTEX bits [55:52]" , fpr1, 52, Ext::kMTE4); /* - MERGE_FEATURE_EXT("DF2 bits [59:56]" , fpr1, 56, ...); - MERGE_FEATURE_EXT("PFAR bits [63:60]" , fpr1, 60, ...); + MERGE_FEATURE_4B("DF2 bits [59:56]" , fpr1, 56, ...); */ + MERGE_FEATURE_4B("PFAR bits [63:60]" , fpr1, 60, Ext::kPFAR); // ID_AA64PFR0_EL1 + ID_AA64PFR1_EL1 // ================================= @@ -849,176 +875,212 @@ static ASMJIT_FAVOR_SIZE void detectAArch64FeaturesViaCPUID_AA64PFR0_AA64PFR1(Cp // Detects features based on the content of ID_AA64ISAR0_EL1 and ID_AA64ISAR1_EL1 registers. ASMJIT_MAYBE_UNUSED -static ASMJIT_FAVOR_SIZE void detectAArch64FeaturesViaCPUID_AA64ISAR0_AA64ISAR1(CpuInfo& cpu, uint64_t isar0, uint64_t isar1) noexcept { +static inline void detectAArch64FeaturesViaCPUID_AA64ISAR0_AA64ISAR1(CpuInfo& cpu, uint64_t isar0, uint64_t isar1) noexcept { // ID_AA64ISAR0_EL1 // ================ - MERGE_FEATURE_EXT("AES bits [7:4]" , isar0, 4, Ext::kAES, Ext::kPMULL); - MERGE_FEATURE_EXT("SHA1 bits [11:8]" , isar0, 8, Ext::kSHA1); - MERGE_FEATURE_EXT("SHA2 bits [15:12]" , isar0, 12, Ext::kSHA256, Ext::kSHA512); - MERGE_FEATURE_EXT("CRC32 bits [19:16]" , isar0, 16, Ext::kCRC32); - MERGE_FEATURE_EXT("Atomic bits [23:20]" , isar0, 20, Ext::kNone, Ext::kLSE, Ext::kLSE128); - MERGE_FEATURE_EXT("TME bits [27:24]" , isar0, 24, Ext::kTME); - MERGE_FEATURE_EXT("RDM bits [31:28]" , isar0, 28, Ext::kRDM); - MERGE_FEATURE_EXT("SHA3 bits [35:32]" , isar0, 32, Ext::kSHA3); - MERGE_FEATURE_EXT("SM3 bits [39:36]" , isar0, 36, Ext::kSM3); - MERGE_FEATURE_EXT("SM4 bits [43:40]" , isar0, 40, Ext::kSM4); - MERGE_FEATURE_EXT("DP bits [47:44]" , isar0, 44, Ext::kDOTPROD); - MERGE_FEATURE_EXT("FHM bits [51:48]" , isar0, 48, Ext::kFHM); - MERGE_FEATURE_EXT("TS bits [55:52]" , isar0, 52, Ext::kFLAGM, Ext::kFLAGM2); + MERGE_FEATURE_4B("AES bits [7:4]" , isar0, 4, Ext::kAES, Ext::kPMULL); + MERGE_FEATURE_4B("SHA1 bits [11:8]" , isar0, 8, Ext::kSHA1); + MERGE_FEATURE_4B("SHA2 bits [15:12]" , isar0, 12, Ext::kSHA256, Ext::kSHA512); + MERGE_FEATURE_4B("CRC32 bits [19:16]" , isar0, 16, Ext::kCRC32); + MERGE_FEATURE_4B("Atomic bits [23:20]" , isar0, 20, Ext::kNone, Ext::kLSE, Ext::kLSE128); + MERGE_FEATURE_4B("TME bits [27:24]" , isar0, 24, Ext::kTME); + MERGE_FEATURE_4B("RDM bits [31:28]" , isar0, 28, Ext::kRDM); + MERGE_FEATURE_4B("SHA3 bits [35:32]" , isar0, 32, Ext::kSHA3); + MERGE_FEATURE_4B("SM3 bits [39:36]" , isar0, 36, Ext::kSM3); + MERGE_FEATURE_4B("SM4 bits [43:40]" , isar0, 40, Ext::kSM4); + MERGE_FEATURE_4B("DP bits [47:44]" , isar0, 44, Ext::kDOTPROD); + MERGE_FEATURE_4B("FHM bits [51:48]" , isar0, 48, Ext::kFHM); + MERGE_FEATURE_4B("TS bits [55:52]" , isar0, 52, Ext::kFLAGM, Ext::kFLAGM2); /* - MERGE_FEATURE_EXT("TLB bits [59:56]" , isar0, 56, ...); + MERGE_FEATURE_4B("TLB bits [59:56]" , isar0, 56, ...); */ - MERGE_FEATURE_EXT("RNDR bits [63:60]" , isar0, 60, Ext::kFLAGM, Ext::kRNG); + MERGE_FEATURE_4B("RNDR bits [63:60]" , isar0, 60, Ext::kFLAGM, Ext::kRNG); // ID_AA64ISAR1_EL1 // ================ - MERGE_FEATURE_EXT("DPB bits [3:0]" , isar1, 0, Ext::kDPB, Ext::kDPB2); + MERGE_FEATURE_4B("DPB bits [3:0]" , isar1, 0, Ext::kDPB, Ext::kDPB2); /* - MERGE_FEATURE_EXT("APA bits [7:4]" , isar1, 4, ...); - MERGE_FEATURE_EXT("API bits [11:8]" , isar1, 8, ...); + MERGE_FEATURE_4B("APA bits [7:4]" , isar1, 4, ...); + MERGE_FEATURE_4B("API bits [11:8]" , isar1, 8, ...); */ - MERGE_FEATURE_EXT("JSCVT bits [15:12]" , isar1, 12, Ext::kJSCVT); - MERGE_FEATURE_EXT("FCMA bits [19:16]" , isar1, 16, Ext::kFCMA); - MERGE_FEATURE_EXT("LRCPC bits [23:20]" , isar1, 20, Ext::kLRCPC, Ext::kLRCPC2, Ext::kLRCPC3); + MERGE_FEATURE_4B("JSCVT bits [15:12]" , isar1, 12, Ext::kJSCVT); + MERGE_FEATURE_4B("FCMA bits [19:16]" , isar1, 16, Ext::kFCMA); + MERGE_FEATURE_4B("LRCPC bits [23:20]" , isar1, 20, Ext::kLRCPC, Ext::kLRCPC2, Ext::kLRCPC3); /* - MERGE_FEATURE_EXT("GPA bits [27:24]" , isar1, 24, ...); - MERGE_FEATURE_EXT("GPI bits [31:28]" , isar1, 28, ...); + MERGE_FEATURE_4B("GPA bits [27:24]" , isar1, 24, ...); + MERGE_FEATURE_4B("GPI bits [31:28]" , isar1, 28, ...); */ - MERGE_FEATURE_EXT("FRINTTS bits [35:32]" , isar1, 32, Ext::kFRINTTS); - MERGE_FEATURE_EXT("SB bits [39:36]" , isar1, 36, Ext::kSB); - MERGE_FEATURE_EXT("SPECRES bits [43:40]" , isar1, 40, Ext::kSPECRES, Ext::kSPECRES2); - MERGE_FEATURE_EXT("BF16 bits [47:44]" , isar1, 44, Ext::kBF16, Ext::kEBF16); - MERGE_FEATURE_EXT("DGH bits [51:48]" , isar1, 48, Ext::kDGH); - MERGE_FEATURE_EXT("I8MM bits [55:52]" , isar1, 52, Ext::kI8MM); - MERGE_FEATURE_EXT("XS bits [59:56]" , isar1, 56, Ext::kXS); - MERGE_FEATURE_EXT("LS64 bits [63:60]" , isar1, 60, Ext::kLS64, Ext::kLS64_V, Ext::kLS64_ACCDATA); + MERGE_FEATURE_4B("FRINTTS bits [35:32]" , isar1, 32, Ext::kFRINTTS); + MERGE_FEATURE_4B("SB bits [39:36]" , isar1, 36, Ext::kSB); + MERGE_FEATURE_4B("SPECRES bits [43:40]" , isar1, 40, Ext::kSPECRES, Ext::kSPECRES2); + MERGE_FEATURE_4B("BF16 bits [47:44]" , isar1, 44, Ext::kBF16, Ext::kEBF16); + MERGE_FEATURE_4B("DGH bits [51:48]" , isar1, 48, Ext::kDGH); + MERGE_FEATURE_4B("I8MM bits [55:52]" , isar1, 52, Ext::kI8MM); + MERGE_FEATURE_4B("XS bits [59:56]" , isar1, 56, Ext::kXS); + MERGE_FEATURE_4B("LS64 bits [63:60]" , isar1, 60, Ext::kLS64, Ext::kLS64_V, Ext::kLS64_ACCDATA); } // Detects features based on the content of ID_AA64ISAR2_EL1 register. ASMJIT_MAYBE_UNUSED -static ASMJIT_FAVOR_SIZE void detectAArch64FeaturesViaCPUID_AA64ISAR2(CpuInfo& cpu, uint64_t isar2) noexcept { - MERGE_FEATURE_EXT("WFxT bits [3:0]" , isar2, 0, Ext::kNone, Ext::kWFXT); - MERGE_FEATURE_EXT("RPRES bits [7:4]" , isar2, 4, Ext::kRPRES); +static inline void detectAArch64FeaturesViaCPUID_AA64ISAR2(CpuInfo& cpu, uint64_t isar2) noexcept { + MERGE_FEATURE_4B("WFxT bits [3:0]" , isar2, 0, Ext::kNone, Ext::kWFXT); + MERGE_FEATURE_4B("RPRES bits [7:4]" , isar2, 4, Ext::kRPRES); /* - MERGE_FEATURE_EXT("GPA3 bits [11:8]" , isar2, 8, ...); - MERGE_FEATURE_EXT("APA3 bits [15:12]" , isar2, 12, ...); + MERGE_FEATURE_4B("GPA3 bits [11:8]" , isar2, 8, ...); + MERGE_FEATURE_4B("APA3 bits [15:12]" , isar2, 12, ...); */ - MERGE_FEATURE_EXT("MOPS bits [19:16]" , isar2, 16, Ext::kMOPS); - MERGE_FEATURE_EXT("BC bits [23:20]" , isar2, 20, Ext::kHBC); - /* - MERGE_FEATURE_EXT("PAC_frac bits [27:24]" , isar2, 24, ...); - */ - MERGE_FEATURE_EXT("CLRBHB bits [31:28]" , isar2, 28, Ext::kCLRBHB); - MERGE_FEATURE_EXT("SYSREG128 bits [35:32]" , isar2, 32, Ext::kSYSREG128); - MERGE_FEATURE_EXT("SYSINSTR128 bits [39:36]" , isar2, 36, Ext::kSYSINSTR128); - MERGE_FEATURE_EXT("PRFMSLC bits [43:40]" , isar2, 40, Ext::kPRFMSLC); - MERGE_FEATURE_EXT("RPRFM bits [51:48]" , isar2, 48, Ext::kRPRFM); - MERGE_FEATURE_EXT("CSSC bits [55:52]" , isar2, 52, Ext::kCSSC); + MERGE_FEATURE_4B("MOPS bits [19:16]" , isar2, 16, Ext::kMOPS); + MERGE_FEATURE_4B("BC bits [23:20]" , isar2, 20, Ext::kHBC); + MERGE_FEATURE_4B("PAC_frac bits [27:24]" , isar2, 24, Ext::kCONSTPACFIELD); + MERGE_FEATURE_4B("CLRBHB bits [31:28]" , isar2, 28, Ext::kCLRBHB); + MERGE_FEATURE_4B("SYSREG128 bits [35:32]" , isar2, 32, Ext::kSYSREG128); + MERGE_FEATURE_4B("SYSINSTR128 bits [39:36]" , isar2, 36, Ext::kSYSINSTR128); + MERGE_FEATURE_4B("PRFMSLC bits [43:40]" , isar2, 40, Ext::kPRFMSLC); + MERGE_FEATURE_4B("RPRFM bits [51:48]" , isar2, 48, Ext::kRPRFM); + MERGE_FEATURE_4B("CSSC bits [55:52]" , isar2, 52, Ext::kCSSC); + MERGE_FEATURE_4B("LUT bits [59:56]" , isar2, 56, Ext::kLUT); } +// TODO: This register is not accessed at the moment. +#if 0 +// Detects features based on the content of ID_AA64ISAR3_EL1register. ASMJIT_MAYBE_UNUSED -static ASMJIT_FAVOR_SIZE void detectAArch64FeaturesViaCPUID_AA64MMFR0(CpuInfo& cpu, uint64_t mmfr0) noexcept { +static inline void detectAArch64FeaturesViaCPUID_AA64ISAR3(CpuInfo& cpu, uint64_t isar3) noexcept { + // ID_AA64ISAR3_EL1 + // ================ + + MERGE_FEATURE_4B("CPA bits [3:0]" , isar3, 0, Ext::kCPA, Ext::kCPA2); + MERGE_FEATURE_4B("FAMINMAX bits [7:4]" , isar3, 4, Ext::kFAMINMAX); + MERGE_FEATURE_4B("TLBIW bits [11:8]" , isar3, 8, Ext::kTLBIW); +} +#endif + +ASMJIT_MAYBE_UNUSED +static inline void detectAArch64FeaturesViaCPUID_AA64MMFR0(CpuInfo& cpu, uint64_t mmfr0) noexcept { // ID_AA64MMFR0_EL1 // ================ /* - MERGE_FEATURE_EXT("PARange bits [3:0]" , mmfr0, 0, ...); - MERGE_FEATURE_EXT("ASIDBits bits [7:4]" , mmfr0, 4, ...); - MERGE_FEATURE_EXT("BigEnd bits [11:8]" , mmfr0, 8, ...); - MERGE_FEATURE_EXT("SNSMem bits [15:12]" , mmfr0, 12, ...); - MERGE_FEATURE_EXT("BigEndEL0 bits [19:16]" , mmfr0, 16, ...); - MERGE_FEATURE_EXT("TGran16 bits [23:20]" , mmfr0, 20, ...); - MERGE_FEATURE_EXT("TGran64 bits [27:24]" , mmfr0, 24, ...); - MERGE_FEATURE_EXT("TGran4 bits [31:28]" , mmfr0, 28, ...); - MERGE_FEATURE_EXT("TGran16_2 bits [35:32]" , mmfr0, 32, ...); - MERGE_FEATURE_EXT("TGran64_2 bits [39:36]" , mmfr0, 36, ...); - MERGE_FEATURE_EXT("TGran4_2 bits [43:40]" , mmfr0, 40, ...); - MERGE_FEATURE_EXT("ExS bits [47:44]" , mmfr0, 44, ...); + MERGE_FEATURE_4B("PARange bits [3:0]" , mmfr0, 0, ...); + MERGE_FEATURE_4B("ASIDBits bits [7:4]" , mmfr0, 4, ...); + MERGE_FEATURE_4B("BigEnd bits [11:8]" , mmfr0, 8, ...); + MERGE_FEATURE_4B("SNSMem bits [15:12]" , mmfr0, 12, ...); + MERGE_FEATURE_4B("BigEndEL0 bits [19:16]" , mmfr0, 16, ...); + MERGE_FEATURE_4B("TGran16 bits [23:20]" , mmfr0, 20, ...); + MERGE_FEATURE_4B("TGran64 bits [27:24]" , mmfr0, 24, ...); + MERGE_FEATURE_4B("TGran4 bits [31:28]" , mmfr0, 28, ...); + MERGE_FEATURE_4B("TGran16_2 bits [35:32]" , mmfr0, 32, ...); + MERGE_FEATURE_4B("TGran64_2 bits [39:36]" , mmfr0, 36, ...); + MERGE_FEATURE_4B("TGran4_2 bits [43:40]" , mmfr0, 40, ...); + MERGE_FEATURE_4B("ExS bits [47:44]" , mmfr0, 44, ...); */ - MERGE_FEATURE_EXT("FGT bits [59:56]" , mmfr0, 56, Ext::kFGT, Ext::kFGT2); - MERGE_FEATURE_EXT("ECV bits [63:60]" , mmfr0, 60, Ext::kECV); + MERGE_FEATURE_4B("FGT bits [59:56]" , mmfr0, 56, Ext::kFGT, Ext::kFGT2); + MERGE_FEATURE_4B("ECV bits [63:60]" , mmfr0, 60, Ext::kECV); } ASMJIT_MAYBE_UNUSED -static ASMJIT_FAVOR_SIZE void detectAArch64FeaturesViaCPUID_AA64MMFR1(CpuInfo& cpu, uint64_t mmfr1) noexcept { +static inline void detectAArch64FeaturesViaCPUID_AA64MMFR1(CpuInfo& cpu, uint64_t mmfr1) noexcept { // ID_AA64MMFR1_EL1 // ================ + MERGE_FEATURE_4B("HAFDBS bits [3:0]" , mmfr1, 0, Ext::kHAFDBS, Ext::kNone, Ext::kHAFT, Ext::kHDBSS); + MERGE_FEATURE_4B("VMIDBits bits [7:4]" , mmfr1, 4, Ext::kVMID16); + MERGE_FEATURE_4B("VH bits [11:8]" , mmfr1, 8, Ext::kVHE); + MERGE_FEATURE_4B("HPDS bits [15:12]" , mmfr1, 12, Ext::kHPDS, Ext::kHPDS2); + MERGE_FEATURE_4B("LO bits [19:16]" , mmfr1, 16, Ext::kLOR); + MERGE_FEATURE_4B("PAN bits [23:20]" , mmfr1, 20, Ext::kPAN, Ext::kPAN2, Ext::kPAN3); /* - MERGE_FEATURE_EXT("HAFDBS bits [3:0]" , mmfr1, 0, ...); - MERGE_FEATURE_EXT("VMIDBits bits [7:4]" , mmfr1, 4, ...); + MERGE_FEATURE_4B("SpecSEI bits [27:24]" , mmfr1, 24, ...); */ - MERGE_FEATURE_EXT("VH bits [11:8]" , mmfr1, 8, Ext::kVHE); + MERGE_FEATURE_4B("XNX bits [31:28]" , mmfr1, 28, Ext::kXNX); /* - MERGE_FEATURE_EXT("HPDS bits [15:12]" , mmfr1, 12, ...); + MERGE_FEATURE_4B("TWED bits [35:32]" , mmfr1, 32, ...); + MERGE_FEATURE_4B("ETS bits [39:36]" , mmfr1, 36, ...); */ - MERGE_FEATURE_EXT("LO bits [19:16]" , mmfr1, 16, Ext::kLOR); - MERGE_FEATURE_EXT("PAN bits [23:20]" , mmfr1, 20, Ext::kPAN, Ext::kPAN2, Ext::kPAN3); + MERGE_FEATURE_4B("HCX bits [43:40]" , mmfr1, 40, Ext::kHCX); + MERGE_FEATURE_4B("AFP bits [47:44]" , mmfr1, 44, Ext::kAFP); /* - MERGE_FEATURE_EXT("SpecSEI bits [27:24]" , mmfr1, 24, ...); - MERGE_FEATURE_EXT("XNX bits [31:28]" , mmfr1, 28, ...); - MERGE_FEATURE_EXT("TWED bits [35:32]" , mmfr1, 32, ...); - MERGE_FEATURE_EXT("ETS bits [39:36]" , mmfr1, 36, ...); - */ - MERGE_FEATURE_EXT("HCX bits [43:40]" , mmfr1, 40, Ext::kHCX); - MERGE_FEATURE_EXT("AFP bits [47:44]" , mmfr1, 44, Ext::kAFP); - /* - MERGE_FEATURE_EXT("nTLBPA bits [51:48]" , mmfr1, 48, ...); - MERGE_FEATURE_EXT("TIDCP1 bits [55:52]" , mmfr1, 52, ...); - MERGE_FEATURE_EXT("CMOW bits [59:56]" , mmfr1, 56, ...); - MERGE_FEATURE_EXT("ECBHB bits [63:60]" , mmfr1, 60, ...); + MERGE_FEATURE_4B("nTLBPA bits [51:48]" , mmfr1, 48, ...); + MERGE_FEATURE_4B("TIDCP1 bits [55:52]" , mmfr1, 52, ...); */ + MERGE_FEATURE_4B("CMOW bits [59:56]" , mmfr1, 56, Ext::kCMOW); + MERGE_FEATURE_4B("ECBHB bits [63:60]" , mmfr1, 60, Ext::kECBHB); } ASMJIT_MAYBE_UNUSED -static ASMJIT_FAVOR_SIZE void detectAArch64FeaturesViaCPUID_AA64MMFR2(CpuInfo& cpu, uint64_t mmfr2) noexcept { +static inline void detectAArch64FeaturesViaCPUID_AA64MMFR2(CpuInfo& cpu, uint64_t mmfr2) noexcept { // ID_AA64MMFR2_EL1 // ================ /* - MERGE_FEATURE_EXT("CnP bits [3:0]" , mmfr2, 0, ...); + MERGE_FEATURE_4B("CnP bits [3:0]" , mmfr2, 0, ...); */ - MERGE_FEATURE_EXT("UAO bits [7:4]" , mmfr2, 4, Ext::kUAO); + MERGE_FEATURE_4B("UAO bits [7:4]" , mmfr2, 4, Ext::kUAO); /* - MERGE_FEATURE_EXT("LSM bits [11:8]" , mmfr2, 8, ...); - MERGE_FEATURE_EXT("IESB bits [15:12]" , mmfr2, 12, ...); - MERGE_FEATURE_EXT("VARange bits [19:16]" , mmfr2, 16, ...); + MERGE_FEATURE_4B("LSM bits [11:8]" , mmfr2, 8, ...); + MERGE_FEATURE_4B("IESB bits [15:12]" , mmfr2, 12, ...); */ - MERGE_FEATURE_EXT("CCIDX bits [23:20]" , mmfr2, 20, Ext::kCCIDX); - MERGE_FEATURE_EXT("NV bits [27:24]" , mmfr2, 24, Ext::kNV, Ext::kNV2); + MERGE_FEATURE_4B("VARange bits [19:16]" , mmfr2, 16, Ext::kLVA, Ext::kLVA3); + MERGE_FEATURE_4B("CCIDX bits [23:20]" , mmfr2, 20, Ext::kCCIDX); + MERGE_FEATURE_4B("NV bits [27:24]" , mmfr2, 24, Ext::kNV, Ext::kNV2); /* - MERGE_FEATURE_EXT("ST bits [31:28]" , mmfr2, 28, ...); + MERGE_FEATURE_4B("ST bits [31:28]" , mmfr2, 28, ...); */ - MERGE_FEATURE_EXT("AT bits [35:32]" , mmfr2, 32, Ext::kLSE2); + MERGE_FEATURE_4B("AT bits [35:32]" , mmfr2, 32, Ext::kLSE2); /* - MERGE_FEATURE_EXT("IDS bits [39:36]" , mmfr2, 36, ...); - MERGE_FEATURE_EXT("FWB bits [43:40]" , mmfr2, 40, ...); - MERGE_FEATURE_EXT("TTL bits [51:48]" , mmfr2, 48, ...); - MERGE_FEATURE_EXT("BBM bits [55:52]" , mmfr2, 52, ...); - MERGE_FEATURE_EXT("EVT bits [59:56]" , mmfr2, 56, ...); - MERGE_FEATURE_EXT("E0PD bits [63:60]" , mmfr2, 60, ...); + MERGE_FEATURE_4B("IDS bits [39:36]" , mmfr2, 36, ...); + MERGE_FEATURE_4B("FWB bits [43:40]" , mmfr2, 40, ...); + MERGE_FEATURE_4B("TTL bits [51:48]" , mmfr2, 48, ...); + MERGE_FEATURE_4B("BBM bits [55:52]" , mmfr2, 52, ...); + MERGE_FEATURE_4B("EVT bits [59:56]" , mmfr2, 56, ...); + MERGE_FEATURE_4B("E0PD bits [63:60]" , mmfr2, 60, ...); */ } // Detects features based on the content of ID_AA64ZFR0_EL1 register. ASMJIT_MAYBE_UNUSED -static ASMJIT_FAVOR_SIZE void detectAArch64FeaturesViaCPUID_AA64ZFR0(CpuInfo& cpu, uint64_t zfr0) noexcept { - MERGE_FEATURE_EXT("SVEver bits [3:0]" , zfr0, 0, Ext::kSVE2, Ext::kSVE2_1); - MERGE_FEATURE_EXT("AES bits [7:4]" , zfr0, 4, Ext::kSVE_AES, Ext::kSVE_PMULL128); - MERGE_FEATURE_EXT("BitPerm bits [19:16]" , zfr0, 16, Ext::kSVE_BITPERM); - MERGE_FEATURE_EXT("BF16 bits [23:20]" , zfr0, 20, Ext::kSVE_BF16, Ext::kSVE_EBF16); - MERGE_FEATURE_EXT("B16B16 bits [27:24]" , zfr0, 24, Ext::kSVE_B16B16); - MERGE_FEATURE_EXT("SHA3 bits [35:32]" , zfr0, 32, Ext::kSVE_SHA3); - MERGE_FEATURE_EXT("SM4 bits [43:40]" , zfr0, 40, Ext::kSVE_SM4); - MERGE_FEATURE_EXT("I8MM bits [47:44]" , zfr0, 44, Ext::kSVE_I8MM); - MERGE_FEATURE_EXT("F32MM bits [55:52]" , zfr0, 52, Ext::kSVE_F32MM); - MERGE_FEATURE_EXT("F64MM bits [59:56]" , zfr0, 56, Ext::kSVE_F64MM); +static inline void detectAArch64FeaturesViaCPUID_AA64ZFR0(CpuInfo& cpu, uint64_t zfr0) noexcept { + MERGE_FEATURE_4B("SVEver bits [3:0]" , zfr0, 0, Ext::kSVE2, Ext::kSVE2_1); + MERGE_FEATURE_4B("AES bits [7:4]" , zfr0, 4, Ext::kSVE_AES, Ext::kSVE_PMULL128); + MERGE_FEATURE_4B("BitPerm bits [19:16]" , zfr0, 16, Ext::kSVE_BITPERM); + MERGE_FEATURE_4B("BF16 bits [23:20]" , zfr0, 20, Ext::kSVE_BF16, Ext::kSVE_EBF16); + MERGE_FEATURE_4B("B16B16 bits [27:24]" , zfr0, 24, Ext::kSVE_B16B16); + MERGE_FEATURE_4B("SHA3 bits [35:32]" , zfr0, 32, Ext::kSVE_SHA3); + MERGE_FEATURE_4B("SM4 bits [43:40]" , zfr0, 40, Ext::kSVE_SM4); + MERGE_FEATURE_4B("I8MM bits [47:44]" , zfr0, 44, Ext::kSVE_I8MM); + MERGE_FEATURE_4B("F32MM bits [55:52]" , zfr0, 52, Ext::kSVE_F32MM); + MERGE_FEATURE_4B("F64MM bits [59:56]" , zfr0, 56, Ext::kSVE_F64MM); } -#undef MERGE_FEATURE_EXT -#undef MERGE_FEATURE_N_A +ASMJIT_MAYBE_UNUSED +static inline void detectAArch64FeaturesViaCPUID_AA64SMFR0(CpuInfo& cpu, uint64_t smfr0) noexcept { + MERGE_FEATURE_1B("SF8DP2 bit [28]" , smfr0, 29, Ext::kSSVE_FP8DOT2); + MERGE_FEATURE_1B("SF8DP4 bit [29]" , smfr0, 29, Ext::kSSVE_FP8DOT4); + MERGE_FEATURE_1B("SF8FMA bit [30]" , smfr0, 30, Ext::kSSVE_FP8FMA); + MERGE_FEATURE_1B("F32F32 bit [32]" , smfr0, 32, Ext::kSME_F32F32); + MERGE_FEATURE_1B("BI32I32 bit [33]" , smfr0, 33, Ext::kSME_BI32I32); + MERGE_FEATURE_1B("B16F32 bit [34]" , smfr0, 34, Ext::kSME_B16F32); + MERGE_FEATURE_1B("F16F32 bit [35]" , smfr0, 35, Ext::kSME_F16F32); + MERGE_FEATURE_4S("I8I32 bits [39:36]" , smfr0, 36, 0xF, Ext::kSME_I8I32); + MERGE_FEATURE_1B("F8F32 bit [40]" , smfr0, 40, Ext::kSME_F8F32); + MERGE_FEATURE_1B("F8F16 bit [41]" , smfr0, 41, Ext::kSME_F8F16); + MERGE_FEATURE_1B("F16F16 bit [42]" , smfr0, 42, Ext::kSME_F16F16); + MERGE_FEATURE_1B("B16B16 bit [43]" , smfr0, 43, Ext::kSME_B16B16); + MERGE_FEATURE_4S("I16I32 bits [47:44]" , smfr0, 44, 0x5, Ext::kSME_I16I32); + MERGE_FEATURE_1B("F64F64 bit [48]" , smfr0, 48, Ext::kSME_F64F64); + MERGE_FEATURE_4S("I16I64 bits [55:52]" , smfr0, 52, 0xF, Ext::kSME_I16I64); + MERGE_FEATURE_4B("SMEver bits [59:56]" , smfr0, 56, Ext::kSME2, Ext::kSME2_1); + MERGE_FEATURE_1B("LUTv2 bit [60]" , smfr0, 60, Ext::kSME_LUTv2); + MERGE_FEATURE_1B("FA64 bit [63]" , smfr0, 63, Ext::kSME_FA64); +} + +#undef MERGE_FEATURE_4S +#undef MERGE_FEATURE_4B +#undef MERGE_FEATURE_2B +#undef MERGE_FEATURE_1B +#undef MERGE_FEATURE_NA // CpuInfo - Detect - ARM - CPU Vendor Features // ============================================ @@ -1081,11 +1143,10 @@ static ASMJIT_FAVOR_SIZE bool detectARMFeaturesViaAppleFamilyId(CpuInfo& cpu) no // Apple A14/M1 (ARMv8.5-A). case uint32_t(Id::kFIRESTORM_ICESTORM): - // Missing: CSV2, CSV3. populateARMv8AFeatures(features, 4); - features.add(Ext::kAES, Ext::kDPB2, Ext::kECV, Ext::kFHM, Ext::kFLAGM2, Ext::kFP16, Ext::kFP16CONV, - Ext::kFRINTTS, Ext::kPMU, Ext::kPMULL, Ext::kSB, Ext::kSHA1, Ext::kSHA256, Ext::kSHA3, - Ext::kSHA512, Ext::kSSBS); + features.add(Ext::kAES, Ext::kCSV2, Ext::kCSV3, Ext::kDPB2, Ext::kECV, Ext::kFHM, Ext::kFLAGM2, + Ext::kFP16, Ext::kFP16CONV, Ext::kFRINTTS, Ext::kPMU, Ext::kPMULL, Ext::kSB, + Ext::kSHA1, Ext::kSHA256, Ext::kSHA3, Ext::kSHA512, Ext::kSSBS); return true; // Apple A15/M2. @@ -1390,7 +1451,7 @@ ASMJIT_AARCH64_DEFINE_CPUID_READ_FN(aarch64ReadZFR0, S3_0_C0_C4_4) // ID_AA64ZFR // dependent is zeroed, only the bits that are used for CPU feature identification would be present. // // References: -// - https://docs.kernel.org/arm64/cpu-feature-registers.html +// - https://docs.kernel.org/arch/arm64/cpu-feature-registers.html ASMJIT_MAYBE_UNUSED static ASMJIT_FAVOR_SIZE void detectAArch64FeaturesViaCPUID(CpuInfo& cpu) noexcept { populateBaseARMFeatures(cpu); @@ -1499,7 +1560,7 @@ static ASMJIT_FAVOR_SIZE void detectARMCpu(CpuInfo& cpu) noexcept { #ifndef AT_HWCAP #define AT_HWCAP 16 -#endif // AT_HWCAP +#endif // !AT_HWCAP #ifndef AT_HWCAP2 #define AT_HWCAP2 26 @@ -1593,7 +1654,7 @@ static ASMJIT_FAVOR_SIZE void detectARMCpu(CpuInfo& cpu) noexcept { #else // Reference: -// - https://docs.kernel.org/arm64/elf_hwcaps.html +// - https://docs.kernel.org/arch/arm64/elf_hwcaps.html // - https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h static const HWCapMapping hwCapMapping[] = { { uint8_t(Ext::kFP) , 0 }, // HWCAP_FP @@ -1677,7 +1738,12 @@ static const HWCapMapping hwCap2Mapping[] = { { uint8_t(Ext::kSME_I16I32) , 39 }, // HWCAP2_SME_I16I32 { uint8_t(Ext::kSME_BI32I32) , 40 }, // HWCAP2_SME_BI32I32 { uint8_t(Ext::kSME_B16B16) , 41 }, // HWCAP2_SME_B16B16 - { uint8_t(Ext::kSME_F16F16) , 42 } // HWCAP2_SME_F16F16 + { uint8_t(Ext::kSME_F16F16) , 42 }, // HWCAP2_SME_F16F16 + { uint8_t(Ext::kMOPS) , 43 }, // HWCAP2_MOPS + { uint8_t(Ext::kHBC) , 44 }, // HWCAP2_HBC + { uint8_t(Ext::kSVE_B16B16) , 45 }, // HWCAP2_SVE_B16B16 + { uint8_t(Ext::kLRCPC3) , 46 }, // HWCAP2_LRCPC3 + { uint8_t(Ext::kLSE128) , 47 }, // HWCAP2_LSE128 }; static ASMJIT_FAVOR_SIZE void detectARMCpu(CpuInfo& cpu) noexcept { @@ -1751,6 +1817,9 @@ static ASMJIT_FAVOR_SIZE void detectARMCpu(CpuInfo& cpu) noexcept { // Only read CPU_ID_AA64ZFR0 when either SVE or SME is available. if (cpu.features().arm().hasAny(Ext::kSVE, Ext::kSME)) { detectAArch64FeaturesViaCPUID_AA64ZFR0(cpu, openbsdReadAArch64CPUID(ID::kAA64ZFR0)); + + if (cpu.features().arm().hasSME()) + detectAArch64FeaturesViaCPUID_AA64SMFR0(cpu, openbsdReadAArch64CPUID(ID::kAA64SMFR0)); } postProcessARMCpuInfo(cpu); @@ -1883,7 +1952,7 @@ static ASMJIT_FAVOR_SIZE void detectARMCpu(CpuInfo& cpu) noexcept { #else #if ASMJIT_ARCH_ARM == 32 - #pragma message("[asmjit] Disabling runtime CPU detection - unsupported OS/CPU combination (Unknown OS with ARM CPU)") + #pragma message("[asmjit] Disabling runtime CPU detection - unsupported OS/CPU combination (Unknown OS with AArch32 CPU)") #else #pragma message("[asmjit] Disabling runtime CPU detection - unsupported OS/CPU combination (Unknown OS with AArch64 CPU)") #endif @@ -1902,13 +1971,13 @@ static ASMJIT_FAVOR_SIZE void detectARMCpu(CpuInfo& cpu) noexcept { // CpuInfo - Detect - Host // ======================= -static uint32_t cpuInfoInitialized; -static CpuInfo cpuInfoGlobal(Globals::NoInit); - const CpuInfo& CpuInfo::host() noexcept { - // This should never cause a problem as the resulting information should always be the same. - // In the worst case it would just be overwritten non-atomically. - if (!cpuInfoInitialized) { + static std::atomic cpuInfoInitialized; + static CpuInfo cpuInfoGlobal(Globals::NoInit); + + // This should never cause a problem as the resulting information should always + // be the same. In the worst case it would just be overwritten non-atomically. + if (!cpuInfoInitialized.load(std::memory_order_relaxed)) { CpuInfo cpuInfoLocal; cpuInfoLocal._arch = Arch::kHost; @@ -1918,13 +1987,11 @@ const CpuInfo& CpuInfo::host() noexcept { x86::detectX86Cpu(cpuInfoLocal); #elif ASMJIT_ARCH_ARM arm::detectARMCpu(cpuInfoLocal); -#else - #pragma message("[asmjit] Disabling runtime CPU detection - unsupported OS/CPU combination (Unknown CPU)") #endif cpuInfoLocal._hwThreadCount = detectHWThreadCount(); cpuInfoGlobal = cpuInfoLocal; - cpuInfoInitialized = 1; + cpuInfoInitialized.store(1, std::memory_order_seq_cst); } return cpuInfoGlobal; diff --git a/deps/asmjit/src/asmjit/core/cpuinfo.h b/deps/asmjit/src/asmjit/core/cpuinfo.h index 8ddc1e1f..2638146a 100644 --- a/deps/asmjit/src/asmjit/core/cpuinfo.h +++ b/deps/asmjit/src/asmjit/core/cpuinfo.h @@ -22,11 +22,6 @@ ASMJIT_BEGIN_NAMESPACE //! Each feature is represented by a single bit in an embedded bit array. class CpuFeatures { public: - //! A word that is used to represents feature bits. - typedef Support::BitWord BitWord; - //! Iterator that can iterate all CPU features set. - typedef Support::BitVectorIterator Iterator; - //! \name Constants //! \{ @@ -37,6 +32,13 @@ public: }; //! \endcond + //! A word that is used to represents feature bits. + typedef Support::BitWord BitWord; + //! Iterator that can iterate all CPU features set. + typedef Support::BitVectorIterator Iterator; + + typedef Support::Array Bits; + //! \} //! \name Data @@ -48,15 +50,15 @@ public: //! \{ //! Data bits. - Support::Array _bits; + Bits _bits; //! \} //! \name Overloaded Operators //! \{ - ASMJIT_INLINE_NODEBUG bool operator==(const Data& other) noexcept { return eq(other); } - ASMJIT_INLINE_NODEBUG bool operator!=(const Data& other) noexcept { return !eq(other); } + ASMJIT_INLINE_NODEBUG bool operator==(const Data& other) const noexcept { return equals(other); } + ASMJIT_INLINE_NODEBUG bool operator!=(const Data& other) const noexcept { return !equals(other); } //! \} @@ -88,11 +90,16 @@ public: return bool((_bits[idx] >> bit) & 0x1); } + //! \cond NONE template ASMJIT_INLINE_NODEBUG bool hasAny(const FeatureId& featureId) const noexcept { return has(featureId); } + //! \endcond + //! Tests whether any feature given is present. + //! + //! \note This is a variadic function template that can be used with multiple features. template ASMJIT_INLINE_NODEBUG bool hasAny(const FeatureId& featureId, Args&&... otherFeatureIds) const noexcept { return bool(unsigned(has(featureId)) | unsigned(hasAny(std::forward(otherFeatureIds)...))); @@ -111,6 +118,7 @@ public: //! \name Manipulation //! \{ + //! Clears all features set. ASMJIT_INLINE_NODEBUG void reset() noexcept { _bits.fill(0); } //! Adds the given CPU `featureId` to the list of features. @@ -164,11 +172,15 @@ public: } //! Tests whether this CPU features data matches `other`. - ASMJIT_INLINE_NODEBUG bool eq(const Data& other) const noexcept { return _bits == other._bits; } + ASMJIT_INLINE_NODEBUG bool equals(const Data& other) const noexcept { return _bits == other._bits; } + +#if !defined(ASMJIT_NO_DEPRECATED) + ASMJIT_DEPRECATED("Use CpuFeatures::Data::equals() instead") + ASMJIT_INLINE_NODEBUG bool eq(const Data& other) const noexcept { return equals(other); } +#endif // !ASMJIT_NO_DEPRECATED //! \} - - }; + }; //! X86 specific features data. struct X86 : public Data { @@ -333,6 +345,7 @@ public: }; #define ASMJIT_X86_FEATURE(FEATURE) \ + /*! Tests whether FEATURE is present. */ \ ASMJIT_INLINE_NODEBUG bool has##FEATURE() const noexcept { return has(X86::k##FEATURE); } ASMJIT_X86_FEATURE(MT) @@ -502,137 +515,213 @@ public: kARMv6, //!< CPU is at least ARMv6 {A32}. kARMv7, //!< CPU is at least ARMv7 {A32}. kARMv8a, //!< CPU is at least ARMv8A. - kTHUMB, //!< CPU has THUMB (16-bit THUMB encoding) {A32}. - kTHUMBv2, //!< CPU has THUMBv2 (32-bit THUMB encoding) {A32}. + kTHUMB, //!< CPU has THUMB (16-bit THUMB encoding) {A32}. + kTHUMBv2, //!< CPU has THUMBv2 (32-bit THUMB encoding) {A32}. - kAES, //!< CPU has AES (ASIMD AES instructions). - kAFP, //!< CPU has AFP (alternate floating-point behavior) {A64}. - kASIMD, //!< CPU has ASIMD (NEON on ARM/THUMB). - kBF16, //!< CPU has BF16 (BFloat16 instructions) {A64}. - kBTI, //!< CPU has BTI (branch target identification). - kCCIDX, //!< CPU has CCIDX (extend of the CCSIDR number of sets). - kCHK, //!< CPU has CHK (CHKFEAT instruction) {A64}. - kCLRBHB, //!< CPU has CLRBHB (clear BHB instruction). - kCPUID, //!< CPU has CPUID (CPUID registers accessible in user-space). - kCRC32, //!< CPU has CRC32 (CRC32 instructions). - kCSSC, //!< CPU has CSSC (common short sequence compression) {A64}. - kD128, //!< CPU has D128 (128-bit translation tables, 56 bit PA) {A64}. - kDGH, //!< CPU has DGH (data gathering hint) {A64}. - kDIT, //!< CPU has DIT (data independent timing of instructions). - kDOTPROD, //!< CPU has DOTPROD (ASIMD Int8 dot product instructions). - kDPB, //!< CPU has DPB (DC CVAP instruction) {A64}. - kDPB2, //!< CPU has DPB2 (DC CVADP instruction) {A64}. - kEBF16, //!< CPU has EBF16 (extended BFloat16 mode) {A64}. - kECV, //!< CPU has ECV (enhanced counter virtualization). - kEDSP, //!< CPU has EDSP (ARM/THUMB only). - kFCMA, //!< CPU has FCMA (FCADD/FCMLA). - kFGT, //!< CPU has FGT (fine-grained traps). - kFGT2, //!< CPU has FGT2 (fine-grained traps 2). - kFHM, //!< CPU has FHM (half-precision floating-point FMLAL instructions). - kFLAGM, //!< CPU has FLAGM (condition flag manipulation) {A64}. - kFLAGM2, //!< CPU has FLAGM2 (condition flag manipulation version v2) {A64}. - kFMAC, //!< CPU has FMAC (ARM/THUMB only). - kFP, //!< CPU has FP (floating-point) (on 32-bit ARM this means VFPv3). - kFP16, //!< CPU has FP16 (half-precision floating-point data processing). - kFP16CONV, //!< CPU has FP16CONV (half-precision float conversion). - kFRINTTS, //!< CPU has FRINTTS (FRINT[32|64][X|Z] instructions) {A64}. - kGCS, //!< CPU has GCS (guarded control stack extension) {A64}. - kHBC, //!< CPU has HBC (hinted conditional branches) {A64} - kHCX, //!< CPU has HCX (support for the HCRX_EL2 register) {A64}. - kI8MM, //!< CPU has I8MM (int8 matrix multiplication) {A64}. - kIDIVA, //!< CPU has IDIV (hardware SDIV and UDIV in ARM mode). - kIDIVT, //!< CPU has IDIV (hardware SDIV and UDIV in THUMB mode). - kJSCVT, //!< CPU has JSCVT (JavaScript FJCVTS conversion instruction) {A64}. - kLOR, //!< CPU has LOR (limited ordering regions extension). - kLRCPC, //!< CPU has LRCPC (load-acquire RCpc instructions) {A64}. - kLRCPC2, //!< CPU has LRCPC2 (load-acquire RCpc instructions v2) {A64}. - kLRCPC3, //!< CPU has LRCPC3 (load-Acquire RCpc instructions v3) {A64}. - kLS64, //!< CPU has LS64 (64 byte loads/stores without return) {A64}. - kLS64_ACCDATA, //!< CPU has LS64_ACCDATA (64-byte EL0 stores with return) {A64}. - kLS64_V, //!< CPU has LS64_V (64-byte stores with return) {A64}. - kLSE, //!< CPU has LSE (large system extensions) {A64}. - kLSE128, //!< CPU has LSE128 (128-bit atomics) {A64}. - kLSE2, //!< CPU has LSE2 (large system extensions v2) {A64}. - kMOPS, //!< CPU has MOPS (memcpy and memset acceleration instructions) {A64}. - kMPAM, //!< CPU has MPAM (memory system partitioning and monitoring extension) {A64}. - kMTE, //!< CPU has MTE (instruction-only memory tagging extension) {A64}. - kMTE2, //!< CPU has MTE2 (full memory tagging extension) {A64}. - kMTE3, //!< CPU has MTE3 (MTE asymmetric fault handling) {A64}. - kMTE4, //!< CPU has MTE4 (MTE v4) {A64}. - kNMI, //!< CPU has NMI (non-maskable Interrupt) {A64}. - kNV, //!< CPU has NV (nested virtualization enchancement) {A64}. - kNV2, //!< CPU has NV2 (enhanced support for nested virtualization) {A64}. - kPAN, //!< CPU has PAN (privileged access-never extension) {A64}. - kPAN2, //!< CPU has PAN2 (PAN s1e1R and s1e1W variants) {A64}. - kPAN3, //!< CPU has PAN3 (support for SCTLR_ELx.EPAN) {A64}. - kPAUTH, //!< CPU has PAUTH (pointer authentication extension) {A64}. - kPMU, //!< CPU has PMU {A64}. - kPMULL, //!< CPU has PMULL {A64}. - kPRFMSLC, //!< CPU has PRFMSLC (PRFM instructions support the SLC target) {A64} - kRAS, //!< CPU has RAS (reliability, availability and serviceability extensions). - kRAS1_1, //!< CPU has RASv1p1 (RAS v1.1). - kRAS2, //!< CPU has RASv2 (RAS v2). - kRDM, //!< CPU has RDM (rounding double multiply accumulate) {A64}. - kRME, //!< CPU has RME (memory encryption contexts extension) {A64}. - kRNG, //!< CPU has RNG (random number generation). - kRNG_TRAP, //!< CPU has RNG_TRAP (random number trap to EL3 field) {A64}. - kRPRES, //!< CPU has RPRES (increased precision of reciprocal estimate and RSQRT estimate) {A64}. - kRPRFM, //!! CPU has RPRFM (range prefetch hint instruction). - kSB, //!< CPU has SB (speculative barrier). - kSHA1, //!< CPU has SHA1 (ASIMD SHA1 instructions). - kSHA256, //!< CPU has SHA256 (ASIMD SHA256 instructions). - kSHA3, //!< CPU has SHA3 (ASIMD EOR3, RAX1, XAR, and BCAX instructions). - kSHA512, //!< CPU has SHA512 (ASIMD SHA512 instructions). - kSM3, //!< CPU has SM3 (ASIMD SM3 instructions). - kSM4, //!< CPU has SM4 (ASIMD SM4 instructions). - kSME, //!< CPU has SME (SME v1 - scalable matrix extension) {A64}. - kSME2, //!< CPU has SME2 (SME v2) {A64}. - kSME2_1, //!< CPU has SME2p1 (SME v2.1) {A64}. - kSME_B16B16, //!< CPU has SME_B16B16 (SME non-widening BFloat16 to BFloat16 arithmetic) {A64}. - kSME_B16F32, //!< CPU has SME_B16F32 {A64}. - kSME_BI32I32, //!< CPU has SME_BI32I32 {A64}. - kSME_F16F16, //!< CPU has SME_F16F16 (SME2.1 non-widening half-precision FP16 to FP16 arithmetic) {A64}. - kSME_F16F32, //!< CPU has SME_F16F32 {A64}. - kSME_F32F32, //!< CPU has SME_F32F32 {A64}. - kSME_F64F64, //!< CPU has SME_F64F64 {A64}. - kSME_FA64, //!< CPU has SME_FA64 {A64}. - kSME_I16I32, //!< CPU has SME_I16I32 {A64}. - kSME_I16I64, //!< CPU has SME_I16I64 {A64}. - kSME_I8I32, //!< CPU has SME_I8I32 {A64}. - kSPECRES, //!< CPU has SPECRES (speculation restriction instructions). - kSPECRES2, //!< CPU has SPECRES2 (clear other speculative predictions). - kSSBS, //!< CPU has SSBS (speculative store bypass safe instruction). - kSSBS2, //!< CPU has SSBS2 (MRS and MSR instructions for SSBS). - kSVE, //!< CPU has SVE (SVE v1 - scalable vector extension) {A64}. - kSVE2, //!< CPU has SVE2 (SVE v2) {A64}. - kSVE2_1, //!< CPU has SVE2p1 (SVE v2.1) {A64}. - kSVE_AES, //!< CPU has SVE_AES (SVE AES instructions) {A64}. - kSVE_B16B16, //!< CPU has SVE_B16B16 (SVE non-widening BFloat16 to BFloat16 arithmetic) {A64}. - kSVE_BF16, //!< CPU has SVE_BF16 (SVE BF16 instructions) {A64}. - kSVE_BITPERM, //!< CPU has SVE_BITPERM (SVE bit permute) {A64}. - kSVE_EBF16, //!< CPU has SVE_EBF16 (SVE extended BFloat16 mode) {A64}. - kSVE_F32MM, //!< CPU has SVE_F32MM (SVE single-precision floating-point matrix multiply instruction) {A64}. - kSVE_F64MM, //!< CPU has SVE_F64MM (SVE double-precision floating-point matrix multiply instruction) {A64}. - kSVE_I8MM, //!< CPU has SVE_I8MM (SVE int8 matrix multiplication) {A64}. - kSVE_PMULL128, //!< CPU has SVE_PMULL128 (SVE PMULL instructions) {A64}. - kSVE_SHA3, //!< CPU has SVE_SHA3 (SVE SHA-3 instructions) {A64}. - kSVE_SM4, //!< CPU has SVE_SM4 (SVE SM4 instructions {A64}. - kSYSINSTR128, //!< CPU has SYSINSTR128 (128-bit system instructions) {A64}. - kSYSREG128, //!< CPU has SYSREG128 (128-bit system registers) {A64}. - kTHE, //!< CPU has THE (translation hardening extension). - kTME, //!< CPU has TME (transactional memory extensions). - kTRF, //!< CPU has TRF (trace extension). - kUAO, //!< CPU has UAO (AArch64 v8.2 UAO PState) {A64}. - kVFP_D32, //!< CPU has VFP_D32 (32 VFP-D registers) (ARM/THUMB only). - kVHE, //!< CPU has VHE (virtual host extension). - kWFXT, //!< CPU has WFxT (WFE and WFI instructions with timeout) {A64}. - kXS, //!< CPU has XS (XS attribute in TLBI and DSB instructions) {A64}. + kABLE, //!< CPU has ABLE (address breakpoint linking extension) {A64}. + kADERR, //!< CPU has ADERR (asynchronous device error exceptions) {A64}. + kAES, //!< CPU has AES (ASIMD AES instructions). + kAFP, //!< CPU has AFP (alternate floating-point behavior) {A64}. + kAIE, //!< CPU has AIE (memory attribute index enhancement) {A64}. + kAMU1, //!< CPU has AMUv1 (activity monitors extension version 1) {A64}. + kAMU1_1, //!< CPU has AMUv1p1 (activity monitors extension version 1.1) {A64}. + kANERR, //!< CPU has ANERR (asynchronous normal error exception) {A64}. + kASIMD, //!< CPU has ASIMD (NEON on ARM/THUMB). + kBF16, //!< CPU has BF16 (BFloat16 instructions) {A64}. + kBRBE, //!< CPU has BRBE (branch record buffer extension) {A64}. + kBTI, //!< CPU has BTI (branch target identification). + kBWE, //!< CPU has BWE (breakpoint mismatch and range extension) {A64}. + kCCIDX, //!< CPU has CCIDX (extend of the CCSIDR number of sets). + kCHK, //!< CPU has CHK (check feature status - CHKFEAT instruction) {A64}. + kCLRBHB, //!< CPU has CLRBHB (clear BHB instruction). + kCMOW, //!< CPU has CMOW (control for cache maintenance permission) {A64}. + kCONSTPACFIELD, //!< CPU has CONSTPACFIELD (PAC algorithm enhancement) {A64}. + kCPA, //!< CPU has CPA (instruction-only Checked Pointer Arithmetic) {A64}. + kCPA2, //!< CPU has CPA2 (checked Pointer Arithmetic) {A64}. + kCPUID, //!< CPU has CPUID (CPUID registers accessible in user-space). + kCRC32, //!< CPU has CRC32 (CRC32 instructions). + kCSSC, //!< CPU has CSSC (common short sequence compression) {A64}. + kCSV2, //!< CPU has CSV2 (cache speculation variant 2 version 2.1) {A64}. + kCSV2_3, //!< CPU has CSV2_3 (cache speculation variant 2 version 3) {A64}. + kCSV3, //!< CPU has CSV3 (cache speculation Variant 3) {A64}. + kD128, //!< CPU has D128 (128-bit translation tables, 56 bit PA) {A64}. + kDGH, //!< CPU has DGH (data gathering hint) {A64}. + kDIT, //!< CPU has DIT (data independent timing of instructions). + kDOTPROD, //!< CPU has DOTPROD (ASIMD Int8 dot product instructions). + kDPB, //!< CPU has DPB (DC CVAP instruction) {A64}. + kDPB2, //!< CPU has DPB2 (DC CVADP instruction) {A64}. + kEBEP, //!< CPU has EBEP (exception-based event profiling) {A64}. + kEBF16, //!< CPU has EBF16 (extended BFloat16 mode) {A64}. + kECBHB, //!< CPU has ECBHB (exploitative control using branch history information) {A64}. + kECV, //!< CPU has ECV (enhanced counter virtualization). + kEDHSR, //!< CPU has EDHSR (support for EDHSR) {A64}. + kEDSP, //!< CPU has EDSP (ARM/THUMB only). + kFAMINMAX, //!< CPU has FAMINMAX (floating-point maximum and minimum absolute value instructions) {A64}. + kFCMA, //!< CPU has FCMA (FCADD/FCMLA). + kFGT, //!< CPU has FGT (fine-grained traps). + kFGT2, //!< CPU has FGT2 (fine-grained traps 2). + kFHM, //!< CPU has FHM (half-precision floating-point FMLAL instructions). + kFLAGM, //!< CPU has FLAGM (condition flag manipulation) {A64}. + kFLAGM2, //!< CPU has FLAGM2 (condition flag manipulation version v2) {A64}. + kFMAC, //!< CPU has FMAC (ARM/THUMB only). + kFP, //!< CPU has FP (floating-point) (on 32-bit ARM this means VFPv3). + kFP16, //!< CPU has FP16 (half-precision floating-point data processing). + kFP16CONV, //!< CPU has FP16CONV (half-precision float conversion). + kFP8, //!< CPU has FP8 (FP8 convert instructions) {A64}. + kFP8DOT2, //!< CPU has FP8DOT2 (FP8 2-way dot product to half-precision instructions) {A64}. + kFP8DOT4, //!< CPU has FP8DOT4 (FP8 4-way dot product to single-precision instructions) {A64}. + kFP8FMA, //!< CPU has FP8FMA (FP8 multiply-accumulate to half-precision and single-precision instructions) {A64}. + kFPMR, //!< CPU has FPMR (floating-point Mode Register) {A64}. + kFRINTTS, //!< CPU has FRINTTS (FRINT[32|64][X|Z] instructions) {A64}. + kGCS, //!< CPU has GCS (guarded control stack extension) {A64}. + kHACDBS, //!< CPU has HACDBS (hardware accelerator for cleaning Dirty state) {A64}. + kHAFDBS, //!< CPU has HAFDBS (hardware management of the access flag and dirty state) {A64}. + kHAFT, //!< CPU has HAFT (hardware managed access flag for table descriptors) {A64}. + kHDBSS, //!< CPU has HDBSS (hardware Dirty state tracking Structure) {A64}. + kHBC, //!< CPU has HBC (hinted conditional branches) {A64}. + kHCX, //!< CPU has HCX (support for the HCRX_EL2 register) {A64}. + kHPDS, //!< CPU has HPDS (hierarchical permission disables in translation tables ) {A64}. + kHPDS2, //!< CPU has HPDS2 (hierarchical permission disables) {A64}. + kI8MM, //!< CPU has I8MM (int8 matrix multiplication) {A64}. + kIDIVA, //!< CPU has IDIV (hardware SDIV and UDIV in ARM mode). + kIDIVT, //!< CPU has IDIV (hardware SDIV and UDIV in THUMB mode). + kITE, //!< CPU has ITE (instrumentation extension) {A64}. + kJSCVT, //!< CPU has JSCVT (JavaScript FJCVTS conversion instruction) {A64}. + kLOR, //!< CPU has LOR (limited ordering regions extension). + kLRCPC, //!< CPU has LRCPC (load-acquire RCpc instructions) {A64}. + kLRCPC2, //!< CPU has LRCPC2 (load-acquire RCpc instructions v2) {A64}. + kLRCPC3, //!< CPU has LRCPC3 (load-Acquire RCpc instructions v3) {A64}. + kLS64, //!< CPU has LS64 (64 byte loads/stores without return) {A64}. + kLS64_ACCDATA, //!< CPU has LS64_ACCDATA (64-byte EL0 stores with return) {A64}. + kLS64_V, //!< CPU has LS64_V (64-byte stores with return) {A64}. + kLSE, //!< CPU has LSE (large system extensions) {A64}. + kLSE128, //!< CPU has LSE128 (128-bit atomics) {A64}. + kLSE2, //!< CPU has LSE2 (large system extensions v2) {A64}. + kLUT, //!< CPU has LUT (lookup table instructions with 2-bit and 4-bit indices) {A64}. + kLVA, //!< CPU has LVA (large VA support) {A64}. + kLVA3, //!< CPU has LVA3 (56-bit VA) {A64}. + kMEC, //!< CPU has MEC (memory encryption contexts) {A64}. + kMOPS, //!< CPU has MOPS (memcpy and memset acceleration instructions) {A64}. + kMPAM, //!< CPU has MPAM (memory system partitioning and monitoring extension) {A64}. + kMTE, //!< CPU has MTE (instruction-only memory tagging extension) {A64}. + kMTE2, //!< CPU has MTE2 (full memory tagging extension) {A64}. + kMTE3, //!< CPU has MTE3 (MTE asymmetric fault handling) {A64}. + kMTE4, //!< CPU has MTE4 (MTE v4) {A64}. + kMTE_ASYM_FAULT, //!< CPU has MTE_ASYM_FAULT (memory tagging asymmetric faults) {A64}. + kMTE_ASYNC, //!< CPU has MTE_ASYNC (memory tagging asynchronous faulting) {A64}. + kMTE_CANONICAL_TAGS, //!< CPU has MTE_CANONICAL_TAGS (canonical tag checking for untagged memory) {A64}. + kMTE_NO_ADDRESS_TAGS, //!< CPU has MTE_NO_ADDRESS_TAGS (memory tagging with address tagging disabled) {A64}. + kMTE_PERM_S1, //!< CPU has MTE_PERM_S1 (allocation tag access permission) {A64}. + kMTE_STORE_ONLY, //!< CPU has MTE_STORE_ONLY (store-only tag checking) {A64}. + kMTE_TAGGED_FAR, //!< CPU has MTE_TAGGED_FAR (FAR_ELx on a tag check fault) {A64}. + kMTPMU, //!< CPU has MTPMU (multi-threaded PMU extensions) {A64}. + kNMI, //!< CPU has NMI (non-maskable Interrupt) {A64}. + kNV, //!< CPU has NV (nested virtualization enchancement) {A64}. + kNV2, //!< CPU has NV2 (enhanced support for nested virtualization) {A64}. + kPAN, //!< CPU has PAN (privileged access-never extension) {A64}. + kPAN2, //!< CPU has PAN2 (PAN s1e1R and s1e1W variants) {A64}. + kPAN3, //!< CPU has PAN3 (support for SCTLR_ELx.EPAN) {A64}. + kPAUTH, //!< CPU has PAUTH (pointer authentication extension) {A64}. + kPFAR, //!< CPU has PFAR (physical fault address registers) {A64}. + kPMU, //!< CPU has PMU {A64}. + kPMULL, //!< CPU has PMULL (ASIMD PMULL instructions) {A64}. + kPRFMSLC, //!< CPU has PRFMSLC (PRFM instructions support the SLC target) {A64}. + kRAS, //!< CPU has RAS (reliability, availability and serviceability extensions). + kRAS1_1, //!< CPU has RASv1p1 (RAS v1.1). + kRAS2, //!< CPU has RASv2 (RAS v2). + kRASSA2, //!< CPU has RASSAv2 (RAS v2 system architecture). + kRDM, //!< CPU has RDM (rounding double multiply accumulate) {A64}. + kRME, //!< CPU has RME (memory encryption contexts extension) {A64}. + kRNG, //!< CPU has RNG (random number generation). + kRNG_TRAP, //!< CPU has RNG_TRAP (random number trap to EL3 field) {A64}. + kRPRES, //!< CPU has RPRES (increased precision of reciprocal estimate and RSQRT estimate) {A64}. + kRPRFM, //!< CPU has RPRFM (range prefetch hint instruction). + kS1PIE, //!< CPU has S1PIE (permission model enhancements) {A64}. + kS1POE, //!< CPU has S1POE (permission model enhancements) {A64}. + kS2PIE, //!< CPU has S2PIE (permission model enhancements) {A64}. + kS2POE, //!< CPU has S2POE (permission model enhancements) {A64}. + kSB, //!< CPU has SB (speculative barrier). + kSCTLR2, //!< CPU has SCTLR2 (extension to SCTLR_ELx) {A64}. + kSEBEP, //!< CPU has SEBEP (synchronous exception-based event profiling) {A64}. + kSEL2, //!< CPU has SEL2 (secure EL2) {A64}. + kSHA1, //!< CPU has SHA1 (ASIMD SHA1 instructions). + kSHA256, //!< CPU has SHA256 (ASIMD SHA256 instructions). + kSHA3, //!< CPU has SHA3 (ASIMD EOR3, RAX1, XAR, and BCAX instructions). + kSHA512, //!< CPU has SHA512 (ASIMD SHA512 instructions). + kSM3, //!< CPU has SM3 (ASIMD SM3 instructions). + kSM4, //!< CPU has SM4 (ASIMD SM4 instructions). + kSME, //!< CPU has SME (SME v1 - scalable matrix extension) {A64}. + kSME2, //!< CPU has SME2 (SME v2) {A64}. + kSME2_1, //!< CPU has SME2p1 (SME v2.1) {A64}. + kSME_B16B16, //!< CPU has SME_B16B16 (SME non-widening BFloat16 to BFloat16 arithmetic) {A64}. + kSME_B16F32, //!< CPU has SME_B16F32 (BFMOPA and BFMOPS instructions that accumulate BFloat16 outer products into single-precision tiles) {A64}. + kSME_BI32I32, //!< CPU has SME_BI32I32 (BMOPA and BMOPS instructions that accumulate 1-bit binary outer products into 32-bit integer tiles) {A64}. + kSME_F16F16, //!< CPU has SME_F16F16 (SME2.1 non-widening half-precision FP16 to FP16 arithmetic) {A64}. + kSME_F16F32, //!< CPU has SME_F16F32 {A64}. + kSME_F32F32, //!< CPU has SME_F32F32 {A64}. + kSME_F64F64, //!< CPU has SME_F64F64 {A64}. + kSME_F8F16, //!< CPU has SME_F8F16 (SME2 ZA-targeting FP8 multiply-accumulate, dot product, and outer product to half-precision instructions) {A64}. + kSME_F8F32, //!< CPU has SME_F8F32 (SME2 ZA-targeting FP8 multiply-accumulate, dot product, and outer product to single-precision instructions) {A64}. + kSME_FA64, //!< CPU has SME_FA64 {A64}. + kSME_I16I32, //!< CPU has SME_I16I32 {A64}. + kSME_I16I64, //!< CPU has SME_I16I64 {A64}. + kSME_I8I32, //!< CPU has SME_I8I32 {A64}. + kSME_LUTv2, //!< CPU has SME_LUTv2 (lookup table instructions with 4-bit indices and 8-bit elements) {A64}. + kSPE, //!< CPU has SPE (statistical profiling extension) {A64}. + kSPE1_1, //!< CPU has SPEv1p1 (statistical profiling extensions version 1.1) {A64}. + kSPE1_2, //!< CPU has SPEv1p2 (statistical profiling extensions version 1.2) {A64}. + kSPE1_3, //!< CPU has SPEv1p3 (statistical profiling extensions version 1.3) {A64}. + kSPE1_4, //!< CPU has SPEv1p4 (statistical profiling extensions version 1.4) {A64}. + kSPE_ALTCLK, //!< CPU has SPE_ALTCLK (statistical profiling alternate clock domain extension) {A64}. + kSPE_CRR, //!< CPU has SPE_CRR (statistical profiling call return branch records) {A64}. + kSPE_EFT, //!< CPU has SPE_EFT (statistical profiling extended filtering by type) {A64}. + kSPE_FDS, //!< CPU has SPE_FDS (statistical profiling data source filtering) {A64}. + kSPE_FPF, //!< CPU has SPE_FPF (statistical profiling floating-point flag extension) {A64}. + kSPE_SME, //!< CPU has SPE_SME (statistical profiling extensions for SME) {A64}. + kSPECRES, //!< CPU has SPECRES (speculation restriction instructions). + kSPECRES2, //!< CPU has SPECRES2 (clear other speculative predictions). + kSPMU, //!< CPU has SPMU (system performance monitors extension) {A64}. + kSSBS, //!< CPU has SSBS (speculative store bypass safe instruction). + kSSBS2, //!< CPU has SSBS2 (MRS and MSR instructions for SSBS). + kSSVE_FP8DOT2, //!< CPU has SSVE_FP8DOT2 (SVE2 FP8 2-way dot product to half-precision instructions in Streaming SVE mode) {A64}. + kSSVE_FP8DOT4, //!< CPU has SSVE_FP8DOT4 (SVE2 FP8 4-way dot product to single-precision instructions in Streaming SVE mode) {A64}. + kSSVE_FP8FMA, //!< CPU has SSVE_FP8FMA (SVE2 FP8 multiply-accumulate to half-precision and single-precision instructions in Streaming SVE mode) {A64}. + kSVE, //!< CPU has SVE (SVE v1 - scalable vector extension) {A64}. + kSVE2, //!< CPU has SVE2 (SVE v2) {A64}. + kSVE2_1, //!< CPU has SVE2p1 (SVE v2.1) {A64}. + kSVE_AES, //!< CPU has SVE_AES (SVE AES instructions) {A64}. + kSVE_B16B16, //!< CPU has SVE_B16B16 (SVE non-widening BFloat16 to BFloat16 arithmetic) {A64}. + kSVE_BF16, //!< CPU has SVE_BF16 (SVE BF16 instructions) {A64}. + kSVE_BITPERM, //!< CPU has SVE_BITPERM (SVE bit permute) {A64}. + kSVE_EBF16, //!< CPU has SVE_EBF16 (SVE extended BFloat16 mode) {A64}. + kSVE_F32MM, //!< CPU has SVE_F32MM (SVE single-precision floating-point matrix multiply instruction) {A64}. + kSVE_F64MM, //!< CPU has SVE_F64MM (SVE double-precision floating-point matrix multiply instruction) {A64}. + kSVE_I8MM, //!< CPU has SVE_I8MM (SVE int8 matrix multiplication) {A64}. + kSVE_PMULL128, //!< CPU has SVE_PMULL128 (SVE PMULL instructions) {A64}. + kSVE_SHA3, //!< CPU has SVE_SHA3 (SVE SHA-3 instructions) {A64}. + kSVE_SM4, //!< CPU has SVE_SM4 (SVE SM4 instructions {A64}. + kSYSINSTR128, //!< CPU has SYSINSTR128 (128-bit system instructions) {A64}. + kSYSREG128, //!< CPU has SYSREG128 (128-bit system registers) {A64}. + kTHE, //!< CPU has THE (translation hardening extension). + kTLBIOS, //!< CPU has TLBIOS (TLBI instructions in Outer Shareable domain) {A64}. + kTLBIRANGE, //!< CPU has TLBIRANGE (TLBI range instructions) {A64}. + kTLBIW, //!< CPU has TLBIW (TLBI VMALL for dirty state) {A64}. + kTME, //!< CPU has TME (transactional memory extensions). + kTRF, //!< CPU has TRF (self-hosted trace extensions). + kUAO, //!< CPU has UAO (AArch64 v8.2 UAO PState) {A64}. + kVFP_D32, //!< CPU has VFP_D32 (32 VFP-D registers) (ARM/THUMB only). + kVHE, //!< CPU has VHE (virtual host extension). + kVMID16, //!< CPU has VMID16 (16-bit VMID) {A64}. + kWFXT, //!< CPU has WFxT (WFE and WFI instructions with timeout) {A64}. + kXNX, //!< CPU has XNX (translation table stage 2 unprivileged execute-never) {A64}. + kXS, //!< CPU has XS (XS attribute in TLBI and DSB instructions) {A64}. // @EnumValuesEnd@ kMaxValue = kXS }; #define ASMJIT_ARM_FEATURE(FEATURE) \ + /*! Tests whether FEATURE is present. */ \ ASMJIT_INLINE_NODEBUG bool has##FEATURE() const noexcept { return has(ARM::k##FEATURE); } ASMJIT_ARM_FEATURE(THUMB) @@ -642,26 +731,45 @@ public: ASMJIT_ARM_FEATURE(ARMv7) ASMJIT_ARM_FEATURE(ARMv8a) + ASMJIT_ARM_FEATURE(ABLE) + ASMJIT_ARM_FEATURE(ADERR) ASMJIT_ARM_FEATURE(AES) ASMJIT_ARM_FEATURE(AFP) + ASMJIT_ARM_FEATURE(AIE) + ASMJIT_ARM_FEATURE(AMU1) + ASMJIT_ARM_FEATURE(AMU1_1) + ASMJIT_ARM_FEATURE(ANERR) ASMJIT_ARM_FEATURE(ASIMD) ASMJIT_ARM_FEATURE(BF16) + ASMJIT_ARM_FEATURE(BRBE) ASMJIT_ARM_FEATURE(BTI) + ASMJIT_ARM_FEATURE(BWE) ASMJIT_ARM_FEATURE(CCIDX) ASMJIT_ARM_FEATURE(CHK) ASMJIT_ARM_FEATURE(CLRBHB) + ASMJIT_ARM_FEATURE(CMOW) + ASMJIT_ARM_FEATURE(CONSTPACFIELD) + ASMJIT_ARM_FEATURE(CPA) + ASMJIT_ARM_FEATURE(CPA2) ASMJIT_ARM_FEATURE(CPUID) ASMJIT_ARM_FEATURE(CRC32) ASMJIT_ARM_FEATURE(CSSC) + ASMJIT_ARM_FEATURE(CSV2) + ASMJIT_ARM_FEATURE(CSV2_3) + ASMJIT_ARM_FEATURE(CSV3) ASMJIT_ARM_FEATURE(D128) ASMJIT_ARM_FEATURE(DGH) ASMJIT_ARM_FEATURE(DIT) ASMJIT_ARM_FEATURE(DOTPROD) ASMJIT_ARM_FEATURE(DPB) ASMJIT_ARM_FEATURE(DPB2) + ASMJIT_ARM_FEATURE(EBEP) ASMJIT_ARM_FEATURE(EBF16) + ASMJIT_ARM_FEATURE(ECBHB) ASMJIT_ARM_FEATURE(ECV) + ASMJIT_ARM_FEATURE(EDHSR) ASMJIT_ARM_FEATURE(EDSP) + ASMJIT_ARM_FEATURE(FAMINMAX) ASMJIT_ARM_FEATURE(FCMA) ASMJIT_ARM_FEATURE(FGT) ASMJIT_ARM_FEATURE(FGT2) @@ -672,13 +780,25 @@ public: ASMJIT_ARM_FEATURE(FP) ASMJIT_ARM_FEATURE(FP16) ASMJIT_ARM_FEATURE(FP16CONV) + ASMJIT_ARM_FEATURE(FP8) + ASMJIT_ARM_FEATURE(FP8DOT2) + ASMJIT_ARM_FEATURE(FP8DOT4) + ASMJIT_ARM_FEATURE(FP8FMA) + ASMJIT_ARM_FEATURE(FPMR) ASMJIT_ARM_FEATURE(FRINTTS) ASMJIT_ARM_FEATURE(GCS) + ASMJIT_ARM_FEATURE(HACDBS) + ASMJIT_ARM_FEATURE(HAFDBS) + ASMJIT_ARM_FEATURE(HAFT) + ASMJIT_ARM_FEATURE(HDBSS) ASMJIT_ARM_FEATURE(HBC) ASMJIT_ARM_FEATURE(HCX) + ASMJIT_ARM_FEATURE(HPDS) + ASMJIT_ARM_FEATURE(HPDS2) ASMJIT_ARM_FEATURE(I8MM) ASMJIT_ARM_FEATURE(IDIVA) ASMJIT_ARM_FEATURE(IDIVT) + ASMJIT_ARM_FEATURE(ITE) ASMJIT_ARM_FEATURE(JSCVT) ASMJIT_ARM_FEATURE(LOR) ASMJIT_ARM_FEATURE(LRCPC) @@ -690,12 +810,24 @@ public: ASMJIT_ARM_FEATURE(LSE) ASMJIT_ARM_FEATURE(LSE128) ASMJIT_ARM_FEATURE(LSE2) + ASMJIT_ARM_FEATURE(LUT) + ASMJIT_ARM_FEATURE(LVA) + ASMJIT_ARM_FEATURE(LVA3) + ASMJIT_ARM_FEATURE(MEC) ASMJIT_ARM_FEATURE(MOPS) ASMJIT_ARM_FEATURE(MPAM) ASMJIT_ARM_FEATURE(MTE) ASMJIT_ARM_FEATURE(MTE2) ASMJIT_ARM_FEATURE(MTE3) ASMJIT_ARM_FEATURE(MTE4) + ASMJIT_ARM_FEATURE(MTE_ASYM_FAULT) + ASMJIT_ARM_FEATURE(MTE_ASYNC) + ASMJIT_ARM_FEATURE(MTE_CANONICAL_TAGS) + ASMJIT_ARM_FEATURE(MTE_NO_ADDRESS_TAGS) + ASMJIT_ARM_FEATURE(MTE_PERM_S1) + ASMJIT_ARM_FEATURE(MTE_STORE_ONLY) + ASMJIT_ARM_FEATURE(MTE_TAGGED_FAR) + ASMJIT_ARM_FEATURE(MTPMU) ASMJIT_ARM_FEATURE(NMI) ASMJIT_ARM_FEATURE(NV) ASMJIT_ARM_FEATURE(NV2) @@ -703,19 +835,28 @@ public: ASMJIT_ARM_FEATURE(PAN2) ASMJIT_ARM_FEATURE(PAN3) ASMJIT_ARM_FEATURE(PAUTH) + ASMJIT_ARM_FEATURE(PFAR) ASMJIT_ARM_FEATURE(PMU) ASMJIT_ARM_FEATURE(PMULL) ASMJIT_ARM_FEATURE(PRFMSLC) ASMJIT_ARM_FEATURE(RAS) ASMJIT_ARM_FEATURE(RAS1_1) ASMJIT_ARM_FEATURE(RAS2) + ASMJIT_ARM_FEATURE(RASSA2) ASMJIT_ARM_FEATURE(RDM) ASMJIT_ARM_FEATURE(RME) ASMJIT_ARM_FEATURE(RNG) ASMJIT_ARM_FEATURE(RNG_TRAP) ASMJIT_ARM_FEATURE(RPRES) ASMJIT_ARM_FEATURE(RPRFM) + ASMJIT_ARM_FEATURE(S1PIE) + ASMJIT_ARM_FEATURE(S1POE) + ASMJIT_ARM_FEATURE(S2PIE) + ASMJIT_ARM_FEATURE(S2POE) ASMJIT_ARM_FEATURE(SB) + ASMJIT_ARM_FEATURE(SCTLR2) + ASMJIT_ARM_FEATURE(SEBEP) + ASMJIT_ARM_FEATURE(SEL2) ASMJIT_ARM_FEATURE(SHA1) ASMJIT_ARM_FEATURE(SHA256) ASMJIT_ARM_FEATURE(SHA3) @@ -732,14 +873,32 @@ public: ASMJIT_ARM_FEATURE(SME_F16F32) ASMJIT_ARM_FEATURE(SME_F32F32) ASMJIT_ARM_FEATURE(SME_F64F64) + ASMJIT_ARM_FEATURE(SME_F8F16) + ASMJIT_ARM_FEATURE(SME_F8F32) ASMJIT_ARM_FEATURE(SME_FA64) ASMJIT_ARM_FEATURE(SME_I16I32) ASMJIT_ARM_FEATURE(SME_I16I64) ASMJIT_ARM_FEATURE(SME_I8I32) + ASMJIT_ARM_FEATURE(SME_LUTv2) + ASMJIT_ARM_FEATURE(SPE) + ASMJIT_ARM_FEATURE(SPE1_1) + ASMJIT_ARM_FEATURE(SPE1_2) + ASMJIT_ARM_FEATURE(SPE1_3) + ASMJIT_ARM_FEATURE(SPE1_4) + ASMJIT_ARM_FEATURE(SPE_ALTCLK) + ASMJIT_ARM_FEATURE(SPE_CRR) + ASMJIT_ARM_FEATURE(SPE_EFT) + ASMJIT_ARM_FEATURE(SPE_FDS) + ASMJIT_ARM_FEATURE(SPE_FPF) + ASMJIT_ARM_FEATURE(SPE_SME) ASMJIT_ARM_FEATURE(SPECRES) ASMJIT_ARM_FEATURE(SPECRES2) + ASMJIT_ARM_FEATURE(SPMU) ASMJIT_ARM_FEATURE(SSBS) ASMJIT_ARM_FEATURE(SSBS2) + ASMJIT_ARM_FEATURE(SSVE_FP8DOT2) + ASMJIT_ARM_FEATURE(SSVE_FP8DOT4) + ASMJIT_ARM_FEATURE(SSVE_FP8FMA) ASMJIT_ARM_FEATURE(SVE) ASMJIT_ARM_FEATURE(SVE2) ASMJIT_ARM_FEATURE(SVE2_1) @@ -757,12 +916,17 @@ public: ASMJIT_ARM_FEATURE(SYSINSTR128) ASMJIT_ARM_FEATURE(SYSREG128) ASMJIT_ARM_FEATURE(THE) + ASMJIT_ARM_FEATURE(TLBIOS) + ASMJIT_ARM_FEATURE(TLBIRANGE) + ASMJIT_ARM_FEATURE(TLBIW) ASMJIT_ARM_FEATURE(TME) ASMJIT_ARM_FEATURE(TRF) ASMJIT_ARM_FEATURE(UAO) ASMJIT_ARM_FEATURE(VFP_D32) ASMJIT_ARM_FEATURE(VHE) + ASMJIT_ARM_FEATURE(VMID16) ASMJIT_ARM_FEATURE(WFXT) + ASMJIT_ARM_FEATURE(XNX) ASMJIT_ARM_FEATURE(XS) #undef ASMJIT_ARM_FEATURE @@ -785,6 +949,7 @@ public: ASMJIT_INLINE_NODEBUG CpuFeatures() noexcept {} ASMJIT_INLINE_NODEBUG CpuFeatures(const CpuFeatures& other) noexcept = default; + ASMJIT_INLINE_NODEBUG explicit CpuFeatures(const Data& other) noexcept : _data{other._bits} {} ASMJIT_INLINE_NODEBUG explicit CpuFeatures(Globals::NoInit_) noexcept {} //! \} @@ -794,8 +959,8 @@ public: ASMJIT_INLINE_NODEBUG CpuFeatures& operator=(const CpuFeatures& other) noexcept = default; - ASMJIT_INLINE_NODEBUG bool operator==(const CpuFeatures& other) noexcept { return eq(other); } - ASMJIT_INLINE_NODEBUG bool operator!=(const CpuFeatures& other) noexcept { return !eq(other); } + ASMJIT_INLINE_NODEBUG bool operator==(const CpuFeatures& other) const noexcept { return equals(other); } + ASMJIT_INLINE_NODEBUG bool operator!=(const CpuFeatures& other) const noexcept { return !equals(other); } //! \} @@ -849,6 +1014,7 @@ public: //! \name Manipulation //! \{ + //! Clears all features set. ASMJIT_INLINE_NODEBUG void reset() noexcept { _data.reset(); } //! Adds the given CPU `featureId` to the list of features. @@ -864,7 +1030,12 @@ public: ASMJIT_INLINE_NODEBUG void remove(Args&&... args) noexcept { return _data.remove(std::forward(args)...); } //! Tests whether this CPU features matches `other`. - ASMJIT_INLINE_NODEBUG bool eq(const CpuFeatures& other) const noexcept { return _data.eq(other._data); } + ASMJIT_INLINE_NODEBUG bool equals(const CpuFeatures& other) const noexcept { return _data.equals(other._data); } + +#if !defined(ASMJIT_NO_DEPRECATED) + ASMJIT_DEPRECATED("Use CpuFeatures::equals() instead") + ASMJIT_INLINE_NODEBUG bool eq(const CpuFeatures& other) const noexcept { return equals(other); } +#endif // !ASMJIT_NO_DEPRECATED //! \} }; @@ -876,65 +1047,82 @@ public: //! \{ //! Architecture. - Arch _arch; + Arch _arch {}; //! Sub-architecture. - SubArch _subArch; + SubArch _subArch {}; //! True if the CPU was detected, false if the detection failed or it's not available. - bool _wasDetected; + bool _wasDetected {}; //! Reserved for future use. - uint8_t _reserved; + uint8_t _reserved {}; //! CPU family ID. - uint32_t _familyId; + uint32_t _familyId {}; //! CPU model ID. - uint32_t _modelId; + uint32_t _modelId {}; //! CPU brand ID. - uint32_t _brandId; + uint32_t _brandId {}; //! CPU stepping. - uint32_t _stepping; + uint32_t _stepping {}; //! Processor type. - uint32_t _processorType; + uint32_t _processorType {}; //! Maximum number of addressable IDs for logical processors. - uint32_t _maxLogicalProcessors; + uint32_t _maxLogicalProcessors {}; //! Cache line size (in bytes). - uint32_t _cacheLineSize; + uint32_t _cacheLineSize {}; //! Number of hardware threads. - uint32_t _hwThreadCount; + uint32_t _hwThreadCount {}; //! CPU vendor string. - FixedString<16> _vendor; + FixedString<16> _vendor {}; //! CPU brand string. - FixedString<64> _brand; + FixedString<64> _brand {}; //! CPU features. - CpuFeatures _features; + CpuFeatures _features {}; //! \} //! \name Construction & Destruction //! \{ - ASMJIT_INLINE_NODEBUG CpuInfo() noexcept { reset(); } + //! Creates a new CpuInfo instance. + ASMJIT_INLINE_NODEBUG CpuInfo() noexcept {} + //! Creates a copy of `other` instance. ASMJIT_INLINE_NODEBUG CpuInfo(const CpuInfo& other) noexcept = default; + //! Creates an unitialized `CpuInfo` instance. ASMJIT_INLINE_NODEBUG explicit CpuInfo(Globals::NoInit_) noexcept : _features(Globals::NoInit) {}; + //! \} + + //! \name CPU Information Detection + //! \{ + //! Returns the host CPU information. + //! + //! \note The returned reference is global - it's setup only once and then shared. ASMJIT_API static const CpuInfo& host() noexcept; + //! \} + + //! \name Overloaded Operators + //! \{ + + //! Copy assignment. + ASMJIT_INLINE_NODEBUG CpuInfo& operator=(const CpuInfo& other) noexcept = default; + + //! \} + + //! \name Initialization & Reset + //! \{ + //! Initializes CpuInfo architecture and sub-architecture members to `arch` and `subArch`, respectively. ASMJIT_INLINE_NODEBUG void initArch(Arch arch, SubArch subArch = SubArch::kUnknown) noexcept { _arch = arch; _subArch = subArch; } - ASMJIT_INLINE_NODEBUG void reset() noexcept { memset(this, 0, sizeof(*this)); } - - //! \} - - //! \name Overloaded Operators - //! \{ - - ASMJIT_INLINE_NODEBUG CpuInfo& operator=(const CpuInfo& other) noexcept = default; + //! Resets this \ref CpuInfo to a default constructed state. + ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = CpuInfo{}; } //! \} @@ -1004,7 +1192,7 @@ public: //! Returns a CPU vendor string. ASMJIT_INLINE_NODEBUG const char* vendor() const noexcept { return _vendor.str; } //! Tests whether the CPU vendor string is equal to `s`. - ASMJIT_INLINE_NODEBUG bool isVendor(const char* s) const noexcept { return _vendor.eq(s); } + ASMJIT_INLINE_NODEBUG bool isVendor(const char* s) const noexcept { return _vendor.equals(s); } //! Returns a CPU brand string. ASMJIT_INLINE_NODEBUG const char* brand() const noexcept { return _brand.str; } diff --git a/deps/asmjit/src/asmjit/core/emithelper.cpp b/deps/asmjit/src/asmjit/core/emithelper.cpp index c06bbe2a..36b984f8 100644 --- a/deps/asmjit/src/asmjit/core/emithelper.cpp +++ b/deps/asmjit/src/asmjit/core/emithelper.cpp @@ -216,14 +216,17 @@ ASMJIT_FAVOR_SIZE Error BaseEmitHelper::emitArgsAssignment(const FuncFrame& fram } else { WorkData& wd = workData[outGroup]; - if (!wd.isAssigned(outId)) { + if (!wd.isAssigned(outId) || curId == outId) { EmitMove: ASMJIT_PROPAGATE( emitArgMove( BaseReg(archTraits.regTypeToSignature(out.regType()), outId), out.typeId(), BaseReg(archTraits.regTypeToSignature(cur.regType()), curId), cur.typeId())); - wd.reassign(varId, outId, curId); + // Only reassign if this is not a sign/zero extension that happens on the same in/out register. + if (curId != outId) + wd.reassign(varId, outId, curId); + cur.initReg(out.regType(), outId, out.typeId()); if (outId == out.regId()) diff --git a/deps/asmjit/src/asmjit/core/emitter.cpp b/deps/asmjit/src/asmjit/core/emitter.cpp index b9b2f896..4c855ea5 100644 --- a/deps/asmjit/src/asmjit/core/emitter.cpp +++ b/deps/asmjit/src/asmjit/core/emitter.cpp @@ -384,6 +384,7 @@ Error BaseEmitter::onDetach(CodeHolder* code) noexcept { _errorHandler = nullptr; _clearEmitterFlags(~kEmitterPreservedFlags); + _instructionAlignment = uint8_t(0); _forcedInstOptions = InstOptions::kReserved; _privateData = 0; @@ -393,6 +394,7 @@ Error BaseEmitter::onDetach(CodeHolder* code) noexcept { _instOptions = InstOptions::kNone; _extraReg.reset(); _inlineComment = nullptr; + _funcs.reset(); return kErrorOk; } diff --git a/deps/asmjit/src/asmjit/core/emitter.h b/deps/asmjit/src/asmjit/core/emitter.h index a8367906..3053721c 100644 --- a/deps/asmjit/src/asmjit/core/emitter.h +++ b/deps/asmjit/src/asmjit/core/emitter.h @@ -194,6 +194,7 @@ ASMJIT_DEFINE_ENUM_FLAGS(DiagnosticOptions) class ASMJIT_VIRTAPI BaseEmitter { public: ASMJIT_BASE_CLASS(BaseEmitter) + ASMJIT_NONCOPYABLE(BaseEmitter) //! \name Members //! \{ @@ -202,6 +203,11 @@ public: EmitterType _emitterType = EmitterType::kNone; //! See \ref EmitterFlags. EmitterFlags _emitterFlags = EmitterFlags::kNone; + //! Instruction alignment. + uint8_t _instructionAlignment = 0u; + //! \cond + uint8_t _reservedBaseEmitter = 0u; + //! \endcond //! Validation flags in case validation is used. //! //! \note Validation flags are specific to the emitter and they are setup at construction time and then never @@ -262,7 +268,7 @@ public: Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount) ASMJIT_NOEXCEPT_TYPE; - typedef Error (ASMJIT_CDECL* ValidateFunc)(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) ASMJIT_NOEXCEPT_TYPE; + typedef Error (ASMJIT_CDECL* ValidateFunc)(const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) ASMJIT_NOEXCEPT_TYPE; //! Emit prolog implementation. EmitProlog emitProlog; @@ -331,10 +337,17 @@ public: //! Tests whether the emitter is destroyed (only used during destruction). ASMJIT_INLINE_NODEBUG bool isDestroyed() const noexcept { return hasEmitterFlag(EmitterFlags::kDestroyed); } + //! \} + + //! \cond INTERNAL + //! \name Internal Functions + //! \{ + ASMJIT_INLINE_NODEBUG void _addEmitterFlags(EmitterFlags flags) noexcept { _emitterFlags |= flags; } ASMJIT_INLINE_NODEBUG void _clearEmitterFlags(EmitterFlags flags) noexcept { _emitterFlags &= _emitterFlags & ~flags; } //! \} + //! \endcond //! \name Target Information //! \{ @@ -360,6 +373,17 @@ public: //! Returns the target architecture's GP register size (4 or 8 bytes). ASMJIT_INLINE_NODEBUG uint32_t registerSize() const noexcept { return environment().registerSize(); } + //! Returns a signature of a native general purpose register (either 32-bit or 64-bit depending on the architecture). + ASMJIT_INLINE_NODEBUG OperandSignature gpSignature() const noexcept { return _gpSignature; } + + //! Returns instruction alignment. + //! + //! The following values are returned based on the target architecture: + //! - X86 and X86_64 - instruction alignment is 1 + //! - AArch32 - instruction alignment is 4 in A32 mode and 2 in THUMB mode. + //! - AArch64 - instruction alignment is 4 + ASMJIT_INLINE_NODEBUG uint32_t instructionAlignment() const noexcept { return _instructionAlignment; } + //! \} //! \name Initialization & Finalization @@ -540,23 +564,38 @@ public: //! \name Emitter State //! \{ + //! Resets the emitter state, which contains instruction options, extra register, and inline comment. + //! + //! Emitter can have a state that describes instruction options and extra register used by the instruction. Most + //! instructions don't need nor use the state, however, if an instruction uses a prefix such as REX or REP prefix, + //! which is set explicitly, then the state would contain it. This allows to mimic the syntax of assemblers such + //! as X86. For example `rep().movs(...)` would map to a `REP MOVS` instuction on X86. The same applies to various + //! hints and the use of a mask register in AVX-512 mode. ASMJIT_INLINE_NODEBUG void resetState() noexcept { resetInstOptions(); resetExtraReg(); resetInlineComment(); } + //! \cond INTERNAL + + //! Grabs the current emitter state and resets the emitter state at the same time, returning the state the emitter + //! had before the state was reset. ASMJIT_INLINE_NODEBUG State _grabState() noexcept { State s{_instOptions | _forcedInstOptions, _extraReg, _inlineComment}; resetState(); return s; } + //! \endcond //! \} //! \name Sections //! \{ + //! Switches the given `section`. + //! + //! Once switched, everything is added to the given `section`. ASMJIT_API virtual Error section(Section* section); //! \} @@ -620,35 +659,51 @@ public: ASMJIT_API Error _emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5); //! Emits an instruction `instId` with the given `operands`. + //! + //! This is the most universal way of emitting code, which accepts an instruction identifier and instruction + //! operands. This is called an "unchecked" API as emit doesn't provide any type checks at compile-time. This + //! allows to emit instruction with just \ref Operand instances, which could be handy in some cases - for + //! example emitting generic code where you don't know whether some operand is register, memory, or immediate. template ASMJIT_INLINE_NODEBUG Error emit(InstId instId, Args&&... operands) { return _emitI(instId, Support::ForwardOp::forward(operands)...); } + //! Similar to \ref emit(), but uses array of `operands` instead. ASMJIT_INLINE_NODEBUG Error emitOpArray(InstId instId, const Operand_* operands, size_t opCount) { return _emitOpArray(instId, operands, opCount); } + //! Similar to \ref emit(), but emits instruction with both instruction options and extra register, followed + //! by an array of `operands`. ASMJIT_FORCE_INLINE Error emitInst(const BaseInst& inst, const Operand_* operands, size_t opCount) { setInstOptions(inst.options()); setExtraReg(inst.extraReg()); return _emitOpArray(inst.id(), operands, opCount); } + //! \} + //! \cond INTERNAL + //! \name Emit Internals + //! \{ + //! Emits an instruction - all 6 operands must be defined. ASMJIT_API virtual Error _emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* oExt); //! Emits instruction having operands stored in array. ASMJIT_API virtual Error _emitOpArray(InstId instId, const Operand_* operands, size_t opCount); - //! \endcond //! \} + //! \endcond //! \name Emit Utilities //! \{ + //! Emits a function prolog described by the given function `frame`. ASMJIT_API Error emitProlog(const FuncFrame& frame); + //! Emits a function epilog described by the given function `frame`. ASMJIT_API Error emitEpilog(const FuncFrame& frame); + //! Emits code that reassigns function `frame` arguments to the given `args`. ASMJIT_API Error emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args); //! \} diff --git a/deps/asmjit/src/asmjit/core/environment.h b/deps/asmjit/src/asmjit/core/environment.h index 3095405c..c3678dc6 100644 --- a/deps/asmjit/src/asmjit/core/environment.h +++ b/deps/asmjit/src/asmjit/core/environment.h @@ -24,7 +24,7 @@ enum class Vendor : uint8_t { //! Unknown or uninitialized platform vendor. kUnknown = 0, - //! Maximum value of `PlatformVendor`. + //! Maximum value of `Vendor`. kMaxValue = kUnknown, //! Platform vendor detected at compile-time. @@ -116,7 +116,7 @@ enum class Platform : uint8_t { //! Platform ABI (application binary interface). enum class PlatformABI : uint8_t { - //! Unknown or uninitialied environment. + //! Unknown or uninitialized environment. kUnknown = 0, //! Microsoft ABI. kMSVC, @@ -126,6 +126,8 @@ enum class PlatformABI : uint8_t { kAndroid, //! Cygwin ABI. kCygwin, + //! Darwin ABI. + kDarwin, //! Maximum value of `PlatformABI`. kMaxValue, @@ -142,11 +144,26 @@ enum class PlatformABI : uint8_t { kGNU #elif defined(__ANDROID__) kAndroid +#elif defined(__APPLE__) + kDarwin #else kUnknown #endif }; +//! Floating point ABI (ARM). +enum class FloatABI : uint8_t { + kHardFloat = 0, + kSoftFloat, + + kHost = +#if ASMJIT_ARCH_ARM == 32 && defined(__SOFTFP__) + kSoftFloat +#else + kHardFloat +#endif +}; + //! Object format. //! //! \note AsmJit doesn't really use anything except \ref ObjectFormat::kUnknown and \ref ObjectFormat::kJIT at @@ -186,53 +203,56 @@ public: //! \{ //! Architecture. - Arch _arch; + Arch _arch = Arch::kUnknown; //! Sub-architecture type. - SubArch _subArch; + SubArch _subArch = SubArch::kUnknown; //! Vendor type. - Vendor _vendor; + Vendor _vendor = Vendor::kUnknown; //! Platform. - Platform _platform; + Platform _platform = Platform::kUnknown; //! Platform ABI. - PlatformABI _platformABI; + PlatformABI _platformABI = PlatformABI::kUnknown; //! Object format. - ObjectFormat _objectFormat; + ObjectFormat _objectFormat = ObjectFormat::kUnknown; + //! Floating point ABI. + FloatABI _floatABI = FloatABI::kHardFloat; //! Reserved for future use, must be zero. - uint8_t _reserved[2]; + uint8_t _reserved = 0; //! \} //! \name Construction & Destruction //! \{ - ASMJIT_INLINE_NODEBUG Environment() noexcept : - _arch(Arch::kUnknown), - _subArch(SubArch::kUnknown), - _vendor(Vendor::kUnknown), - _platform(Platform::kUnknown), - _platformABI(PlatformABI::kUnknown), - _objectFormat(ObjectFormat::kUnknown), - _reserved { 0, 0 } {} + //! Creates a default initialized environment (all values either unknown or set to safe defaults). + ASMJIT_INLINE_NODEBUG constexpr Environment() noexcept = default; + //! Creates a copy of `other` instance. + ASMJIT_INLINE_NODEBUG constexpr Environment(const Environment& other) noexcept = default; - ASMJIT_INLINE_NODEBUG explicit Environment( + //! Creates \ref Environment initialized to `arch`, `subArch`, `vendor`, `platform`, `platformABI`, `objectFormat`, + //! and `floatABI`. + ASMJIT_INLINE_NODEBUG constexpr explicit Environment( Arch arch, SubArch subArch = SubArch::kUnknown, Vendor vendor = Vendor::kUnknown, Platform platform = Platform::kUnknown, - PlatformABI abi = PlatformABI::kUnknown, - ObjectFormat objectFormat = ObjectFormat::kUnknown) noexcept { - - init(arch, subArch, vendor, platform, abi, objectFormat); - } - - ASMJIT_INLINE_NODEBUG Environment(const Environment& other) noexcept = default; + PlatformABI platformABI = PlatformABI::kUnknown, + ObjectFormat objectFormat = ObjectFormat::kUnknown, + FloatABI floatABI = FloatABI::kHardFloat) noexcept + : _arch(arch), + _subArch(subArch), + _vendor(vendor), + _platform(platform), + _platformABI(platformABI), + _objectFormat(objectFormat), + _floatABI(floatABI) {} //! Returns the host environment constructed from preprocessor macros defined by the compiler. //! //! The returned environment should precisely match the target host architecture, sub-architecture, platform, //! and ABI. static ASMJIT_INLINE_NODEBUG Environment host() noexcept { - return Environment(Arch::kHost, SubArch::kHost, Vendor::kHost, Platform::kHost, PlatformABI::kHost, ObjectFormat::kUnknown); + return Environment(Arch::kHost, SubArch::kHost, Vendor::kHost, Platform::kHost, PlatformABI::kHost, ObjectFormat::kUnknown, FloatABI::kHost); } //! \} @@ -271,20 +291,10 @@ public: } //! Resets all members of the environment to zero / unknown. - ASMJIT_INLINE_NODEBUG void reset() noexcept { - _arch = Arch::kUnknown; - _subArch = SubArch::kUnknown; - _vendor = Vendor::kUnknown; - _platform = Platform::kUnknown; - _platformABI = PlatformABI::kUnknown; - _objectFormat = ObjectFormat::kUnknown; - _reserved[0] = 0; - _reserved[1] = 0; - } + ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = Environment{}; } - ASMJIT_INLINE_NODEBUG bool equals(const Environment& other) const noexcept { - return _packed() == other._packed(); - } + //! Tests whether this environment is equal to `other`. + ASMJIT_INLINE_NODEBUG bool equals(const Environment& other) const noexcept { return _packed() == other._packed(); } //! Returns the architecture. ASMJIT_INLINE_NODEBUG Arch arch() const noexcept { return _arch; } @@ -298,14 +308,19 @@ public: ASMJIT_INLINE_NODEBUG PlatformABI platformABI() const noexcept { return _platformABI; } //! Returns target's object format. ASMJIT_INLINE_NODEBUG ObjectFormat objectFormat() const noexcept { return _objectFormat; } + //! Returns floating point ABI. + ASMJIT_INLINE_NODEBUG FloatABI floatABI() const noexcept { return _floatABI; } + //! Initializes \ref Environment to `arch`, `subArch`, `vendor`, `platform`, `platformABI`, `objectFormat`, + //! and `floatABI`. inline void init( Arch arch, SubArch subArch = SubArch::kUnknown, Vendor vendor = Vendor::kUnknown, Platform platform = Platform::kUnknown, PlatformABI platformABI = PlatformABI::kUnknown, - ObjectFormat objectFormat = ObjectFormat::kUnknown) noexcept { + ObjectFormat objectFormat = ObjectFormat::kUnknown, + FloatABI floatABI = FloatABI::kHardFloat) noexcept { _arch = arch; _subArch = subArch; @@ -313,18 +328,27 @@ public: _platform = platform; _platformABI = platformABI; _objectFormat = objectFormat; - _reserved[0] = 0; - _reserved[1] = 0; + _floatABI = floatABI; + _reserved = 0; } + //! Tests whether this environment describes a 32-bit X86. ASMJIT_INLINE_NODEBUG bool isArchX86() const noexcept { return _arch == Arch::kX86; } + //! Tests whether this environment describes a 64-bit X86. ASMJIT_INLINE_NODEBUG bool isArchX64() const noexcept { return _arch == Arch::kX64; } + //! Tests whether this environment describes a 32-bit ARM. ASMJIT_INLINE_NODEBUG bool isArchARM() const noexcept { return isArchARM(_arch); } + //! Tests whether this environment describes a 32-bit ARM in THUMB mode. ASMJIT_INLINE_NODEBUG bool isArchThumb() const noexcept { return isArchThumb(_arch); } + //! Tests whether this environment describes a 64-bit X86. ASMJIT_INLINE_NODEBUG bool isArchAArch64() const noexcept { return isArchAArch64(_arch); } + //! Tests whether this environment describes a 32-bit MIPS. ASMJIT_INLINE_NODEBUG bool isArchMIPS32() const noexcept { return isArchMIPS32(_arch); } + //! Tests whether this environment describes a 64-bit MIPS. ASMJIT_INLINE_NODEBUG bool isArchMIPS64() const noexcept { return isArchMIPS64(_arch); } + //! Tests whether this environment describes a 32-bit RISC-V. ASMJIT_INLINE_NODEBUG bool isArchRISCV32() const noexcept { return _arch == Arch::kRISCV32; } + //! Tests whether this environment describes a 64-bit RISC-V. ASMJIT_INLINE_NODEBUG bool isArchRISCV64() const noexcept { return _arch == Arch::kRISCV64; } //! Tests whether the architecture is 32-bit. @@ -352,13 +376,10 @@ public: //! Tests whether the environment platform is Windows. ASMJIT_INLINE_NODEBUG bool isPlatformWindows() const noexcept { return _platform == Platform::kWindows; } - //! Tests whether the environment platform is Linux. ASMJIT_INLINE_NODEBUG bool isPlatformLinux() const noexcept { return _platform == Platform::kLinux; } - //! Tests whether the environment platform is Hurd. ASMJIT_INLINE_NODEBUG bool isPlatformHurd() const noexcept { return _platform == Platform::kHurd; } - //! Tests whether the environment platform is Haiku. ASMJIT_INLINE_NODEBUG bool isPlatformHaiku() const noexcept { return _platform == Platform::kHaiku; } @@ -382,6 +403,8 @@ public: ASMJIT_INLINE_NODEBUG bool isMSVC() const noexcept { return _platformABI == PlatformABI::kMSVC; } //! Tests whether the ABI is GNU. ASMJIT_INLINE_NODEBUG bool isGNU() const noexcept { return _platformABI == PlatformABI::kGNU; } + //! Tests whether the ABI is GNU. + ASMJIT_INLINE_NODEBUG bool isDarwin() const noexcept { return _platformABI == PlatformABI::kDarwin; } //! Returns a calculated stack alignment for this environment. ASMJIT_API uint32_t stackAlignment() const noexcept; @@ -402,6 +425,9 @@ public: //! Sets the object format to `objectFormat`. ASMJIT_INLINE_NODEBUG void setObjectFormat(ObjectFormat objectFormat) noexcept { _objectFormat = objectFormat; } + //! Sets floating point ABI to `floatABI`. + ASMJIT_INLINE_NODEBUG void setFloatABI(FloatABI floatABI) noexcept { _floatABI = floatABI; } + //! \} //! \name Static Utilities @@ -465,11 +491,6 @@ public: return arch == Arch::kX86 || arch == Arch::kX64; } - //! Tests whether the given architecture family is ARM, THUMB, or AArch64. - static ASMJIT_INLINE_NODEBUG bool isFamilyARM(Arch arch) noexcept { - return isArchARM(arch) || isArchAArch64(arch) || isArchThumb(arch); - } - //! Tests whether the given architecture family is AArch32 (ARM or THUMB). static ASMJIT_INLINE_NODEBUG bool isFamilyAArch32(Arch arch) noexcept { return isArchARM(arch) || isArchThumb(arch); @@ -480,7 +501,12 @@ public: return isArchAArch64(arch); } - //! Tests whether the given architecture family is MISP or MIPS64. + //! Tests whether the given architecture family is ARM, THUMB, or AArch64. + static ASMJIT_INLINE_NODEBUG bool isFamilyARM(Arch arch) noexcept { + return isFamilyAArch32(arch) || isFamilyAArch64(arch); + } + + //! Tests whether the given architecture family is MIPS or MIPS64. static ASMJIT_INLINE_NODEBUG bool isFamilyMIPS(Arch arch) noexcept { return isArchMIPS32(arch) || isArchMIPS64(arch); } diff --git a/deps/asmjit/src/asmjit/core/formatter.cpp b/deps/asmjit/src/asmjit/core/formatter.cpp index 3fd51371..0f12e416 100644 --- a/deps/asmjit/src/asmjit/core/formatter.cpp +++ b/deps/asmjit/src/asmjit/core/formatter.cpp @@ -57,7 +57,7 @@ Error formatTypeId(String& sb, TypeId typeId) noexcept { if (!TypeUtils::isValid(typeId)) return sb.append("unknown"); - const char* typeName = "unknown"; + const char* typeName = nullptr; uint32_t typeSize = TypeUtils::sizeOf(typeId); TypeId scalarType = TypeUtils::scalarOf(typeId); @@ -166,8 +166,8 @@ Error formatRegister( #endif #if !defined(ASMJIT_NO_AARCH64) - if (Environment::isFamilyAArch64(arch)) - return a64::FormatterInternal::formatRegister(sb, formatFlags, emitter, arch, regType, regId); + if (Environment::isFamilyARM(arch)) + return arm::FormatterInternal::formatRegister(sb, formatFlags, emitter, arch, regType, regId); #endif return kErrorInvalidArch; @@ -186,8 +186,8 @@ Error formatOperand( #endif #if !defined(ASMJIT_NO_AARCH64) - if (Environment::isFamilyAArch64(arch)) - return a64::FormatterInternal::formatOperand(sb, formatFlags, emitter, arch, op); + if (Environment::isFamilyARM(arch)) + return arm::FormatterInternal::formatOperand(sb, formatFlags, emitter, arch, op); #endif return kErrorInvalidArch; @@ -284,7 +284,7 @@ Error formatInstruction( #endif #if !defined(ASMJIT_NO_AARCH64) - if (Environment::isFamilyARM(arch)) + if (Environment::isFamilyAArch64(arch)) return a64::FormatterInternal::formatInstruction(sb, formatFlags, emitter, arch, inst, operands, opCount); #endif @@ -514,7 +514,7 @@ Error formatNode( ASMJIT_PROPAGATE(sb.append("[FuncRet]")); for (uint32_t i = 0; i < 2; i++) { - const Operand_& op = retNode->_opArray[i]; + const Operand_& op = retNode->op(i); if (!op.isNone()) { ASMJIT_PROPAGATE(sb.append(i == 0 ? " " : ", ")); ASMJIT_PROPAGATE(formatOperand(sb, formatOptions.flags(), builder, builder->arch(), op)); diff --git a/deps/asmjit/src/asmjit/core/func.cpp b/deps/asmjit/src/asmjit/core/func.cpp index 04dc2aaf..a8a6d3ab 100644 --- a/deps/asmjit/src/asmjit/core/func.cpp +++ b/deps/asmjit/src/asmjit/core/func.cpp @@ -20,8 +20,8 @@ ASMJIT_BEGIN_NAMESPACE -// CallConv - Init & Reset -// ======================= +// CallConv - Initialization & Reset +// ================================= ASMJIT_FAVOR_SIZE Error CallConv::init(CallConvId ccId, const Environment& environment) noexcept { reset(); @@ -75,7 +75,7 @@ ASMJIT_FAVOR_SIZE Error FuncDetail::init(const FuncSignature& signature, const E #if !defined(ASMJIT_NO_AARCH64) if (environment.isFamilyAArch64()) - return a64::FuncInternal::initFuncDetail(*this, signature, registerSize); + return a64::FuncInternal::initFuncDetail(*this, signature); #endif // We should never bubble here as if `cc.init()` succeeded then there has to be an implementation for the current @@ -283,4 +283,18 @@ ASMJIT_FAVOR_SIZE Error FuncArgsAssignment::updateFuncFrame(FuncFrame& frame) co return kErrorOk; } +// Func API - Tests +// ================ + +#if defined(ASMJIT_TEST) +UNIT(func_signature) { + FuncSignature signature; + signature.setRetT(); + signature.addArgT(); + signature.addArg(TypeId::kInt32); + + EXPECT_EQ(signature, FuncSignature::build()); +} +#endif + ASMJIT_END_NAMESPACE diff --git a/deps/asmjit/src/asmjit/core/func.h b/deps/asmjit/src/asmjit/core/func.h index 2dbedc1c..695a23bb 100644 --- a/deps/asmjit/src/asmjit/core/func.h +++ b/deps/asmjit/src/asmjit/core/func.h @@ -28,9 +28,6 @@ ASMJIT_BEGIN_NAMESPACE //! - Target specific - calling conventions that are used by a particular architecture and ABI. For example //! Windows 64-bit calling convention and AMD64 SystemV calling convention. enum class CallConvId : uint8_t { - //! None or invalid (can't be used). - kNone = 0, - // Universal Calling Conventions // ----------------------------- @@ -38,48 +35,38 @@ enum class CallConvId : uint8_t { //! //! This is a universal calling convention, which is used to initialize specific calling conventions based on //! architecture, platform, and its ABI. - kCDecl = 1, + kCDecl = 0, //! `__stdcall` on targets that support this calling convention (X86). //! //! \note This calling convention is only supported on 32-bit X86. If used on environment that doesn't support //! this calling convention it will be replaced by \ref CallConvId::kCDecl. - kStdCall = 2, + kStdCall = 1, //! `__fastcall` on targets that support this calling convention (X86). //! //! \note This calling convention is only supported on 32-bit X86. If used on environment that doesn't support //! this calling convention it will be replaced by \ref CallConvId::kCDecl. - kFastCall = 3, + kFastCall = 2, //! `__vectorcall` on targets that support this calling convention (X86/X64). //! //! \note This calling convention is only supported on 32-bit and 64-bit X86 architecture on Windows platform. //! If used on environment that doesn't support this calling it will be replaced by \ref CallConvId::kCDecl. - kVectorCall = 4, + kVectorCall = 3, //! `__thiscall` on targets that support this calling convention (X86). //! //! \note This calling convention is only supported on 32-bit X86 Windows platform. If used on environment that //! doesn't support this calling convention it will be replaced by \ref CallConvId::kCDecl. - kThisCall = 5, + kThisCall = 4, //! `__attribute__((regparm(1)))` convention (GCC and Clang). - kRegParm1 = 6, + kRegParm1 = 5, //! `__attribute__((regparm(2)))` convention (GCC and Clang). - kRegParm2 = 7, + kRegParm2 = 6, //! `__attribute__((regparm(3)))` convention (GCC and Clang). - kRegParm3 = 8, - - //! Soft-float calling convention (ARM). - //! - //! Floating point arguments are passed via general purpose registers. - kSoftFloat = 9, - - //! Hard-float calling convention (ARM). - //! - //! Floating point arguments are passed via SIMD registers. - kHardFloat = 10, + kRegParm3 = 7, //! AsmJit specific calling convention designed for calling functions inside a multimedia code that don't use many //! registers internally, but are long enough to be called and not inlined. These functions are usually used to @@ -91,28 +78,32 @@ enum class CallConvId : uint8_t { // ABI-Specific Calling Conventions // -------------------------------- + //! Soft-float calling convention (AArch32). + //! + //! Floating point arguments are passed via general purpose registers. + kSoftFloat = 30, + + //! Hard-float calling convention (AArch32). + //! + //! Floating point arguments are passed via SIMD registers. + kHardFloat = 31, + //! X64 System-V calling convention. kX64SystemV = 32, //! X64 Windows calling convention. kX64Windows = 33, //! Maximum value of `CallConvId`. - kMaxValue = kX64Windows, + kMaxValue = kX64Windows - // Host Calling Conventions - // ------------------------ + // Deprecated Aliases + // ------------------ - //! Host calling convention detected at compile-time. - kHost = -#if defined(_DOXYGEN) - DETECTED_AT_COMPILE_TIME -#elif ASMJIT_ARCH_ARM == 32 && defined(__SOFTFP__) - kSoftFloat -#elif ASMJIT_ARCH_ARM == 32 && !defined(__SOFTFP__) - kHardFloat -#else - kCDecl -#endif +#if !defined(ASMJIT_NO_DEPRECATED) + , + kNone = kCDecl, + kHost = kCDecl +#endif // !ASMJIT_NO_DEPRECATED }; //! Strategy used by calling conventions to assign registers to function arguments. @@ -128,6 +119,8 @@ enum class CallConvStrategy : uint8_t { kX64Windows = 1, //! Windows 64-bit __vectorcall register assignment strategy. kX64VectorCall = 2, + //! Apple's AArch64 calling convention (differs compared to AArch64 calling convention used by Linux). + kAArch64Apple = 3, //! Maximum value of `CallConvStrategy`. kMaxValue = kX64VectorCall @@ -189,6 +182,11 @@ struct CallConv { //! Natural stack alignment as defined by OS/ABI. uint8_t _naturalStackAlignment; + //! \cond INTERNAL + //! Reserved for future use. + uint8_t _reserved[2]; + //! \endcond + //! Calling convention flags. CallConvFlags _flags; @@ -229,7 +227,7 @@ struct CallConv { //! as it prevents from using an uninitialized data (CallConv doesn't have a constructor that would initialize it, //! it's just a struct). ASMJIT_INLINE_NODEBUG void reset() noexcept { - memset(this, 0, sizeof(*this)); + *this = CallConv{}; memset(_passedOrder.data(), 0xFF, sizeof(_passedOrder)); } @@ -362,8 +360,15 @@ struct CallConv { //! Function signature. //! -//! Contains information about function return type, count of arguments and their TypeIds. Function signature is -//! a low level structure which doesn't contain platform specific or calling convention specific information. +//! Contains information about a function return type, count of arguments, and their TypeIds. Function signature +//! is a low level structure which doesn't contain platform specific or calling convention specific information. +//! It's typically used to describe function arguments in a C-API like form, which is then used to calculate a +//! \ref FuncDetail instance, which then maps function signature into a platform and calling convention specific +//! format. +//! +//! Function signature can be built either dynamically by using \ref addArg() and \ref addArgT() functionality, +//! or dynamically by using a template-based \ref FuncSignature::build() function, which maps template types +//! into a function signature. struct FuncSignature { //! \name Constants //! \{ @@ -377,36 +382,91 @@ struct FuncSignature { //! \{ //! Calling convention id. - CallConvId _ccId; + CallConvId _ccId = CallConvId::kCDecl; //! Count of arguments. - uint8_t _argCount; + uint8_t _argCount = 0; //! Index of a first VA or `kNoVarArgs`. - uint8_t _vaIndex; + uint8_t _vaIndex = kNoVarArgs; //! Return value TypeId. - TypeId _ret; - //! Function arguments TypeIds. - const TypeId* _args; + TypeId _ret = TypeId::kVoid; + //! Reserved for future use. + uint8_t _reserved[4] {}; + //! Function argument TypeIds. + TypeId _args[Globals::kMaxFuncArgs] {}; + + //! \} + + //! \name Construction & Destruction + //! \{ + + //! Default constructed function signature, initialized to \ref CallConvId::kCDecl, having no return value and no arguments. + ASMJIT_FORCE_INLINE constexpr FuncSignature() = default; + + //! Copy constructor, which is initialized to the same function signature as `other`. + ASMJIT_FORCE_INLINE constexpr FuncSignature(const FuncSignature& other) = default; + + //! Initializes the function signature with calling convention id `ccId` and variable argument's index `vaIndex`. + ASMJIT_FORCE_INLINE constexpr FuncSignature(CallConvId ccId, uint32_t vaIndex = kNoVarArgs) noexcept + : _ccId(ccId), + _vaIndex(uint8_t(vaIndex)) {} + + //! Initializes the function signature with calling convention id `ccId`, `vaIndex`, return value, and function arguments. + template + ASMJIT_FORCE_INLINE constexpr FuncSignature(CallConvId ccId, uint32_t vaIndex, TypeId ret, Args&&...args) noexcept + : _ccId(ccId), + _argCount(uint8_t(sizeof...(args))), + _vaIndex(uint8_t(vaIndex)), + _ret(ret), + _args{std::forward(args)...} {} + + //! Builds a function signature based on `RetValueAndArgs`. The first template argument is a function return type, + //! and function arguments follow. + //! + //! \note This function returns a new function signature, which can be passed to functions where it's required. It's + //! a convenience function that allows to build function signature statically based on types known at compile time, + //! which is common in JIT code generation. + template + static ASMJIT_INLINE_NODEBUG constexpr FuncSignature build(CallConvId ccId = CallConvId::kCDecl, uint32_t vaIndex = kNoVarArgs) noexcept { + return FuncSignature(ccId, vaIndex, (TypeId(TypeUtils::TypeIdOfT::kTypeId))... ); + } + + //! \} + + //! \name Overloaded Operators + //! \{ + + //! Copy assignment - function signature can be copied by value. + ASMJIT_FORCE_INLINE FuncSignature& operator=(const FuncSignature& other) noexcept = default; + + //! Compares this function signature with `other` for equality.. + ASMJIT_FORCE_INLINE bool operator==(const FuncSignature& other) const noexcept { return equals(other); } + //! Compares this function signature with `other` for inequality.. + ASMJIT_FORCE_INLINE bool operator!=(const FuncSignature& other) const noexcept { return !equals(other); } //! \} //! \name Initialization & Reset //! \{ - //! Initializes the function signature. - inline void init(CallConvId ccId, uint32_t vaIndex, TypeId ret, const TypeId* args, uint32_t argCount) noexcept { - ASMJIT_ASSERT(argCount <= 0xFF); - - _ccId = ccId; - _argCount = uint8_t(argCount); - _vaIndex = uint8_t(vaIndex); - _ret = ret; - _args = args; - } - + //! Resets this function signature to a default constructed state. ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = FuncSignature{}; } //! \} + //! \name Equality & Comparison + //! \{ + + //! Compares this function signature with `other` for equality.. + ASMJIT_INLINE_NODEBUG bool equals(const FuncSignature& other) const noexcept { + return _ccId == other._ccId && + _argCount == other._argCount && + _vaIndex == other._vaIndex && + _ret == other._ret && + memcmp(_args, other._args, sizeof(_args)) == 0; + } + + //! \} + //! \name Accessors //! \{ @@ -415,6 +475,55 @@ struct FuncSignature { //! Sets the calling convention to `ccId`; ASMJIT_INLINE_NODEBUG void setCallConvId(CallConvId ccId) noexcept { _ccId = ccId; } + //! Tests whether the function signature has a return value. + ASMJIT_INLINE_NODEBUG bool hasRet() const noexcept { return _ret != TypeId::kVoid; } + //! Returns the type of the return value. + ASMJIT_INLINE_NODEBUG TypeId ret() const noexcept { return _ret; } + //! Sets the return type to `retType`. + ASMJIT_INLINE_NODEBUG void setRet(TypeId retType) noexcept { _ret = retType; } + //! Sets the return type based on `T`. + template + ASMJIT_INLINE_NODEBUG void setRetT() noexcept { setRet(TypeId(TypeUtils::TypeIdOfT::kTypeId)); } + + + //! Returns the array of function arguments' types. + ASMJIT_INLINE_NODEBUG const TypeId* args() const noexcept { return _args; } + //! Returns the number of function arguments. + ASMJIT_INLINE_NODEBUG uint32_t argCount() const noexcept { return _argCount; } + + //! Returns the type of the argument at index `i`. + inline TypeId arg(uint32_t i) const noexcept { + ASMJIT_ASSERT(i < _argCount); + return _args[i]; + } + + //! Sets the argument at index `index` to `argType`. + inline void setArg(uint32_t index, TypeId argType) noexcept { + ASMJIT_ASSERT(index < _argCount); + _args[index] = argType; + } + //! Sets the argument at index `i` to the type based on `T`. + template + inline void setArgT(uint32_t index) noexcept { setArg(index, TypeId(TypeUtils::TypeIdOfT::kTypeId)); } + + //! Tests whether an argument can be added to the signature, use before calling \ref addArg() and \ref addArgT(). + //! + //! \note If you know that you are not adding more arguments than \ref Globals::kMaxFuncArgs then it's not necessary + //! to use this function. However, if you are adding arguments based on user input, for example, then either check + //! the number of arguments before using function signature or use \ref canAddArg() before actually adding them to + //! the function signature. + inline bool canAddArg() const noexcept { return _argCount < Globals::kMaxFuncArgs; } + + //! Appends an argument of `type` to the function prototype. + inline void addArg(TypeId type) noexcept { + ASMJIT_ASSERT(_argCount < Globals::kMaxFuncArgs); + _args[_argCount++] = type; + } + + //! Appends an argument of type based on `T` to the function prototype. + template + inline void addArgT() noexcept { addArg(TypeId(TypeUtils::TypeIdOfT::kTypeId)); } + //! Tests whether the function has variable number of arguments (...). ASMJIT_INLINE_NODEBUG bool hasVarArgs() const noexcept { return _vaIndex != kNoVarArgs; } //! Returns the variable arguments (...) index, `kNoVarArgs` if none. @@ -424,76 +533,21 @@ struct FuncSignature { //! Resets the variable arguments index (making it a non-va function). ASMJIT_INLINE_NODEBUG void resetVaIndex() noexcept { _vaIndex = kNoVarArgs; } - //! Returns the number of function arguments. - ASMJIT_INLINE_NODEBUG uint32_t argCount() const noexcept { return _argCount; } - - ASMJIT_INLINE_NODEBUG bool hasRet() const noexcept { return _ret != TypeId::kVoid; } - //! Returns the return value type. - ASMJIT_INLINE_NODEBUG TypeId ret() const noexcept { return _ret; } - - //! Returns the type of the argument at index `i`. - inline TypeId arg(uint32_t i) const noexcept { - ASMJIT_ASSERT(i < _argCount); - return _args[i]; - } - //! Returns the array of function arguments' types. - ASMJIT_INLINE_NODEBUG const TypeId* args() const noexcept { return _args; } - //! \} }; -template +#if !defined(ASMJIT_NO_DEPRECATED) +template class FuncSignatureT : public FuncSignature { public: - ASMJIT_INLINE_NODEBUG FuncSignatureT(CallConvId ccId = CallConvId::kHost, uint32_t vaIndex = kNoVarArgs) noexcept { - static constexpr TypeId ret_args[] = { (TypeId(TypeUtils::TypeIdOfT::kTypeId))... }; - init(ccId, vaIndex, ret_args[0], ret_args + 1, uint32_t(ASMJIT_ARRAY_SIZE(ret_args) - 1)); - } + ASMJIT_DEPRECATED("Use FuncSignature::build() instead") + ASMJIT_INLINE_NODEBUG constexpr FuncSignatureT(CallConvId ccId = CallConvId::kCDecl, uint32_t vaIndex = kNoVarArgs) noexcept + : FuncSignature(ccId, vaIndex, (TypeId(TypeUtils::TypeIdOfT::kTypeId))... ) {} }; -//! Function signature builder. -class FuncSignatureBuilder : public FuncSignature { -public: - TypeId _builderArgList[Globals::kMaxFuncArgs]; - - //! \name Initialization & Reset - //! \{ - - ASMJIT_INLINE_NODEBUG FuncSignatureBuilder(CallConvId ccId = CallConvId::kHost, uint32_t vaIndex = kNoVarArgs) noexcept { - init(ccId, vaIndex, TypeId::kVoid, _builderArgList, 0); - } - - //! \} - - //! \name Accessors - //! \{ - - //! Sets the return type to `retType`. - ASMJIT_INLINE_NODEBUG void setRet(TypeId retType) noexcept { _ret = retType; } - //! Sets the return type based on `T`. - template - ASMJIT_INLINE_NODEBUG void setRetT() noexcept { setRet(TypeId(TypeUtils::TypeIdOfT::kTypeId)); } - - //! Sets the argument at index `index` to `argType`. - inline void setArg(uint32_t index, TypeId argType) noexcept { - ASMJIT_ASSERT(index < _argCount); - _builderArgList[index] = argType; - } - //! Sets the argument at index `i` to the type based on `T`. - template - inline void setArgT(uint32_t index) noexcept { setArg(index, TypeId(TypeUtils::TypeIdOfT::kTypeId)); } - - //! Appends an argument of `type` to the function prototype. - inline void addArg(TypeId type) noexcept { - ASMJIT_ASSERT(_argCount < Globals::kMaxFuncArgs); - _builderArgList[_argCount++] = type; - } - //! Appends an argument of type based on `T` to the function prototype. - template - inline void addArgT() noexcept { addArg(TypeId(TypeUtils::TypeIdOfT::kTypeId)); } - - //! \} -}; +ASMJIT_DEPRECATED("Use FuncSignature instead of FuncSignatureBuilder") +typedef FuncSignature FuncSignatureBuilder; +#endif // !ASMJIT_NO_DEPRECATED //! Argument or return value (or its part) as defined by `FuncSignature`, but with register or stack address //! (and other metadata) assigned. @@ -536,15 +590,17 @@ struct FuncValue { //! //! \{ - //! Initializes the `typeId` of this `FuncValue`. + //! Initializes this `FuncValue` only to the `typeId` provided - the rest of the values will be cleared. ASMJIT_INLINE_NODEBUG void initTypeId(TypeId typeId) noexcept { _data = uint32_t(typeId) << kTypeIdShift; } + //! Initializes this `FuncValue` to a register of `regType`, `regId`, and assigns its `typeId` and `flags`. ASMJIT_INLINE_NODEBUG void initReg(RegType regType, uint32_t regId, TypeId typeId, uint32_t flags = 0) noexcept { _data = (uint32_t(regType) << kRegTypeShift) | (regId << kRegIdShift) | (uint32_t(typeId) << kTypeIdShift) | kFlagIsReg | flags; } + //! Initializes this `FuncValue` to a stack at the given `offset` and assigns its `typeId`. ASMJIT_INLINE_NODEBUG void initStack(int32_t offset, TypeId typeId) noexcept { _data = (uint32_t(offset) << kStackOffsetShift) | (uint32_t(typeId) << kTypeIdShift) | kFlagIsStack; } @@ -561,11 +617,13 @@ struct FuncValue { //! //! \{ + //! Assigns a register of `regType` and `regId`. inline void assignRegData(RegType regType, uint32_t regId) noexcept { ASMJIT_ASSERT((_data & (kRegTypeMask | kRegIdMask)) == 0); _data |= (uint32_t(regType) << kRegTypeShift) | (regId << kRegIdShift) | kFlagIsReg; } + //! Assigns a stack location at `offset`. inline void assignStackOffset(int32_t offset) noexcept { ASMJIT_ASSERT((_data & kStackOffsetMask) == 0); _data |= (uint32_t(offset) << kStackOffsetShift) | kFlagIsStack; @@ -579,7 +637,9 @@ struct FuncValue { //! Returns true if the value is initialized (explicit bool cast). ASMJIT_INLINE_NODEBUG explicit operator bool() const noexcept { return _data != 0; } + //! \cond INTERNAL ASMJIT_INLINE_NODEBUG void _replaceValue(uint32_t mask, uint32_t value) noexcept { _data = (_data & ~mask) | value; } + //! \endcond //! Tests whether the `FuncValue` has a flag `flag` set. ASMJIT_INLINE_NODEBUG bool hasFlag(uint32_t flag) const noexcept { return Support::test(_data, flag); } @@ -661,40 +721,52 @@ public: return n; } + //! Returns values in this value in the pack. + //! + //! \note The returned array has exactly \ref Globals::kMaxValuePack elements. ASMJIT_INLINE_NODEBUG FuncValue* values() noexcept { return _values; } + //! \overload ASMJIT_INLINE_NODEBUG const FuncValue* values() const noexcept { return _values; } + //! Resets a value at the given `index` in the pack, which makes it unassigned. inline void resetValue(size_t index) noexcept { ASMJIT_ASSERT(index < Globals::kMaxValuePack); _values[index].reset(); } + //! Tests whether the value at the given `index` in the pack is assigned. inline bool hasValue(size_t index) noexcept { ASMJIT_ASSERT(index < Globals::kMaxValuePack); return _values[index].isInitialized(); } + //! Assigns a register at the given `index` to `reg` and an optional `typeId`. inline void assignReg(size_t index, const BaseReg& reg, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(index < Globals::kMaxValuePack); ASMJIT_ASSERT(reg.isPhysReg()); _values[index].initReg(reg.type(), reg.id(), typeId); } + //! Assigns a register at the given `index` to `regType`, `regId`, and an optional `typeId`. inline void assignReg(size_t index, RegType regType, uint32_t regId, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(index < Globals::kMaxValuePack); _values[index].initReg(regType, regId, typeId); } + //! Assigns a stack location at the given `index` to `offset` and an optional `typeId`. inline void assignStack(size_t index, int32_t offset, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(index < Globals::kMaxValuePack); _values[index].initStack(offset, typeId); } + //! Accesses the value in the pack at the given `index`. + //! + //! \note The maximum index value is `Globals::kMaxValuePack - 1`. inline FuncValue& operator[](size_t index) { ASMJIT_ASSERT(index < Globals::kMaxValuePack); return _values[index]; } - + //! \overload inline const FuncValue& operator[](size_t index) const { ASMJIT_ASSERT(index < Globals::kMaxValuePack); return _values[index]; @@ -717,6 +789,11 @@ enum class FuncAttributes : uint32_t { kHasFuncCalls = 0x00000020u, //! Function has aligned save/restore of vector registers. kAlignedVecSR = 0x00000040u, + //! Function must begin with an instruction that marks a start of a branch or function. + //! + //! * `ENDBR32/ENDBR64` instruction is inserted at the beginning of the function (X86, X86_64). + //! * `BTI` instruction is inserted at the beginning of the function (AArch64) + kIndirectBranchProtection = 0x00000080u, //! FuncFrame is finalized and can be used by prolog/epilog inserter (PEI). kIsFinalized = 0x00000800u, @@ -753,10 +830,8 @@ public: //! \name Constants //! \{ - enum : uint8_t { - //! Doesn't have variable number of arguments (`...`). - kNoVarArgs = 0xFFu - }; + //! Function doesn't have a variable number of arguments (`...`). + static constexpr uint8_t kNoVarArgs = 0xFFu; //! \} @@ -785,22 +860,35 @@ public: //! \name Construction & Destruction //! \{ + //! Creates a default constructed \ref FuncDetail. ASMJIT_INLINE_NODEBUG FuncDetail() noexcept {} + + //! Copy constructor. + //! + //! Function details are copyable. ASMJIT_INLINE_NODEBUG FuncDetail(const FuncDetail& other) noexcept = default; //! Initializes this `FuncDetail` to the given signature. ASMJIT_API Error init(const FuncSignature& signature, const Environment& environment) noexcept; - ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = FuncDetail{}; } //! \} //! \name Overloaded Operators //! \{ + //! Assignment operator, copies `other` to this \ref FuncDetail. ASMJIT_INLINE_NODEBUG FuncDetail& operator=(const FuncDetail& other) noexcept = default; //! \} + //! \name Reset + //! \{ + + //! Resets the function detail to its default constructed state. + ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = FuncDetail{}; } + + //! \} + //! \name Accessors //! \{ @@ -957,87 +1045,98 @@ public: //! \{ //! Function attributes. - FuncAttributes _attributes; + FuncAttributes _attributes {}; //! Target architecture. - Arch _arch; + Arch _arch {}; //! SP register ID (to access call stack and local stack). - uint8_t _spRegId; + uint8_t _spRegId = uint8_t(BaseReg::kIdBad); //! SA register ID (to access stack arguments). - uint8_t _saRegId; + uint8_t _saRegId = uint8_t(BaseReg::kIdBad); //! Red zone size (copied from CallConv). - uint8_t _redZoneSize; + uint8_t _redZoneSize = 0; //! Spill zone size (copied from CallConv). - uint8_t _spillZoneSize; + uint8_t _spillZoneSize = 0; //! Natural stack alignment (copied from CallConv). - uint8_t _naturalStackAlignment; + uint8_t _naturalStackAlignment = 0; //! Minimum stack alignment to turn on dynamic alignment. - uint8_t _minDynamicAlignment; + uint8_t _minDynamicAlignment = 0; //! Call stack alignment. - uint8_t _callStackAlignment; + uint8_t _callStackAlignment = 0; //! Local stack alignment. - uint8_t _localStackAlignment; + uint8_t _localStackAlignment = 0; //! Final stack alignment. - uint8_t _finalStackAlignment; + uint8_t _finalStackAlignment = 0; //! Adjustment of the stack before returning (X86-STDCALL). - uint16_t _calleeStackCleanup; + uint16_t _calleeStackCleanup = 0; //! Call stack size. - uint32_t _callStackSize; + uint32_t _callStackSize = 0; //! Local stack size. - uint32_t _localStackSize; + uint32_t _localStackSize = 0; //! Final stack size (sum of call stack and local stack). - uint32_t _finalStackSize; + uint32_t _finalStackSize = 0; //! Local stack offset (non-zero only if call stack is used). - uint32_t _localStackOffset; + uint32_t _localStackOffset = 0; //! Offset relative to SP that contains previous SP (before alignment). - uint32_t _daOffset; + uint32_t _daOffset = 0; //! Offset of the first stack argument relative to SP. - uint32_t _saOffsetFromSP; + uint32_t _saOffsetFromSP = 0; //! Offset of the first stack argument relative to SA (_saRegId or FP). - uint32_t _saOffsetFromSA; + uint32_t _saOffsetFromSA = 0; //! Local stack adjustment in prolog/epilog. - uint32_t _stackAdjustment; + uint32_t _stackAdjustment = 0; //! Registers that are dirty. - Support::Array _dirtyRegs; + Support::Array _dirtyRegs {}; //! Registers that must be preserved (copied from CallConv). - Support::Array _preservedRegs; + Support::Array _preservedRegs {}; //! Size to save/restore per register group. - Support::Array _saveRestoreRegSize; + Support::Array _saveRestoreRegSize {}; //! Alignment of save/restore area per register group. - Support::Array _saveRestoreAlignment; + Support::Array _saveRestoreAlignment {}; //! Stack size required to save registers with push/pop. - uint16_t _pushPopSaveSize; + uint16_t _pushPopSaveSize = 0; //! Stack size required to save extra registers that cannot use push/pop. - uint16_t _extraRegSaveSize; + uint16_t _extraRegSaveSize = 0; //! Offset where registers saved/restored via push/pop are stored - uint32_t _pushPopSaveOffset; + uint32_t _pushPopSaveOffset = 0; //! Offset where extra registers that cannot use push/pop are stored. - uint32_t _extraRegSaveOffset; + uint32_t _extraRegSaveOffset = 0; //! \} //! \name Construction & Destruction //! \{ - ASMJIT_INLINE_NODEBUG FuncFrame() noexcept { reset(); } + //! Creates a default constructed function frame, which has initialized all members to their default values. + ASMJIT_INLINE_NODEBUG FuncFrame() noexcept = default; + //! Creates a copy of `other` function frame. ASMJIT_INLINE_NODEBUG FuncFrame(const FuncFrame& other) noexcept = default; - ASMJIT_API Error init(const FuncDetail& func) noexcept; + //! \} - ASMJIT_INLINE_NODEBUG void reset() noexcept { - memset(this, 0, sizeof(FuncFrame)); - _spRegId = BaseReg::kIdBad; - _saRegId = BaseReg::kIdBad; - _daOffset = kTagInvalidOffset; - } + //! \name Initialization & Reset + //! \{ + + //! Initializes the function frame based on `func` detail. + ASMJIT_API Error init(const FuncDetail& func) noexcept; + //! Resets the function frame into its default constructed state. + ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = FuncFrame{}; } + + //! \} + + //! \name Overloaded Operators + //! \{ + + //! Copy assignment - function frame is copy assignable. + ASMJIT_INLINE_NODEBUG FuncFrame& operator=(const FuncFrame& other) noexcept = default; //! \} @@ -1072,11 +1171,18 @@ public: //! Tests whether the function calls other functions. ASMJIT_INLINE_NODEBUG bool hasFuncCalls() const noexcept { return hasAttribute(FuncAttributes::kHasFuncCalls); } - //! Sets `kFlagHasCalls` to true. + //! Sets `FuncAttributes::kHasFuncCalls` to true. ASMJIT_INLINE_NODEBUG void setFuncCalls() noexcept { addAttributes(FuncAttributes::kHasFuncCalls); } - //! Sets `kFlagHasCalls` to false. + //! Sets `FuncAttributes::kHasFuncCalls` to false. ASMJIT_INLINE_NODEBUG void resetFuncCalls() noexcept { clearAttributes(FuncAttributes::kHasFuncCalls); } + //! Tests whether the function uses indirect branch protection, see \ref FuncAttributes::kIndirectBranchProtection. + ASMJIT_INLINE_NODEBUG bool hasIndirectBranchProtection() const noexcept { return hasAttribute(FuncAttributes::kIndirectBranchProtection); } + //! Enabled indirect branch protection (sets `FuncAttributes::kIndirectBranchProtection` attribute to true). + ASMJIT_INLINE_NODEBUG void setIndirectBranchProtection() noexcept { addAttributes(FuncAttributes::kIndirectBranchProtection); } + //! Disables indirect branch protection (sets `FuncAttributes::kIndirectBranchProtection` attribute to false). + ASMJIT_INLINE_NODEBUG void resetIndirectBranchProtection() noexcept { clearAttributes(FuncAttributes::kIndirectBranchProtection); } + //! Tests whether the function has AVX enabled. ASMJIT_INLINE_NODEBUG bool isAvxEnabled() const noexcept { return hasAttribute(FuncAttributes::kX86_AVXEnabled); } //! Enables AVX use. @@ -1251,11 +1357,16 @@ public: addDirtyRegs(std::forward(args)...); } + //! A helper function to set all registers from all register groups dirty. + //! + //! \note This should not be used in general as it's the most pessimistic case. However, it can be used for testing + //! or in cases in which all registers are considered clobbered. ASMJIT_INLINE_NODEBUG void setAllDirty() noexcept { for (size_t i = 0; i < ASMJIT_ARRAY_SIZE(_dirtyRegs); i++) _dirtyRegs[i] = 0xFFFFFFFFu; } + //! A helper function to set all registers from the given register `group` dirty. inline void setAllDirty(RegGroup group) noexcept { ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); _dirtyRegs[group] = 0xFFFFFFFFu; @@ -1278,6 +1389,7 @@ public: return _preservedRegs[group]; } + //! Returns the size of a save-restore are for the required register `group`. inline uint32_t saveRestoreRegSize(RegGroup group) const noexcept { ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); return _saveRestoreRegSize[group]; @@ -1332,25 +1444,27 @@ public: //! \{ //! Function detail. - const FuncDetail* _funcDetail; + const FuncDetail* _funcDetail {}; //! Register that can be used to access arguments passed by stack. - uint8_t _saRegId; + uint8_t _saRegId = uint8_t(BaseReg::kIdBad); //! Reserved for future use. - uint8_t _reserved[3]; + uint8_t _reserved[3] {}; //! Mapping of each function argument. - FuncValuePack _argPacks[Globals::kMaxFuncArgs]; + FuncValuePack _argPacks[Globals::kMaxFuncArgs] {}; //! \} //! \name Construction & Destruction //! \{ + //! Creates either a default initialized `FuncArgsAssignment` or to assignment that links to `fd`, if non-null. ASMJIT_INLINE_NODEBUG explicit FuncArgsAssignment(const FuncDetail* fd = nullptr) noexcept { reset(fd); } - ASMJIT_INLINE_NODEBUG FuncArgsAssignment(const FuncArgsAssignment& other) noexcept { - memcpy(this, &other, sizeof(*this)); - } + //! Copy constructor. + ASMJIT_INLINE_NODEBUG FuncArgsAssignment(const FuncArgsAssignment& other) noexcept = default; + //! Resets this `FuncArgsAssignment` to either default constructed state or to assignment that links to `fd`, + //! if non-null. inline void reset(const FuncDetail* fd = nullptr) noexcept { _funcDetail = fd; _saRegId = uint8_t(BaseReg::kIdBad); @@ -1360,10 +1474,20 @@ public: //! \} + //! \name Overloaded Operators + //! \{ + + //! Copy assignment. + ASMJIT_INLINE_NODEBUG FuncArgsAssignment& operator=(const FuncArgsAssignment& other) noexcept = default; + + //! \} + //! \name Accessors //! \{ + //! Returns the associated \ref FuncDetail of this `FuncArgsAssignment`. ASMJIT_INLINE_NODEBUG const FuncDetail* funcDetail() const noexcept { return _funcDetail; } + //! Associates \ref FuncDetails with this `FuncArgsAssignment`. ASMJIT_INLINE_NODEBUG void setFuncDetail(const FuncDetail* fd) noexcept { _funcDetail = fd; } ASMJIT_INLINE_NODEBUG bool hasSARegId() const noexcept { return _saRegId != BaseReg::kIdBad; } @@ -1371,47 +1495,59 @@ public: ASMJIT_INLINE_NODEBUG void setSARegId(uint32_t regId) { _saRegId = uint8_t(regId); } ASMJIT_INLINE_NODEBUG void resetSARegId() { _saRegId = uint8_t(BaseReg::kIdBad); } + //! Returns assigned argument at `argIndex` and `valueIndex`. + //! + //! \note `argIndex` refers to he function argument and `valueIndex` refers to a value pack (in case multiple + //! values are passed as a single argument). inline FuncValue& arg(size_t argIndex, size_t valueIndex) noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); return _argPacks[argIndex][valueIndex]; } + //! \overload inline const FuncValue& arg(size_t argIndex, size_t valueIndex) const noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); return _argPacks[argIndex][valueIndex]; } + //! Tests whether argument at `argIndex` and `valueIndex` has been assigned. inline bool isAssigned(size_t argIndex, size_t valueIndex) const noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); return _argPacks[argIndex][valueIndex].isAssigned(); } + //! Assigns register at `argIndex` and value index of 0 to `reg` and an optional `typeId`. inline void assignReg(size_t argIndex, const BaseReg& reg, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); ASMJIT_ASSERT(reg.isPhysReg()); _argPacks[argIndex][0].initReg(reg.type(), reg.id(), typeId); } + //! Assigns register at `argIndex` and value index of 0 to `regType`, `regId`, and an optional `typeId`. inline void assignReg(size_t argIndex, RegType regType, uint32_t regId, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); _argPacks[argIndex][0].initReg(regType, regId, typeId); } + //! Assigns stack at `argIndex` and value index of 0 to `offset` and an optional `typeId`. inline void assignStack(size_t argIndex, int32_t offset, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); _argPacks[argIndex][0].initStack(offset, typeId); } + //! Assigns register at `argIndex` and `valueIndex` to `reg` and an optional `typeId`. inline void assignRegInPack(size_t argIndex, size_t valueIndex, const BaseReg& reg, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); ASMJIT_ASSERT(reg.isPhysReg()); _argPacks[argIndex][valueIndex].initReg(reg.type(), reg.id(), typeId); } + //! Assigns register at `argIndex` and `valueIndex` to `regType`, `regId`, and an optional `typeId`. inline void assignRegInPack(size_t argIndex, size_t valueIndex, RegType regType, uint32_t regId, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); _argPacks[argIndex][valueIndex].initReg(regType, regId, typeId); } + //! Assigns stack at `argIndex` and `valueIndex` to `offset` and an optional `typeId`. inline void assignStackInPack(size_t argIndex, size_t valueIndex, int32_t offset, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); _argPacks[argIndex][valueIndex].initStack(offset, typeId); @@ -1430,6 +1566,9 @@ public: _assignAllInternal(argIndex + 1, std::forward(args)...); } + //! Assigns all argument at once. + //! + //! \note This function can be only used if the arguments don't contain value packs (multiple values per argument). template inline void assignAll(Args&&... args) noexcept { _assignAllInternal(0, std::forward(args)...); @@ -1442,8 +1581,8 @@ public: //! Update `FuncFrame` based on function's arguments assignment. //! - //! \note You MUST call this in order to use `BaseEmitter::emitArgsAssignment()`, otherwise the FuncFrame would - //! not contain the information necessary to assign all arguments into the registers and/or stack specified. + //! \note This function must be called in order to use `BaseEmitter::emitArgsAssignment()`, otherwise the \ref FuncFrame + //! would not contain the information necessary to assign all arguments into the registers and/or stack specified. ASMJIT_API Error updateFuncFrame(FuncFrame& frame) const noexcept; //! \} @@ -1454,4 +1593,3 @@ public: ASMJIT_END_NAMESPACE #endif // ASMJIT_CORE_FUNC_H_INCLUDED - diff --git a/deps/asmjit/src/asmjit/core/funcargscontext.cpp b/deps/asmjit/src/asmjit/core/funcargscontext.cpp index 1db50a70..a6580874 100644 --- a/deps/asmjit/src/asmjit/core/funcargscontext.cpp +++ b/deps/asmjit/src/asmjit/core/funcargscontext.cpp @@ -102,9 +102,23 @@ ASMJIT_FAVOR_SIZE Error FuncArgsContext::initWorkData(const FuncFrame& frame, co ASMJIT_ASSERT(dstWd != nullptr); dstWd->assign(varId, srcId); - // The best case, register is allocated where it is expected to be. - if (dstId == srcId) - var.markDone(); + // The best case, register is allocated where it is expected to be. However, we should + // not mark this as done if both registers are GP and sign or zero extension is required. + if (dstId == srcId) { + if (dstGroup != RegGroup::kGp) { + var.markDone(); + } + else { + TypeId dt = dst.typeId(); + TypeId st = src.typeId(); + + uint32_t dstSize = TypeUtils::sizeOf(dt); + uint32_t srcSize = TypeUtils::sizeOf(st); + + if (dt == TypeId::kVoid || st == TypeId::kVoid || dstSize <= srcSize) + var.markDone(); + } + } } else { if (ASMJIT_UNLIKELY(srcGroup > RegGroup::kMaxVirt)) diff --git a/deps/asmjit/src/asmjit/core/globals.cpp b/deps/asmjit/src/asmjit/core/globals.cpp index 1fbb3997..4a98431b 100644 --- a/deps/asmjit/src/asmjit/core/globals.cpp +++ b/deps/asmjit/src/asmjit/core/globals.cpp @@ -87,6 +87,7 @@ ASMJIT_FAVOR_SIZE const char* DebugUtils::errorAsString(Error err) noexcept { "ExpressionOverflow\0" "FailedToOpenAnonymousMemory\0" "FailedToOpenFile\0" + "ProtectionFailure\0" "\0"; static const uint16_t sErrorIndex[] = { @@ -94,7 +95,7 @@ ASMJIT_FAVOR_SIZE const char* DebugUtils::errorAsString(Error err) noexcept { 247, 264, 283, 298, 314, 333, 352, 370, 392, 410, 429, 444, 460, 474, 488, 508, 533, 551, 573, 595, 612, 629, 645, 661, 677, 694, 709, 724, 744, 764, 784, 817, 837, 852, 869, 888, 909, 929, 943, 964, 978, 996, 1012, 1028, 1047, - 1073, 1088, 1104, 1119, 1134, 1164, 1188, 1207, 1235, 1252 + 1073, 1088, 1104, 1119, 1134, 1164, 1188, 1207, 1235, 1252, 1270 }; // @EnumStringEnd@ diff --git a/deps/asmjit/src/asmjit/core/globals.h b/deps/asmjit/src/asmjit/core/globals.h index 1a589d31..db921cfc 100644 --- a/deps/asmjit/src/asmjit/core/globals.h +++ b/deps/asmjit/src/asmjit/core/globals.h @@ -96,10 +96,9 @@ static constexpr uint32_t kMaxTreeHeight = (ASMJIT_ARCH_BITS == 32 ? 30 : 61) + static constexpr uint32_t kMaxOpCount = 6; //! Maximum arguments of a function supported by the Compiler / Function API. -static constexpr uint32_t kMaxFuncArgs = 16; +static constexpr uint32_t kMaxFuncArgs = 32; -//! The number of values that can be assigned to a single function argument or -//! return value. +//! The number of values that can be assigned to a single function argument or return value. static constexpr uint32_t kMaxValuePack = 4; //! Maximum number of physical registers AsmJit can use per register group. @@ -132,14 +131,18 @@ static constexpr uint32_t kNumVirtGroups = 4; struct Init_ {}; struct NoInit_ {}; +//! A decorator used to initialize. static const constexpr Init_ Init {}; +//! A decorator used to not initialize. static const constexpr NoInit_ NoInit {}; } // {Globals} +//! Casts a `void*` pointer `func` to a function pointer `Func`. template static ASMJIT_INLINE_NODEBUG Func ptr_as_func(void* func) noexcept { return Support::ptr_cast_impl(func); } +//! Casts a function pointer `func` to a void pointer `void*`. template static ASMJIT_INLINE_NODEBUG void* func_as_ptr(Func func) noexcept { return Support::ptr_cast_impl(func); } @@ -331,6 +334,10 @@ enum ErrorCode : uint32_t { //! \note This is a generic error that is used by internal filesystem API. kErrorFailedToOpenFile, + //! Protection failure can be returned from a virtual memory allocator or when trying to change memory access + //! permissions. + kErrorProtectionFailure, + // @EnumValuesEnd@ //! Count of AsmJit error codes. diff --git a/deps/asmjit/src/asmjit/core/inst.cpp b/deps/asmjit/src/asmjit/core/inst.cpp index 8f29d8b7..ade4ae00 100644 --- a/deps/asmjit/src/asmjit/core/inst.cpp +++ b/deps/asmjit/src/asmjit/core/inst.cpp @@ -24,12 +24,12 @@ ASMJIT_BEGIN_NAMESPACE Error InstAPI::instIdToString(Arch arch, InstId instId, String& output) noexcept { #if !defined(ASMJIT_NO_X86) if (Environment::isFamilyX86(arch)) - return x86::InstInternal::instIdToString(arch, instId, output); + return x86::InstInternal::instIdToString(instId, output); #endif #if !defined(ASMJIT_NO_AARCH64) if (Environment::isFamilyAArch64(arch)) - return a64::InstInternal::instIdToString(arch, instId, output); + return a64::InstInternal::instIdToString(instId, output); #endif return DebugUtils::errored(kErrorInvalidArch); @@ -38,12 +38,12 @@ Error InstAPI::instIdToString(Arch arch, InstId instId, String& output) noexcept InstId InstAPI::stringToInstId(Arch arch, const char* s, size_t len) noexcept { #if !defined(ASMJIT_NO_X86) if (Environment::isFamilyX86(arch)) - return x86::InstInternal::stringToInstId(arch, s, len); + return x86::InstInternal::stringToInstId(s, len); #endif #if !defined(ASMJIT_NO_AARCH64) if (Environment::isFamilyAArch64(arch)) - return a64::InstInternal::stringToInstId(arch, s, len); + return a64::InstInternal::stringToInstId(s, len); #endif return 0; @@ -56,13 +56,17 @@ InstId InstAPI::stringToInstId(Arch arch, const char* s, size_t len) noexcept { #ifndef ASMJIT_NO_VALIDATION Error InstAPI::validate(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept { #if !defined(ASMJIT_NO_X86) - if (Environment::isFamilyX86(arch)) - return x86::InstInternal::validate(arch, inst, operands, opCount, validationFlags); + if (Environment::isFamilyX86(arch)) { + if (arch == Arch::kX86) + return x86::InstInternal::validateX86(inst, operands, opCount, validationFlags); + else + return x86::InstInternal::validateX64(inst, operands, opCount, validationFlags); + } #endif #if !defined(ASMJIT_NO_AARCH64) if (Environment::isFamilyAArch64(arch)) - return a64::InstInternal::validate(arch, inst, operands, opCount, validationFlags); + return a64::InstInternal::validate(inst, operands, opCount, validationFlags); #endif return DebugUtils::errored(kErrorInvalidArch); @@ -84,7 +88,7 @@ Error InstAPI::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* oper #if !defined(ASMJIT_NO_AARCH64) if (Environment::isFamilyAArch64(arch)) - return a64::InstInternal::queryRWInfo(arch, inst, operands, opCount, out); + return a64::InstInternal::queryRWInfo(inst, operands, opCount, out); #endif return DebugUtils::errored(kErrorInvalidArch); @@ -103,7 +107,7 @@ Error InstAPI::queryFeatures(Arch arch, const BaseInst& inst, const Operand_* op #if !defined(ASMJIT_NO_AARCH64) if (Environment::isFamilyAArch64(arch)) - return a64::InstInternal::queryFeatures(arch, inst, operands, opCount, out); + return a64::InstInternal::queryFeatures(inst, operands, opCount, out); #endif return DebugUtils::errored(kErrorInvalidArch); diff --git a/deps/asmjit/src/asmjit/core/inst.h b/deps/asmjit/src/asmjit/core/inst.h index d0ddd8e3..a653fe8e 100644 --- a/deps/asmjit/src/asmjit/core/inst.h +++ b/deps/asmjit/src/asmjit/core/inst.h @@ -303,6 +303,9 @@ public: ASMJIT_INLINE_NODEBUG arm::CondCode armCondCode() const noexcept { return (arm::CondCode)getInstIdPart(); } ASMJIT_INLINE_NODEBUG void setArmCondCode(arm::CondCode cc) noexcept { setInstIdPart(uint32_t(cc)); } + ASMJIT_INLINE_NODEBUG a32::DataType armDt() const noexcept { return (a32::DataType)getInstIdPart(); } + ASMJIT_INLINE_NODEBUG a32::DataType armDt2() const noexcept { return (a32::DataType)getInstIdPart(); } + //! \} //! \name Statics @@ -312,12 +315,12 @@ public: return id | (uint32_t(cc) << Support::ConstCTZ::value); } - static ASMJIT_INLINE_NODEBUG constexpr InstId composeARMInstId(uint32_t id, arm::DataType dt, arm::CondCode cc = arm::CondCode::kAL) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr InstId composeARMInstId(uint32_t id, a32::DataType dt, arm::CondCode cc = arm::CondCode::kAL) noexcept { return id | (uint32_t(dt) << Support::ConstCTZ::value) | (uint32_t(cc) << Support::ConstCTZ::value); } - static ASMJIT_INLINE_NODEBUG constexpr InstId composeARMInstId(uint32_t id, arm::DataType dt, arm::DataType dt2, arm::CondCode cc = arm::CondCode::kAL) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr InstId composeARMInstId(uint32_t id, a32::DataType dt, a32::DataType dt2, arm::CondCode cc = arm::CondCode::kAL) noexcept { return id | (uint32_t(dt) << Support::ConstCTZ::value) | (uint32_t(dt2) << Support::ConstCTZ::value) | (uint32_t(cc) << Support::ConstCTZ::value); @@ -344,16 +347,16 @@ enum class CpuRWFlags : uint32_t { // Common RW Flags (0x000000FF) // ---------------------------- - //! Carry flag. - kCF = 0x00000001u, //! Signed overflow flag. - kOF = 0x00000002u, - //! Sign flag (negative/sign, if set). - kSF = 0x00000004u, + kOF = 0x00000001u, + //! Carry flag. + kCF = 0x00000002u, //! Zero and/or equality flag (1 if zero/equal). - kZF = 0x00000008u, + kZF = 0x00000004u, + //! Sign flag (negative/sign, if set). + kSF = 0x00000008u, - // X86 Specific RW Flags (0xFFFFFF00) + // X86 Specific RW Flags // ---------------------------------- //! Carry flag (X86, X86_64). @@ -384,12 +387,22 @@ enum class CpuRWFlags : uint32_t { //! FPU C2 status flag (X86, X86_64). kX86_C2 = 0x00040000u, //! FPU C3 status flag (X86, X86_64). - kX86_C3 = 0x00080000u + kX86_C3 = 0x00080000u, + + // ARM Specific RW Flags + // ---------------------------------- + + kARM_V = kOF, + kARM_C = kCF, + kARM_Z = kZF, + kARM_N = kSF, + kARM_Q = 0x00000100u, + kARM_GE = 0x00000200u }; ASMJIT_DEFINE_ENUM_FLAGS(CpuRWFlags) //! Operand read/write flags describe how the operand is accessed and some additional features. -enum class OpRWFlags { +enum class OpRWFlags : uint32_t { //! No flags. kNone = 0, @@ -499,7 +512,8 @@ struct OpRWInfo { _consecutiveLeadCount = 0; _resetReserved(); - uint64_t mask = Support::lsbMask(regSize); + uint64_t mask = Support::lsbMask(Support::min(regSize, 64)); + _readByteMask = Support::test(opFlags, OpRWFlags::kRead) ? mask : uint64_t(0); _writeByteMask = Support::test(opFlags, OpRWFlags::kWrite) ? mask : uint64_t(0); _extendByteMask = 0; diff --git a/deps/asmjit/src/asmjit/core/instdb.cpp b/deps/asmjit/src/asmjit/core/instdb.cpp new file mode 100644 index 00000000..cde369f6 --- /dev/null +++ b/deps/asmjit/src/asmjit/core/instdb.cpp @@ -0,0 +1,101 @@ +// This file is part of AsmJit project +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#include "../core/api-build_p.h" +#include "../core/instdb_p.h" + +ASMJIT_BEGIN_NAMESPACE + +namespace InstNameUtils { + +static constexpr uint32_t kBufferSize = 32; + +static ASMJIT_FORCE_INLINE char decode5BitChar(uint32_t c) noexcept { + uint32_t base = c <= 26 ? uint32_t('a') - 1u : uint32_t('0') - 27u; + return char(base + c); +} + +static ASMJIT_FORCE_INLINE size_t decodeToBuffer(char nameOut[kBufferSize], uint32_t nameValue, const char* stringTable) noexcept { + size_t i; + + if (nameValue & 0x80000000u) { + // Small string of 5-bit characters. + for (i = 0; i < 6; i++, nameValue >>= 5) { + uint32_t c = nameValue & 0x1F; + if (c == 0) + break; + nameOut[i] = decode5BitChar(c); + } + return i; + } + else { + size_t prefixBase = nameValue & 0xFFFu; + size_t prefixSize = (nameValue >> 12) & 0xFu; + + size_t suffixBase = (nameValue >> 16) & 0xFFFu; + size_t suffixSize = (nameValue >> 28) & 0x7u; + + for (i = 0; i < prefixSize; i++) + nameOut[i] = stringTable[prefixBase + i]; + + char* suffixOut = nameOut + prefixSize; + for (i = 0; i < suffixSize; i++) + suffixOut[i] = stringTable[suffixBase + i]; + + return prefixSize + suffixSize; + } +} + +Error decode(String& output, uint32_t nameValue, const char* stringTable) noexcept { + char nameData[kBufferSize]; + size_t nameSize = decodeToBuffer(nameData, nameValue, stringTable); + + return output.append(nameData, nameSize); +} + +InstId find(const char* s, size_t len, const InstNameIndex& nameIndex, const uint32_t* nameTable, const char* stringTable) noexcept { + if (ASMJIT_UNLIKELY(!s)) + return BaseInst::kIdNone; + + if (len == SIZE_MAX) + len = strlen(s); + + if (ASMJIT_UNLIKELY(len == 0 || len > nameIndex.maxNameLength)) + return BaseInst::kIdNone; + + uint32_t prefix = uint32_t(s[0]) - 'a'; + if (ASMJIT_UNLIKELY(prefix > 'z' - 'a')) + return BaseInst::kIdNone; + + size_t base = nameIndex.data[prefix].start; + size_t end = nameIndex.data[prefix].end; + + if (ASMJIT_UNLIKELY(!base)) + return BaseInst::kIdNone; + + char nameData[kBufferSize]; + for (size_t lim = end - base; lim != 0; lim >>= 1) { + size_t instId = base + (lim >> 1); + size_t nameSize = decodeToBuffer(nameData, nameTable[instId], stringTable); + + int result = Support::compareStringViews(s, len, nameData, nameSize); + if (result < 0) + continue; + + if (result > 0) { + base = instId + 1; + lim--; + continue; + } + + return InstId(instId); + } + + return BaseInst::kIdNone; +} + +} // {InstNameUtils} + +ASMJIT_END_NAMESPACE diff --git a/deps/asmjit/src/asmjit/core/instdb_p.h b/deps/asmjit/src/asmjit/core/instdb_p.h new file mode 100644 index 00000000..b5afb72c --- /dev/null +++ b/deps/asmjit/src/asmjit/core/instdb_p.h @@ -0,0 +1,40 @@ +// This file is part of AsmJit project +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_CORE_INSTDB_P_H_INCLUDED +#define ASMJIT_CORE_INSTDB_P_H_INCLUDED + +#include "../core/inst.h" +#include "../core/string.h" + +ASMJIT_BEGIN_NAMESPACE + +//! \cond INTERNAL +//! \addtogroup asmjit_instruction_db +//! \{ + +struct InstNameIndex { + struct Span { + uint16_t start; + uint16_t end; + }; + + Span data[26]; + uint16_t maxNameLength; +}; + +namespace InstNameUtils { + +Error decode(String& output, uint32_t nameValue, const char* stringTable) noexcept; +InstId find(const char* s, size_t len, const InstNameIndex& nameIndex, const uint32_t* nameTable, const char* stringTable) noexcept; + +} // {InstNameUtils} + +//! \} +//! \endcond + +ASMJIT_END_NAMESPACE + +#endif // ASMJIT_CORE_INSTDB_P_H_INCLUDED diff --git a/deps/asmjit/src/asmjit/core/jitallocator.cpp b/deps/asmjit/src/asmjit/core/jitallocator.cpp index 3aef8c58..760826b0 100644 --- a/deps/asmjit/src/asmjit/core/jitallocator.cpp +++ b/deps/asmjit/src/asmjit/core/jitallocator.cpp @@ -37,12 +37,13 @@ static constexpr uint32_t kJitAllocatorMaxBlockSize = 1024 * 1024 * 64; // =========================== static inline uint32_t JitAllocator_defaultFillPattern() noexcept { +#if ASMJIT_ARCH_X86 // X86 and X86_64 - 4x 'int3' instruction. - if (ASMJIT_ARCH_X86) - return 0xCCCCCCCCu; - + return 0xCCCCCCCCu; +#else // Unknown... return 0u; +#endif } // JitAllocator - BitVectorRangeIterator @@ -447,7 +448,7 @@ static inline JitAllocatorPrivateImpl* JitAllocatorImpl_new(const JitAllocator:: // Setup pool count to [1..3]. size_t poolCount = 1; if (Support::test(options, JitAllocatorOptions::kUseMultiplePools)) - poolCount = kJitAllocatorMultiPoolCount;; + poolCount = kJitAllocatorMultiPoolCount; // Setup block size [64kB..256MB]. if (blockSize < 64 * 1024 || blockSize > 256 * 1024 * 1024 || !Support::isPowerOf2(blockSize)) @@ -1398,11 +1399,12 @@ static void test_jit_allocator_alloc_release() noexcept { using Opt = JitAllocatorOptions; + VirtMem::HardenedRuntimeInfo hri = VirtMem::hardenedRuntimeInfo(); + TestParams testParams[] = { { "Default" , Opt::kNone, 0, 0 }, { "16MB blocks" , Opt::kNone, 16 * 1024 * 1024, 0 }, { "256B granularity" , Opt::kNone, 0, 256 }, - { "kUseDualMapping" , Opt::kUseDualMapping , 0, 0 }, { "kUseMultiplePools" , Opt::kUseMultiplePools, 0, 0 }, { "kFillUnusedMemory" , Opt::kFillUnusedMemory, 0, 0 }, { "kImmediateRelease" , Opt::kImmediateRelease, 0, 0 }, @@ -1410,6 +1412,7 @@ static void test_jit_allocator_alloc_release() noexcept { { "kUseLargePages" , Opt::kUseLargePages, 0, 0 }, { "kUseLargePages | kFillUnusedMemory" , Opt::kUseLargePages | Opt::kFillUnusedMemory, 0, 0 }, { "kUseLargePages | kAlignBlockSizeToLargePage", Opt::kUseLargePages | Opt::kAlignBlockSizeToLargePage, 0, 0 }, + { "kUseDualMapping" , Opt::kUseDualMapping , 0, 0 }, { "kUseDualMapping | kFillUnusedMemory" , Opt::kUseDualMapping | Opt::kFillUnusedMemory, 0, 0 } }; @@ -1426,6 +1429,12 @@ static void test_jit_allocator_alloc_release() noexcept { } for (uint32_t testId = 0; testId < ASMJIT_ARRAY_SIZE(testParams); testId++) { + // Don't try to allocate dual-mapping if dual mapping is not possible - it would fail the test. + if (Support::test(testParams[testId].options, JitAllocatorOptions::kUseDualMapping) && + !Support::test(hri.flags, VirtMem::HardenedRuntimeFlags::kDualMapping)) { + continue; + } + INFO("JitAllocator(%s)", testParams[testId].name); JitAllocator::CreateParams params {}; diff --git a/deps/asmjit/src/asmjit/core/jitallocator.h b/deps/asmjit/src/asmjit/core/jitallocator.h index 8ff85583..b694f8cd 100644 --- a/deps/asmjit/src/asmjit/core/jitallocator.h +++ b/deps/asmjit/src/asmjit/core/jitallocator.h @@ -65,7 +65,7 @@ enum class JitAllocatorOptions : uint32_t { //! since AsmJit can be compiled as a shared library and used by applications instrumented by UBSAN, it's not //! possible to conditionally compile the support only when necessary. //! - //! \important This flag controls a workaround to make it possible to use LLVM UBSAN with AsmJit's \ref JitAllocator. + //! \remarks This flag controls a workaround to make it possible to use LLVM UBSAN with AsmJit's \ref JitAllocator. //! There is no undefined behavior even when `kDisableInitialPadding` is used, however, that doesn't really matter //! as LLVM's UBSAN introduces one, and according to LLVM developers it's a "trade-off". This flag is safe to use //! when the code is not instrumented with LLVM's UBSAN. @@ -73,7 +73,7 @@ enum class JitAllocatorOptions : uint32_t { //! Enables the use of large pages, if they are supported and the process can actually allocate them. //! - //! \important This flag is a hint - if large pages can be allocated, JitAllocator would try to allocate them. + //! \remarks This flag is a hint - if large pages can be allocated, JitAllocator would try to allocate them. //! However, if the allocation fails, it will still try to fallback to use regular pages as \ref JitAllocator //! is designed to minimize allocation failures, so a regular page is better than no page at all. Also, if a //! block \ref JitAllocator wants to allocate is too small to consume a whole large page, regular page(s) will @@ -174,7 +174,7 @@ public: uint32_t fillPattern = 0; // Reset the content of `CreateParams`. - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } + ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = CreateParams{}; } }; //! Creates a `JitAllocator` instance. @@ -272,17 +272,18 @@ public: //! Depending on the type of the allocation strategy this could either be: //! //! - the same address as returned by `rx()` if the allocator uses RWX mapping (pages have all of Read, Write, - //! and Execute permissions) or MAP_JIT, which requires either \ref ProtectJitReadWriteScope or to call - //! VirtMem::protectJitMemory() manually. + //! and Execute permissions) or MAP_JIT, which requires either \ref VirtMem::ProtectJitReadWriteScope or to + //! call \ref VirtMem::protectJitMemory() manually. //! - a valid pointer, but not the same as `rx` - this would be valid if dual mapping is used. //! - NULL pointer, in case that the allocation strategy doesn't use RWX, MAP_JIT, or dual mapping. In this - //! case only \ref JitAllocator can copy new code into the executable memory referenced by \ref Addr. + //! case only \ref JitAllocator can copy new code into the executable memory referenced by \ref Span. //! //! \note If `rw()` returns a non-null pointer it's important to use either VirtMem::protectJitMemory() or - //! \ref ProtectJitReadWriteScope to guard the write, because in case of `MAP_JIT` it would temporarily switch - //! the permissions of the pointer to RW (that's per thread permissions). if \ref ProtectJitReadWriteScope is - //! not used it's important to clear the instruction cache via \ref VirtMem::flushInstructionCache() after the - //! write is done. + //! \ref VirtMem::ProtectJitReadWriteScope to guard the write, because in case of `MAP_JIT` it would temporarily + //! switch the permissions of the pointer to RW (that's per thread permissions). + //! + //! If \ref VirtMem::ProtectJitReadWriteScope is not used it's important to clear the instruction cache via + //! \ref VirtMem::flushInstructionCache() after the write is done. ASMJIT_INLINE_NODEBUG void* rw() const noexcept { return _rw; } //! Returns size of this span, aligned to the allocator granularity. @@ -430,12 +431,12 @@ public: //! This is mostly for internal purposes, please use \ref WriteScope::write() instead. ASMJIT_API Error scopedWrite(WriteScopeData& scope, Span& span, size_t offset, const void* src, size_t size) noexcept; - //! Alternative to `JitAllocator::write(span. writeFunc, userData)`, but under a write `scope`. + //! Alternative to `JitAllocator::write(span, writeFunc, userData)`, but under a write `scope`. //! //! This is mostly for internal purposes, please use \ref WriteScope::write() instead. ASMJIT_API Error scopedWrite(WriteScopeData& scope, Span& span, WriteFunc writeFunc, void* userData) noexcept; - //! Alternative to `JitAllocator::write(span. )`, but under a write `scope`. + //! Alternative to `JitAllocator::write(span, [lambda])`, but under a write `scope`. //! //! This is mostly for internal purposes, please use \ref WriteScope::write() instead. template diff --git a/deps/asmjit/src/asmjit/core/jitruntime.h b/deps/asmjit/src/asmjit/core/jitruntime.h index 761d7e1f..717a6b58 100644 --- a/deps/asmjit/src/asmjit/core/jitruntime.h +++ b/deps/asmjit/src/asmjit/core/jitruntime.h @@ -20,8 +20,10 @@ class CodeHolder; //! \addtogroup asmjit_virtual_memory //! \{ -//! JIT execution runtime is a special `Target` that is designed to store and -//! execute the generated code. +//! JIT execution runtime is a special `Target` that is designed to store and execute a generated code. +//! +//! JIT runtime is the easiest way of using AsmJit as it abstracts allocation and deallocation of virtual memory +//! where executable code can be placed and from which it can be executed as well. class ASMJIT_VIRTAPI JitRuntime : public Target { public: ASMJIT_NONCOPYABLE(JitRuntime) @@ -37,6 +39,16 @@ public: //! Destroys the `JitRuntime` instance. ASMJIT_API ~JitRuntime() noexcept override; + //! \} + + //! \name Accessors + //! \{ + + //! Resets the \ref JitRuntime, freeing everything that was allocated by it. + //! + //! Depending on `resetPolicy` the currently held memory can be either freed entirely when ResetPolicy::kHard is used, + //! or the allocator can keep some of it for next allocations when ResetPolicy::kSoft is used, which is the default + //! behavior. ASMJIT_INLINE_NODEBUG void reset(ResetPolicy resetPolicy = ResetPolicy::kSoft) noexcept { _allocator.reset(resetPolicy); } diff --git a/deps/asmjit/src/asmjit/core/operand.h b/deps/asmjit/src/asmjit/core/operand.h index 6ffde240..8a1eee79 100644 --- a/deps/asmjit/src/asmjit/core/operand.h +++ b/deps/asmjit/src/asmjit/core/operand.h @@ -23,13 +23,15 @@ enum class OperandType : uint32_t { kReg = 1, //! Operand is a memory. kMem = 2, + //! Operand is a register-list. + kRegList = 3, //! Operand is an immediate value. - kImm = 3, + kImm = 4, //! Operand is a label. - kLabel = 4, + kLabel = 5, //! Maximum value of `OperandType`. - kMaxValue = kLabel + kMaxValue = kRegList }; static_assert(uint32_t(OperandType::kMem) == uint32_t(OperandType::kReg) + 1, @@ -47,7 +49,7 @@ enum class RegType : uint8_t { //! No register - unused, invalid, multiple meanings. kNone = 0, - //! This is not a register type. This value is reserved for a \ref Label that used in \ref BaseMem as a base. + //! This is not a register type. This value is reserved for a \ref Label that's used in \ref BaseMem as a base. //! //! Label tag is used as a sub-type, forming a unique signature across all operand types as 0x1 is never associated //! with any register type. This means that a memory operand's BASE register can be constructed from virtually any @@ -55,7 +57,7 @@ enum class RegType : uint8_t { kLabelTag = 1, //! Universal type describing program counter (PC) or instruction pointer (IP) register, if the target architecture - //! actually exposes it as a separate register type, which most modern targets do. + //! actually exposes it as a separate register type, which most modern architectures do. kPC = 2, //! 8-bit low general purpose register (X86). @@ -64,21 +66,21 @@ enum class RegType : uint8_t { kGp8Hi = 4, //! 16-bit general purpose register (X86). kGp16 = 5, - //! 32-bit general purpose register (X86|ARM). + //! 32-bit general purpose register (X86|AArch32|AArch64). kGp32 = 6, - //! 64-bit general purpose register (X86|ARM). + //! 64-bit general purpose register (X86|AArch64). kGp64 = 7, - //! 8-bit view of a vector register (ARM). + //! 8-bit view of a vector register (AArch64). kVec8 = 8, - //! 16-bit view of a vector register (ARM). + //! 16-bit view of a vector register (AArch64). kVec16 = 9, - //! 32-bit view of a vector register (ARM). + //! 32-bit view of a vector register (AArch32|AArch64). kVec32 = 10, - //! 64-bit view of a vector register (ARM). + //! 64-bit view of a vector register (AArch32|AArch64). //! //! \note This is never used for MMX registers on X86, MMX registers have its own category. kVec64 = 11, - //! 128-bit view of a vector register (X86|ARM). + //! 128-bit view of a vector register (X86|AArch32|AArch64). kVec128 = 12, //! 256-bit view of a vector register (X86). kVec256 = 13, @@ -98,9 +100,6 @@ enum class RegType : uint8_t { // X86 Specific Register Types // --------------------------- - // X86 Specific Register Types - // =========================== - //! Instruction pointer (RIP), only addressable in \ref x86::Mem in 64-bit targets. kX86_Rip = kPC, //! Low GPB register (AL, BL, CL, DL, ...). @@ -137,7 +136,7 @@ enum class RegType : uint8_t { kX86_Tmm = kExtra + 6, // ARM Specific Register Types - // =========================== + // --------------------------- //! Program pointer (PC) register (AArch64). kARM_PC = kPC, @@ -153,7 +152,9 @@ enum class RegType : uint8_t { kARM_VecS = kVec32, //! 64-bit view of VFP/ASIMD register (D). kARM_VecD = kVec64, - //! 128-bit view of VFP/ASIMD register (Q|V). + //! 128-bit view of VFP/ASIMD register (Q). + kARM_VecQ = kVec128, + //! 128-bit view of VFP/ASIMD register (V). kARM_VecV = kVec128, //! Maximum value of `RegType`. @@ -172,8 +173,8 @@ enum class RegGroup : uint8_t { //! Describes X86 XMM|YMM|ZMM registers ARM/AArch64 V registers. kVec = 1, - //! Extra virtual group #2 that can be used by Compiler for register allocation. - kExtraVirt2 = 2, + //! Mask register group compatible with all backends that can use masking. + kMask = 2, //! Extra virtual group #3 that can be used by Compiler for register allocation. kExtraVirt3 = 3, @@ -186,8 +187,8 @@ enum class RegGroup : uint8_t { // X86 Specific Register Groups // ---------------------------- - //! K register group (KReg) - maps to \ref RegGroup::kExtraVirt2 (X86, X86_64). - kX86_K = kExtraVirt2, + //! K register group (KReg) - maps to \ref RegGroup::kMask (X86, X86_64). + kX86_K = kMask, //! MMX register group (MM) - maps to \ref RegGroup::kExtraVirt3 (X86, X86_64). kX86_MM = kExtraVirt3, @@ -331,25 +332,25 @@ struct OperandSignature { ASMJIT_INLINE_NODEBUG constexpr uint32_t bits() const noexcept { return _bits; } ASMJIT_INLINE_NODEBUG void setBits(uint32_t bits) noexcept { _bits = bits; } - template::value> + template ASMJIT_INLINE_NODEBUG constexpr bool hasField() const noexcept { return (_bits & kFieldMask) != 0; } - template::value> + template ASMJIT_INLINE_NODEBUG constexpr bool hasField(uint32_t value) const noexcept { - return (_bits & kFieldMask) != value << kFieldShift; + return (_bits & kFieldMask) != value << Support::ConstCTZ::value; } - template::value> + template ASMJIT_INLINE_NODEBUG constexpr uint32_t getField() const noexcept { - return (_bits >> kFieldShift) & (kFieldMask >> kFieldShift); + return (_bits >> Support::ConstCTZ::value) & (kFieldMask >> Support::ConstCTZ::value); } - template::value> + template ASMJIT_INLINE_NODEBUG void setField(uint32_t value) noexcept { - ASMJIT_ASSERT((value & ~(kFieldMask >> kFieldShift)) == 0); - _bits = (_bits & ~kFieldMask) | (value << kFieldShift); + ASMJIT_ASSERT(((value << Support::ConstCTZ::value) & ~kFieldMask) == 0); + _bits = (_bits & ~kFieldMask) | (value << Support::ConstCTZ::value); } ASMJIT_INLINE_NODEBUG constexpr OperandSignature subset(uint32_t mask) const noexcept { return OperandSignature{_bits & mask}; } @@ -389,8 +390,8 @@ struct OperandSignature { ASMJIT_INLINE_NODEBUG void setRegType(RegType regType) noexcept { setField(uint32_t(regType)); } ASMJIT_INLINE_NODEBUG void setRegGroup(RegGroup regGroup) noexcept { setField(uint32_t(regGroup)); } - ASMJIT_INLINE_NODEBUG void setMemBaseType(RegGroup baseType) noexcept { setField(uint32_t(baseType)); } - ASMJIT_INLINE_NODEBUG void setMemIndexType(RegGroup indexType) noexcept { setField(uint32_t(indexType)); } + ASMJIT_INLINE_NODEBUG void setMemBaseType(RegType baseType) noexcept { setField(uint32_t(baseType)); } + ASMJIT_INLINE_NODEBUG void setMemIndexType(RegType indexType) noexcept { setField(uint32_t(indexType)); } ASMJIT_INLINE_NODEBUG void setPredicate(uint32_t predicate) noexcept { setField(predicate); } ASMJIT_INLINE_NODEBUG void setSize(uint32_t size) noexcept { setField(size); } @@ -529,7 +530,12 @@ struct Operand_ { //! \endcond //! Initializes the operand from `other` operand (used by operator overloads). - ASMJIT_INLINE_NODEBUG void copyFrom(const Operand_& other) noexcept { memcpy(this, &other, sizeof(Operand_)); } + ASMJIT_INLINE_NODEBUG void copyFrom(const Operand_& other) noexcept { + _signature._bits = other._signature._bits; + _baseId = other._baseId; + _data[0] = other._data[0]; + _data[1] = other._data[1]; + } //! Resets the `Operand` to none. //! @@ -590,6 +596,22 @@ struct Operand_ { //! \} + //! \name Equality + //! \{ + + //! Tests whether the operand is 100% equal to `other` operand. + //! + //! \note This basically performs a binary comparison, if aby bit is + //! different the operands are not equal. + ASMJIT_INLINE_NODEBUG constexpr bool equals(const Operand_& other) const noexcept { + return bool(unsigned(_signature == other._signature) & + unsigned(_baseId == other._baseId ) & + unsigned(_data[0] == other._data[0] ) & + unsigned(_data[1] == other._data[1] )); + } + + //! \} + //! \name Accessors //! \{ @@ -608,6 +630,8 @@ struct Operand_ { //! //! \note Improper use of `setSignature()` can lead to hard-to-debug errors. ASMJIT_INLINE_NODEBUG void setSignature(const Signature& signature) noexcept { _signature = signature; } + //! \overload + ASMJIT_INLINE_NODEBUG void setSignature(uint32_t signature) noexcept { _signature._bits = signature; } //! Returns the type of the operand, see `OpType`. ASMJIT_INLINE_NODEBUG constexpr OperandType opType() const noexcept { return _signature.opType(); } @@ -615,6 +639,10 @@ struct Operand_ { ASMJIT_INLINE_NODEBUG constexpr bool isNone() const noexcept { return _signature == Signature::fromBits(0); } //! Tests whether the operand is a register (`OperandType::kReg`). ASMJIT_INLINE_NODEBUG constexpr bool isReg() const noexcept { return opType() == OperandType::kReg; } + //! Tests whether the operand is a register-list. + //! + //! \note Register-list is currently only used by 32-bit ARM architecture. + ASMJIT_INLINE_NODEBUG constexpr bool isRegList() const noexcept { return opType() == OperandType::kRegList; } //! Tests whether the operand is a memory location (`OperandType::kMem`). ASMJIT_INLINE_NODEBUG constexpr bool isMem() const noexcept { return opType() == OperandType::kMem; } //! Tests whether the operand is an immediate (`OperandType::kImm`). @@ -638,32 +666,71 @@ struct Operand_ { //! not initialized. ASMJIT_INLINE_NODEBUG constexpr uint32_t id() const noexcept { return _baseId; } - //! Tests whether the operand is 100% equal to `other` operand. - //! - //! \note This basically performs a binary comparison, if aby bit is - //! different the operands are not equal. - ASMJIT_INLINE_NODEBUG constexpr bool equals(const Operand_& other) const noexcept { - return (_signature == other._signature) & - (_baseId == other._baseId ) & - (_data[0] == other._data[0] ) & - (_data[1] == other._data[1] ) ; - } - //! Tests whether the operand is a register matching the given register `type`. ASMJIT_INLINE_NODEBUG constexpr bool isReg(RegType type) const noexcept { return _signature.subset(Signature::kOpTypeMask | Signature::kRegTypeMask) == (Signature::fromOpType(OperandType::kReg) | Signature::fromRegType(type)); } - //! Tests whether the operand is register and of register `type` and `id`. - ASMJIT_INLINE_NODEBUG constexpr bool isReg(RegType type, uint32_t id) const noexcept { - return isReg(type) && this->id() == id; + //! Tests whether the operand is a register of the provided register group `regGroup`. + ASMJIT_INLINE_NODEBUG constexpr bool isReg(RegGroup regGroup) const noexcept { + return _signature.subset(Signature::kOpTypeMask | Signature::kRegGroupMask) == (Signature::fromOpType(OperandType::kReg) | Signature::fromRegGroup(regGroup)); + } + + //! Tests whether the operand is register and of register type `regType` and `regId`. + ASMJIT_INLINE_NODEBUG constexpr bool isReg(RegType regType, uint32_t regId) const noexcept { return isReg(regType) && _baseId == regId; } + //! Tests whether the operand is register and of register group `regGroup` and `regId`. + ASMJIT_INLINE_NODEBUG constexpr bool isReg(RegGroup regGroup, uint32_t regId) const noexcept { return isReg(regGroup) && _baseId == regId; } + + //! Tests whether the register is a general purpose register (any size). + ASMJIT_INLINE_NODEBUG constexpr bool isGp() const noexcept { return isReg(RegGroup::kGp); } + //! Tests whether the register is a 32-bit general purpose register. + ASMJIT_INLINE_NODEBUG constexpr bool isGp32() const noexcept { return isReg(RegType::kGp32); } + //! Tests whether the register is a 64-bit general purpose register. + ASMJIT_INLINE_NODEBUG constexpr bool isGp64() const noexcept { return isReg(RegType::kGp64); } + + //! Tests whether the register is a vector register of any size. + ASMJIT_INLINE_NODEBUG constexpr bool isVec() const noexcept { return isReg(RegGroup::kVec); } + //! Tests whether the register is an 8-bit vector register or view (AArch64). + ASMJIT_INLINE_NODEBUG constexpr bool isVec8() const noexcept { return isReg(RegType::kVec8); } + //! Tests whether the register is a 16-bit vector register or view (AArch64). + ASMJIT_INLINE_NODEBUG constexpr bool isVec16() const noexcept { return isReg(RegType::kVec16); } + //! Tests whether the register is a 32-bit vector register or view (AArch32, AArch64). + ASMJIT_INLINE_NODEBUG constexpr bool isVec32() const noexcept { return isReg(RegType::kVec32); } + //! Tests whether the register is a 64-bit vector register or view (AArch32, AArch64). + ASMJIT_INLINE_NODEBUG constexpr bool isVec64() const noexcept { return isReg(RegType::kVec64); } + //! Tests whether the register is a 128-bit vector register or view (AArch32, AArch64, X86, X86_64). + ASMJIT_INLINE_NODEBUG constexpr bool isVec128() const noexcept { return isReg(RegType::kVec128); } + //! Tests whether the register is a 256-bit vector register or view (X86, X86_64). + ASMJIT_INLINE_NODEBUG constexpr bool isVec256() const noexcept { return isReg(RegType::kVec256); } + //! Tests whether the register is a 512-bit vector register or view (X86, X86_64). + ASMJIT_INLINE_NODEBUG constexpr bool isVec512() const noexcept { return isReg(RegType::kVec512); } + + //! Tests whether the register is a mask register of any size. + ASMJIT_INLINE_NODEBUG constexpr bool isMask() const noexcept { return isReg(RegGroup::kMask); } + + //! Tests whether the operand is a register matching the given register `type`. + ASMJIT_INLINE_NODEBUG constexpr bool isRegList(RegType type) const noexcept { + return _signature.subset(Signature::kOpTypeMask | Signature::kRegTypeMask) == (Signature::fromOpType(OperandType::kRegList) | Signature::fromRegType(type)); } //! Tests whether the operand is a register or memory. + //! + //! \note This is useful on X86 and X86_64 architectures as many instructions support Reg/Mem operand combination. + //! So if the user code works with just \ref Operand, it's possible to check whether the operand is either a register + //! or memory location with a single check. ASMJIT_INLINE_NODEBUG constexpr bool isRegOrMem() const noexcept { return Support::isBetween(uint32_t(opType()), uint32_t(OperandType::kReg), uint32_t(OperandType::kMem)); } + //! Tests whether the operand is a register, register-list, or memory. + //! + //! \note This is useful on 32-bit ARM architecture to check whether an operand references a register. It can be + //! used in other architectures too, but it would work identically to \ref isRegOrMem() as other architectures + //! don't provide register lists. + ASMJIT_INLINE_NODEBUG constexpr bool isRegOrRegListOrMem() const noexcept { + return Support::isBetween(uint32_t(opType()), uint32_t(OperandType::kReg), uint32_t(OperandType::kRegList)); + } + //! \} //! \name Accessors (X86 Specific) @@ -680,10 +747,10 @@ struct Operand_ { } #if !defined(ASMJIT_NO_DEPRECATED) - ASMJIT_DEPRECATED("hasSize() is no longer portable - use x86RmSize() instead if, your target is X86/X86_64") + ASMJIT_DEPRECATED("hasSize() is no longer portable - use x86RmSize() instead, if your target is X86/X86_64") ASMJIT_INLINE_NODEBUG constexpr bool hasSize() const noexcept { return x86RmSize() != 0u; } - ASMJIT_DEPRECATED("hasSize() is no longer portable - use x86RmSize() instead if, your target is X86/X86_64") + ASMJIT_DEPRECATED("hasSize() is no longer portable - use x86RmSize() instead, if your target is X86/X86_64") ASMJIT_INLINE_NODEBUG constexpr bool hasSize(uint32_t s) const noexcept { return x86RmSize() == s; } ASMJIT_DEPRECATED("size() is no longer portable - use x86RmSize() instead, if your target is X86/X86_64") @@ -712,7 +779,7 @@ public: //! Creates an operand initialized to raw `[u0, u1, u2, u3]` values. ASMJIT_INLINE_NODEBUG constexpr Operand(Globals::Init_, const Signature& u0, uint32_t u1, uint32_t u2, uint32_t u3) noexcept - : Operand_{ u0, u1, { u2, u3 }} {} + : Operand_{{u0._bits}, u1, {u2, u3}} {} //! Creates an uninitialized operand (dangerous). ASMJIT_INLINE_NODEBUG explicit Operand(Globals::NoInit_) noexcept {} @@ -818,10 +885,8 @@ struct BaseRegTraits { kTypeId = uint32_t(TypeId::kVoid), //! RegType is not valid by default. kValid = 0, - //! Count of registers (0 if none). - kCount = 0, - //! Zero type by default (defeaults to None). + //! Zero type by default (defaults to None). kType = uint32_t(RegType::kNone), //! Zero group by default (defaults to GP). kGroup = uint32_t(RegGroup::kGp), @@ -834,7 +899,7 @@ struct BaseRegTraits { }; //! \endcond -//! Physical or virtual register operand. +//! Physical or virtual register operand (base). class BaseReg : public Operand { public: //! \name Constants @@ -916,7 +981,7 @@ public: } //! Tests whether the register is valid (either virtual or physical). - ASMJIT_INLINE_NODEBUG constexpr bool isValid() const noexcept { return (_signature != 0) & (_baseId != kIdBad); } + ASMJIT_INLINE_NODEBUG constexpr bool isValid() const noexcept { return bool(unsigned(_signature != 0) & unsigned(_baseId != kIdBad)); } //! Tests whether this is a physical register. ASMJIT_INLINE_NODEBUG constexpr bool isPhysReg() const noexcept { return _baseId < kIdBad; } @@ -930,8 +995,10 @@ public: //! Tests whether the register is a general purpose register (any size). ASMJIT_INLINE_NODEBUG constexpr bool isGp() const noexcept { return isGroup(RegGroup::kGp); } - //! Tests whether the register is a vector register. + //! Tests whether the register is a vector register of any size. ASMJIT_INLINE_NODEBUG constexpr bool isVec() const noexcept { return isGroup(RegGroup::kVec); } + //! Tests whether the register is a mask register of any size. + ASMJIT_INLINE_NODEBUG constexpr bool isMask() const noexcept { return isGroup(RegGroup::kMask); } using Operand_::isReg; @@ -1098,13 +1165,10 @@ struct RegOnly { //! \cond INTERNAL //! Adds a template specialization for `REG_TYPE` into the local `RegTraits`. -#define ASMJIT_DEFINE_REG_TRAITS(REG, REG_TYPE, GROUP, SIZE, COUNT, TYPE_ID) \ +#define ASMJIT_DEFINE_REG_TRAITS(REG_TYPE, GROUP, SIZE, TYPE_ID) \ template<> \ struct RegTraits { \ - typedef REG RegT; \ - \ static constexpr uint32_t kValid = 1; \ - static constexpr uint32_t kCount = COUNT; \ static constexpr RegType kType = REG_TYPE; \ static constexpr RegGroup kGroup = GROUP; \ static constexpr uint32_t kSize = SIZE; \ @@ -1168,6 +1232,196 @@ public: : BASE(Signature{kSignature}, id) {} //! \endcond +//! List of physical registers (base). +//! +//! \note List of registers is only used by some ARM instructions at the moment. +class BaseRegList : public Operand { +public: + //! \name Constants + //! \{ + + enum : uint32_t { + kSignature = Signature::fromOpType(OperandType::kRegList).bits() + }; + + //! \} + + //! \name Construction & Destruction + //! \{ + + //! Creates a dummy register operand. + ASMJIT_INLINE_NODEBUG constexpr BaseRegList() noexcept + : Operand(Globals::Init, Signature::fromOpType(OperandType::kRegList), 0, 0, 0) {} + + //! Creates a new register operand which is the same as `other` . + ASMJIT_INLINE_NODEBUG constexpr BaseRegList(const BaseRegList& other) noexcept + : Operand(other) {} + + //! Creates a new register operand compatible with `other`, but with a different `id`. + ASMJIT_INLINE_NODEBUG constexpr BaseRegList(const BaseRegList& other, RegMask regMask) noexcept + : Operand(Globals::Init, other._signature, regMask, 0, 0) {} + + //! Creates a register initialized to the given `signature` and `id`. + ASMJIT_INLINE_NODEBUG constexpr BaseRegList(const Signature& signature, RegMask regMask) noexcept + : Operand(Globals::Init, signature, regMask, 0, 0) {} + + ASMJIT_INLINE_NODEBUG explicit BaseRegList(Globals::NoInit_) noexcept + : Operand(Globals::NoInit) {} + + //! \} + + //! \name Overloaded Operators + //! \{ + + ASMJIT_INLINE_NODEBUG BaseRegList& operator=(const BaseRegList& other) noexcept = default; + + //! \} + + //! \name Accessors + //! \{ + + //! Tests whether the register-list is valid, which means it has a type and at least a single register in the list. + ASMJIT_INLINE_NODEBUG constexpr bool isValid() const noexcept { return bool(unsigned(_signature != 0u) & unsigned(_baseId != 0u)); } + + //! Tests whether the register type matches `type` - same as `isReg(type)`, provided for convenience. + ASMJIT_INLINE_NODEBUG constexpr bool isType(RegType type) const noexcept { return _signature.subset(Signature::kRegTypeMask) == Signature::fromRegType(type); } + //! Tests whether the register group matches `group`. + ASMJIT_INLINE_NODEBUG constexpr bool isGroup(RegGroup group) const noexcept { return _signature.subset(Signature::kRegGroupMask) == Signature::fromRegGroup(group); } + + //! Tests whether the register is a general purpose register (any size). + ASMJIT_INLINE_NODEBUG constexpr bool isGp() const noexcept { return isGroup(RegGroup::kGp); } + //! Tests whether the register is a vector register. + ASMJIT_INLINE_NODEBUG constexpr bool isVec() const noexcept { return isGroup(RegGroup::kVec); } + + //! Returns the register type. + ASMJIT_INLINE_NODEBUG constexpr RegType type() const noexcept { return _signature.regType(); } + //! Returns the register group. + ASMJIT_INLINE_NODEBUG constexpr RegGroup group() const noexcept { return _signature.regGroup(); } + //! Returns the size of a single register in this register-list or 0 if unspecified. + ASMJIT_INLINE_NODEBUG constexpr uint32_t size() const noexcept { return _signature.getField(); } + + //! Returns the register list as a mask, where each bit represents one physical register. + ASMJIT_INLINE_NODEBUG constexpr RegMask list() const noexcept { return _baseId; } + //! Sets the register list to `mask`. + ASMJIT_INLINE_NODEBUG void setList(RegMask mask) noexcept { _baseId = mask; } + //! Remoes all registers from the register-list by making the underlying register-mask zero. + ASMJIT_INLINE_NODEBUG void resetList() noexcept { _baseId = 0; } + + //! Adds registers passed by a register `mask` to the register-list. + ASMJIT_INLINE_NODEBUG void addList(RegMask mask) noexcept { _baseId |= mask; } + //! Removes registers passed by a register `mask` to the register-list. + ASMJIT_INLINE_NODEBUG void clearList(RegMask mask) noexcept { _baseId &= ~mask; } + //! Uses AND operator to combine the current register-list with other register `mask`. + ASMJIT_INLINE_NODEBUG void andList(RegMask mask) noexcept { _baseId &= mask; } + //! Uses XOR operator to combine the current register-list with other register `mask`. + ASMJIT_INLINE_NODEBUG void xorList(RegMask mask) noexcept { _baseId ^= mask; } + + //! Checks whether a physical register `physId` is in the register-list. + ASMJIT_INLINE_NODEBUG bool hasReg(uint32_t physId) const noexcept { return physId < 32u ? (_baseId & (1u << physId)) != 0 : false; } + //! Adds a physical register `physId` to the register-list. + ASMJIT_INLINE_NODEBUG void addReg(uint32_t physId) noexcept { addList(1u << physId); } + //! Removes a physical register `physId` from the register-list. + ASMJIT_INLINE_NODEBUG void clearReg(uint32_t physId) noexcept { clearList(1u << physId); } + + //! Clones the register-list operand. + ASMJIT_INLINE_NODEBUG constexpr BaseRegList clone() const noexcept { return BaseRegList(*this); } + + //! Casts this register to `RegT` by also changing its signature. + //! + //! \note Improper use of `cloneAs()` can lead to hard-to-debug errors. + template + ASMJIT_INLINE_NODEBUG constexpr RegListT cloneAs() const noexcept { return RegListT(Signature(RegListT::kSignature), list()); } + + //! Casts this register to `other` by also changing its signature. + //! + //! \note Improper use of `cloneAs()` can lead to hard-to-debug errors. + template + ASMJIT_INLINE_NODEBUG constexpr RegListT cloneAs(const RegListT& other) const noexcept { return RegListT(other.signature(), list()); } + + //! \} +}; + +template +class RegListT : public BaseRegList { +public: + //! \name Construction & Destruction + //! \{ + + //! Creates a dummy register operand. + ASMJIT_INLINE_NODEBUG constexpr RegListT() noexcept + : BaseRegList() {} + + //! Creates a new register operand which is the same as `other` . + ASMJIT_INLINE_NODEBUG constexpr RegListT(const RegListT& other) noexcept + : BaseRegList(other) {} + + //! Creates a new register operand compatible with `other`, but with a different `id`. + ASMJIT_INLINE_NODEBUG constexpr RegListT(const RegListT& other, RegMask regMask) noexcept + : BaseRegList(other, regMask) {} + + //! Creates a register initialized to the given `signature` and `id`. + ASMJIT_INLINE_NODEBUG constexpr RegListT(const Signature& signature, RegMask regMask) noexcept + : BaseRegList(signature, regMask) {} + + //! Creates a register initialized to the given `signature` and `regs`. + ASMJIT_INLINE_NODEBUG RegListT(const Signature& signature, std::initializer_list regs) noexcept + : BaseRegList(signature, RegMask(0)) { addRegs(regs); } + + ASMJIT_INLINE_NODEBUG explicit RegListT(Globals::NoInit_) noexcept + : BaseRegList(Globals::NoInit) {} + + //! \} + + //! \name Overloaded Operators + //! \{ + + ASMJIT_INLINE_NODEBUG RegListT& operator=(const RegListT& other) noexcept = default; + + //! \} + + //! \name Accessors + //! \{ + + using BaseRegList::addList; + using BaseRegList::clearList; + using BaseRegList::andList; + using BaseRegList::xorList; + + //! Adds registers to this register-list as provided by `other` register-list. + ASMJIT_INLINE_NODEBUG void addList(const RegListT& other) noexcept { addList(other.list()); } + //! Removes registers contained in `other` register-list. + ASMJIT_INLINE_NODEBUG void clearList(const RegListT& other) noexcept { clearList(other.list()); } + //! Uses AND operator to combine the current register-list with `other` register-list. + ASMJIT_INLINE_NODEBUG void andList(const RegListT& other) noexcept { andList(other.list()); } + //! Uses XOR operator to combine the current register-list with `other` register-list. + ASMJIT_INLINE_NODEBUG void xorList(const RegListT& other) noexcept { xorList(other.list()); } + + using BaseRegList::addReg; + using BaseRegList::clearReg; + + ASMJIT_INLINE_NODEBUG void addReg(const RegT& reg) noexcept { + if (reg.id() < 32u) + addReg(reg.id()); + } + + ASMJIT_INLINE_NODEBUG void addRegs(std::initializer_list regs) noexcept { + for (const RegT& reg : regs) + addReg(reg); + } + + ASMJIT_INLINE_NODEBUG void clearReg(const RegT& reg) noexcept { + if (reg.id() < 32u) + clearReg(reg.id()); + } + + ASMJIT_INLINE_NODEBUG void clearRegs(std::initializer_list regs) noexcept { + for (const RegT& reg : regs) + clearReg(reg); + } + + //! \} +}; + //! Base class for all memory operands. //! //! The data is split into the following parts: @@ -1316,8 +1570,13 @@ public: //! Sets the id of the BASE register (without modifying its type). ASMJIT_INLINE_NODEBUG void setBaseId(uint32_t id) noexcept { _baseId = id; } + //! Sets the register type of the BASE register (without modifying its id). + ASMJIT_INLINE_NODEBUG void setBaseType(RegType regType) noexcept { _signature.setMemBaseType(regType); } + //! Sets the id of the INDEX register (without modifying its type). ASMJIT_INLINE_NODEBUG void setIndexId(uint32_t id) noexcept { _data[kDataMemIndexId] = id; } + //! Sets the register type of the INDEX register (without modifying its id). + ASMJIT_INLINE_NODEBUG void setIndexType(RegType regType) noexcept { _signature.setMemIndexType(regType); } //! Sets the base register to type and id of the given `base` operand. ASMJIT_INLINE_NODEBUG void setBase(const BaseReg& base) noexcept { return _setBase(base.type(), base.id()); } diff --git a/deps/asmjit/src/asmjit/core/radefs_p.h b/deps/asmjit/src/asmjit/core/radefs_p.h index d5389d49..d61a9cc2 100644 --- a/deps/asmjit/src/asmjit/core/radefs_p.h +++ b/deps/asmjit/src/asmjit/core/radefs_p.h @@ -67,7 +67,7 @@ public: uint32_t registerCount = arch == Arch::kX86 ? 8 : 16; _availableRegs[RegGroup::kGp] = Support::lsbMask(registerCount) & ~Support::bitMask(4u); _availableRegs[RegGroup::kVec] = Support::lsbMask(registerCount); - _availableRegs[RegGroup::kExtraVirt2] = Support::lsbMask(8); + _availableRegs[RegGroup::kMask] = Support::lsbMask(8); _availableRegs[RegGroup::kExtraVirt3] = Support::lsbMask(8); return kErrorOk; } @@ -75,7 +75,7 @@ public: case Arch::kAArch64: { _availableRegs[RegGroup::kGp] = 0xFFFFFFFFu & ~Support::bitMask(18, 31u); _availableRegs[RegGroup::kVec] = 0xFFFFFFFFu; - _availableRegs[RegGroup::kExtraVirt2] = 0; + _availableRegs[RegGroup::kMask] = 0; _availableRegs[RegGroup::kExtraVirt3] = 0; return kErrorOk; } @@ -767,6 +767,12 @@ enum class RATiedFlags : uint32_t { // Instruction Flags (Never used by RATiedReg) // ------------------------------------------- + //! Instruction has been patched to address a memory location instead of a register. + //! + //! This is currently only possible on X86 or X86_64 targets. It informs rewriter to rewrite the instruction if + //! necessary. + kInst_RegToMemPatched = 0x40000000u, + //! Instruction is transformable to another instruction if necessary. //! //! This is flag that is only used by \ref RAInst to inform register allocator that the instruction has some diff --git a/deps/asmjit/src/asmjit/core/ralocal.cpp b/deps/asmjit/src/asmjit/core/ralocal.cpp index 6378ec43..95ccd163 100644 --- a/deps/asmjit/src/asmjit/core/ralocal.cpp +++ b/deps/asmjit/src/asmjit/core/ralocal.cpp @@ -21,8 +21,8 @@ static ASMJIT_FORCE_INLINE RATiedReg* RALocal_findTiedRegByWorkId(RATiedReg* tie return nullptr; } -// RALocalAllocator - Init & Reset -// =============================== +// RALocalAllocator - Initialization & Reset +// ========================================= Error RALocalAllocator::init() noexcept { PhysToWorkMap* physToWorkMap; @@ -137,6 +137,7 @@ Error RALocalAllocator::switchToAssignment(PhysToWorkMap* dstPhysToWorkMap, cons dst.initMaps(dstPhysToWorkMap, _tmpWorkToPhysMap); dst.assignWorkIdsFromPhysIds(); + // TODO: Remove this - finally enable this functionality. if (tryMode) return kErrorOk; @@ -601,6 +602,7 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { tiedReg->_useRewriteMask = 0; tiedReg->markUseDone(); + raInst->addFlags(RATiedFlags::kInst_RegToMemPatched); usePending--; rmAllocated = true; @@ -687,7 +689,7 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { // ------ // // ALLOCATE / SHUFFLE all registers that we marked as `willUse` and weren't allocated yet. This is a bit - // complicated as the allocation is iterative. In some cases we have to wait before allocating a particual + // complicated as the allocation is iterative. In some cases we have to wait before allocating a particular // physical register as it's still occupied by some other one, which we need to move before we can use it. // In this case we skip it and allocate another some other instead (making it free for another iteration). // @@ -836,7 +838,7 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { // STEP 9 // ------ // - // Vector registers can be cloberred partially by invoke - find if that's the case and clobber when necessary. + // Vector registers can be clobbered partially by invoke - find if that's the case and clobber when necessary. if (node->isInvoke() && group == RegGroup::kVec) { const InvokeNode* invokeNode = node->as(); diff --git a/deps/asmjit/src/asmjit/core/ralocal_p.h b/deps/asmjit/src/asmjit/core/ralocal_p.h index 1e9e5a8d..63fd1b78 100644 --- a/deps/asmjit/src/asmjit/core/ralocal_p.h +++ b/deps/asmjit/src/asmjit/core/ralocal_p.h @@ -29,52 +29,45 @@ public: typedef RAAssignment::WorkToPhysMap WorkToPhysMap; //! Link to `BaseRAPass`. - BaseRAPass* _pass; + BaseRAPass* _pass {}; //! Link to `BaseCompiler`. - BaseCompiler* _cc; + BaseCompiler* _cc {}; //! Architecture traits. - const ArchTraits* _archTraits; + const ArchTraits* _archTraits {}; //! Registers available to the allocator. - RARegMask _availableRegs; + RARegMask _availableRegs {}; //! Registers clobbered by the allocator. - RARegMask _clobberedRegs; + RARegMask _clobberedRegs {}; //! Register assignment (current). - RAAssignment _curAssignment; + RAAssignment _curAssignment {}; //! Register assignment used temporarily during assignment switches. - RAAssignment _tmpAssignment; + RAAssignment _tmpAssignment {}; //! Link to the current `RABlock`. - RABlock* _block; + RABlock* _block {}; //! InstNode. - InstNode* _node; + InstNode* _node {}; //! RA instruction. - RAInst* _raInst; + RAInst* _raInst {}; //! Count of all TiedReg's. - uint32_t _tiedTotal; + uint32_t _tiedTotal {}; //! TiedReg's total counter. - RARegCount _tiedCount; + RARegCount _tiedCount {}; //! Temporary workToPhysMap that can be used freely by the allocator. - WorkToPhysMap* _tmpWorkToPhysMap; + WorkToPhysMap* _tmpWorkToPhysMap {}; //! \name Construction & Destruction //! \{ - inline RALocalAllocator(BaseRAPass* pass) noexcept + inline explicit RALocalAllocator(BaseRAPass* pass) noexcept : _pass(pass), _cc(pass->cc()), _archTraits(pass->_archTraits), - _availableRegs(pass->_availableRegs), - _clobberedRegs(), - _curAssignment(), - _block(nullptr), - _node(nullptr), - _raInst(nullptr), - _tiedTotal(), - _tiedCount() {} + _availableRegs(pass->_availableRegs) {} Error init() noexcept; diff --git a/deps/asmjit/src/asmjit/core/rapass.cpp b/deps/asmjit/src/asmjit/core/rapass.cpp index a5b11678..837cbe29 100644 --- a/deps/asmjit/src/asmjit/core/rapass.cpp +++ b/deps/asmjit/src/asmjit/core/rapass.cpp @@ -366,21 +366,18 @@ Error BaseRAPass::initSharedAssignments(const ZoneVector& sharedAssign class RABlockVisitItem { public: + RABlock* _block {}; + uint32_t _index {}; + inline RABlockVisitItem(RABlock* block, uint32_t index) noexcept : _block(block), _index(index) {} - inline RABlockVisitItem(const RABlockVisitItem& other) noexcept - : _block(other._block), - _index(other._index) {} - + inline RABlockVisitItem(const RABlockVisitItem& other) noexcept = default; inline RABlockVisitItem& operator=(const RABlockVisitItem& other) noexcept = default; inline RABlock* block() const noexcept { return _block; } inline uint32_t index() const noexcept { return _index; } - - RABlock* _block; - uint32_t _index; }; Error BaseRAPass::buildCFGViews() noexcept { @@ -479,12 +476,18 @@ Error BaseRAPass::buildCFGDominators() noexcept { entryBlock->setIDom(entryBlock); bool changed = true; - uint32_t nIters = 0; + +#ifndef ASMJIT_NO_LOGGING + uint32_t numIters = 0; +#endif while (changed) { - nIters++; changed = false; +#ifndef ASMJIT_NO_LOGGING + numIters++; +#endif + uint32_t i = _pov.size(); while (i) { RABlock* block = _pov[--i]; @@ -511,7 +514,7 @@ Error BaseRAPass::buildCFGDominators() noexcept { } } - ASMJIT_RA_LOG_FORMAT(" Done (%u iterations)\n", nIters); + ASMJIT_RA_LOG_FORMAT(" Done (%u iterations)\n", numIters); return kErrorOk; } @@ -759,6 +762,13 @@ namespace LiveOps { static ASMJIT_FORCE_INLINE bool op(BitWord* dst, const BitWord* a, const BitWord* b, const BitWord* c, uint32_t n) noexcept { BitWord changed = 0; +#if defined(_MSC_VER) && _MSC_VER <= 1938 + // MSVC workaround (see #427). + // + // MSVC incorrectly auto-vectorizes this loop when used with operator. For some reason it trashes a content + // of a register, which causes the result to be incorrect. It's a compiler bug we have to prevent unfortunately. + #pragma loop(no_vector) +#endif for (uint32_t i = 0; i < n; i++) { BitWord before = dst[i]; BitWord after = Operator::op(before, a[i], b[i], c[i]); @@ -770,7 +780,7 @@ namespace LiveOps { return changed != 0; } - static ASMJIT_FORCE_INLINE bool recalcInOut(RABlock* block, uint32_t numBitWords, bool initial = false) noexcept { + static ASMJIT_NOINLINE bool recalcInOut(RABlock* block, uint32_t numBitWords, bool initial = false) noexcept { bool changed = initial; const RABlocks& successors = block->successors(); @@ -801,7 +811,6 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { uint32_t numAllBlocks = blockCount(); uint32_t numReachableBlocks = reachableBlockCount(); - uint32_t numVisits = numReachableBlocks; uint32_t numWorkRegs = workRegCount(); uint32_t numBitWords = ZoneBitVector::_wordsPerBits(numWorkRegs); @@ -871,7 +880,7 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { if (tiedReg->hasConsecutiveParent()) { RAWorkReg* consecutiveParentReg = workRegById(tiedReg->consecutiveParent()); - consecutiveParentReg->addImmediateConsecutive(allocator(), workId); + ASMJIT_PROPAGATE(consecutiveParentReg->addImmediateConsecutive(allocator(), workId)); } } @@ -891,6 +900,10 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { // Calculate IN/OUT of Each Block // ------------------------------ +#ifndef ASMJIT_NO_LOGGING + uint32_t numVisits = numReachableBlocks; +#endif + { ZoneStack workList; ZoneBitVector workBits; @@ -921,7 +934,9 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { } } } +#ifndef ASMJIT_NO_LOGGING numVisits++; +#endif } workList.reset(); @@ -1208,6 +1223,7 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::binPack(RegGroup group) noexcept { uint32_t numWorkRegs = workRegs.size(); RegMask availableRegs = _availableRegs[group]; + RegMask preservedRegs = func()->frame().preservedRegs(group); // First try to pack everything that provides register-id hint as these are most likely function arguments and fixed // (precolored) virtual registers. @@ -1339,18 +1355,30 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::binPack(RegGroup group) noexcept { if (workReg->isAllocated()) continue; - RegMask physRegs = availableRegs; - if (physRegs & workReg->preferredMask()) - physRegs &= workReg->preferredMask(); + RegMask remainingPhysRegs = availableRegs; + if (remainingPhysRegs & workReg->preferredMask()) + remainingPhysRegs &= workReg->preferredMask(); - while (physRegs) { - RegMask preferredMask = physRegs; - uint32_t physId = Support::ctz(preferredMask); + RegMask physRegs = remainingPhysRegs & ~preservedRegs; + remainingPhysRegs &= preservedRegs; + + for (;;) { + if (!physRegs) { + if (!remainingPhysRegs) + break; + physRegs = remainingPhysRegs; + remainingPhysRegs = 0; + } + + uint32_t physId = Support::ctz(physRegs); if (workReg->clobberSurvivalMask()) { - preferredMask &= workReg->clobberSurvivalMask(); - if (preferredMask) + RegMask preferredMask = (physRegs | remainingPhysRegs) & workReg->clobberSurvivalMask(); + if (preferredMask) { + if (preferredMask & ~remainingPhysRegs) + preferredMask &= ~remainingPhysRegs; physId = Support::ctz(preferredMask); + } } LiveRegSpans& live = _globalLiveSpans[group][physId]; @@ -1366,7 +1394,8 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::binPack(RegGroup group) noexcept { if (ASMJIT_UNLIKELY(err != 0xFFFFFFFFu)) return err; - physRegs ^= Support::bitMask(physId); + physRegs &= ~Support::bitMask(physId); + remainingPhysRegs &= ~Support::bitMask(physId); } // Keep it in `workRegs` if it was not allocated. diff --git a/deps/asmjit/src/asmjit/core/rapass_p.h b/deps/asmjit/src/asmjit/core/rapass_p.h index 90d4ae49..96762404 100644 --- a/deps/asmjit/src/asmjit/core/rapass_p.h +++ b/deps/asmjit/src/asmjit/core/rapass_p.h @@ -335,6 +335,8 @@ public: //! Clears instruction `flags` from this RAInst. ASMJIT_INLINE_NODEBUG void clearFlags(RATiedFlags flags) noexcept { _flags &= ~flags; } + //! Tests whether one operand of this instruction has been patched from Reg to Mem. + ASMJIT_INLINE_NODEBUG bool isRegToMemPatched() const noexcept { return hasFlag(RATiedFlags::kInst_RegToMemPatched); } //! Tests whether this instruction can be transformed to another instruction if necessary. ASMJIT_INLINE_NODEBUG bool isTransformable() const noexcept { return hasFlag(RATiedFlags::kInst_IsTransformable); } diff --git a/deps/asmjit/src/asmjit/core/string.cpp b/deps/asmjit/src/asmjit/core/string.cpp index 518dd717..123e8619 100644 --- a/deps/asmjit/src/asmjit/core/string.cpp +++ b/deps/asmjit/src/asmjit/core/string.cpp @@ -463,7 +463,7 @@ Error String::truncate(size_t newSize) noexcept { return kErrorOk; } -bool String::eq(const char* other, size_t size) const noexcept { +bool String::equals(const char* other, size_t size) const noexcept { const char* aData = data(); const char* bData = other; @@ -499,8 +499,8 @@ UNIT(core_string) { EXPECT_EQ(s.capacity(), String::kSSOCapacity); EXPECT_EQ(s.data()[0], 'a'); EXPECT_EQ(s.data()[1], '\0'); - EXPECT_TRUE(s.eq("a")); - EXPECT_TRUE(s.eq("a", 1)); + EXPECT_TRUE(s.equals("a")); + EXPECT_TRUE(s.equals("a", 1)); EXPECT_EQ(s.assignChars('b', 4), kErrorOk); EXPECT_EQ(s.size(), 4u); @@ -510,8 +510,8 @@ UNIT(core_string) { EXPECT_EQ(s.data()[2], 'b'); EXPECT_EQ(s.data()[3], 'b'); EXPECT_EQ(s.data()[4], '\0'); - EXPECT_TRUE(s.eq("bbbb")); - EXPECT_TRUE(s.eq("bbbb", 4)); + EXPECT_TRUE(s.equals("bbbb")); + EXPECT_TRUE(s.equals("bbbb", 4)); EXPECT_EQ(s.assign("abc"), kErrorOk); EXPECT_EQ(s.size(), 3u); @@ -520,16 +520,16 @@ UNIT(core_string) { EXPECT_EQ(s.data()[1], 'b'); EXPECT_EQ(s.data()[2], 'c'); EXPECT_EQ(s.data()[3], '\0'); - EXPECT_TRUE(s.eq("abc")); - EXPECT_TRUE(s.eq("abc", 3)); + EXPECT_TRUE(s.equals("abc")); + EXPECT_TRUE(s.equals("abc", 3)); const char* large = "Large string that will not fit into SSO buffer"; EXPECT_EQ(s.assign(large), kErrorOk); EXPECT_TRUE(s.isLargeOrExternal()); EXPECT_EQ(s.size(), strlen(large)); EXPECT_GT(s.capacity(), String::kSSOCapacity); - EXPECT_TRUE(s.eq(large)); - EXPECT_TRUE(s.eq(large, strlen(large))); + EXPECT_TRUE(s.equals(large)); + EXPECT_TRUE(s.equals(large, strlen(large))); const char* additional = " (additional content)"; EXPECT_TRUE(s.isLargeOrExternal()); @@ -543,10 +543,10 @@ UNIT(core_string) { EXPECT_TRUE(s.isLargeOrExternal()); // Clear should never release the memory. EXPECT_EQ(s.appendUInt(1234), kErrorOk); - EXPECT_TRUE(s.eq("1234")); + EXPECT_TRUE(s.equals("1234")); EXPECT_EQ(s.assignUInt(0xFFFF, 16, 0, StringFormatFlags::kAlternate), kErrorOk); - EXPECT_TRUE(s.eq("0xFFFF")); + EXPECT_TRUE(s.equals("0xFFFF")); StringTmp<64> sTmp; EXPECT_TRUE(sTmp.isLargeOrExternal()); diff --git a/deps/asmjit/src/asmjit/core/string.h b/deps/asmjit/src/asmjit/core/string.h index 197aa59b..c4dee14b 100644 --- a/deps/asmjit/src/asmjit/core/string.h +++ b/deps/asmjit/src/asmjit/core/string.h @@ -53,9 +53,12 @@ union FixedString { //! \name Utilities //! \{ - inline bool eq(const char* other) const noexcept { - return strcmp(str, other) == 0; - } + inline bool equals(const char* other) const noexcept { return strcmp(str, other) == 0; } + +#if !defined(ASMJIT_NO_DEPRECATED) + ASMJIT_DEPRECATED("Use FixedString::equals() instead") + inline bool eq(const char* other) const noexcept { return equals(other); } +#endif // !ASMJIT_NO_DEPRECATED //! \} }; @@ -158,11 +161,11 @@ public: return *this; } - ASMJIT_INLINE_NODEBUG bool operator==(const char* other) const noexcept { return eq(other); } - ASMJIT_INLINE_NODEBUG bool operator!=(const char* other) const noexcept { return !eq(other); } + ASMJIT_INLINE_NODEBUG bool operator==(const char* other) const noexcept { return equals(other); } + ASMJIT_INLINE_NODEBUG bool operator!=(const char* other) const noexcept { return !equals(other); } - ASMJIT_INLINE_NODEBUG bool operator==(const String& other) const noexcept { return eq(other); } - ASMJIT_INLINE_NODEBUG bool operator!=(const String& other) const noexcept { return !eq(other); } + ASMJIT_INLINE_NODEBUG bool operator==(const String& other) const noexcept { return equals(other); } + ASMJIT_INLINE_NODEBUG bool operator!=(const String& other) const noexcept { return !equals(other); } //! \} @@ -312,8 +315,16 @@ public: //! Truncate the string length into `newSize`. ASMJIT_API Error truncate(size_t newSize) noexcept; - ASMJIT_API bool eq(const char* other, size_t size = SIZE_MAX) const noexcept; - ASMJIT_INLINE_NODEBUG bool eq(const String& other) const noexcept { return eq(other.data(), other.size()); } + ASMJIT_API bool equals(const char* other, size_t size = SIZE_MAX) const noexcept; + ASMJIT_INLINE_NODEBUG bool equals(const String& other) const noexcept { return equals(other.data(), other.size()); } + +#if !defined(ASMJIT_NO_DEPRECATED) + ASMJIT_DEPRECATED("Use String::equals() instead") + ASMJIT_INLINE_NODEBUG bool eq(const char* other, size_t size = SIZE_MAX) const noexcept { return equals(other, size); } + + ASMJIT_DEPRECATED("Use String::equals() instead") + ASMJIT_INLINE_NODEBUG bool eq(const String& other) const noexcept { return equals(other.data(), other.size()); } +#endif // !ASMJIT_NO_DEPRECATED //! \} diff --git a/deps/asmjit/src/asmjit/core/support.h b/deps/asmjit/src/asmjit/core/support.h index 5ba726c3..b5be91bc 100644 --- a/deps/asmjit/src/asmjit/core/support.h +++ b/deps/asmjit/src/asmjit/core/support.h @@ -230,7 +230,7 @@ static ASMJIT_INLINE_NODEBUG constexpr T lsbMask(const CountT& n) noexcept { : n ? T(shr(allOnes(), bitSizeOf() - size_t(n))) : T(0); } -//! Generats a leading bit-mask that has `n` most significant (leading) bits set. +//! Generates a leading bit-mask that has `n` most significant (leading) bits set. template static ASMJIT_INLINE_NODEBUG constexpr T msbMask(const CountT& n) noexcept { typedef typename std::make_unsigned::type U; @@ -321,12 +321,12 @@ struct BitScanCalc { }; template -constexpr ASMJIT_INLINE_NODEBUG uint32_t clzFallback(const T& x) noexcept { +ASMJIT_INLINE_NODEBUG constexpr uint32_t clzFallback(const T& x) noexcept { return BitScanCalc() / 2u>::clz(BitScanData{x, 1}).n; } template -constexpr ASMJIT_INLINE_NODEBUG uint32_t ctzFallback(const T& x) noexcept { +ASMJIT_INLINE_NODEBUG constexpr uint32_t ctzFallback(const T& x) noexcept { return BitScanCalc() / 2u>::ctz(BitScanData{x, 1}).n; } @@ -457,31 +457,30 @@ namespace Internal { } static ASMJIT_INLINE_NODEBUG uint32_t constPopcntImpl(uint64_t x) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - x = x - ((x >> 1) & 0x5555555555555555u); - x = (x & 0x3333333333333333u) + ((x >> 2) & 0x3333333333333333u); - return uint32_t((((x + (x >> 4)) & 0x0F0F0F0F0F0F0F0Fu) * 0x0101010101010101u) >> 56); - } - else { - return constPopcntImpl(uint32_t(x >> 32)) + - constPopcntImpl(uint32_t(x & 0xFFFFFFFFu)); - } +#if ASMJIT_ARCH_BITS >= 64 + x = x - ((x >> 1) & 0x5555555555555555u); + x = (x & 0x3333333333333333u) + ((x >> 2) & 0x3333333333333333u); + return uint32_t((((x + (x >> 4)) & 0x0F0F0F0F0F0F0F0Fu) * 0x0101010101010101u) >> 56); +#else + return constPopcntImpl(uint32_t(x >> 32)) + + constPopcntImpl(uint32_t(x & 0xFFFFFFFFu)); +#endif } static ASMJIT_INLINE_NODEBUG uint32_t popcntImpl(uint32_t x) noexcept { - #if defined(__GNUC__) +#if defined(__GNUC__) return uint32_t(__builtin_popcount(x)); - #else +#else return constPopcntImpl(asUInt(x)); - #endif +#endif } static ASMJIT_INLINE_NODEBUG uint32_t popcntImpl(uint64_t x) noexcept { - #if defined(__GNUC__) +#if defined(__GNUC__) return uint32_t(__builtin_popcountll(x)); - #else +#else return constPopcntImpl(asUInt(x)); - #endif +#endif } } //! \endcond @@ -596,9 +595,9 @@ namespace Internal { template inline T subOverflowImpl(const T& x, const T& y, FastUInt8* of) noexcept { return subOverflowFallback(x, y, of); } template inline T mulOverflowImpl(const T& x, const T& y, FastUInt8* of) noexcept { return mulOverflowFallback(x, y, of); } - #if defined(__GNUC__) && !defined(ASMJIT_NO_INTRINSICS) - #if defined(__clang__) || __GNUC__ >= 5 - #define ASMJIT_ARITH_OVERFLOW_SPECIALIZE(FUNC, T, RESULT_T, BUILTIN) \ +#if defined(__GNUC__) && !defined(ASMJIT_NO_INTRINSICS) +#if defined(__clang__) || __GNUC__ >= 5 +#define ASMJIT_ARITH_OVERFLOW_SPECIALIZE(FUNC, T, RESULT_T, BUILTIN) \ template<> \ inline T FUNC(const T& x, const T& y, FastUInt8* of) noexcept { \ RESULT_T result; \ @@ -617,13 +616,13 @@ namespace Internal { ASMJIT_ARITH_OVERFLOW_SPECIALIZE(mulOverflowImpl, uint32_t, unsigned int , __builtin_umul_overflow ) ASMJIT_ARITH_OVERFLOW_SPECIALIZE(mulOverflowImpl, int64_t , long long , __builtin_smulll_overflow) ASMJIT_ARITH_OVERFLOW_SPECIALIZE(mulOverflowImpl, uint64_t, unsigned long long, __builtin_umulll_overflow) - #undef ASMJIT_ARITH_OVERFLOW_SPECIALIZE - #endif - #endif +#undef ASMJIT_ARITH_OVERFLOW_SPECIALIZE +#endif +#endif // There is a bug in MSVC that makes these specializations unusable, maybe in the future... - #if defined(_MSC_VER) && 0 - #define ASMJIT_ARITH_OVERFLOW_SPECIALIZE(FUNC, T, ALT_T, BUILTIN) \ +#if defined(_MSC_VER) && 0 +#define ASMJIT_ARITH_OVERFLOW_SPECIALIZE(FUNC, T, ALT_T, BUILTIN) \ template<> \ inline T FUNC(T x, T y, FastUInt8* of) noexcept { \ ALT_T result; \ @@ -632,12 +631,12 @@ namespace Internal { } ASMJIT_ARITH_OVERFLOW_SPECIALIZE(addOverflowImpl, uint32_t, unsigned int , _addcarry_u32 ) ASMJIT_ARITH_OVERFLOW_SPECIALIZE(subOverflowImpl, uint32_t, unsigned int , _subborrow_u32) - #if ARCH_BITS >= 64 +#if ARCH_BITS >= 64 ASMJIT_ARITH_OVERFLOW_SPECIALIZE(addOverflowImpl, uint64_t, unsigned __int64 , _addcarry_u64 ) ASMJIT_ARITH_OVERFLOW_SPECIALIZE(subOverflowImpl, uint64_t, unsigned __int64 , _subborrow_u64) - #endif - #undef ASMJIT_ARITH_OVERFLOW_SPECIALIZE - #endif +#endif +#undef ASMJIT_ARITH_OVERFLOW_SPECIALIZE +#endif } // {Internal} //! \endcond @@ -926,19 +925,6 @@ static ASMJIT_INLINE_NODEBUG const char* findPackedString(const char* p, uint32_ return p; } -//! Compares two instruction names. -//! -//! `a` is a null terminated instruction name from arch-specific `nameData[]` -//! table. `b` is a possibly non-null terminated instruction name passed to -//! `InstAPI::stringToInstId()`. -static ASMJIT_FORCE_INLINE int cmpInstName(const char* a, const char* b, size_t size) noexcept { - for (size_t i = 0; i < size; i++) { - int c = int(uint8_t(a[i])) - int(uint8_t(b[i])); - if (c != 0) return c; - } - return int(uint8_t(a[size])); -} - //! Compares two string views. static ASMJIT_FORCE_INLINE int compareStringViews(const char* aData, size_t aSize, const char* bData, size_t bSize) noexcept { size_t size = Support::min(aSize, bSize); @@ -951,6 +937,7 @@ static ASMJIT_FORCE_INLINE int compareStringViews(const char* aData, size_t aSiz return int(aSize) - int(bSize); } + // Support - Memory Read Access - 8 Bits // ===================================== @@ -997,9 +984,9 @@ static ASMJIT_INLINE_NODEBUG int16_t readI16aBE(const void* p) noexcept { return template static inline uint32_t readU24u(const void* p) noexcept { - uint32_t b0 = readU8(static_cast(p) + (BO == ByteOrder::kLE ? 2 : 0)); - uint32_t b1 = readU8(static_cast(p) + (BO == ByteOrder::kLE ? 1 : 1)); - uint32_t b2 = readU8(static_cast(p) + (BO == ByteOrder::kLE ? 0 : 2)); + uint32_t b0 = readU8(static_cast(p) + (BO == ByteOrder::kLE ? 2u : 0u)); + uint32_t b1 = readU8(static_cast(p) + 1u); + uint32_t b2 = readU8(static_cast(p) + (BO == ByteOrder::kLE ? 0u : 2u)); return (b0 << 16) | (b1 << 8) | b2; } @@ -1119,7 +1106,7 @@ static ASMJIT_INLINE_NODEBUG void writeI16aBE(void* p, int16_t x) noexcept { wri template static inline void writeU24u(void* p, uint32_t v) noexcept { static_cast(p)[0] = uint8_t((v >> (BO == ByteOrder::kLE ? 0 : 16)) & 0xFFu); - static_cast(p)[1] = uint8_t((v >> (BO == ByteOrder::kLE ? 8 : 8)) & 0xFFu); + static_cast(p)[1] = uint8_t((v >> 8) & 0xFFu); static_cast(p)[2] = uint8_t((v >> (BO == ByteOrder::kLE ? 16 : 0)) & 0xFFu); } @@ -1580,6 +1567,75 @@ static ASMJIT_INLINE_NODEBUG void qSort(T* base, size_t size, const CompareT& cm Internal::QSortImpl::sort(base, size, cmp); } +// Support - ReverseIterator +// ========================= + +//! Reverse iterator to avoid including `` header for iteration over arrays, specialized for +//! AsmJit use (noexcept by design). +template +class ArrayReverseIterator { +public: + //! \name Members + //! \{ + + T* _ptr {}; + + //! \} + + //! \name Construction & Destruction + //! \{ + + ASMJIT_INLINE_NODEBUG constexpr ArrayReverseIterator() noexcept = default; + ASMJIT_INLINE_NODEBUG constexpr ArrayReverseIterator(const ArrayReverseIterator& other) noexcept = default; + ASMJIT_INLINE_NODEBUG constexpr ArrayReverseIterator(T* ptr) noexcept : _ptr(ptr) {} + + //! \} + + //! \name Overloaded Operators + //! \{ + + ASMJIT_INLINE_NODEBUG ArrayReverseIterator& operator=(const ArrayReverseIterator& other) noexcept = default; + + ASMJIT_INLINE_NODEBUG bool operator==(const T* other) const noexcept { return _ptr == other; } + ASMJIT_INLINE_NODEBUG bool operator==(const ArrayReverseIterator& other) const noexcept { return _ptr == other._ptr; } + + ASMJIT_INLINE_NODEBUG bool operator!=(const T* other) const noexcept { return _ptr != other; } + ASMJIT_INLINE_NODEBUG bool operator!=(const ArrayReverseIterator& other) const noexcept { return _ptr != other._ptr; } + + ASMJIT_INLINE_NODEBUG bool operator<(const T* other) const noexcept { return _ptr < other; } + ASMJIT_INLINE_NODEBUG bool operator<(const ArrayReverseIterator& other) const noexcept { return _ptr < other._ptr; } + + ASMJIT_INLINE_NODEBUG bool operator<=(const T* other) const noexcept { return _ptr <= other; } + ASMJIT_INLINE_NODEBUG bool operator<=(const ArrayReverseIterator& other) const noexcept { return _ptr <= other._ptr; } + + ASMJIT_INLINE_NODEBUG bool operator>(const T* other) const noexcept { return _ptr > other; } + ASMJIT_INLINE_NODEBUG bool operator>(const ArrayReverseIterator& other) const noexcept { return _ptr > other._ptr; } + + ASMJIT_INLINE_NODEBUG bool operator>=(const T* other) const noexcept { return _ptr >= other; } + ASMJIT_INLINE_NODEBUG bool operator>=(const ArrayReverseIterator& other) const noexcept { return _ptr >= other._ptr; } + + ASMJIT_INLINE_NODEBUG ArrayReverseIterator& operator++() noexcept { _ptr--; return *this; } + ASMJIT_INLINE_NODEBUG ArrayReverseIterator& operator--() noexcept { _ptr++; return *this; } + + ASMJIT_INLINE_NODEBUG ArrayReverseIterator operator++(int) noexcept { ArrayReverseIterator prev(*this); _ptr--; return prev; } + ASMJIT_INLINE_NODEBUG ArrayReverseIterator operator--(int) noexcept { ArrayReverseIterator prev(*this); _ptr++; return prev; } + + template ASMJIT_INLINE_NODEBUG ArrayReverseIterator operator+(const Diff& n) noexcept { return ArrayReverseIterator(_ptr -= n); } + template ASMJIT_INLINE_NODEBUG ArrayReverseIterator operator-(const Diff& n) noexcept { return ArrayReverseIterator(_ptr += n); } + + template ASMJIT_INLINE_NODEBUG ArrayReverseIterator& operator+=(const Diff& n) noexcept { _ptr -= n; return *this; } + template ASMJIT_INLINE_NODEBUG ArrayReverseIterator& operator-=(const Diff& n) noexcept { _ptr += n; return *this; } + + ASMJIT_INLINE_NODEBUG constexpr T& operator*() const noexcept { return _ptr[-1]; } + ASMJIT_INLINE_NODEBUG constexpr T* operator->() const noexcept { return &_ptr[-1]; } + + template ASMJIT_INLINE_NODEBUG T& operator[](const Diff& n) noexcept { return *(_ptr - n - 1); } + + ASMJIT_INLINE_NODEBUG operator T*() const noexcept { return _ptr; } + + //! \} +}; + // Support - Array // =============== diff --git a/deps/asmjit/src/asmjit/core/support_p.h b/deps/asmjit/src/asmjit/core/support_p.h index a3de944d..1caec934 100644 --- a/deps/asmjit/src/asmjit/core/support_p.h +++ b/deps/asmjit/src/asmjit/core/support_p.h @@ -16,43 +16,6 @@ ASMJIT_BEGIN_NAMESPACE namespace Support { //! \cond INTERNAL - -static ASMJIT_FORCE_INLINE char decode5BitChar(uint32_t c) noexcept { - uint32_t base = c <= 26 ? uint32_t('a') - 1u : uint32_t('0') - 27u; - return char(base + c); -} - -static ASMJIT_FORCE_INLINE size_t decodeInstName(char nameOut[32], uint32_t index, const char* stringTable) noexcept { - size_t i; - - if (index & 0x80000000u) { - // Small string of 5-bit characters. - for (i = 0; i < 6; i++, index >>= 5) { - uint32_t c = index & 0x1F; - if (c == 0) - break; - nameOut[i] = decode5BitChar(c); - } - return i; - } - else { - size_t prefixBase = index & 0xFFFu; - size_t prefixSize = (index >> 12) & 0xFu; - - size_t suffixBase = (index >> 16) & 0xFFFu; - size_t suffixSize = (index >> 28) & 0x7u; - - for (i = 0; i < prefixSize; i++) - nameOut[i] = stringTable[prefixBase + i]; - - char* suffixOut = nameOut + prefixSize; - for (i = 0; i < suffixSize; i++) - suffixOut[i] = stringTable[suffixBase + i]; - - return prefixSize + suffixSize; - } -} - //! \endcond } // {Support} diff --git a/deps/asmjit/src/asmjit/core/type.h b/deps/asmjit/src/asmjit/core/type.h index a54ad4ec..415fe0a4 100644 --- a/deps/asmjit/src/asmjit/core/type.h +++ b/deps/asmjit/src/asmjit/core/type.h @@ -202,9 +202,13 @@ static ASMJIT_INLINE_NODEBUG constexpr bool isInt64(TypeId typeId) noexcept { re //! Tests whether a given type is a scalar 64-bit integer (unsigned). static ASMJIT_INLINE_NODEBUG constexpr bool isUInt64(TypeId typeId) noexcept { return typeId == TypeId::kUInt64; } +//! Tests whether a given type is an 8-bit general purpose register representing either signed or unsigned 8-bit integer. static ASMJIT_INLINE_NODEBUG constexpr bool isGp8(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt8, TypeId::kUInt8); } +//! Tests whether a given type is a 16-bit general purpose register representing either signed or unsigned 16-bit integer static ASMJIT_INLINE_NODEBUG constexpr bool isGp16(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt16, TypeId::kUInt16); } +//! Tests whether a given type is a 32-bit general purpose register representing either signed or unsigned 32-bit integer static ASMJIT_INLINE_NODEBUG constexpr bool isGp32(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt32, TypeId::kUInt32); } +//! Tests whether a given type is a 64-bit general purpose register representing either signed or unsigned 64-bit integer static ASMJIT_INLINE_NODEBUG constexpr bool isGp64(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt64, TypeId::kUInt64); } //! Tests whether a given type is a scalar floating point of any size. @@ -216,21 +220,41 @@ static ASMJIT_INLINE_NODEBUG constexpr bool isFloat64(TypeId typeId) noexcept { //! Tests whether a given type is a scalar 80-bit float. static ASMJIT_INLINE_NODEBUG constexpr bool isFloat80(TypeId typeId) noexcept { return typeId == TypeId::kFloat80; } +//! Tests whether a given type is a mask register of any size. static ASMJIT_INLINE_NODEBUG constexpr bool isMask(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kMaskStart, TypeId::_kMaskEnd); } +//! Tests whether a given type is an 8-bit mask register. static ASMJIT_INLINE_NODEBUG constexpr bool isMask8(TypeId typeId) noexcept { return typeId == TypeId::kMask8; } +//! Tests whether a given type is an 16-bit mask register. static ASMJIT_INLINE_NODEBUG constexpr bool isMask16(TypeId typeId) noexcept { return typeId == TypeId::kMask16; } +//! Tests whether a given type is an 32-bit mask register. static ASMJIT_INLINE_NODEBUG constexpr bool isMask32(TypeId typeId) noexcept { return typeId == TypeId::kMask32; } +//! Tests whether a given type is an 64-bit mask register. static ASMJIT_INLINE_NODEBUG constexpr bool isMask64(TypeId typeId) noexcept { return typeId == TypeId::kMask64; } +//! Tests whether a given type is an MMX register. +//! +//! \note MMX functionality is in general deprecated on X86 architecture. AsmJit provides it just for completeness. static ASMJIT_INLINE_NODEBUG constexpr bool isMmx(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kMmxStart, TypeId::_kMmxEnd); } +//! Tests whether a given type is an MMX register, which only uses the low 32 bits of data (only specific cases). +//! +//! \note MMX functionality is in general deprecated on X86 architecture. AsmJit provides it just for completeness. static ASMJIT_INLINE_NODEBUG constexpr bool isMmx32(TypeId typeId) noexcept { return typeId == TypeId::kMmx32; } +//! Tests whether a given type is an MMX register, which uses 64 bits of data (default). +//! +//! \note MMX functionality is in general deprecated on X86 architecture. AsmJit provides it just for completeness. static ASMJIT_INLINE_NODEBUG constexpr bool isMmx64(TypeId typeId) noexcept { return typeId == TypeId::kMmx64; } +//! Tests whether a given type is a vector register of any size. static ASMJIT_INLINE_NODEBUG constexpr bool isVec(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec32Start, TypeId::_kVec512End); } +//! Tests whether a given type is a 32-bit or 32-bit view of a vector register. static ASMJIT_INLINE_NODEBUG constexpr bool isVec32(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec32Start, TypeId::_kVec32End); } +//! Tests whether a given type is a 64-bit or 64-bit view of a vector register. static ASMJIT_INLINE_NODEBUG constexpr bool isVec64(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec64Start, TypeId::_kVec64End); } +//! Tests whether a given type is a 128-bit or 128-bit view of a vector register. static ASMJIT_INLINE_NODEBUG constexpr bool isVec128(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec128Start, TypeId::_kVec128End); } +//! Tests whether a given type is a 256-bit or 256-bit view of a vector register. static ASMJIT_INLINE_NODEBUG constexpr bool isVec256(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec256Start, TypeId::_kVec256End); } +//! Tests whether a given type is a 512-bit or 512-bit view of a vector register. static ASMJIT_INLINE_NODEBUG constexpr bool isVec512(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec512Start, TypeId::_kVec512End); } //! \cond diff --git a/deps/asmjit/src/asmjit/core/virtmem.cpp b/deps/asmjit/src/asmjit/core/virtmem.cpp index ab4f5890..74384774 100644 --- a/deps/asmjit/src/asmjit/core/virtmem.cpp +++ b/deps/asmjit/src/asmjit/core/virtmem.cpp @@ -76,8 +76,6 @@ #define MAP_ANONYMOUS MAP_ANON #endif - #define ASMJIT_ANONYMOUS_MEMORY_USE_FD - // Android NDK doesn't provide `shm_open()` and `shm_unlink()`. #if !defined(__BIONIC__) && !defined(ASMJIT_NO_SHM_OPEN) #define ASMJIT_HAS_SHM_OPEN @@ -89,18 +87,60 @@ #define ASMJIT_VM_SHM_DETECT 1 #endif - #if defined(__APPLE__) && TARGET_OS_OSX && ASMJIT_ARCH_ARM >= 64 - #define ASMJIT_HAS_PTHREAD_JIT_WRITE_PROTECT_NP + #if defined(__APPLE__) && TARGET_OS_OSX + #if ASMJIT_ARCH_X86 != 0 + #define ASMJIT_ANONYMOUS_MEMORY_USE_MACH_VM_REMAP + #endif + #if ASMJIT_ARCH_ARM >= 64 + #define ASMJIT_HAS_PTHREAD_JIT_WRITE_PROTECT_NP + #endif + #endif + + #if defined(__APPLE__) && ASMJIT_ARCH_X86 == 0 + #define ASMJIT_NO_DUAL_MAPPING #endif #if defined(__NetBSD__) && defined(MAP_REMAPDUP) && defined(PROT_MPROTECT) - #undef ASMJIT_ANONYMOUS_MEMORY_USE_FD #define ASMJIT_ANONYMOUS_MEMORY_USE_REMAPDUP #endif + + #if !defined(ASMJIT_ANONYMOUS_MEMORY_USE_REMAPDUP) && \ + !defined(ASMJIT_ANONYMOUS_MEMORY_USE_MACH_VM_REMAP) && \ + !defined(ASMJIT_NO_DUAL_MAPPING) + #define ASMJIT_ANONYMOUS_MEMORY_USE_FD + #endif #endif #include +#if defined(ASMJIT_ANONYMOUS_MEMORY_USE_MACH_VM_REMAP) +#include +#include + +extern "C" { + +#ifdef mig_external +mig_external +#else +extern +#endif +kern_return_t mach_vm_remap( + vm_map_t target_task, + mach_vm_address_t *target_address, + mach_vm_size_t size, + mach_vm_offset_t mask, + int flags, + vm_map_t src_task, + mach_vm_address_t src_address, + boolean_t copy, + vm_prot_t *cur_protection, + vm_prot_t *max_protection, + vm_inherit_t inheritance +); + +} // {extern "C"} +#endif + ASMJIT_BEGIN_SUB_NAMESPACE(VirtMem) // Virtual Memory Utilities @@ -141,6 +181,11 @@ static size_t detectLargePageSize() noexcept { return ::GetLargePageMinimum(); } +static bool hasDualMappingSupport() noexcept { + // TODO: This assumption works on X86 platforms, this may not work on AArch64. + return true; +} + // Returns windows-specific protectFlags from \ref MemoryFlags. static DWORD protectFlagsFromMemoryFlags(MemoryFlags memoryFlags) noexcept { DWORD protectFlags; @@ -165,7 +210,12 @@ static DWORD desiredAccessFromMemoryFlags(MemoryFlags memoryFlags) noexcept { } static HardenedRuntimeFlags getHardenedRuntimeFlags() noexcept { - return HardenedRuntimeFlags::kNone; + HardenedRuntimeFlags flags = HardenedRuntimeFlags::kNone; + + if (hasDualMappingSupport()) + flags |= HardenedRuntimeFlags::kDualMapping; + + return flags; } Error alloc(void** p, size_t size, MemoryFlags memoryFlags) noexcept { @@ -703,8 +753,8 @@ static bool hasHardenedRuntime() noexcept { // Detects whether MAP_JIT is available. static inline bool hasMapJitSupport() noexcept { -#if defined(__APPLE__) && TARGET_OS_OSX && ASMJIT_ARCH_ARM >= 64 - // OSX on AArch64 always uses hardened runtime + MAP_JIT: +#if defined(__APPLE__) && TARGET_OS_OSX && ASMJIT_ARCH_X86 == 0 + // Apple platforms always use hardened runtime + MAP_JIT on non-x86 hardware: // - https://developer.apple.com/documentation/apple_silicon/porting_just-in-time_compilers_to_apple_silicon return true; #elif defined(__APPLE__) && TARGET_OS_OSX @@ -746,6 +796,14 @@ static inline int mmMapJitFromMemoryFlags(MemoryFlags memoryFlags) noexcept { #endif } +static inline bool hasDualMappingSupport() noexcept { +#if defined(ASMJIT_NO_DUAL_MAPPING) + return false; +#else + return true; +#endif +} + static HardenedRuntimeFlags getHardenedRuntimeFlags() noexcept { HardenedRuntimeFlags flags = HardenedRuntimeFlags::kNone; @@ -755,6 +813,9 @@ static HardenedRuntimeFlags getHardenedRuntimeFlags() noexcept { if (hasMapJitSupport()) flags |= HardenedRuntimeFlags::kMapJit; + if (hasDualMappingSupport()) + flags |= HardenedRuntimeFlags::kDualMapping; + return flags; } @@ -828,6 +889,7 @@ Error protect(void* p, size_t size, MemoryFlags memoryFlags) noexcept { // Virtual Memory [Posix] - Dual Mapping // ===================================== +#if !defined(ASMJIT_NO_DUAL_MAPPING) static Error unmapDualMapping(DualMapping* dm, size_t size) noexcept { Error err1 = unmapMemory(dm->rx, size); Error err2 = kErrorOk; @@ -843,6 +905,7 @@ static Error unmapDualMapping(DualMapping* dm, size_t size) noexcept { dm->rw = nullptr; return kErrorOk; } +#endif // !ASMJIT_NO_DUAL_MAPPING #if defined(ASMJIT_ANONYMOUS_MEMORY_USE_REMAPDUP) static Error allocDualMappingUsingRemapdup(DualMapping* dmOut, size_t size, MemoryFlags memoryFlags) noexcept { @@ -875,16 +938,105 @@ static Error allocDualMappingUsingRemapdup(DualMapping* dmOut, size_t size, Memo } #endif -Error allocDualMapping(DualMapping* dm, size_t size, MemoryFlags memoryFlags) noexcept { - dm->rx = nullptr; - dm->rw = nullptr; +#if defined(ASMJIT_ANONYMOUS_MEMORY_USE_MACH_VM_REMAP) +static Error asmjitErrorFromKernResult(kern_return_t result) noexcept { + switch (result) { + case KERN_PROTECTION_FAILURE: + return DebugUtils::errored(kErrorProtectionFailure); + case KERN_NO_SPACE: + return DebugUtils::errored(kErrorOutOfMemory); + case KERN_INVALID_ARGUMENT: + return DebugUtils::errored(kErrorInvalidArgument); + default: + return DebugUtils::errored(kErrorInvalidState); + } +} - if (off_t(size) <= 0) - return DebugUtils::errored(size == 0 ? kErrorInvalidArgument : kErrorTooLarge); +static Error allocDualMappingUsingMachVmRemap(DualMapping* dmOut, size_t size, MemoryFlags memoryFlags) noexcept { + DualMapping dm {}; -#if defined(ASMJIT_ANONYMOUS_MEMORY_USE_REMAPDUP) - return allocDualMappingUsingRemapdup(dm, size, memoryFlags); -#elif defined(ASMJIT_ANONYMOUS_MEMORY_USE_FD) + MemoryFlags mmapFlags = MemoryFlags::kAccessReadWrite | (memoryFlags & MemoryFlags::kMapShared); + ASMJIT_PROPAGATE(mapMemory(&dm.rx, size, mmapFlags)); + + vm_prot_t curProt; + vm_prot_t maxProt; + + int rwProtectFlags = VM_PROT_READ | VM_PROT_WRITE; + int rxProtectFlags = VM_PROT_READ; + + if (Support::test(memoryFlags, MemoryFlags::kAccessExecute)) + rxProtectFlags |= VM_PROT_EXECUTE; + + kern_return_t result {}; + do { + vm_map_t task = mach_task_self(); + mach_vm_address_t remappedAddr {}; + +#if defined(VM_FLAGS_RANDOM_ADDR) + int remapFlags = VM_FLAGS_ANYWHERE | VM_FLAGS_RANDOM_ADDR; +#else + int remapFlags = VM_FLAGS_ANYWHERE; +#endif + + // Try to remap the existing memory into a different address. + result = mach_vm_remap( + task, // target_task + &remappedAddr, // target_address + size, // size + 0, // mask + remapFlags, // flags + task, // src_task + (mach_vm_address_t)dm.rx, // src_address + false, // copy + &curProt, // cur_protection + &maxProt, // max_protection + VM_INHERIT_DEFAULT); // inheritance + + if (result != KERN_SUCCESS) + break; + + dm.rw = (void*)remappedAddr; + + // Now, try to change permissions of both map regions into RW and RX. The vm_protect() + // API is used twice as we also want to set maximum permissions, so nobody would be + // allowed to change the RX region back to RW or RWX (if RWX is allowed). + uint32_t i; + for (i = 0; i < 2; i++) { + bool setMaximum = (i == 0); + + result = vm_protect( + task, // target_task + (vm_address_t)dm.rx, // address + size, // size + setMaximum, // set_maximum + rxProtectFlags); // new_protection + + if (result != KERN_SUCCESS) + break; + + result = vm_protect(task, // target_task + (vm_address_t)dm.rw, // address + size, // size + setMaximum, // set_maximum + rwProtectFlags); // new_protection + + if (result != KERN_SUCCESS) + break; + } + } while (0); + + if (result != KERN_SUCCESS) { + unmapDualMapping(&dm, size); + return DebugUtils::errored(asmjitErrorFromKernResult(result)); + } + + *dmOut = dm; + return kErrorOk; +} +#endif // ASMJIT_ANONYMOUS_MEMORY_USE_MACH_VM_REMAP + +#if defined(ASMJIT_ANONYMOUS_MEMORY_USE_FD) +static Error allocDualMappingUsingFile(DualMapping* dm, size_t size, MemoryFlags memoryFlags) noexcept { bool preferTmpOverDevShm = Support::test(memoryFlags, MemoryFlags::kMappingPreferTmp); if (!preferTmpOverDevShm) { AnonymousMemoryStrategy strategy; @@ -910,13 +1062,39 @@ Error allocDualMapping(DualMapping* dm, size_t size, MemoryFlags memoryFlags) no dm->rx = ptr[0]; dm->rw = ptr[1]; return kErrorOk; +} +#endif // ASMJIT_ANONYMOUS_MEMORY_USE_FD + +Error allocDualMapping(DualMapping* dm, size_t size, MemoryFlags memoryFlags) noexcept { + dm->rx = nullptr; + dm->rw = nullptr; + +#if defined(ASMJIT_NO_DUAL_MAPPING) + DebugUtils::unused(size, memoryFlags); + return DebugUtils::errored(kErrorFeatureNotEnabled); #else - #error "[asmjit] VirtMem::allocDualMapping() doesn't have implementation for the target OS and compiler" + if (off_t(size) <= 0) + return DebugUtils::errored(size == 0 ? kErrorInvalidArgument : kErrorTooLarge); + +#if defined(ASMJIT_ANONYMOUS_MEMORY_USE_REMAPDUP) + return allocDualMappingUsingRemapdup(dm, size, memoryFlags); +#elif defined(ASMJIT_ANONYMOUS_MEMORY_USE_MACH_VM_REMAP) + return allocDualMappingUsingMachVmRemap(dm, size, memoryFlags); +#elif defined(ASMJIT_ANONYMOUS_MEMORY_USE_FD) + return allocDualMappingUsingFile(dm, size, memoryFlags); +#else + #error "[asmjit] VirtMem::allocDualMapping() doesn't have implementation for the target OS or architecture" #endif +#endif // ASMJIT_NO_DUAL_MAPPING } Error releaseDualMapping(DualMapping* dm, size_t size) noexcept { +#if defined(ASMJIT_NO_DUAL_MAPPING) + DebugUtils::unused(dm, size); + return DebugUtils::errored(kErrorFeatureNotEnabled); +#else return unmapDualMapping(dm, size); +#endif // ASMJIT_NO_DUAL_MAPPING } #endif @@ -996,8 +1174,8 @@ void protectJitMemory(ProtectJitAccess access) noexcept { ASMJIT_END_SUB_NAMESPACE -// JitAllocator - Tests -// ==================== +// Virtual Memory - Tests +// ====================== #if defined(ASMJIT_TEST) ASMJIT_BEGIN_NAMESPACE @@ -1017,8 +1195,9 @@ UNIT(virt_mem) { INFO("VirtMem::hardenedRuntimeInfo():"); INFO(" flags:"); - INFO(" kEnabled: %s", Support::test(hardenedFlags, VirtMem::HardenedRuntimeFlags::kEnabled) ? "true" : "false"); - INFO(" kMapJit: %s", Support::test(hardenedFlags, VirtMem::HardenedRuntimeFlags::kMapJit) ? "true" : "false"); + INFO(" kEnabled: %s" , Support::test(hardenedFlags, VirtMem::HardenedRuntimeFlags::kEnabled ) ? "true" : "false"); + INFO(" kMapJit: %s" , Support::test(hardenedFlags, VirtMem::HardenedRuntimeFlags::kMapJit ) ? "true" : "false"); + INFO(" kDualMapping: %s", Support::test(hardenedFlags, VirtMem::HardenedRuntimeFlags::kDualMapping) ? "true" : "false"); } ASMJIT_END_NAMESPACE diff --git a/deps/asmjit/src/asmjit/core/virtmem.h b/deps/asmjit/src/asmjit/core/virtmem.h index 655c9828..17996dcb 100644 --- a/deps/asmjit/src/asmjit/core/virtmem.h +++ b/deps/asmjit/src/asmjit/core/virtmem.h @@ -10,6 +10,7 @@ #ifndef ASMJIT_NO_JIT #include "../core/globals.h" +#include "../core/support.h" ASMJIT_BEGIN_NAMESPACE @@ -143,7 +144,7 @@ enum class MemoryFlags : uint32_t { //! Request large memory mapped pages. //! - //! \important If this option is used and large page(s) cannot be mapped, the allocation will fail. Fallback to + //! \remarks If this option is used and large page(s) cannot be mapped, the allocation will fail. Fallback to //! regular pages must be done by the user in this case. Higher level API such as \ref JitAllocator provides an //! additional mechanism to allocate regular page(s) when large page(s) allocation fails. kMMapLargePages = 0x00000200u, @@ -215,15 +216,31 @@ enum class HardenedRuntimeFlags : uint32_t { //! architecture. kEnabled = 0x00000001u, - //! Read+Write+Execute can only be allocated with MAP_JIT flag (Apple specific, only available on OSX). - kMapJit = 0x00000002u + //! Read+Write+Execute can only be allocated with MAP_JIT flag (Apple specific, only available on Apple platforms). + kMapJit = 0x00000002u, + + //! Read+Write+Execute can be allocated with dual mapping approach (one region with RW and the other with RX). + kDualMapping = 0x00000004u }; ASMJIT_DEFINE_ENUM_FLAGS(HardenedRuntimeFlags) //! Hardened runtime information. struct HardenedRuntimeInfo { + //! \name Members + //! \{ + //! Hardened runtime flags. HardenedRuntimeFlags flags; + + //! \} + + //! \name Accessors + //! \{ + + //! Tests whether the hardened runtime `flag` is set. + ASMJIT_INLINE_NODEBUG bool hasFlag(HardenedRuntimeFlags flag) const noexcept { return Support::test(flags, flag); } + + //! \} }; //! Returns runtime features provided by the OS. @@ -275,7 +292,7 @@ public: //! \} - //! \name Construction / Destruction + //! \name Construction & Destruction //! \{ //! Makes the given memory block RW protected. diff --git a/deps/asmjit/src/asmjit/core/zone.cpp b/deps/asmjit/src/asmjit/core/zone.cpp index d68e110b..e1948ebb 100644 --- a/deps/asmjit/src/asmjit/core/zone.cpp +++ b/deps/asmjit/src/asmjit/core/zone.cpp @@ -16,8 +16,8 @@ ASMJIT_BEGIN_NAMESPACE // and should never be modified. const Zone::Block Zone::_zeroBlock = { nullptr, nullptr, 0 }; -// Zone - Init & Reset -// =================== +// Zone - Initialization & Reset +// ============================= void Zone::_init(size_t blockSize, size_t blockAlignment, const Support::Temporary* temporary) noexcept { ASMJIT_ASSERT(blockSize >= kMinBlockSize); @@ -215,8 +215,8 @@ static bool ZoneAllocator_hasDynamicBlock(ZoneAllocator* self, ZoneAllocator::Dy } #endif -// ZoneAllocator - Init & Reset -// ============================ +// ZoneAllocator - Initialization & Reset +// ====================================== void ZoneAllocator::reset(Zone* zone) noexcept { // Free dynamic blocks. @@ -227,9 +227,9 @@ void ZoneAllocator::reset(Zone* zone) noexcept { block = next; } - // Zero the entire class and initialize to the given `zone`. - memset(this, 0, sizeof(*this)); _zone = zone; + memset(_slots, 0, sizeof(_slots)); + _dynamicBlocks = nullptr; } // asmjit::ZoneAllocator - Alloc & Release diff --git a/deps/asmjit/src/asmjit/core/zonestack.cpp b/deps/asmjit/src/asmjit/core/zonestack.cpp index 66f706d5..7d666709 100644 --- a/deps/asmjit/src/asmjit/core/zonestack.cpp +++ b/deps/asmjit/src/asmjit/core/zonestack.cpp @@ -9,8 +9,8 @@ ASMJIT_BEGIN_NAMESPACE -// ZoneStackBase - Init & Reset -// ============================ +// ZoneStackBase - Initialization & Reset +// ====================================== Error ZoneStackBase::_init(ZoneAllocator* allocator, size_t middleIndex) noexcept { ZoneAllocator* oldAllocator = _allocator; diff --git a/deps/asmjit/src/asmjit/core/zonevector.cpp b/deps/asmjit/src/asmjit/core/zonevector.cpp index 4e5067e1..24860219 100644 --- a/deps/asmjit/src/asmjit/core/zonevector.cpp +++ b/deps/asmjit/src/asmjit/core/zonevector.cpp @@ -52,7 +52,8 @@ Error ZoneVectorBase::_grow(ZoneAllocator* allocator, uint32_t sizeOfT, uint32_t Error ZoneVectorBase::_reserve(ZoneAllocator* allocator, uint32_t sizeOfT, uint32_t n) noexcept { uint32_t oldCapacity = _capacity; - if (oldCapacity >= n) return kErrorOk; + if (oldCapacity >= n) + return kErrorOk; uint32_t nBytes = n * sizeOfT; if (ASMJIT_UNLIKELY(nBytes < n)) @@ -65,11 +66,10 @@ Error ZoneVectorBase::_reserve(ZoneAllocator* allocator, uint32_t sizeOfT, uint3 return DebugUtils::errored(kErrorOutOfMemory); void* oldData = _data; - if (_size) + if (oldData && _size) { memcpy(newData, oldData, size_t(_size) * sizeOfT); - - if (oldData) allocator->release(oldData, size_t(oldCapacity) * sizeOfT); + } _capacity = uint32_t(allocatedBytes / sizeOfT); ASMJIT_ASSERT(_capacity >= n); @@ -289,9 +289,22 @@ static void test_zone_vector(ZoneAllocator* allocator, const char* typeName) { } EXPECT_FALSE(vec.empty()); EXPECT_EQ(vec.size(), uint32_t(kMax)); + EXPECT_EQ(vec.indexOf(T(0)), uint32_t(0)); EXPECT_EQ(vec.indexOf(T(kMax - 1)), uint32_t(kMax - 1)); + EXPECT_EQ(vec.begin()[0], 0); + EXPECT_EQ(vec.end()[-1], kMax - 1); + EXPECT_EQ(vec.rbegin()[0], kMax - 1); + EXPECT_EQ(vec.rend()[-1], 0); + + int64_t fsum = 0; + int64_t rsum = 0; + + for (const T& item : vec) { fsum += item; } + for (auto it = vec.rbegin(); it != vec.rend(); ++it) { rsum += *it; } + + EXPECT_EQ(fsum, rsum); vec.release(allocator); } diff --git a/deps/asmjit/src/asmjit/core/zonevector.h b/deps/asmjit/src/asmjit/core/zonevector.h index afb4f754..13d28bbe 100644 --- a/deps/asmjit/src/asmjit/core/zonevector.h +++ b/deps/asmjit/src/asmjit/core/zonevector.h @@ -128,8 +128,8 @@ public: typedef T* iterator; typedef const T* const_iterator; - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; + typedef Support::ArrayReverseIterator reverse_iterator; + typedef Support::ArrayReverseIterator const_reverse_iterator; //! \name Construction & Destruction //! \{ @@ -194,8 +194,13 @@ public: if (ASMJIT_UNLIKELY(_size == _capacity)) ASMJIT_PROPAGATE(grow(allocator, 1)); - ::memmove(static_cast(_data) + 1, _data, size_t(_size) * sizeof(T)); - memcpy(_data, &item, sizeof(T)); + memmove(static_cast(static_cast(_data) + 1), + static_cast(_data), + size_t(_size) * sizeof(T)); + + memcpy(static_cast(_data), + static_cast(&item), + sizeof(T)); _size++; return kErrorOk; @@ -209,10 +214,15 @@ public: ASMJIT_PROPAGATE(grow(allocator, 1)); T* dst = static_cast(_data) + index; - ::memmove(dst + 1, dst, size_t(_size - index) * sizeof(T)); - memcpy(dst, &item, sizeof(T)); - _size++; + memmove(static_cast(dst + 1), + static_cast(dst), + size_t(_size - index) * sizeof(T)); + memcpy(static_cast(dst), + static_cast(&item), + sizeof(T)); + + _size++; return kErrorOk; } @@ -221,9 +231,11 @@ public: if (ASMJIT_UNLIKELY(_size == _capacity)) ASMJIT_PROPAGATE(grow(allocator, 1)); - memcpy(static_cast(_data) + _size, &item, sizeof(T)); - _size++; + memcpy(static_cast(static_cast(_data) + _size), + static_cast(&item), + sizeof(T)); + _size++; return kErrorOk; } @@ -234,7 +246,9 @@ public: ASMJIT_PROPAGATE(grow(allocator, size)); if (size) { - memcpy(static_cast(_data) + _size, other._data, size_t(size) * sizeof(T)); + memcpy(static_cast(static_cast(_data) + _size), + static_cast(other._data), + size_t(size) * sizeof(T)); _size += size; } @@ -249,10 +263,15 @@ public: ASMJIT_ASSERT(_size < _capacity); T* data = static_cast(_data); - if (_size) - ::memmove(data + 1, data, size_t(_size) * sizeof(T)); + if (_size) { + memmove(static_cast(data + 1), + static_cast(data), + size_t(_size) * sizeof(T)); + } - memcpy(data, &item, sizeof(T)); + memcpy(static_cast(data), + static_cast(&item), + sizeof(T)); _size++; } @@ -263,7 +282,9 @@ public: ASMJIT_FORCE_INLINE void appendUnsafe(const T& item) noexcept { ASMJIT_ASSERT(_size < _capacity); - memcpy(static_cast(_data) + _size, &item, sizeof(T)); + memcpy(static_cast(static_cast(_data) + _size), + static_cast(&item), + sizeof(T)); _size++; } @@ -273,17 +294,26 @@ public: ASMJIT_ASSERT(index <= _size); T* dst = static_cast(_data) + index; - ::memmove(dst + 1, dst, size_t(_size - index) * sizeof(T)); - memcpy(dst, &item, sizeof(T)); + memmove(static_cast(dst + 1), + static_cast(dst), + size_t(_size - index) * sizeof(T)); + + memcpy(static_cast(dst), + static_cast(&item), + sizeof(T)); + _size++; } + //! Concatenates all items of `other` at the end of the vector. ASMJIT_FORCE_INLINE void concatUnsafe(const ZoneVector& other) noexcept { uint32_t size = other._size; ASMJIT_ASSERT(_capacity - _size >= size); if (size) { - memcpy(static_cast(_data) + _size, other._data, size_t(size) * sizeof(T)); + memcpy(static_cast(static_cast(_data) + _size), + static_cast(other._data), + size_t(size) * sizeof(T)); _size += size; } } @@ -311,8 +341,11 @@ public: T* data = static_cast(_data) + i; size_t size = --_size - i; - if (size) - ::memmove(data, data + 1, size_t(size) * sizeof(T)); + if (size) { + memmove(static_cast(data), + static_cast(data + 1), + size_t(size) * sizeof(T)); + } } //! Pops the last element from the vector and returns it. @@ -460,8 +493,8 @@ public: //! \name Overloaded Operators //! \{ - ASMJIT_INLINE_NODEBUG bool operator==(const ZoneBitVector& other) const noexcept { return eq(other); } - ASMJIT_INLINE_NODEBUG bool operator!=(const ZoneBitVector& other) const noexcept { return !eq(other); } + ASMJIT_INLINE_NODEBUG bool operator==(const ZoneBitVector& other) const noexcept { return equals(other); } + ASMJIT_INLINE_NODEBUG bool operator!=(const ZoneBitVector& other) const noexcept { return !equals(other); } //! \} @@ -628,7 +661,7 @@ public: _data[idx] &= (BitWord(1) << bit) - 1u; } - ASMJIT_FORCE_INLINE bool eq(const ZoneBitVector& other) const noexcept { + ASMJIT_FORCE_INLINE bool equals(const ZoneBitVector& other) const noexcept { if (_size != other._size) return false; @@ -642,6 +675,11 @@ public: return true; } +#if !defined(ASMJIT_NO_DEPRECATED) + ASMJIT_DEPRECATED("Use ZoneVector::equals() instead") + ASMJIT_FORCE_INLINE bool eq(const ZoneBitVector& other) const noexcept { return equals(other); } +#endif // !ASMJIT_NO_DEPRECATED + //! \} //! \name Memory Management diff --git a/deps/asmjit/src/asmjit/x86/x86assembler.cpp b/deps/asmjit/src/asmjit/x86/x86assembler.cpp index 2564e245..35c5502c 100644 --- a/deps/asmjit/src/asmjit/x86/x86assembler.cpp +++ b/deps/asmjit/src/asmjit/x86/x86assembler.cpp @@ -345,6 +345,10 @@ static ASMJIT_FORCE_INLINE uint32_t x86AltOpcodeOf(const InstDB::InstInfo* info) return InstDB::_altOpcodeTable[info->_altOpcodeIndex]; } +static ASMJIT_FORCE_INLINE bool x86IsMmxOrXmm(const Reg& reg) noexcept { + return reg.type() == RegType::kX86_Mm || reg.type() == RegType::kX86_Xmm; +} + // x86::Assembler - X86BufferWriter // ================================ @@ -529,8 +533,6 @@ static ASMJIT_FORCE_INLINE bool x86ShouldUseMovabs(Assembler* self, X86BufferWri Assembler::Assembler(CodeHolder* code) noexcept : BaseAssembler() { _archMask = (uint64_t(1) << uint32_t(Arch::kX86)) | (uint64_t(1) << uint32_t(Arch::kX64)) ; - assignEmitterFuncs(this); - if (code) code->attach(this); } @@ -560,7 +562,7 @@ ASMJIT_FAVOR_SPEED Error Assembler::_emit(InstId instId, const Operand_& o0, con const Operand_* rmRel; // Memory operand or operand that holds Label|Imm. uint32_t rmInfo; // Memory operand's info based on x86MemInfo. - uint32_t rbReg; // Memory base or modRM register. + uint32_t rbReg = 0; // Memory base or modRM register. uint32_t rxReg; // Memory index register. uint32_t opReg; // ModR/M opcode or register id. @@ -610,7 +612,7 @@ ASMJIT_FAVOR_SPEED Error Assembler::_emit(InstId instId, const Operand_& o0, con Operand_ opArray[Globals::kMaxOpCount]; EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); - err = _funcs.validate(arch(), BaseInst(instId, options, _extraReg), opArray, Globals::kMaxOpCount, ValidationFlags::kNone); + err = _funcs.validate(BaseInst(instId, options, _extraReg), opArray, Globals::kMaxOpCount, ValidationFlags::kNone); if (ASMJIT_UNLIKELY(err)) goto Failed; } @@ -653,7 +655,6 @@ ASMJIT_FAVOR_SPEED Error Assembler::_emit(InstId instId, const Operand_& o0, con // This sequence seems to be the fastest. opcode = InstDB::_mainOpcodeTable[instInfo->_mainOpcodeIndex]; opReg = opcode.extractModO(); - rbReg = 0; opcode |= instInfo->_mainOpcodeValue; // Encoding Scope @@ -991,13 +992,13 @@ CaseX86M_GPB_MulDiv: goto EmitX86R; // MOD/RM: Alternative encoding selected via instruction options. - opcode += 2; + opcode += 2u; std::swap(opReg, rbReg); goto EmitX86R; } if (isign3 == ENC_OPS2(Reg, Mem)) { - opcode += 2; + opcode += 2u; opcode.addArithBySize(o0.x86RmSize()); opReg = o0.id(); @@ -1075,7 +1076,7 @@ CaseX86M_GPB_MulDiv: goto EmitX86Op; } - opcode += size != 1 ? (immSize != 1 ? 1 : 3) : 0; + opcode += size != 1 ? (immSize != 1 ? 1u : 3u) : 0u; goto EmitX86R; } @@ -1095,7 +1096,7 @@ CaseX86M_GPB_MulDiv: if (Support::isInt8(immValue) && !Support::test(options, InstOptions::kLongForm)) immSize = 1; - opcode += memSize != 1 ? (immSize != 1 ? 1 : 3) : 0; + opcode += memSize != 1 ? (immSize != 1 ? 1u : 3u) : 0u; opcode.addPrefixBySize(memSize); rmRel = &o0; @@ -1251,7 +1252,7 @@ CaseX86M_GPB_MulDiv: // This seems to be the only exception of encoding '66F2' prefix. if (o1.x86RmSize() == 2) writer.emit8(0x66); - opcode += o1.x86RmSize() != 1; + opcode += uint32_t(o1.x86RmSize() != 1u); goto EmitX86M; } break; @@ -1379,7 +1380,7 @@ CaseX86M_GPB_MulDiv: if (ASMJIT_UNLIKELY(o0.id() != Gp::kIdAx || o1.id() != Gp::kIdDx)) goto InvalidInstruction; - opcode += o0.x86RmSize() != 1; + opcode += uint32_t(o0.x86RmSize() != 1u); opcode.add66hBySize(o0.x86RmSize()); goto EmitX86Op; } @@ -1395,7 +1396,7 @@ CaseX86M_GPB_MulDiv: goto AmbiguousOperandSize; rmRel = &o0; - opcode += (size != 1); + opcode += uint32_t(size != 1u); opcode.add66hBySize(size); goto EmitX86OpImplicitMem; @@ -1552,7 +1553,7 @@ CaseX86M_GPB_MulDiv: if (!Support::test(options, InstOptions::kX86_ModRM)) goto EmitX86R; - opcode += 2; + opcode += 2u; std::swap(opReg, rbReg); goto EmitX86R; } @@ -1563,7 +1564,7 @@ CaseX86M_GPB_MulDiv: if (!Support::test(options, InstOptions::kX86_ModRM)) goto EmitX86R; - opcode += 2; + opcode += 2u; std::swap(opReg, rbReg); goto EmitX86R; } @@ -1652,7 +1653,7 @@ CaseX86M_GPB_MulDiv: // Handle a special form of `mov al|ax|eax|rax, [ptr64]` that doesn't use MOD. if (opReg == Gp::kIdAx && !rmRel->as().hasBaseOrIndex()) { if (x86ShouldUseMovabs(this, writer, o0.x86RmSize(), options, rmRel->as())) { - opcode += 0xA0; + opcode += 0xA0u; immValue = rmRel->as().offset(); goto EmitX86OpMovAbs; } @@ -1661,7 +1662,7 @@ CaseX86M_GPB_MulDiv: if (o0.x86RmSize() == 1) FIXUP_GPB(o0, opReg); - opcode += 0x8A; + opcode += 0x8Au; goto EmitX86M; } } @@ -1685,7 +1686,7 @@ CaseX86M_GPB_MulDiv: // Handle a special form of `mov [ptr64], al|ax|eax|rax` that doesn't use MOD. if (opReg == Gp::kIdAx && !rmRel->as().hasBaseOrIndex()) { if (x86ShouldUseMovabs(this, writer, o1.x86RmSize(), options, rmRel->as())) { - opcode += 0xA2; + opcode += 0xA2u; immValue = rmRel->as().offset(); goto EmitX86OpMovAbs; } @@ -1694,7 +1695,7 @@ CaseX86M_GPB_MulDiv: if (o1.x86RmSize() == 1) FIXUP_GPB(o1, opReg); - opcode += 0x88; + opcode += 0x88u; goto EmitX86M; } } @@ -1995,7 +1996,7 @@ CaseX86PushPop_Gp: if (ASMJIT_UNLIKELY(o1.id() != Gp::kIdCx)) goto InvalidInstruction; - opcode += 2; + opcode += 2u; goto EmitX86R; } @@ -2020,7 +2021,7 @@ CaseX86PushPop_Gp: if (ASMJIT_UNLIKELY(o1.id() != Gp::kIdCx)) goto InvalidInstruction; - opcode += 2; + opcode += 2u; rmRel = &o0; goto EmitX86M; } @@ -2390,7 +2391,7 @@ CaseFpuArith_Mem: } if (o0.x86RmSize() == 8 && commonInfo->hasFlag(InstDB::InstFlags::kFpuM64)) { - opcode += 4; + opcode += 4u; goto EmitX86M; } @@ -2415,7 +2416,7 @@ CaseFpuArith_Mem: rmRel = &o0; if (o0.x86RmSize() == 2 && commonInfo->hasFlag(InstDB::InstFlags::kFpuM16)) { - opcode += 4; + opcode += 4u; goto EmitX86M; } @@ -2433,7 +2434,7 @@ CaseFpuArith_Mem: case InstDB::kEncodingFpuRDef: if (isign3 == 0) { - opcode += 1; + opcode += 1u; goto EmitFpuOp; } ASMJIT_FALLTHROUGH; @@ -2575,37 +2576,41 @@ CaseFpuArith_Mem: case InstDB::kEncodingExtMovd: CaseExtMovd: - opReg = o0.id(); - opcode.add66hIf(Reg::isXmm(o0)); + if (x86IsMmxOrXmm(o0.as())) { + opReg = o0.id(); + opcode.add66hIf(Reg::isXmm(o0)); - // MM/XMM <- Gp - if (isign3 == ENC_OPS2(Reg, Reg) && Reg::isGp(o1)) { - rbReg = o1.id(); - goto EmitX86R; - } + // MM/XMM <- Gp + if (isign3 == ENC_OPS2(Reg, Reg) && Reg::isGp(o1)) { + rbReg = o1.id(); + goto EmitX86R; + } - // MM/XMM <- Mem - if (isign3 == ENC_OPS2(Reg, Mem)) { - rmRel = &o1; - goto EmitX86M; + // MM/XMM <- Mem + if (isign3 == ENC_OPS2(Reg, Mem)) { + rmRel = &o1; + goto EmitX86M; + } } // The following instructions use the secondary opcode. - opcode &= Opcode::kW; - opcode |= x86AltOpcodeOf(instInfo); - opReg = o1.id(); - opcode.add66hIf(Reg::isXmm(o1)); + if (x86IsMmxOrXmm(o1.as())) { + opcode &= Opcode::kW; + opcode |= x86AltOpcodeOf(instInfo); + opReg = o1.id(); + opcode.add66hIf(Reg::isXmm(o1)); - // GP <- MM/XMM - if (isign3 == ENC_OPS2(Reg, Reg) && Reg::isGp(o0)) { - rbReg = o0.id(); - goto EmitX86R; - } + // GP <- MM/XMM + if (isign3 == ENC_OPS2(Reg, Reg) && Reg::isGp(o0)) { + rbReg = o0.id(); + goto EmitX86R; + } - // Mem <- MM/XMM - if (isign3 == ENC_OPS2(Mem, Reg)) { - rmRel = &o0; - goto EmitX86M; + // Mem <- MM/XMM + if (isign3 == ENC_OPS2(Mem, Reg)) { + rmRel = &o0; + goto EmitX86M; + } } break; @@ -2621,7 +2626,7 @@ CaseExtMovd: if (!Support::test(options, InstOptions::kX86_ModMR)) goto EmitX86R; - opcode += 0x10; + opcode += 0x10u; std::swap(opReg, rbReg); goto EmitX86R; } @@ -5089,6 +5094,9 @@ Error Assembler::onAttach(CodeHolder* code) noexcept { Arch arch = code->arch(); ASMJIT_PROPAGATE(Base::onAttach(code)); + _instructionAlignment = uint8_t(1); + assignEmitterFuncs(this); + if (Environment::is32Bit(arch)) { // 32 bit architecture - X86. _forcedInstOptions |= InstOptions::kX86_InvalidRex; diff --git a/deps/asmjit/src/asmjit/x86/x86assembler.h b/deps/asmjit/src/asmjit/x86/x86assembler.h index df72dcb1..dd980a72 100644 --- a/deps/asmjit/src/asmjit/x86/x86assembler.h +++ b/deps/asmjit/src/asmjit/x86/x86assembler.h @@ -151,7 +151,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! printf("Status: %s\n", DebugUtils::errorAsString(err)); //! //! // Ambiguous operand size - the pointer requires size. -//! err = a.inc(x86::ptr(x86::rax), 1); +//! err = a.inc(x86::ptr(x86::rax)); //! printf("Status: %s\n", DebugUtils::errorAsString(err)); //! //! return 0; @@ -230,6 +230,9 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! targets easily. If you want to create a register of native size dynamically by specifying its id it's also possible: //! //! ``` +//! #include +//! using namespace asmjit; +//! //! void example(x86::Assembler& a) { //! x86::Gp zax = a.gpz(x86::Gp::kIdAx); //! x86::Gp zbx = a.gpz(x86::Gp::kIdBx); @@ -360,18 +363,19 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! x86::Gp src_a = a.zcx(); //! x86::Gp src_b = a.zdx(); //! -//! X86::Xmm vec0 = x86::xmm0; -//! X86::Xmm vec1 = x86::xmm1; +//! x86::Xmm vec0 = x86::xmm0; +//! x86::Xmm vec1 = x86::xmm1; //! //! // Create/initialize FuncDetail and FuncFrame. //! FuncDetail func; -//! func.init(FuncSignatureT(CallConvId::kHost)); +//! func.init(FuncSignature::build(), +//! rt.environment()); //! //! FuncFrame frame; //! frame.init(func); //! //! // Make XMM0 and XMM1 dirty - RegGroup::kVec describes XMM|YMM|ZMM registers. -//! frame.setDirtyRegs(RegGroup::kVec, IntUtils::mask(0, 1)); +//! frame.setDirtyRegs(RegGroup::kVec, Support::bitMask(0, 1)); //! //! // Alternatively, if you don't want to use register masks you can pass BaseReg //! // to addDirtyRegs(). The following code would add both xmm0 and xmm1. @@ -379,7 +383,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! FuncArgsAssignment args(&func); // Create arguments assignment context. //! args.assignAll(dst, src_a, src_b);// Assign our registers to arguments. -//! args.updateFrameInfo(frame); // Reflect our args in FuncFrame. +//! args.updateFuncFrame(frame); // Reflect our args in FuncFrame. //! frame.finalize(); // Finalize the FuncFrame (updates it). //! //! a.emitProlog(frame); // Emit function prolog. @@ -537,16 +541,16 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! void prefixesExample(x86::Assembler& a) { //! // Lock prefix for implementing atomics: -//! // lock add dword ptr [dst], 1 -//! a.lock().add(x86::dword_ptr(dst), 1); +//! // lock add dword ptr [rdi], 1 +//! a.lock().add(x86::dword_ptr(x86::rdi), 1); //! //! // Similarly, XAcquire/XRelease prefixes are also available: -//! // xacquire add dword ptr [dst], 1 -//! a.xacquire().add(x86::dword_ptr(dst), 1); +//! // xacquire add dword ptr [rdi], 1 +//! a.xacquire().add(x86::dword_ptr(x86::rdi), 1); //! //! // Rep prefix (see also repe/repz and repne/repnz): -//! // rep movs byte ptr [dst], byte ptr [src] -//! a.rep().movs(x86::byte_ptr(dst), x86::byte_ptr(src)); +//! // rep movs byte ptr [rdi], byte ptr [rsi] +//! a.rep().movs(x86::byte_ptr(x86::rdi), x86::byte_ptr(x86::rsi)); //! //! // Forcing REX prefix in 64-bit mode. //! // rex mov eax, 1 @@ -610,10 +614,10 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! // ----------------- //! // //! // - Broadcast data is part of memory operand. -//! // - Use x86::Mem::_1toN(), which returns a new x86::Mem operand. +//! // - Use x86::Mem::_1to2(), x86::Mem::_1to4(), etc..., which returns a new x86::Mem operand with broadcast. //! //! // vaddpd zmm0 {k1} {z}, zmm1, [rcx] {1to8} -//! a.k(k1).z().vaddpd(zmm0, zmm1, x86::mem(rcx)._1to8()); +//! a.k(k1).z().vaddpd(zmm0, zmm1, x86::ptr(rcx)._1to8()); //! //! // Embedded Rounding & Suppress-All-Exceptions //! // ------------------------------------------- @@ -659,6 +663,7 @@ public: //! \} //! \endcond + //! \cond INTERNAL //! \name Emit //! \{ diff --git a/deps/asmjit/src/asmjit/x86/x86builder.cpp b/deps/asmjit/src/asmjit/x86/x86builder.cpp index a27948b6..9f025a15 100644 --- a/deps/asmjit/src/asmjit/x86/x86builder.cpp +++ b/deps/asmjit/src/asmjit/x86/x86builder.cpp @@ -18,8 +18,6 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) Builder::Builder(CodeHolder* code) noexcept : BaseBuilder() { _archMask = (uint64_t(1) << uint32_t(Arch::kX86)) | (uint64_t(1) << uint32_t(Arch::kX64)) ; - assignEmitterFuncs(this); - if (code) code->attach(this); } @@ -29,7 +27,12 @@ Builder::~Builder() noexcept {} // ===================== Error Builder::onAttach(CodeHolder* code) noexcept { - return Base::onAttach(code); + ASMJIT_PROPAGATE(Base::onAttach(code)); + + _instructionAlignment = uint8_t(1); + assignEmitterFuncs(this); + + return kErrorOk; } Error Builder::onDetach(CodeHolder* code) noexcept { diff --git a/deps/asmjit/src/asmjit/x86/x86builder.h b/deps/asmjit/src/asmjit/x86/x86builder.h index 0de36e90..194c1402 100644 --- a/deps/asmjit/src/asmjit/x86/x86builder.h +++ b/deps/asmjit/src/asmjit/x86/x86builder.h @@ -61,7 +61,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! // Create and initialize `FuncDetail`. //! FuncDetail func; -//! func.init(FuncSignatureT(CallConvId::kHost)); +//! func.init(FuncSignature::build()); //! //! // Remember prolog insertion point. //! BaseNode* prologInsertionPoint = cb.cursor(); diff --git a/deps/asmjit/src/asmjit/x86/x86compiler.cpp b/deps/asmjit/src/asmjit/x86/x86compiler.cpp index 04d09807..830600ed 100644 --- a/deps/asmjit/src/asmjit/x86/x86compiler.cpp +++ b/deps/asmjit/src/asmjit/x86/x86compiler.cpp @@ -19,8 +19,6 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) Compiler::Compiler(CodeHolder* code) noexcept : BaseCompiler() { _archMask = (uint64_t(1) << uint32_t(Arch::kX86)) | (uint64_t(1) << uint32_t(Arch::kX64)) ; - assignEmitterFuncs(this); - if (code) code->attach(this); } @@ -38,6 +36,9 @@ Error Compiler::onAttach(CodeHolder* code) noexcept { return err; } + _instructionAlignment = uint8_t(1); + assignEmitterFuncs(this); + return kErrorOk; } diff --git a/deps/asmjit/src/asmjit/x86/x86compiler.h b/deps/asmjit/src/asmjit/x86/x86compiler.h index add17b0b..b281e208 100644 --- a/deps/asmjit/src/asmjit/x86/x86compiler.h +++ b/deps/asmjit/src/asmjit/x86/x86compiler.h @@ -35,32 +35,32 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! typedef int (*Func)(void); //! //! int main() { -//! JitRuntime rt; // Runtime specialized for JIT code execution. -//! CodeHolder code; // Holds code and relocation information. +//! JitRuntime rt; // Runtime specialized for JIT code execution. +//! CodeHolder code; // Holds code and relocation information. //! -//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. //! rt.cpuFeatures()); -//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. +//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. //! -//! cc.addFunc(FuncSignatureT());// Begin a function of `int fn(void)` signature. +//! cc.addFunc(FuncSignature::build()); // Begin a function of `int fn(void)` signature. //! -//! x86::Gp vReg = cc.newGpd(); // Create a 32-bit general purpose register. -//! cc.mov(vReg, 1); // Move one to our virtual register `vReg`. -//! cc.ret(vReg); // Return `vReg` from the function. +//! x86::Gp vReg = cc.newGpd(); // Create a 32-bit general purpose register. +//! cc.mov(vReg, 1); // Move one to our virtual register `vReg`. +//! cc.ret(vReg); // Return `vReg` from the function. //! -//! cc.endFunc(); // End of the function body. -//! cc.finalize(); // Translate and assemble the whole 'cc' content. +//! cc.endFunc(); // End of the function body. +//! cc.finalize(); // Translate and assemble the whole 'cc' content. //! // ----> x86::Compiler is no longer needed from here and can be destroyed <---- //! //! Func fn; -//! Error err = rt.add(&fn, &code); // Add the generated code to the runtime. -//! if (err) return 1; // Handle a possible error returned by AsmJit. +//! Error err = rt.add(&fn, &code); // Add the generated code to the runtime. +//! if (err) return 1; // Handle a possible error returned by AsmJit. //! // ----> CodeHolder is no longer needed from here and can be destroyed <---- //! -//! int result = fn(); // Execute the generated code. -//! printf("%d\n", result); // Print the resulting "1". +//! int result = fn(); // Execute the generated code. +//! printf("%d\n", result); // Print the resulting "1". //! -//! rt.release(fn); // Explicitly remove the function from the runtime. +//! rt.release(fn); // Explicitly remove the function from the runtime. //! return 0; //! } //! ``` @@ -80,49 +80,49 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! typedef void (*MemCpy32)(uint32_t* dst, const uint32_t* src, size_t count); //! //! int main() { -//! JitRuntime rt; // Runtime specialized for JIT code execution. -//! CodeHolder code; // Holds code and relocation information. +//! JitRuntime rt; // Runtime specialized for JIT code execution. +//! CodeHolder code; // Holds code and relocation information. //! -//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. //! rt.cpuFeatures()); -//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. +//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. //! -//! FuncNode* funcNode = cc.addFunc( // Begin the function of the following signature: -//! FuncSignatureT()); // 3rd argument - size_t (machine reg-size). +//! FuncNode* funcNode = cc.addFunc ( // Begin the function of the following signature: +//! FuncSignature::build()); // 3rd argument - size_t (machine reg-size). //! -//! Label L_Loop = cc.newLabel(); // Start of the loop. -//! Label L_Exit = cc.newLabel(); // Used to exit early. +//! Label L_Loop = cc.newLabel(); // Start of the loop. +//! Label L_Exit = cc.newLabel(); // Used to exit early. //! -//! x86::Gp dst = cc.newIntPtr("dst");// Create `dst` register (destination pointer). -//! x86::Gp src = cc.newIntPtr("src");// Create `src` register (source pointer). -//! x86::Gp i = cc.newUIntPtr("i"); // Create `i` register (loop counter). +//! x86::Gp dst = cc.newIntPtr("dst"); // Create `dst` register (destination pointer). +//! x86::Gp src = cc.newIntPtr("src"); // Create `src` register (source pointer). +//! x86::Gp i = cc.newUIntPtr("i"); // Create `i` register (loop counter). //! -//! funcNode->setArg(0, dst); // Assign `dst` argument. -//! funcNode->setArg(1, src); // Assign `src` argument. -//! funcNode->setArg(2, i); // Assign `i` argument. +//! funcNode->setArg(0, dst); // Assign `dst` argument. +//! funcNode->setArg(1, src); // Assign `src` argument. +//! funcNode->setArg(2, i); // Assign `i` argument. //! -//! cc.test(i, i); // Early exit if length is zero. +//! cc.test(i, i); // Early exit if length is zero. //! cc.jz(L_Exit); //! -//! cc.bind(L_Loop); // Bind the beginning of the loop here. +//! cc.bind(L_Loop); // Bind the beginning of the loop here. //! -//! x86::Gp tmp = cc.newInt32("tmp"); // Copy a single dword (4 bytes). -//! cc.mov(tmp, x86::dword_ptr(src)); // Load DWORD from [src] address. -//! cc.mov(x86::dword_ptr(dst), tmp); // Store DWORD to [dst] address. +//! x86::Gp tmp = cc.newInt32("tmp"); // Copy a single dword (4 bytes). +//! cc.mov(tmp, x86::dword_ptr(src)); // Load DWORD from [src] address. +//! cc.mov(x86::dword_ptr(dst), tmp); // Store DWORD to [dst] address. //! -//! cc.add(src, 4); // Increment `src`. -//! cc.add(dst, 4); // Increment `dst`. +//! cc.add(src, 4); // Increment `src`. +//! cc.add(dst, 4); // Increment `dst`. //! -//! cc.dec(i); // Loop until `i` is non-zero. +//! cc.dec(i); // Loop until `i` is non-zero. //! cc.jnz(L_Loop); //! -//! cc.bind(L_Exit); // Label used by early exit. -//! cc.endFunc(); // End of the function body. +//! cc.bind(L_Exit); // Label used by early exit. +//! cc.endFunc(); // End of the function body. //! -//! cc.finalize(); // Translate and assemble the whole 'cc' content. +//! cc.finalize(); // Translate and assemble the whole 'cc' content. //! // ----> x86::Compiler is no longer needed from here and can be destroyed <---- //! //! // Add the generated code to the runtime. @@ -163,14 +163,14 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! typedef void (*Func)(void*); //! //! int main() { -//! JitRuntime rt; // Runtime specialized for JIT code execution. -//! CodeHolder code; // Holds code and relocation information. +//! JitRuntime rt; // Runtime specialized for JIT code execution. +//! CodeHolder code; // Holds code and relocation information. //! -//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. //! rt.cpuFeatures()); -//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. +//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. //! -//! FuncNode* funcNode = cc.addFunc(FuncSignatureT()); +//! FuncNode* funcNode = cc.addFunc(FuncSignature::build()); //! //! // Use the following to enable AVX and/or AVX-512. //! funcNode->frame().setAvxEnabled(); @@ -186,13 +186,13 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! cc.vpaddq(vreg, vreg, vreg); //! cc.vmovdqu32(x86::ptr(addr), vreg); //! -//! cc.endFunc(); // End of the function body. -//! cc.finalize(); // Translate and assemble the whole 'cc' content. +//! cc.endFunc(); // End of the function body. +//! cc.finalize(); // Translate and assemble the whole 'cc' content. //! // ----> x86::Compiler is no longer needed from here and can be destroyed <---- //! //! Func fn; -//! Error err = rt.add(&fn, &code); // Add the generated code to the runtime. -//! if (err) return 1; // Handle a possible error returned by AsmJit. +//! Error err = rt.add(&fn, &code); // Add the generated code to the runtime. +//! if (err) return 1; // Handle a possible error returned by AsmJit. //! // ----> CodeHolder is no longer needed from here and can be destroyed <---- //! //! // Execute the generated code and print some output. @@ -200,7 +200,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! fn(data); //! printf("%llu\n", (unsigned long long)data[0]); //! -//! rt.release(fn); // Explicitly remove the function from the runtime. +//! rt.release(fn); // Explicitly remove the function from the runtime. //! return 0; //! } //! ``` @@ -222,48 +222,48 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! typedef uint32_t (*Fibonacci)(uint32_t x); //! //! int main() { -//! JitRuntime rt; // Runtime specialized for JIT code execution. -//! CodeHolder code; // Holds code and relocation information. +//! JitRuntime rt; // Runtime specialized for JIT code execution. +//! CodeHolder code; // Holds code and relocation information. //! -//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. //! rt.cpuFeatures()); -//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. +//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. //! -//! FuncNode* funcNode = cc.addFunc( // Begin of the Fibonacci function, addFunc() -//! FuncSignatureT()); // Returns a pointer to the FuncNode node. +//! FuncNode* funcNode = cc.addFunc( // Begin of the Fibonacci function, addFunc() +//! FuncSignature::build()); // Returns a pointer to the FuncNode node. //! -//! Label L_Exit = cc.newLabel() // Exit label. -//! x86::Gp x = cc.newUInt32(); // Function x argument. -//! x86::Gp y = cc.newUInt32(); // Temporary. +//! Label L_Exit = cc.newLabel(); // Exit label. +//! x86::Gp x = cc.newUInt32(); // Function x argument. +//! x86::Gp y = cc.newUInt32(); // Temporary. //! //! funcNode->setArg(0, x); //! -//! cc.cmp(x, 3); // Return x if less than 3. +//! cc.cmp(x, 3); // Return x if less than 3. //! cc.jb(L_Exit); //! -//! cc.mov(y, x); // Make copy of the original x. -//! cc.dec(x); // Decrease x. +//! cc.mov(y, x); // Make copy of the original x. +//! cc.dec(x); // Decrease x. //! -//! InvokeNode* invokeNode; // Function invocation: -//! cc.invoke(&invokeNode, // - InvokeNode (output). -//! funcNode->label(), // - Function address or Label. -//! FuncSignatureT()); // - Function signature. +//! InvokeNode* invokeNode; // Function invocation: +//! cc.invoke(&invokeNode, // - InvokeNode (output). +//! funcNode->label(), // - Function address or Label. +//! FuncSignature::build()); // - Function signature. //! -//! invokeNode->setArg(0, x); // Assign x as the first argument. -//! invokeNode->setRet(0, x); // Assign x as a return value as well. +//! invokeNode->setArg(0, x); // Assign x as the first argument. +//! invokeNode->setRet(0, x); // Assign x as a return value as well. //! -//! cc.add(x, y); // Combine the return value with y. +//! cc.add(x, y); // Combine the return value with y. //! //! cc.bind(L_Exit); -//! cc.ret(x); // Return x. -//! cc.endFunc(); // End of the function body. +//! cc.ret(x); // Return x. +//! cc.endFunc(); // End of the function body. //! -//! cc.finalize(); // Translate and assemble the whole 'cc' content. +//! cc.finalize(); // Translate and assemble the whole 'cc' content. //! // ----> x86::Compiler is no longer needed from here and can be destroyed <---- //! //! Fibonacci fib; -//! Error err = rt.add(&fib, &code); // Add the generated code to the runtime. -//! if (err) return 1; // Handle a possible error returned by AsmJit. +//! Error err = rt.add(&fib, &code); // Add the generated code to the runtime. +//! if (err) return 1; // Handle a possible error returned by AsmJit. //! // ----> CodeHolder is no longer needed from here and can be destroyed <---- //! //! // Test the generated code. @@ -291,14 +291,14 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! typedef int (*Func)(void); //! //! int main() { -//! JitRuntime rt; // Runtime specialized for JIT code execution. -//! CodeHolder code; // Holds code and relocation information. +//! JitRuntime rt; // Runtime specialized for JIT code execution. +//! CodeHolder code; // Holds code and relocation information. //! -//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. //! rt.cpuFeatures()); -//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. +//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. //! -//! cc.addFunc(FuncSignatureT());// Create a function that returns int. +//! cc.addFunc(FuncSignature::build()); // Create a function that returns int. //! //! x86::Gp p = cc.newIntPtr("p"); //! x86::Gp i = cc.newIntPtr("i"); @@ -306,9 +306,9 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! // Allocate 256 bytes on the stack aligned to 4 bytes. //! x86::Mem stack = cc.newStack(256, 4); //! -//! x86::Mem stackIdx(stack); // Copy of stack with i added. -//! stackIdx.setIndex(i); // stackIdx <- stack[i]. -//! stackIdx.setSize(1); // stackIdx <- byte ptr stack[i]. +//! x86::Mem stackIdx(stack); // Copy of stack with i added. +//! stackIdx.setIndex(i); // stackIdx <- stack[i]. +//! stackIdx.setSize(1); // stackIdx <- byte ptr stack[i]. //! //! // Load a stack address to `p`. This step is purely optional and shows //! // that `lea` is useful to load a memory operands address (even absolute) @@ -321,12 +321,12 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! Label L1 = cc.newLabel(); //! Label L2 = cc.newLabel(); //! -//! cc.bind(L1); // First loop, fill the stack. -//! cc.mov(stackIdx, i.r8()); // stack[i] = uint8_t(i). +//! cc.bind(L1); // First loop, fill the stack. +//! cc.mov(stackIdx, i.r8()); // stack[i] = uint8_t(i). //! -//! cc.inc(i); // i++; -//! cc.cmp(i, 256); // if (i < 256) -//! cc.jb(L1); // goto L1; +//! cc.inc(i); // i++; +//! cc.cmp(i, 256); // if (i < 256) +//! cc.jb(L1); // goto L1; //! //! // Second loop, sum all bytes stored in `stack`. //! x86::Gp sum = cc.newInt32("sum"); @@ -337,25 +337,25 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! cc.bind(L2); //! -//! cc.movzx(val, stackIdx); // val = uint32_t(stack[i]); -//! cc.add(sum, val); // sum += val; +//! cc.movzx(val, stackIdx); // val = uint32_t(stack[i]); +//! cc.add(sum, val); // sum += val; //! -//! cc.inc(i); // i++; -//! cc.cmp(i, 256); // if (i < 256) -//! cc.jb(L2); // goto L2; +//! cc.inc(i); // i++; +//! cc.cmp(i, 256); // if (i < 256) +//! cc.jb(L2); // goto L2; //! -//! cc.ret(sum); // Return the `sum` of all values. -//! cc.endFunc(); // End of the function body. +//! cc.ret(sum); // Return the `sum` of all values. +//! cc.endFunc(); // End of the function body. //! -//! cc.finalize(); // Translate and assemble the whole 'cc' content. +//! cc.finalize(); // Translate and assemble the whole 'cc' content. //! // ----> x86::Compiler is no longer needed from here and can be destroyed <---- //! //! Func func; -//! Error err = rt.add(&func, &code); // Add the generated code to the runtime. -//! if (err) return 1; // Handle a possible error returned by AsmJit. +//! Error err = rt.add(&func, &code); // Add the generated code to the runtime. +//! if (err) return 1; // Handle a possible error returned by AsmJit. //! // ----> CodeHolder is no longer needed from here and can be destroyed <---- //! -//! printf("Func() -> %d\n", func()); // Test the generated code. +//! printf("Func() -> %d\n", func()); // Test the generated code. //! //! rt.release(func); //! return 0; @@ -380,7 +380,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! using namespace asmjit; //! //! static void exampleUseOfConstPool(x86::Compiler& cc) { -//! cc.addFunc(FuncSignatureT()); +//! cc.addFunc(FuncSignature::build()); //! //! x86::Gp v0 = cc.newGpd("v0"); //! x86::Gp v1 = cc.newGpd("v1"); @@ -414,7 +414,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! using namespace asmjit; //! //! static void exampleUseOfIndirectJump(x86::Compiler& cc) { -//! FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); +//! FuncNode* funcNode = cc.addFunc(FuncSignature::build()); //! //! // Function arguments //! x86::Xmm a = cc.newXmmSs("a"); @@ -542,7 +542,7 @@ public: template ASMJIT_INLINE_NODEBUG RegT newSimilarReg(const RegT& ref) { RegT reg(Globals::NoInit); - _newReg(reg, ref); + _newReg(®, ref); return reg; } diff --git a/deps/asmjit/src/asmjit/x86/x86emithelper.cpp b/deps/asmjit/src/asmjit/x86/x86emithelper.cpp index ed8eae1e..9cd1db68 100644 --- a/deps/asmjit/src/asmjit/x86/x86emithelper.cpp +++ b/deps/asmjit/src/asmjit/x86/x86emithelper.cpp @@ -22,6 +22,18 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) // x86::EmitHelper - Utilities // =========================== +static constexpr OperandSignature regSizeToGpSignature[8 + 1] = { + OperandSignature{0}, + OperandSignature{RegTraits::kSignature}, + OperandSignature{RegTraits::kSignature}, + OperandSignature{0}, + OperandSignature{RegTraits::kSignature}, + OperandSignature{0}, + OperandSignature{0}, + OperandSignature{0}, + OperandSignature{RegTraits::kSignature} +}; + static inline uint32_t getXmmMovInst(const FuncFrame& frame) { bool avx = frame.isAvxEnabled(); bool aligned = frame.hasAlignedVecSR(); @@ -182,41 +194,42 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitArgMove( // Not a real loop, just 'break' is nicer than 'goto'. for (;;) { if (TypeUtils::isInt(dstTypeId)) { + // Sign extend. if (TypeUtils::isInt(srcTypeId)) { - instId = Inst::kIdMovsx; uint32_t castOp = makeCastOp(dstTypeId, srcTypeId); - // Sign extend by using 'movsx'. if (castOp == makeCastOp(TypeId::kInt16, TypeId::kInt8 ) || castOp == makeCastOp(TypeId::kInt32, TypeId::kInt8 ) || - castOp == makeCastOp(TypeId::kInt32, TypeId::kInt16) || castOp == makeCastOp(TypeId::kInt64, TypeId::kInt8 ) || - castOp == makeCastOp(TypeId::kInt64, TypeId::kInt16)) - break; + castOp == makeCastOp(TypeId::kInt32, TypeId::kInt16) || + castOp == makeCastOp(TypeId::kInt64, TypeId::kInt16) || + castOp == makeCastOp(TypeId::kInt64, TypeId::kInt32)) { + // Sign extend by using 'movsx' or 'movsxd'. + instId = + castOp == makeCastOp(TypeId::kInt64, TypeId::kInt32) + ? Inst::kIdMovsxd + : Inst::kIdMovsx; - // Sign extend by using 'movsxd'. - instId = Inst::kIdMovsxd; - if (castOp == makeCastOp(TypeId::kInt64, TypeId::kInt32)) + dst.setSignature(regSizeToGpSignature[dstSize]); + if (src.isReg()) + src.setSignature(regSizeToGpSignature[srcSize]); break; + } } + // Zero extend. if (TypeUtils::isInt(srcTypeId) || src_.isMem()) { - // Zero extend by using 'movzx' or 'mov'. - if (dstSize <= 4 && srcSize < 4) { - instId = Inst::kIdMovzx; - dst.setSignature(Reg::signatureOfT()); - } - else { - // We should have caught all possibilities where `srcSize` is less than 4, so we don't have to worry - // about 'movzx' anymore. Minimum size is enough to determine if we want 32-bit or 64-bit move. - instId = Inst::kIdMov; - srcSize = Support::min(srcSize, dstSize); + uint32_t movSize = Support::min(srcSize, dstSize); + if (movSize <= 4) + dstSize = 4; - dst.setSignature(srcSize == 4 ? Reg::signatureOfT() - : Reg::signatureOfT()); - if (src.isReg()) - src.setSignature(dst.signature()); - } + // Zero extend by using 'movzx' or 'mov'. + instId = movSize < 4 ? Inst::kIdMovzx : Inst::kIdMov; + srcSize = Support::min(srcSize, movSize); + + dst.setSignature(regSizeToGpSignature[dstSize]); + if (src.isReg()) + src.setSignature(regSizeToGpSignature[srcSize]); break; } @@ -394,25 +407,29 @@ Error EmitHelper::emitRegSwap( // x86::EmitHelper - Emit Prolog & Epilog // ====================================== -static inline void X86Internal_setupSaveRestoreInfo(RegGroup group, const FuncFrame& frame, Reg& xReg, uint32_t& xInst, uint32_t& xSize) noexcept { +static inline Error X86Internal_setupSaveRestoreInfo(RegGroup group, const FuncFrame& frame, Reg& xReg, uint32_t& xInst, uint32_t& xSize) noexcept { switch (group) { case RegGroup::kVec: xReg = xmm(0); xInst = getXmmMovInst(frame); xSize = xReg.size(); - break; + return kErrorOk; + case RegGroup::kX86_K: xReg = k(0); xInst = Inst::kIdKmovq; xSize = xReg.size(); - break; + return kErrorOk; + case RegGroup::kX86_MM: xReg = mm(0); xInst = Inst::kIdMovq; xSize = xReg.size(); - break; + return kErrorOk; + default: - break; + // This would be a bug in AsmJit if hit. + return DebugUtils::errored(kErrorInvalidState); } } @@ -425,6 +442,12 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitProlog(const FuncFrame& frame) { Gp gpReg = zsp; // General purpose register (temporary). Gp saReg = zsp; // Stack-arguments base pointer. + // Emit: 'endbr32' or 'endbr64' (indirect branch protection). + if (frame.hasIndirectBranchProtection()) { + InstId instId = emitter->is32Bit() ? Inst::kIdEndbr32 : Inst::kIdEndbr64; + ASMJIT_PROPAGATE(emitter->emit(instId)); + } + // Emit: 'push zbp' // 'mov zbp, zsp'. if (frame.hasPreservedFP()) { @@ -473,16 +496,15 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitProlog(const FuncFrame& frame) { // Emit 'movxxx [zsp + X], {[x|y|z]mm, k}'. { - Reg xReg; Mem xBase = ptr(zsp, int32_t(frame.extraRegSaveOffset())); - uint32_t xInst; - uint32_t xSize; - for (RegGroup group : Support::EnumValues{}) { Support::BitWordIterator it(frame.savedRegs(group)); if (it.hasNext()) { - X86Internal_setupSaveRestoreInfo(group, frame, xReg, xInst, xSize); + Reg xReg; + uint32_t xInst = 0; + uint32_t xSize = 0; + ASMJIT_PROPAGATE(X86Internal_setupSaveRestoreInfo(group, frame, xReg, xInst, xSize)); do { xReg.setId(it.next()); ASMJIT_PROPAGATE(emitter->emit(xInst, xBase, xReg)); @@ -514,16 +536,15 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitEpilog(const FuncFrame& frame) { // Emit 'movxxx {[x|y|z]mm, k}, [zsp + X]'. { - Reg xReg; Mem xBase = ptr(zsp, int32_t(frame.extraRegSaveOffset())); - uint32_t xInst; - uint32_t xSize; - for (RegGroup group : Support::EnumValues{}) { Support::BitWordIterator it(frame.savedRegs(group)); if (it.hasNext()) { - X86Internal_setupSaveRestoreInfo(group, frame, xReg, xInst, xSize); + Reg xReg; + uint32_t xInst; + uint32_t xSize; + ASMJIT_PROPAGATE(X86Internal_setupSaveRestoreInfo(group, frame, xReg, xInst, xSize)); do { xReg.setId(it.next()); ASMJIT_PROPAGATE(emitter->emit(xInst, xReg, xBase)); @@ -610,7 +631,7 @@ void assignEmitterFuncs(BaseEmitter* emitter) { #endif #ifndef ASMJIT_NO_VALIDATION - emitter->_funcs.validate = InstInternal::validate; + emitter->_funcs.validate = emitter->is32Bit() ? InstInternal::validateX86 : InstInternal::validateX64; #endif } diff --git a/deps/asmjit/src/asmjit/x86/x86emitter.h b/deps/asmjit/src/asmjit/x86/x86emitter.h index 5ce198e5..60881d3f 100644 --- a/deps/asmjit/src/asmjit/x86/x86emitter.h +++ b/deps/asmjit/src/asmjit/x86/x86emitter.h @@ -139,16 +139,18 @@ struct EmitterExplicitT { // These two are unfortunately reported by the sanitizer. We know what we do, however, the sanitizer doesn't. // I have tried to use reinterpret_cast instead, but that would generate bad code when compiled by MSC. - ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF inline This* _emitter() noexcept { return static_cast(this); } - ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF inline const This* _emitter() const noexcept { return static_cast(this); } + ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF ASMJIT_INLINE_NODEBUG This* _emitter() noexcept { return static_cast(this); } + ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF ASMJIT_INLINE_NODEBUG const This* _emitter() const noexcept { return static_cast(this); } //! \endcond //! \name Native Registers //! \{ - //! Returns either GPD or GPQ register of the given `id` depending on the emitter's architecture. + //! Returns either 32-bit or 64-bit GP register of the given `id` depending on the emitter's architecture. inline Gp gpz(uint32_t id) const noexcept { return Gp(_emitter()->_gpSignature, id); } + //! Clones the given `reg` to either 32-bit or 64-bit GP register depending on the emitter's architecture. + inline Gp gpz(const Gp& reg) const noexcept { return Gp(_emitter()->_gpSignature, reg.id()); } inline Gp zax() const noexcept { return Gp(_emitter()->_gpSignature, Gp::kIdAx); } inline Gp zcx() const noexcept { return Gp(_emitter()->_gpSignature, Gp::kIdCx); } @@ -664,7 +666,6 @@ public: //! \{ // NOTE: For some reason Doxygen is messed up here and thinks we are in cond. - //! \endcond ASMJIT_INST_2x(in, In, Gp_ZAX, Imm) // ANY ASMJIT_INST_2x(in, In, Gp_ZAX, Gp_DX) // ANY @@ -2161,9 +2162,6 @@ public: //! \name GFNI Instructions //! \{ - // NOTE: For some reason Doxygen is messed up here and thinks we are in cond. - //! \endcond - ASMJIT_INST_3x(gf2p8affineinvqb, Gf2p8affineinvqb, Xmm, Xmm, Imm) // GFNI ASMJIT_INST_3x(gf2p8affineinvqb, Gf2p8affineinvqb, Xmm, Mem, Imm) // GFNI ASMJIT_INST_3x(gf2p8affineqb, Gf2p8affineqb, Xmm, Xmm, Imm) // GFNI @@ -2831,7 +2829,7 @@ public: ASMJIT_INST_3x(vpand, Vpand, Vec, Vec, Mem) // AVX+ ASMJIT_INST_3x(vpandd, Vpandd, Vec, Vec, Vec) // AVX512_F{kz|b32} ASMJIT_INST_3x(vpandd, Vpandd, Vec, Vec, Mem) // AVX512_F{kz|b32} - ASMJIT_INST_3x(vpandn, Vpandn, Vec, Vec, Vec) // AV+ + ASMJIT_INST_3x(vpandn, Vpandn, Vec, Vec, Vec) // AVX+ ASMJIT_INST_3x(vpandn, Vpandn, Vec, Vec, Mem) // AVX+ ASMJIT_INST_3x(vpandnd, Vpandnd, Vec, Vec, Vec) // AVX512_F{kz|b32} ASMJIT_INST_3x(vpandnd, Vpandnd, Vec, Vec, Mem) // AVX512_F{kz|b32} @@ -3190,7 +3188,7 @@ public: ASMJIT_INST_2x(vpopcntq, Vpopcntq, Vec, Mem) // AVX512_VPOPCNTDQ{kz|b64} ASMJIT_INST_2x(vpopcntw, Vpopcntw, Vec, Vec) // AVX512_BITALG{kz|b32} ASMJIT_INST_2x(vpopcntw, Vpopcntw, Vec, Mem) // AVX512_BITALG{kz|b32} - ASMJIT_INST_3x(vpor, Vpor, Vec, Vec, Vec) // AV+ + ASMJIT_INST_3x(vpor, Vpor, Vec, Vec, Vec) // AVX+ ASMJIT_INST_3x(vpor, Vpor, Vec, Vec, Mem) // AVX+ ASMJIT_INST_3x(vpord, Vpord, Vec, Vec, Vec) // AVX512_F{kz|b32} ASMJIT_INST_3x(vpord, Vpord, Vec, Vec, Mem) // AVX512_F{kz|b32} diff --git a/deps/asmjit/src/asmjit/x86/x86formatter.cpp b/deps/asmjit/src/asmjit/x86/x86formatter.cpp index 5508860e..67b38dfa 100644 --- a/deps/asmjit/src/asmjit/x86/x86formatter.cpp +++ b/deps/asmjit/src/asmjit/x86/x86formatter.cpp @@ -95,6 +95,24 @@ struct RegFormatInfo_T { X == uint32_t(RegType::kX86_Gpd ) ? 8 : X == uint32_t(RegType::kX86_Gpq ) ? 8 : X == uint32_t(RegType::kX86_SReg ) ? 7 : + X == uint32_t(RegType::kX86_Rip ) ? 1 : 0, + + kRegCount = X == uint32_t(RegType::kX86_GpbLo) ? 32 : + X == uint32_t(RegType::kX86_GpbHi) ? 4 : + X == uint32_t(RegType::kX86_Gpw ) ? 32 : + X == uint32_t(RegType::kX86_Gpd ) ? 32 : + X == uint32_t(RegType::kX86_Gpq ) ? 32 : + X == uint32_t(RegType::kX86_Xmm ) ? 32 : + X == uint32_t(RegType::kX86_Ymm ) ? 32 : + X == uint32_t(RegType::kX86_Zmm ) ? 32 : + X == uint32_t(RegType::kX86_Mm ) ? 8 : + X == uint32_t(RegType::kX86_KReg ) ? 8 : + X == uint32_t(RegType::kX86_SReg ) ? 7 : + X == uint32_t(RegType::kX86_CReg ) ? 16 : + X == uint32_t(RegType::kX86_DReg ) ? 16 : + X == uint32_t(RegType::kX86_St ) ? 8 : + X == uint32_t(RegType::kX86_Bnd ) ? 4 : + X == uint32_t(RegType::kX86_Tmm ) ? 8 : X == uint32_t(RegType::kX86_Rip ) ? 1 : 0 }; }; @@ -104,7 +122,7 @@ struct RegFormatInfo_T { } #define ASMJIT_REG_NAME_ENTRY(TYPE) { \ - RegTraits::kCount, \ + RegFormatInfo_T::kRegCount, \ RegFormatInfo_T::kFormatIndex, \ RegFormatInfo_T::kSpecialIndex, \ RegFormatInfo_T::kSpecialCount \ @@ -514,8 +532,8 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( // ===================================================== static constexpr char kImmCharStart = '{'; -static constexpr char kImmCharEnd = '}'; -static constexpr char kImmCharOr = '|'; +static constexpr char kImmCharEnd = '}'; +static constexpr char kImmCharOr = '|'; struct ImmBits { enum Mode : uint32_t { @@ -539,8 +557,7 @@ ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmShuf(String& sb, uint3 ASMJIT_PROPAGATE(sb.appendUInt(index)); } - if (kImmCharEnd) - ASMJIT_PROPAGATE(sb.append(kImmCharEnd)); + ASMJIT_PROPAGATE(sb.append(kImmCharEnd)); return kErrorOk; } @@ -576,7 +593,7 @@ ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmBits(String& sb, uint3 ASMJIT_PROPAGATE(sb.append(str)); } - if (n && kImmCharEnd) + if (n) ASMJIT_PROPAGATE(sb.append(kImmCharEnd)); return kErrorOk; @@ -592,10 +609,7 @@ ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmText(String& sb, uint3 ASMJIT_PROPAGATE(sb.append(Support::findPackedString(text, value))); } - if (kImmCharEnd) - ASMJIT_PROPAGATE(sb.append(kImmCharEnd)); - - return kErrorOk; + return sb.append(kImmCharEnd); } ASMJIT_FAVOR_SIZE static Error FormatterInternal_explainConst( @@ -617,8 +631,8 @@ ASMJIT_FAVOR_SIZE static Error FormatterInternal_explainConst( static const char vpcmpx[] = "EQ\0" "LT\0" "LE\0" "FALSE\0" "NEQ\0" "GE\0" "GT\0" "TRUE\0"; static const char vpcomx[] = "LT\0" "LE\0" "GT\0" "GE\0" "EQ\0" "NEQ\0" "FALSE\0" "TRUE\0"; - static const char vshufpd[] = "A0\0A1\0B0\0B1\0A2\0A3\0B2\0B3\0A4\0A5\0B4\0B5\0A6\0A7\0B6\0B7\0"; - static const char vshufps[] = "A0\0A1\0A2\0A3\0A0\0A1\0A2\0A3\0B0\0B1\0B2\0B3\0B0\0B1\0B2\0B3\0"; + static const char vshufpd[] = "A0\0" "A1\0" "B0\0" "B1\0" "A2\0" "A3\0" "B2\0" "B3\0" "A4\0" "A5\0" "B4\0" "B5\0" "A6\0" "A7\0" "B6\0" "B7\0"; + static const char vshufps[] = "A0\0" "A1\0" "A2\0" "A3\0" "A0\0" "A1\0" "A2\0" "A3\0" "B0\0" "B1\0" "B2\0" "B3\0" "B0\0" "B1\0" "B2\0" "B3\0"; static const ImmBits vfpclassxx[] = { { 0x07u, 0, ImmBits::kModeLookup, "QNAN\0" "+0\0" "-0\0" "+INF\0" "-INF\0" "DENORMAL\0" "-FINITE\0" "SNAN\0" } @@ -915,7 +929,7 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatInstruction( } } - ASMJIT_PROPAGATE(InstInternal::instIdToString(arch, instId, sb)); + ASMJIT_PROPAGATE(InstInternal::instIdToString(instId, sb)); } else { ASMJIT_PROPAGATE(sb.appendFormat("[InstId=#%u]", unsigned(instId))); diff --git a/deps/asmjit/src/asmjit/x86/x86func.cpp b/deps/asmjit/src/asmjit/x86/x86func.cpp index bba9eef1..db5b30f8 100644 --- a/deps/asmjit/src/asmjit/x86/x86func.cpp +++ b/deps/asmjit/src/asmjit/x86/x86func.cpp @@ -327,7 +327,8 @@ ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& si } switch (cc.strategy()) { - case CallConvStrategy::kDefault: { + case CallConvStrategy::kDefault: + default: { uint32_t gpzPos = 0; uint32_t vecPos = 0; diff --git a/deps/asmjit/src/asmjit/x86/x86globals.h b/deps/asmjit/src/asmjit/x86/x86globals.h index bd0375e8..21ed41e8 100644 --- a/deps/asmjit/src/asmjit/x86/x86globals.h +++ b/deps/asmjit/src/asmjit/x86/x86globals.h @@ -53,20 +53,23 @@ enum class CondCode : uint8_t { kNLE = 0x0Fu, //!< ZF==0 & SF==OF (signed > ) kZero = kZ, //!< Zero flag. - kNotZero = kNZ, //!< Non-zero flag. - - kSign = kS, //!< Sign flag. - kNotSign = kNS, //!< No sign flag. - - kNegative = kS, //!< Sign flag. - kPositive = kNS, //!< No sign flag. - - kOverflow = kO, //!< Overflow (signed). - kNotOverflow = kNO, //!< Not overflow (signed). + kNotZero = kNZ, //!< Not zero. kEqual = kE, //!< `a == b` (equal). kNotEqual = kNE, //!< `a != b` (not equal). + kCarry = kC, //!< Carry flag. + kNotCarry = kNC, //!< Not carry. + + kSign = kS, //!< Sign flag. + kNotSign = kNS, //!< Not sign. + + kNegative = kS, //!< Sign flag. + kPositive = kNS, //!< Not sign. + + kOverflow = kO, //!< Overflow (signed). + kNotOverflow = kNO, //!< Not overflow (signed). + kSignedLT = kL, //!< `a < b` (signed). kSignedLE = kLE, //!< `a <= b` (signed). kSignedGT = kG, //!< `a > b` (signed). @@ -77,6 +80,9 @@ enum class CondCode : uint8_t { kUnsignedGT = kA, //!< `a > b` (unsigned). kUnsignedGE = kAE, //!< `a >= b` (unsigned). + kBTZero = kNC, //!< Tested bit is zero. + kBTNotZero = kC, //!< Tested bit is non-zero. + kParityEven = kP, //!< Even parity flag. kParityOdd = kPO, //!< Odd parity flag. diff --git a/deps/asmjit/src/asmjit/x86/x86instapi.cpp b/deps/asmjit/src/asmjit/x86/x86instapi.cpp index 60f84141..27671b3a 100644 --- a/deps/asmjit/src/asmjit/x86/x86instapi.cpp +++ b/deps/asmjit/src/asmjit/x86/x86instapi.cpp @@ -3,30 +3,12 @@ // See asmjit.h or LICENSE.md for license and copyright information // SPDX-License-Identifier: Zlib -// ---------------------------------------------------------------------------- -// IMPORTANT: AsmJit now uses an external instruction database to populate -// static tables within this file. Perform the following steps to regenerate -// all tables enclosed by ${...}: -// -// 1. Install node.js environment -// 2. Go to asmjit/tools directory -// 3. Get the latest asmdb from and -// copy/link the `asmdb` directory to `asmjit/tools/asmdb`. -// 4. Execute `node tablegen-x86.js` -// -// Instruction encoding and opcodes were added to the `x86inst.cpp` database -// manually in the past and they are not updated by the script as it became -// tricky. However, everything else is updated including instruction operands -// and tables required to validate them, instruction read/write information -// (including registers and flags), and all indexes to all tables. -// ---------------------------------------------------------------------------- - #include "../core/api-build_p.h" #if !defined(ASMJIT_NO_X86) #include "../core/cpuinfo.h" +#include "../core/instdb_p.h" #include "../core/misc_p.h" -#include "../core/support_p.h" #include "../x86/x86instapi_p.h" #include "../x86/x86instdb_p.h" #include "../x86/x86opcode_p.h" @@ -34,63 +16,21 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) +namespace InstInternal { + // x86::InstInternal - Text // ======================== #ifndef ASMJIT_NO_TEXT -Error InstInternal::instIdToString(Arch arch, InstId instId, String& output) noexcept { - DebugUtils::unused(arch); - +Error instIdToString(InstId instId, String& output) noexcept { if (ASMJIT_UNLIKELY(!Inst::isDefinedId(instId))) return DebugUtils::errored(kErrorInvalidInstruction); - char nameData[32]; - size_t nameSize = Support::decodeInstName(nameData, InstDB::_instNameIndexTable[instId], InstDB::_instNameStringTable); - - return output.append(nameData, nameSize); + return InstNameUtils::decode(output, InstDB::_instNameIndexTable[instId], InstDB::_instNameStringTable); } -InstId InstInternal::stringToInstId(Arch arch, const char* s, size_t len) noexcept { - DebugUtils::unused(arch); - - if (ASMJIT_UNLIKELY(!s)) - return Inst::kIdNone; - - if (len == SIZE_MAX) - len = strlen(s); - - if (ASMJIT_UNLIKELY(len == 0 || len > InstDB::kMaxNameSize)) - return Inst::kIdNone; - - uint32_t prefix = uint32_t(s[0]) - 'a'; - if (ASMJIT_UNLIKELY(prefix > 'z' - 'a')) - return Inst::kIdNone; - - size_t base = InstDB::instNameIndex[prefix].start; - size_t end = InstDB::instNameIndex[prefix].end; - - if (ASMJIT_UNLIKELY(!base)) - return Inst::kIdNone; - - char nameData[32]; - for (size_t lim = end - base; lim != 0; lim >>= 1) { - size_t instId = base + (lim >> 1); - size_t nameSize = Support::decodeInstName(nameData, InstDB::_instNameIndexTable[instId], InstDB::_instNameStringTable); - - int result = Support::compareStringViews(s, len, nameData, nameSize); - if (result < 0) - continue; - - if (result > 0) { - base = instId + 1; - lim--; - continue; - } - - return InstId(instId); - } - - return Inst::kIdNone; +InstId stringToInstId(const char* s, size_t len) noexcept { + return InstNameUtils::find(s, len, InstDB::instNameIndex, InstDB::_instNameIndexTable, InstDB::_instNameStringTable); } #endif // !ASMJIT_NO_TEXT @@ -216,20 +156,11 @@ static ASMJIT_FORCE_INLINE bool x86CheckOSig(const InstDB::OpSignature& op, cons return true; } -ASMJIT_FAVOR_SIZE Error InstInternal::validate(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept { - // Only called when `arch` matches X86 family. - ASMJIT_ASSERT(Environment::isFamilyX86(arch)); - - const X86ValidationData* vd; - if (arch == Arch::kX86) - vd = &_x86ValidationData; - else - vd = &_x64ValidationData; - +static ASMJIT_FAVOR_SIZE Error validate(InstDB::Mode mode, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept { uint32_t i; - InstDB::Mode mode = InstDB::modeFromArch(arch); // Get the instruction data. + const X86ValidationData* vd = (mode == InstDB::Mode::kX86) ? &_x86ValidationData : &_x64ValidationData; InstId instId = inst.id(); InstOptions options = inst.options(); @@ -717,6 +648,15 @@ Next: return kErrorOk; } + +Error validateX86(const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept { + return validate(InstDB::Mode::kX86, inst, operands, opCount, validationFlags); +} + +Error validateX64(const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept { + return validate(InstDB::Mode::kX64, inst, operands, opCount, validationFlags); +} + #endif // !ASMJIT_NO_VALIDATION // x86::InstInternal - QueryRWInfo @@ -785,7 +725,7 @@ static ASMJIT_FORCE_INLINE bool hasSameRegType(const BaseReg* regs, size_t opCou return true; } -Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept { +Error queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept { // Only called when `arch` matches X86 family. ASMJIT_ASSERT(Environment::isFamilyX86(arch)); @@ -919,7 +859,7 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* } } - rmOpsMask &= instRmInfo.rmOpsMask; + rmOpsMask &= uint32_t(instRmInfo.rmOpsMask); if (rmOpsMask && !inst.hasOption(InstOptions::kX86_ER)) { Support::BitWordIterator it(rmOpsMask); do { @@ -1375,6 +1315,10 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* out->_operands[0].reset(W, size0); out->_operands[1].reset(R | MibRead, size1); + + if (BaseReg::isVec(operands[0])) + rwZeroExtendAvxVec(out->_operands[0], operands[0].as()); + return kErrorOk; } @@ -1426,6 +1370,9 @@ Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* out->_operands[0].reset(W, size0); out->_operands[1].reset(R, size1); + if (BaseReg::isVec(operands[0])) + rwZeroExtendAvxVec(out->_operands[0], operands[0].as()); + if (operands[0].isReg() && operands[1].isReg()) { if (instRmInfo.rmOpsMask & 0x1) { out->_operands[0].addOpFlags(RegM); @@ -1500,7 +1447,7 @@ static inline uint32_t InstInternal_usesAvx512(InstOptions instOptions, const Re return hasEvex | hasKMask | hasKOrZmm; } -Error InstInternal::queryFeatures(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept { +Error queryFeatures(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept { typedef CpuFeatures::X86 Ext; // Only called when `arch` matches X86 family. @@ -1707,40 +1654,37 @@ Error InstInternal::queryFeatures(Arch arch, const BaseInst& inst, const Operand } #endif // !ASMJIT_NO_INTROSPECTION +} // {InstInternal} + // x86::InstInternal - Tests // ========================= #if defined(ASMJIT_TEST) -template -static Error queryRWInfoInline(InstRWInfo* out, Arch arch, BaseInst inst, Args&&... args) { - Operand_ opArray[] = { std::forward(args)... }; - return InstInternal::queryRWInfo(arch, inst, opArray, sizeof...(args), out); -} - -template -static Error queryFeaturesInline(CpuFeatures* out, Arch arch, BaseInst inst, Args&&... args) { - Operand_ opArray[] = { std::forward(args)... }; - return InstInternal::queryFeatures(arch, inst, opArray, sizeof...(args), out); -} - #ifndef ASMJIT_NO_TEXT UNIT(x86_inst_api_text) { // All known instructions should be matched. INFO("Matching all X86 instructions"); for (uint32_t a = 1; a < Inst::_kIdCount; a++) { StringTmp<128> aName; - EXPECT_EQ(InstInternal::instIdToString(Arch::kX86, a, aName), kErrorOk) + EXPECT_EQ(InstInternal::instIdToString(a, aName), kErrorOk) .message("Failed to get the name of instruction #%u", a); - uint32_t b = InstInternal::stringToInstId(Arch::kX86, aName.data(), aName.size()); + uint32_t b = InstInternal::stringToInstId(aName.data(), aName.size()); StringTmp<128> bName; - InstInternal::instIdToString(Arch::kX86, b, bName); + InstInternal::instIdToString(b, bName); EXPECT_EQ(a, b) .message("Instructions do not match \"%s\" (#%u) != \"%s\" (#%u)", aName.data(), a, bName.data(), b); } } #endif // !ASMJIT_NO_TEXT +#ifndef ASMJIT_NO_INTROSPECTION +template +static Error queryFeaturesInline(CpuFeatures* out, Arch arch, BaseInst inst, Args&&... args) { + Operand_ opArray[] = { std::forward(args)... }; + return InstInternal::queryFeatures(arch, inst, opArray, sizeof...(args), out); +} + UNIT(x86_inst_api_cpu_features) { INFO("Verifying whether SSE2+ features are reported correctly for legacy instructions"); { @@ -1815,6 +1759,14 @@ UNIT(x86_inst_api_cpu_features) { EXPECT_TRUE(f.x86().hasAVX512_F()); } } +#endif // !ASMJIT_NO_INTROSPECTION + +#ifndef ASMJIT_NO_INTROSPECTION +template +static Error queryRWInfoInline(InstRWInfo* out, Arch arch, BaseInst inst, Args&&... args) { + Operand_ opArray[] = { std::forward(args)... }; + return InstInternal::queryRWInfo(arch, inst, opArray, sizeof...(args), out); +} UNIT(x86_inst_api_rm_features) { INFO("Verifying whether RM/feature is reported correctly for PEXTRW instruction"); @@ -1869,7 +1821,9 @@ UNIT(x86_inst_api_rm_features) { EXPECT_EQ(rwi.rmFeature(), 0u); } } -#endif +#endif // !ASMJIT_NO_INTROSPECTION + +#endif // ASMJIT_TEST ASMJIT_END_SUB_NAMESPACE diff --git a/deps/asmjit/src/asmjit/x86/x86instapi_p.h b/deps/asmjit/src/asmjit/x86/x86instapi_p.h index 56f7fb92..e0866ea7 100644 --- a/deps/asmjit/src/asmjit/x86/x86instapi_p.h +++ b/deps/asmjit/src/asmjit/x86/x86instapi_p.h @@ -18,12 +18,13 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) namespace InstInternal { #ifndef ASMJIT_NO_TEXT -Error ASMJIT_CDECL instIdToString(Arch arch, InstId instId, String& output) noexcept; -InstId ASMJIT_CDECL stringToInstId(Arch arch, const char* s, size_t len) noexcept; +Error ASMJIT_CDECL instIdToString(InstId instId, String& output) noexcept; +InstId ASMJIT_CDECL stringToInstId(const char* s, size_t len) noexcept; #endif // !ASMJIT_NO_TEXT #ifndef ASMJIT_NO_VALIDATION -Error ASMJIT_CDECL validate(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept; +Error ASMJIT_CDECL validateX86(const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept; +Error ASMJIT_CDECL validateX64(const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept; #endif // !ASMJIT_NO_VALIDATION #ifndef ASMJIT_NO_INTROSPECTION diff --git a/deps/asmjit/src/asmjit/x86/x86instdb.cpp b/deps/asmjit/src/asmjit/x86/x86instdb.cpp index 635936fe..4269076f 100644 --- a/deps/asmjit/src/asmjit/x86/x86instdb.cpp +++ b/deps/asmjit/src/asmjit/x86/x86instdb.cpp @@ -3,24 +3,6 @@ // See asmjit.h or LICENSE.md for license and copyright information // SPDX-License-Identifier: Zlib -// ---------------------------------------------------------------------------- -// IMPORTANT: AsmJit now uses an external instruction database to populate -// static tables within this file. Perform the following steps to regenerate -// all tables enclosed by ${...}: -// -// 1. Install node.js environment -// 2. Go to asmjit/tools directory -// 3. Get the latest asmdb from and -// copy/link the `asmdb` directory to `asmjit/tools/asmdb`. -// 4. Execute `node tablegen-x86.js` -// -// Instruction encoding and opcodes were added to the `x86inst.cpp` database -// manually in the past and they are not updated by the script as it became -// tricky. However, everything else is updated including instruction operands -// and tables required to validate them, instruction read/write information -// (including registers and flags), and all indexes to all tables. -// ---------------------------------------------------------------------------- - #include "../core/api-build_p.h" #if !defined(ASMJIT_NO_X86) @@ -2940,6 +2922,65 @@ const InstRWFlags InstDB::_instFlagsTable[] = { #ifndef ASMJIT_NO_TEXT // ${NameData:Begin} // ------------------- Automatically generated, do not edit ------------------- +const InstNameIndex InstDB::instNameIndex = {{ + { Inst::kIdAaa , Inst::kIdAxor + 1 }, + { Inst::kIdBextr , Inst::kIdBzhi + 1 }, + { Inst::kIdCall , Inst::kIdCwde + 1 }, + { Inst::kIdDaa , Inst::kIdDpps + 1 }, + { Inst::kIdEmms , Inst::kIdExtrq + 1 }, + { Inst::kIdF2xm1 , Inst::kIdFyl2xp1 + 1 }, + { Inst::kIdGetsec , Inst::kIdGf2p8mulb + 1 }, + { Inst::kIdHaddpd , Inst::kIdHsubps + 1 }, + { Inst::kIdIdiv , Inst::kIdIretq + 1 }, + { Inst::kIdJa , Inst::kIdJz + 1 }, + { Inst::kIdKaddb , Inst::kIdKxorw + 1 }, + { Inst::kIdLahf , Inst::kIdLzcnt + 1 }, + { Inst::kIdMaskmovdqu , Inst::kIdMwaitx + 1 }, + { Inst::kIdNeg , Inst::kIdNot + 1 }, + { Inst::kIdOr , Inst::kIdOuts + 1 }, + { Inst::kIdPabsb , Inst::kIdPxor + 1 }, + { Inst::kIdNone , Inst::kIdNone + 1 }, + { Inst::kIdRcl , Inst::kIdRstorssp + 1 }, + { Inst::kIdSahf , Inst::kIdSysretq + 1 }, + { Inst::kIdT1mskc , Inst::kIdTzmsk + 1 }, + { Inst::kIdUcomisd , Inst::kIdUnpcklps + 1 }, + { Inst::kIdV4fmaddps , Inst::kIdVzeroupper + 1 }, + { Inst::kIdWbinvd , Inst::kIdWrussq + 1 }, + { Inst::kIdXabort , Inst::kIdXtest + 1 }, + { Inst::kIdNone , Inst::kIdNone + 1 }, + { Inst::kIdNone , Inst::kIdNone + 1 } +}, uint16_t(17)}; + +const char InstDB::_instNameStringTable[] = + "vgf2p8affineinvqbvaeskeygenassistvbroadcastf32x464x264x4i32x2i32x4i32x8i64x2i64x" + "4vpbroadcastmb2w2dvbcstnebf162p128i128vcvtne2ps2vcvtneebf16vcvtneobf16vfmaddsub1" + "32ph213pd213ph213ps231pd231ph231psvfmsubadd132vpmultishiftvscatterpf0dqpdqps1dpd" + "1dps1qpd1qpsvcvtneps2vextracvextractfvgatherpf0vp2intersecttcmmimfp16tcmmrlfp16s" + "h2pssdph2psvfnmadd132213sd213sh213ss231sd231sh231ssvfnmsub132vinservinsertfvpshu" + "fbitqvsha512rndprefetchitntawt1saveprevsssha256rndtileloaddtilereleavaesdeclvaes" + "enclvcompressvcvttpd2uqqvcvttph2uvcvttps2uvcvttsd2uvcvttsh2uvcvttss2uvfixupimmvf" + "madd132vfmsub132vmaskmovdqvpcompressvpconflictvphminposuvpmadd52hluqvpscatterqdv" + "punpckhqlqdqvrndscalemsg1msg2clflushopcmpnbexcmpnlexcmpxchg16t0t2tilestorev4fnma" + "ddssvcvtpd2uvcvtph2psudqvcvtps2phvcvtsd2uvcvtsh2uvcvtss2uvcvtudq2vcvtuqq2vcvtusi" + "2vfcmaddcvfpclassvgetmanmulbvp4dpwssvpclmuvpcmpestrvpcmpistrvperm2fvpermil2vpgat" + "hervpmacssdqvpmadcsswubswvpmaskmovpternlogbwwdlbwldqlwdvrsqrt1428pd28ps28sd28ssv" + "shufvshuffvzeroupxsaveoptcmpbexcmplexcmpnbxcmpnlxcmpnoxcmpnpxcmpnsxcmpnzx8bfxrst" + "orldtilecfmovdir64pvalidarmpadjurmpupdaserialisha1nexsha1rndssttilecftdpbf16tdpf" + "p16v4fmadvaddsubvblendmvpdvcvtdq2uwvcvtqq2vcvtsi2vcvtuwvdbpsadvdpbf16vexpanvfcmu" + "lccphcshvgetexpvmovdqau16u32u64vmovmskvmovntvmovshdvmovsldvpackssdwbvpackuswbvpb" + "lendmdvpdpbssudsvpdpbusvpdpwssvpdpwus2pdvpermtvpexpanvphaddubwqdqhvpmovmskvpmovs" + "xbvpmovusqwvpmovzxbvpmulhrvptestnmqvreducevscalefvsm3rndvsm4rndsvunpckhlpdlpsxre" + "sldtrs64xsusldtrcldemoclrssbscmpbxcmplxcmpoxcmppxcmpsxcmpzxcvtpifcmovfxsavekorte" + "stkshiftrbkunpckmonitorpfrcpipfrsqirtvrdfsbrdgsbsspseamcalsenduisetssbssysesysex" + "vcvtwvfmulvldmxcsvmlaundupu8vmovhvmovlhvmpsadvmresumvpadduvpaligngtbgtdgtqgtw2b2" + "qbdbqvphsubvplzcnb2md2mq2mw2mvpopcnvpshldvqvpshrdvwhwvpsubuvrangevrcp14vroundsdv" + "sm4keyvstmxcsvucomiallwbnoinwrfsbwrgsbc64blcfiblsficmovnendbrenqcmnufdecsfincsfn" + "stefrndfsincfucomfyl2xincsspqinvlinvlpinvpcinvvpmcommmovq2pavgupfcmpepfpnaptwris" + "eamoseamrsyscsysretdpbutlbsyvaesivaligvandnvcomivfrczvhadvhsubvmclevmgexvmmcvmov" + "avmovuvmptvmwrivpandvpextrwvpinsvpmaxvpminvprolvprorvpsadvpsigvpslvpsllvpsravpsr" + "lvsqrvtes"; + + const uint32_t InstDB::_instNameIndexTable[] = { 0x80000000, // Small ''. 0x80000421, // Small 'aaa'. @@ -4664,65 +4705,6 @@ const uint32_t InstDB::_instNameIndexTable[] = { 0x101585A8, // Large 'xsusldtr|k'. 0x81499698 // Small 'xtest'. }; - -const char InstDB::_instNameStringTable[] = - "vgf2p8affineinvqbvaeskeygenassistvbroadcastf32x464x264x4i32x2i32x4i32x8i64x2i64x" - "4vpbroadcastmb2w2dvbcstnebf162p128i128vcvtne2ps2vcvtneebf16vcvtneobf16vfmaddsub1" - "32ph213pd213ph213ps231pd231ph231psvfmsubadd132vpmultishiftvscatterpf0dqpdqps1dpd" - "1dps1qpd1qpsvcvtneps2vextracvextractfvgatherpf0vp2intersecttcmmimfp16tcmmrlfp16s" - "h2pssdph2psvfnmadd132213sd213sh213ss231sd231sh231ssvfnmsub132vinservinsertfvpshu" - "fbitqvsha512rndprefetchitntawt1saveprevsssha256rndtileloaddtilereleavaesdeclvaes" - "enclvcompressvcvttpd2uqqvcvttph2uvcvttps2uvcvttsd2uvcvttsh2uvcvttss2uvfixupimmvf" - "madd132vfmsub132vmaskmovdqvpcompressvpconflictvphminposuvpmadd52hluqvpscatterqdv" - "punpckhqlqdqvrndscalemsg1msg2clflushopcmpnbexcmpnlexcmpxchg16t0t2tilestorev4fnma" - "ddssvcvtpd2uvcvtph2psudqvcvtps2phvcvtsd2uvcvtsh2uvcvtss2uvcvtudq2vcvtuqq2vcvtusi" - "2vfcmaddcvfpclassvgetmanmulbvp4dpwssvpclmuvpcmpestrvpcmpistrvperm2fvpermil2vpgat" - "hervpmacssdqvpmadcsswubswvpmaskmovpternlogbwwdlbwldqlwdvrsqrt1428pd28ps28sd28ssv" - "shufvshuffvzeroupxsaveoptcmpbexcmplexcmpnbxcmpnlxcmpnoxcmpnpxcmpnsxcmpnzx8bfxrst" - "orldtilecfmovdir64pvalidarmpadjurmpupdaserialisha1nexsha1rndssttilecftdpbf16tdpf" - "p16v4fmadvaddsubvblendmvpdvcvtdq2uwvcvtqq2vcvtsi2vcvtuwvdbpsadvdpbf16vexpanvfcmu" - "lccphcshvgetexpvmovdqau16u32u64vmovmskvmovntvmovshdvmovsldvpackssdwbvpackuswbvpb" - "lendmdvpdpbssudsvpdpbusvpdpwssvpdpwus2pdvpermtvpexpanvphaddubwqdqhvpmovmskvpmovs" - "xbvpmovusqwvpmovzxbvpmulhrvptestnmqvreducevscalefvsm3rndvsm4rndsvunpckhlpdlpsxre" - "sldtrs64xsusldtrcldemoclrssbscmpbxcmplxcmpoxcmppxcmpsxcmpzxcvtpifcmovfxsavekorte" - "stkshiftrbkunpckmonitorpfrcpipfrsqirtvrdfsbrdgsbsspseamcalsenduisetssbssysesysex" - "vcvtwvfmulvldmxcsvmlaundupu8vmovhvmovlhvmpsadvmresumvpadduvpaligngtbgtdgtqgtw2b2" - "qbdbqvphsubvplzcnb2md2mq2mw2mvpopcnvpshldvqvpshrdvwhwvpsubuvrangevrcp14vroundsdv" - "sm4keyvstmxcsvucomiallwbnoinwrfsbwrgsbc64blcfiblsficmovnendbrenqcmnufdecsfincsfn" - "stefrndfsincfucomfyl2xincsspqinvlinvlpinvpcinvvpmcommmovq2pavgupfcmpepfpnaptwris" - "eamoseamrsyscsysretdpbutlbsyvaesivaligvandnvcomivfrczvhadvhsubvmclevmgexvmmcvmov" - "avmovuvmptvmwrivpandvpextrwvpinsvpmaxvpminvprolvprorvpsadvpsigvpslvpsllvpsravpsr" - "lvsqrvtes"; - - -const InstDB::InstNameIndex InstDB::instNameIndex[26] = { - { Inst::kIdAaa , Inst::kIdAxor + 1 }, - { Inst::kIdBextr , Inst::kIdBzhi + 1 }, - { Inst::kIdCall , Inst::kIdCwde + 1 }, - { Inst::kIdDaa , Inst::kIdDpps + 1 }, - { Inst::kIdEmms , Inst::kIdExtrq + 1 }, - { Inst::kIdF2xm1 , Inst::kIdFyl2xp1 + 1 }, - { Inst::kIdGetsec , Inst::kIdGf2p8mulb + 1 }, - { Inst::kIdHaddpd , Inst::kIdHsubps + 1 }, - { Inst::kIdIdiv , Inst::kIdIretq + 1 }, - { Inst::kIdJa , Inst::kIdJz + 1 }, - { Inst::kIdKaddb , Inst::kIdKxorw + 1 }, - { Inst::kIdLahf , Inst::kIdLzcnt + 1 }, - { Inst::kIdMaskmovdqu , Inst::kIdMwaitx + 1 }, - { Inst::kIdNeg , Inst::kIdNot + 1 }, - { Inst::kIdOr , Inst::kIdOuts + 1 }, - { Inst::kIdPabsb , Inst::kIdPxor + 1 }, - { Inst::kIdNone , Inst::kIdNone + 1 }, - { Inst::kIdRcl , Inst::kIdRstorssp + 1 }, - { Inst::kIdSahf , Inst::kIdSysretq + 1 }, - { Inst::kIdT1mskc , Inst::kIdTzmsk + 1 }, - { Inst::kIdUcomisd , Inst::kIdUnpcklps + 1 }, - { Inst::kIdV4fmaddps , Inst::kIdVzeroupper + 1 }, - { Inst::kIdWbinvd , Inst::kIdWrussq + 1 }, - { Inst::kIdXabort , Inst::kIdXtest + 1 }, - { Inst::kIdNone , Inst::kIdNone + 1 }, - { Inst::kIdNone , Inst::kIdNone + 1 } -}; // ---------------------------------------------------------------------------- // ${NameData:End} #endif // !ASMJIT_NO_TEXT diff --git a/deps/asmjit/src/asmjit/x86/x86instdb.h b/deps/asmjit/src/asmjit/x86/x86instdb.h index cfc40183..2bf7d148 100644 --- a/deps/asmjit/src/asmjit/x86/x86instdb.h +++ b/deps/asmjit/src/asmjit/x86/x86instdb.h @@ -464,9 +464,9 @@ struct InstInfo { //! Returns common information, see \ref CommonInfo. ASMJIT_INLINE_NODEBUG const CommonInfo& commonInfo() const noexcept { return _commonInfoTable[_commonInfoIndex]; } - //! Returns instruction flags, see \ref Flags. + //! Returns instruction flags, see \ref InstFlags. ASMJIT_INLINE_NODEBUG InstFlags flags() const noexcept { return commonInfo().flags(); } - //! Tests whether the instruction has flag `flag`, see \ref Flags. + //! Tests whether the instruction has flag `flag`, see \ref InstFlags. ASMJIT_INLINE_NODEBUG bool hasFlag(InstFlags flag) const noexcept { return commonInfo().hasFlag(flag); } //! Returns instruction AVX-512 flags, see \ref Avx512Flags. diff --git a/deps/asmjit/src/asmjit/x86/x86instdb_p.h b/deps/asmjit/src/asmjit/x86/x86instdb_p.h index 2d66897a..cb006060 100644 --- a/deps/asmjit/src/asmjit/x86/x86instdb_p.h +++ b/deps/asmjit/src/asmjit/x86/x86instdb_p.h @@ -6,6 +6,7 @@ #ifndef ASMJIT_X86_X86INSTDB_P_H_INCLUDED #define ASMJIT_X86_X86INSTDB_P_H_INCLUDED +#include "../core/instdb_p.h" #include "../x86/x86instdb.h" ASMJIT_BEGIN_SUB_NAMESPACE(x86) @@ -38,11 +39,11 @@ enum EncodingId : uint32_t { kEncodingX86M_GPB, //!< X86 [M] (handles single-byte size). kEncodingX86M_GPB_MulDiv, //!< X86 [M] (like GPB, handles implicit|explicit MUL|DIV|IDIV). kEncodingX86M_Only, //!< X86 [M] (restricted to memory operand of any size). - kEncodingX86M_Only_EDX_EAX, //!< X86 [M] (memory operand only, followed by implicit and ). + kEncodingX86M_Only_EDX_EAX, //!< X86 [M] (memory operand only, followed by implicit `EDX` and `EAX`). kEncodingX86M_Nop, //!< X86 [M] (special case of NOP instruction). kEncodingX86R_Native, //!< X86 [R] (register must be either 32-bit or 64-bit depending on arch). kEncodingX86R_FromM, //!< X86 [R] - which specifies memory address. - kEncodingX86R32_EDX_EAX, //!< X86 [R32] followed by implicit EDX and EAX. + kEncodingX86R32_EDX_EAX, //!< X86 [R32] followed by implicit `EDX` and `EAX`. kEncodingX86Rm, //!< X86 [RM] (doesn't handle single-byte size). kEncodingX86Rm_Raw66H, //!< X86 [RM] (used by LZCNT, POPCNT, and TZCNT). kEncodingX86Rm_NoSize, //!< X86 [RM] (doesn't add REX.W prefix if 64-bit reg is used). @@ -201,17 +202,6 @@ struct AdditionalInfo { inline const uint8_t* featuresEnd() const noexcept { return _features + ASMJIT_ARRAY_SIZE(_features); } }; -// ${NameLimits:Begin} -// ------------------- Automatically generated, do not edit ------------------- -enum : uint32_t { kMaxNameSize = 17 }; -// ---------------------------------------------------------------------------- -// ${NameLimits:End} - -struct InstNameIndex { - uint16_t start; - uint16_t end; -}; - struct RWInfo { enum Category : uint8_t { kCategoryGeneric = 0, @@ -297,9 +287,9 @@ extern const uint32_t _mainOpcodeTable[]; extern const uint32_t _altOpcodeTable[]; #ifndef ASMJIT_NO_TEXT -extern const uint32_t _instNameIndexTable[]; +extern const InstNameIndex instNameIndex; extern const char _instNameStringTable[]; -extern const InstNameIndex instNameIndex[26]; +extern const uint32_t _instNameIndexTable[]; #endif // !ASMJIT_NO_TEXT extern const AdditionalInfo _additionalInfoTable[]; diff --git a/deps/asmjit/src/asmjit/x86/x86operand.h b/deps/asmjit/src/asmjit/x86/x86operand.h index 6bc365bc..ac56731c 100644 --- a/deps/asmjit/src/asmjit/x86/x86operand.h +++ b/deps/asmjit/src/asmjit/x86/x86operand.h @@ -49,26 +49,26 @@ template struct RegTraits : public BaseRegTraits {}; //! \cond -// <--------------------+-----+-------------------------+------------------------+---+---+------------------+ -// | Reg | Reg-Type | Reg-Group |Sz |Cnt| TypeId | -// <--------------------+-----+-------------------------+------------------------+---+---+------------------+ -ASMJIT_DEFINE_REG_TRAITS(Rip , RegType::kX86_Rip , RegGroup::kX86_Rip , 0 , 1 , TypeId::kVoid ); -ASMJIT_DEFINE_REG_TRAITS(GpbLo, RegType::kX86_GpbLo , RegGroup::kGp , 1 , 16, TypeId::kInt8 ); -ASMJIT_DEFINE_REG_TRAITS(GpbHi, RegType::kX86_GpbHi , RegGroup::kGp , 1 , 4 , TypeId::kInt8 ); -ASMJIT_DEFINE_REG_TRAITS(Gpw , RegType::kX86_Gpw , RegGroup::kGp , 2 , 16, TypeId::kInt16 ); -ASMJIT_DEFINE_REG_TRAITS(Gpd , RegType::kX86_Gpd , RegGroup::kGp , 4 , 16, TypeId::kInt32 ); -ASMJIT_DEFINE_REG_TRAITS(Gpq , RegType::kX86_Gpq , RegGroup::kGp , 8 , 16, TypeId::kInt64 ); -ASMJIT_DEFINE_REG_TRAITS(Xmm , RegType::kX86_Xmm , RegGroup::kVec , 16, 32, TypeId::kInt32x4 ); -ASMJIT_DEFINE_REG_TRAITS(Ymm , RegType::kX86_Ymm , RegGroup::kVec , 32, 32, TypeId::kInt32x8 ); -ASMJIT_DEFINE_REG_TRAITS(Zmm , RegType::kX86_Zmm , RegGroup::kVec , 64, 32, TypeId::kInt32x16); -ASMJIT_DEFINE_REG_TRAITS(KReg , RegType::kX86_KReg , RegGroup::kX86_K , 0 , 8 , TypeId::kVoid ); -ASMJIT_DEFINE_REG_TRAITS(Mm , RegType::kX86_Mm , RegGroup::kX86_MM , 8 , 8 , TypeId::kMmx64 ); -ASMJIT_DEFINE_REG_TRAITS(SReg , RegType::kX86_SReg , RegGroup::kX86_SReg , 2 , 7 , TypeId::kVoid ); -ASMJIT_DEFINE_REG_TRAITS(CReg , RegType::kX86_CReg , RegGroup::kX86_CReg , 0 , 16, TypeId::kVoid ); -ASMJIT_DEFINE_REG_TRAITS(DReg , RegType::kX86_DReg , RegGroup::kX86_DReg , 0 , 16, TypeId::kVoid ); -ASMJIT_DEFINE_REG_TRAITS(St , RegType::kX86_St , RegGroup::kX86_St , 10, 8 , TypeId::kFloat80 ); -ASMJIT_DEFINE_REG_TRAITS(Bnd , RegType::kX86_Bnd , RegGroup::kX86_Bnd , 16, 4 , TypeId::kVoid ); -ASMJIT_DEFINE_REG_TRAITS(Tmm , RegType::kX86_Tmm , RegGroup::kX86_Tmm , 0 , 8 , TypeId::kVoid ); +// <--------------------+------------------------+------------------------+---+------------------+ +// | Reg-Type | Reg-Group |Sz | TypeId | +// <--------------------+------------------------+------------------------+---+------------------+ +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_Rip , RegGroup::kX86_Rip , 0 , TypeId::kVoid ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_GpbLo , RegGroup::kGp , 1 , TypeId::kInt8 ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_GpbHi , RegGroup::kGp , 1 , TypeId::kInt8 ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_Gpw , RegGroup::kGp , 2 , TypeId::kInt16 ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_Gpd , RegGroup::kGp , 4 , TypeId::kInt32 ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_Gpq , RegGroup::kGp , 8 , TypeId::kInt64 ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_Xmm , RegGroup::kVec , 16, TypeId::kInt32x4 ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_Ymm , RegGroup::kVec , 32, TypeId::kInt32x8 ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_Zmm , RegGroup::kVec , 64, TypeId::kInt32x16); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_KReg , RegGroup::kX86_K , 0 , TypeId::kVoid ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_Mm , RegGroup::kX86_MM , 8 , TypeId::kMmx64 ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_SReg , RegGroup::kX86_SReg , 2 , TypeId::kVoid ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_CReg , RegGroup::kX86_CReg , 0 , TypeId::kVoid ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_DReg , RegGroup::kX86_DReg , 0 , TypeId::kVoid ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_St , RegGroup::kX86_St , 10, TypeId::kFloat80 ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_Bnd , RegGroup::kX86_Bnd , 16, TypeId::kVoid ); +ASMJIT_DEFINE_REG_TRAITS(RegType::kX86_Tmm , RegGroup::kX86_Tmm , 0 , TypeId::kVoid ); //! \endcond //! Register (X86). @@ -88,12 +88,26 @@ public: ASMJIT_INLINE_NODEBUG constexpr bool isGpd() const noexcept { return hasBaseSignature(RegTraits::kSignature); } //! Tests whether the register is a GPQ register (64-bit). ASMJIT_INLINE_NODEBUG constexpr bool isGpq() const noexcept { return hasBaseSignature(RegTraits::kSignature); } + + //! Tests whether the register is a 32-bit general purpose register, alias of \ref isGpd(). + ASMJIT_INLINE_NODEBUG constexpr bool isGp32() const noexcept { return hasBaseSignature(RegTraits::kSignature); } + //! Tests whether the register is a 64-bit general purpose register, alias of \ref isGpq() + ASMJIT_INLINE_NODEBUG constexpr bool isGp64() const noexcept { return hasBaseSignature(RegTraits::kSignature); } + //! Tests whether the register is an XMM register (128-bit). ASMJIT_INLINE_NODEBUG constexpr bool isXmm() const noexcept { return hasBaseSignature(RegTraits::kSignature); } //! Tests whether the register is a YMM register (256-bit). ASMJIT_INLINE_NODEBUG constexpr bool isYmm() const noexcept { return hasBaseSignature(RegTraits::kSignature); } //! Tests whether the register is a ZMM register (512-bit). ASMJIT_INLINE_NODEBUG constexpr bool isZmm() const noexcept { return hasBaseSignature(RegTraits::kSignature); } + + //! Tests whether the register is a 128-bit vector register, alias of \ref isXmm(). + ASMJIT_INLINE_NODEBUG constexpr bool isVec128() const noexcept { return hasBaseSignature(RegTraits::kSignature); } + //! Tests whether the register is a 256-bit vector register, alias of \ref isYmm(). + ASMJIT_INLINE_NODEBUG constexpr bool isVec256() const noexcept { return hasBaseSignature(RegTraits::kSignature); } + //! Tests whether the register is a 512-bit vector register, alias of \ref isZmm(). + ASMJIT_INLINE_NODEBUG constexpr bool isVec512() const noexcept { return hasBaseSignature(RegTraits::kSignature); } + //! Tests whether the register is an MMX register (64-bit). ASMJIT_INLINE_NODEBUG constexpr bool isMm() const noexcept { return hasBaseSignature(RegTraits::kSignature); } //! Tests whether the register is a K register (64-bit). @@ -242,11 +256,18 @@ class Vec : public Reg { //! Casts this register to XMM (clone). ASMJIT_INLINE_NODEBUG Xmm xmm() const noexcept; - //! Casts this register to YMM. + //! Casts this register to YMM (clone). ASMJIT_INLINE_NODEBUG Ymm ymm() const noexcept; - //! Casts this register to ZMM. + //! Casts this register to ZMM (clone). ASMJIT_INLINE_NODEBUG Zmm zmm() const noexcept; + //! Casts this register to XMM (clone). + ASMJIT_INLINE_NODEBUG Vec v128() const noexcept; + //! Casts this register to YMM (clone). + ASMJIT_INLINE_NODEBUG Vec v256() const noexcept; + //! Casts this register to ZMM (clone). + ASMJIT_INLINE_NODEBUG Vec v512() const noexcept; + //! Casts this register to a register that has half the size (or XMM if it's already XMM). ASMJIT_INLINE_NODEBUG Vec half() const noexcept { return Vec(type() == RegType::kX86_Zmm ? signatureOfT() : signatureOfT(), id()); @@ -344,6 +365,9 @@ ASMJIT_INLINE_NODEBUG Gpq Gp::r64() const noexcept { return Gpq(id()); } ASMJIT_INLINE_NODEBUG Xmm Vec::xmm() const noexcept { return Xmm(id()); } ASMJIT_INLINE_NODEBUG Ymm Vec::ymm() const noexcept { return Ymm(id()); } ASMJIT_INLINE_NODEBUG Zmm Vec::zmm() const noexcept { return Zmm(id()); } +ASMJIT_INLINE_NODEBUG Vec Vec::v128() const noexcept { return Xmm(id()); } +ASMJIT_INLINE_NODEBUG Vec Vec::v256() const noexcept { return Ymm(id()); } +ASMJIT_INLINE_NODEBUG Vec Vec::v512() const noexcept { return Zmm(id()); } //! \endcond //! \namespace asmjit::x86::regs diff --git a/deps/asmjit/src/asmjit/x86/x86rapass.cpp b/deps/asmjit/src/asmjit/x86/x86rapass.cpp index 98d4f751..c7b46f52 100644 --- a/deps/asmjit/src/asmjit/x86/x86rapass.cpp +++ b/deps/asmjit/src/asmjit/x86/x86rapass.cpp @@ -823,7 +823,7 @@ Error RACFGBuilder::moveImmToStackArg(InvokeNode* invokeNode, const FuncValue& a stackPtr.setSize(4); imm[0] = imm_; - uint32_t nMovs = 0; + uint32_t movCount = 0; // One stack entry has the same size as the native register size. That means that if we want to move a 32-bit // integer on the stack in 64-bit mode, we need to extend it to a 64-bit integer first. In 32-bit mode, pushing @@ -839,7 +839,7 @@ Error RACFGBuilder::moveImmToStackArg(InvokeNode* invokeNode, const FuncValue& a case TypeId::kFloat32: MovU32: imm[0].zeroExtend32Bits(); - nMovs = 1; + movCount = 1; break; case TypeId::kInt64: @@ -849,20 +849,20 @@ MovU32: case TypeId::kMmx64: if (_is64Bit && imm[0].isInt32()) { stackPtr.setSize(8); - nMovs = 1; + movCount = 1; break; } imm[1].setValue(imm[0].uint32Hi()); imm[0].zeroExtend32Bits(); - nMovs = 2; + movCount = 2; break; default: return DebugUtils::errored(kErrorInvalidAssignment); } - for (uint32_t i = 0; i < nMovs; i++) { + for (uint32_t i = 0; i < movCount; i++) { ASMJIT_PROPAGATE(cc()->mov(stackPtr, imm[i])); stackPtr.addOffsetLo32(int32_t(stackPtr.size())); } @@ -1309,6 +1309,54 @@ ASMJIT_FAVOR_SPEED Error X86RAPass::_rewrite(BaseNode* first, BaseNode* stop) no } } + // If one operand was rewritten from Reg to Mem, we have to ensure that we are using the correct instruction. + if (raInst->isRegToMemPatched()) { + switch (inst->id()) { + case Inst::kIdKmovb: { + if (operands[0].isGp() && operands[1].isMem()) { + // Transform from [V]MOVD to MOV. + operands[1].as().setSize(1); + inst->setId(Inst::kIdMovzx); + } + break; + } + + case Inst::kIdVmovw: { + if (operands[0].isGp() && operands[1].isMem()) { + // Transform from [V]MOVD to MOV. + operands[1].as().setSize(2); + inst->setId(Inst::kIdMovzx); + } + break; + } + + case Inst::kIdMovd: + case Inst::kIdVmovd: + case Inst::kIdKmovd: { + if (operands[0].isGp() && operands[1].isMem()) { + // Transform from [V]MOVD to MOV. + operands[1].as().setSize(4); + inst->setId(Inst::kIdMov); + } + break; + } + + case Inst::kIdMovq: + case Inst::kIdVmovq: + case Inst::kIdKmovq: { + if (operands[0].isGp() && operands[1].isMem()) { + // Transform from [V]MOVQ to MOV. + operands[1].as().setSize(8); + inst->setId(Inst::kIdMov); + } + break; + } + + default: + break; + } + } + // Transform VEX instruction to EVEX when necessary. if (raInst->isTransformable()) { if (maxRegId > 15) { diff --git a/deps/asmjit/test/asmjit_test_assembler.cpp b/deps/asmjit/test/asmjit_test_assembler.cpp index 446b1e35..6a56b67a 100644 --- a/deps/asmjit/test/asmjit_test_assembler.cpp +++ b/deps/asmjit/test/asmjit_test_assembler.cpp @@ -46,7 +46,7 @@ int main(int argc, char* argv[]) { printf(" --arch=x86 32-bit X86 architecture (X86)\n"); printf(" --arch=x64 64-bit X86 architecture (X86_64)\n"); #endif -#if !defined(ASMJIT_AARCH64) +#if !defined(ASMJIT_NO_AARCH64) printf(" --arch=aarch64 64-bit ARM architecture (AArch64)\n"); #endif printf("\n"); @@ -56,7 +56,6 @@ int main(int argc, char* argv[]) { const char* arch = cmdLine.valueOf("--arch", "all"); bool x86Failed = false; bool x64Failed = false; - bool armFailed = false; bool aarch64Failed = false; #if !defined(ASMJIT_NO_X86) @@ -72,7 +71,7 @@ int main(int argc, char* argv[]) { aarch64Failed = !testA64Assembler(settings); #endif - bool failed = x86Failed || x64Failed || armFailed || aarch64Failed; + bool failed = x86Failed || x64Failed || aarch64Failed; if (failed) { if (x86Failed) @@ -81,9 +80,6 @@ int main(int argc, char* argv[]) { if (x64Failed) printf("** X64 test suite failed **\n"); - if (armFailed) - printf("** ARM test suite failed **\n"); - if (aarch64Failed) printf("** AArch64 test suite failed **\n"); diff --git a/deps/asmjit/test/asmjit_test_assembler.h b/deps/asmjit/test/asmjit_test_assembler.h index 54f8daf8..26f2c97e 100644 --- a/deps/asmjit/test/asmjit_test_assembler.h +++ b/deps/asmjit/test/asmjit_test_assembler.h @@ -52,7 +52,7 @@ public: assembler.addDiagnosticOptions(asmjit::DiagnosticOptions::kValidateAssembler); } - ASMJIT_NOINLINE bool testValidInstruction(const char* s, const char* expectedOpcode, asmjit::Error err) noexcept { + ASMJIT_NOINLINE bool testValidInstruction(const char* s, const char* expectedOpcode, asmjit::Error err = asmjit::kErrorOk) noexcept { count++; if (err) { diff --git a/deps/asmjit/test/asmjit_test_assembler_a64.cpp b/deps/asmjit/test/asmjit_test_assembler_a64.cpp index 2ae3081d..8da77b3f 100644 --- a/deps/asmjit/test/asmjit_test_assembler_a64.cpp +++ b/deps/asmjit/test/asmjit_test_assembler_a64.cpp @@ -862,6 +862,13 @@ static void ASMJIT_NOINLINE testA64AssemblerBase(AssemblerTester TEST_INSTRUCTION("F42FC1DA", pacdzb(x20)); TEST_INSTRUCTION("4130C39A", pacga(x1, x2, x3)); TEST_INSTRUCTION("4130DF9A", pacga(x1, x2, sp)); + TEST_INSTRUCTION("204080F9", prfm(Predicate::PRFOp::kPLDL1KEEP, ptr(x1, 128))); + TEST_INSTRUCTION("401098F8", prfm(Predicate::PRFOp::kPLDL1KEEP, ptr(x2, -127))); + TEST_INSTRUCTION("601088F8", prfm(Predicate::PRFOp::kPLDL1KEEP, ptr(x3, 129))); + TEST_INSTRUCTION("6068A4F8", prfm(Predicate::PRFOp::kPLDL1KEEP, ptr(x3, x4))); + TEST_INSTRUCTION("6078A4F8", prfm(Predicate::PRFOp::kPLDL1KEEP, ptr(x3, x4, lsl(3)))); + TEST_INSTRUCTION("60C8A4F8", prfm(Predicate::PRFOp::kPLDL1KEEP, ptr(x3, x4, sxtw(0)))); + TEST_INSTRUCTION("73D8A4F8", prfm(Predicate::PRFOp::kPSTL2STRM, ptr(x3, x4, sxtw(3)))); TEST_INSTRUCTION("9F3403D5", pssbb()); TEST_INSTRUCTION("4100C05A", rbit(w1, w2)); TEST_INSTRUCTION("4100C0DA", rbit(x1, x2)); diff --git a/deps/asmjit/test/asmjit_test_compiler.cpp b/deps/asmjit/test/asmjit_test_compiler.cpp index c6b1c28d..cfbb7ede 100644 --- a/deps/asmjit/test/asmjit_test_compiler.cpp +++ b/deps/asmjit/test/asmjit_test_compiler.cpp @@ -35,6 +35,7 @@ using namespace asmjit; int TestApp::handleArgs(int argc, const char* const* argv) { CmdLine cmd(argc, argv); _arch = cmd.valueOf("--arch", "all"); + _filter = cmd.valueOf("--filter", nullptr); if (cmd.hasArg("--help")) _helpOnly = true; if (cmd.hasArg("--verbose")) _verbose = true; @@ -56,11 +57,12 @@ void TestApp::showInfo() { asmjitArchAsString(Arch::kHost)); printf("Usage:\n"); - printf(" --help Show usage only\n"); - printf(" --arch= Select architecture to run ('all' by default)\n"); - printf(" --verbose Verbose output\n"); - printf(" --dump-asm Assembler output\n"); - printf(" --dump-hex Hexadecimal output (relocated, only for host arch)\n"); + printf(" --help Show usage only\n"); + printf(" --arch= Select architecture to run ('all' by default)\n"); + printf(" --filter= Use a filter to restrict which test is called\n"); + printf(" --verbose Verbose output\n"); + printf(" --dump-asm Assembler output\n"); + printf(" --dump-hex Hexadecimal output (relocated, only for host arch)\n"); printf("\n"); } @@ -82,6 +84,13 @@ public: }; #endif // !ASMJIT_NO_LOGGING +bool TestApp::shouldRun(const TestCase* tc) { + if (!_filter) + return true; + + return strstr(tc->name(), _filter) != nullptr; +} + int TestApp::run() { #ifndef ASMJIT_NO_LOGGING FormatOptions formatOptions; @@ -98,8 +107,10 @@ int TestApp::run() { stringLogger.setOptions(formatOptions); auto printStringLoggerContent = [&]() { - if (!_verbose) + if (!_verbose) { printf("%s", stringLogger.data()); + fflush(stdout); + } }; #else auto printStringLoggerContent = [&]() {}; @@ -118,6 +129,11 @@ int TestApp::run() { double finalizeTime = 0; for (std::unique_ptr& test : _tests) { + if (!shouldRun(test.get())) + continue; + + _numTests++; + for (uint32_t pass = 0; pass < 2; pass++) { bool runnable = false; CodeHolder code; @@ -202,6 +218,7 @@ int TestApp::run() { if (pass != 0) { printf("[Test:%s] %s", asmjitArchAsString(test->arch()), test->name()); + fflush(stdout); #ifndef ASMJIT_NO_LOGGING if (_verbose || _dumpAsm || _dumpHex) { @@ -244,16 +261,17 @@ int TestApp::run() { compileTimer.stop(); Error err = errorHandler._err; - if (!err) { + if (err == kErrorOk) { finalizeTimer.start(); err = cc->finalize(); finalizeTimer.stop(); } - // The first pass is only for timing serialization and compilation, because otherwise it would be biased by - // logging, which takes much more time than finalize() does. We want to benchmark Compiler the way it would - // be used in production. + // The first pass is only used for timing of serialization and compilation, because otherwise it would be + // biased by logging, which takes much more time than finalize() does. We want to benchmark Compiler the + // way it would be used in the production. if (pass == 0) { + _outputSize += code.codeSize(); compileTime += compileTimer.duration(); finalizeTime += finalizeTimer.duration(); continue; @@ -287,8 +305,6 @@ int TestApp::run() { fflush(stdout); if (err == kErrorOk) { - _outputSize += code.codeSize(); - StringTmp<128> result; StringTmp<128> expect; @@ -304,7 +320,7 @@ int TestApp::run() { printf(" [Output]\n"); printf(" Returned: %s\n", result.data()); printf(" Expected: %s\n", expect.data()); - _nFailed++; + _numFailed++; } if (_dumpAsm) @@ -319,7 +335,7 @@ int TestApp::run() { printStringLoggerContent(); printf(" [Status]\n"); printf(" ERROR 0x%08X: %s\n", unsigned(err), errorHandler._message.data()); - _nFailed++; + _numFailed++; } } #endif // !ASMJIT_NO_JIT @@ -328,7 +344,7 @@ int TestApp::run() { if (err) { printf(" [Status]\n"); printf(" ERROR 0x%08X: %s\n", unsigned(err), errorHandler._message.data()); - _nFailed++; + _numFailed++; } else { printf("%s[COMPILE OK]\n", statusSeparator); @@ -350,12 +366,12 @@ int TestApp::run() { printf(" FinalizeTime: %.2f ms\n", finalizeTime); printf("\n"); - if (_nFailed == 0) - printf("** SUCCESS: All %u tests passed **\n", unsigned(_tests.size())); + if (_numFailed == 0) + printf("** SUCCESS: All %u tests passed **\n", _numTests); else - printf("** FAILURE: %u of %u tests failed **\n", _nFailed, unsigned(_tests.size())); + printf("** FAILURE: %u of %u tests failed **\n", _numFailed, _numTests); - return _nFailed == 0 ? 0 : 1; + return _numFailed == 0 ? 0 : 1; } int main(int argc, char* argv[]) { diff --git a/deps/asmjit/test/asmjit_test_compiler.h b/deps/asmjit/test/asmjit_test_compiler.h index 79414d0f..433d4795 100644 --- a/deps/asmjit/test/asmjit_test_compiler.h +++ b/deps/asmjit/test/asmjit_test_compiler.h @@ -52,12 +52,14 @@ public: std::vector> _tests; const char* _arch = nullptr; + const char* _filter = nullptr; bool _helpOnly = false; bool _verbose = false; bool _dumpAsm = false; bool _dumpHex = false; - unsigned _nFailed = 0; + unsigned _numTests = 0; + unsigned _numFailed = 0; size_t _outputSize = 0; TestApp() noexcept @@ -73,6 +75,8 @@ public: int handleArgs(int argc, const char* const* argv); void showInfo(); + + bool shouldRun(const TestCase* tc); int run(); }; diff --git a/deps/asmjit/test/asmjit_test_compiler_a64.cpp b/deps/asmjit/test/asmjit_test_compiler_a64.cpp index 17eb7b4c..4d8cd5e8 100644 --- a/deps/asmjit/test/asmjit_test_compiler_a64.cpp +++ b/deps/asmjit/test/asmjit_test_compiler_a64.cpp @@ -55,7 +55,7 @@ public: uint32_t i; uint32_t argCount = _argCount; - FuncSignatureBuilder signature; + FuncSignature signature; signature.setRetT(); for (i = 0; i < argCount; i++) signature.addArgT(); @@ -64,11 +64,11 @@ public: if (_preserveFP) funcNode->frame().setPreservedFP(); - arm::Gp sum; + a64::Gp sum; if (argCount) { for (i = 0; i < argCount; i++) { - arm::Gp iReg = cc.newInt32("i%u", i); + a64::Gp iReg = cc.newInt32("i%u", i); funcNode->setArg(i, iReg); if (i == 0) @@ -184,7 +184,7 @@ public: result.assignFormat("ret={%u, %u}", resultRet >> 28, resultRet & 0x0FFFFFFFu); expect.assignFormat("ret={%u, %u}", expectRet >> 28, expectRet & 0x0FFFFFFFu); - return resultRet == expectRet; + return result == expect; } }; @@ -201,24 +201,24 @@ public: } virtual void compile(a64::Compiler& cc) { - FuncNode* funcNode = cc.addFunc(FuncSignatureT()); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); - arm::Gp dst = cc.newUIntPtr("dst"); - arm::Gp src1 = cc.newUIntPtr("src1"); - arm::Gp src2 = cc.newUIntPtr("src2"); + a64::Gp dst = cc.newUIntPtr("dst"); + a64::Gp src1 = cc.newUIntPtr("src1"); + a64::Gp src2 = cc.newUIntPtr("src2"); funcNode->setArg(0, dst); funcNode->setArg(1, src1); funcNode->setArg(2, src2); - arm::Vec v1 = cc.newVecQ("vec1"); - arm::Vec v2 = cc.newVecQ("vec2"); - arm::Vec v3 = cc.newVecQ("vec3"); + a64::Vec v1 = cc.newVecQ("vec1"); + a64::Vec v2 = cc.newVecQ("vec2"); + a64::Vec v3 = cc.newVecQ("vec3"); - cc.ldr(v2, arm::ptr(src1)); - cc.ldr(v3, arm::ptr(src2)); + cc.ldr(v2, a64::ptr(src1)); + cc.ldr(v3, a64::ptr(src2)); cc.add(v1.b16(), v2.b16(), v3.b16()); - cc.str(v1, arm::ptr(dst)); + cc.str(v1, a64::ptr(dst)); cc.endFunc(); } @@ -235,13 +235,10 @@ public: ptr_as_func(_func)(dst, aSrc, bSrc); - unsigned int resultRet = 0; - unsigned int expectRet = 0; - result.assignFormat("ret={%u, %u, %u, %u}", dst[0], dst[1], dst[2], dst[3]); expect.assignFormat("ret={%u, %u, %u, %u}", ref[0], ref[1], ref[2], ref[3]); - return resultRet == expectRet; + return result == expect; } }; @@ -264,16 +261,16 @@ public: } virtual void compile(a64::Compiler& cc) { - cc.addFunc(FuncSignatureT()); + cc.addFunc(FuncSignature::build()); - arm::Gp* regs = static_cast(malloc(_regCount * sizeof(arm::Gp))); + a64::Gp* regs = static_cast(malloc(_regCount * sizeof(a64::Gp))); for (uint32_t i = 0; i < _regCount; i++) { regs[i] = cc.newUInt32("reg%u", i); cc.mov(regs[i], i + 1); } - arm::Gp sum = cc.newUInt32("sum"); + a64::Gp sum = cc.newUInt32("sum"); cc.mov(sum, 0); for (uint32_t i = 0; i < _regCount; i++) { @@ -314,15 +311,15 @@ public: } virtual void compile(a64::Compiler& cc) { - cc.addFunc(FuncSignatureT()); + cc.addFunc(FuncSignature::build()); - arm::Gp addr = cc.newIntPtr("addr"); - arm::Gp val = cc.newIntPtr("val"); + a64::Gp addr = cc.newIntPtr("addr"); + a64::Gp val = cc.newIntPtr("val"); Label L_Table = cc.newLabel(); cc.adr(addr, L_Table); - cc.ldrsw(val, arm::ptr(addr, 8)); + cc.ldrsw(val, a64::ptr(addr, 8)); cc.ret(val); cc.endFunc(); @@ -358,11 +355,11 @@ public: } virtual void compile(a64::Compiler& cc) { - FuncNode* funcNode = cc.addFunc(FuncSignatureT()); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); - arm::Gp p = cc.newIntPtr("p"); - arm::Gp count = cc.newIntPtr("count"); - arm::Gp i = cc.newIntPtr("i"); + a64::Gp p = cc.newIntPtr("p"); + a64::Gp count = cc.newIntPtr("count"); + a64::Gp i = cc.newIntPtr("i"); Label L = cc.newLabel(); funcNode->setArg(0, p); @@ -413,12 +410,12 @@ public: } virtual void compile(a64::Compiler& cc) { - FuncNode* funcNode = cc.addFunc(FuncSignatureT()); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); - arm::Gp x = cc.newUInt32("x"); - arm::Gp y = cc.newUInt32("y"); - arm::Gp r = cc.newUInt32("r"); - arm::Gp fn = cc.newUIntPtr("fn"); + a64::Gp x = cc.newUInt32("x"); + a64::Gp y = cc.newUInt32("y"); + a64::Gp r = cc.newUInt32("r"); + a64::Gp fn = cc.newUIntPtr("fn"); funcNode->setArg(0, x); funcNode->setArg(1, y); @@ -426,7 +423,7 @@ public: cc.mov(fn, (uint64_t)calledFunc); InvokeNode* invokeNode; - cc.invoke(&invokeNode, fn, FuncSignatureT(CallConvId::kHost)); + cc.invoke(&invokeNode, fn, FuncSignature::build()); invokeNode->setArg(0, x); invokeNode->setArg(1, y); invokeNode->setRet(0, r); @@ -466,19 +463,19 @@ public: } virtual void compile(a64::Compiler& cc) { - FuncNode* funcNode = cc.addFunc(FuncSignatureT()); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); - arm::Vec x = cc.newVecD("x"); - arm::Vec y = cc.newVecD("y"); - arm::Vec r = cc.newVecD("r"); - arm::Gp fn = cc.newUIntPtr("fn"); + a64::Vec x = cc.newVecD("x"); + a64::Vec y = cc.newVecD("y"); + a64::Vec r = cc.newVecD("r"); + a64::Gp fn = cc.newUIntPtr("fn"); funcNode->setArg(0, x); funcNode->setArg(1, y); cc.mov(fn, (uint64_t)calledFunc); InvokeNode* invokeNode; - cc.invoke(&invokeNode, fn, FuncSignatureT(CallConvId::kHost)); + cc.invoke(&invokeNode, fn, FuncSignature::build()); invokeNode->setArg(0, x); invokeNode->setArg(1, y); invokeNode->setRet(0, r); @@ -518,19 +515,19 @@ public: } virtual void compile(a64::Compiler& cc) { - FuncNode* funcNode = cc.addFunc(FuncSignatureT()); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); - arm::Vec x = cc.newVecD("x"); - arm::Vec y = cc.newVecD("y"); - arm::Vec r = cc.newVecD("r"); - arm::Gp fn = cc.newUIntPtr("fn"); + a64::Vec x = cc.newVecD("x"); + a64::Vec y = cc.newVecD("y"); + a64::Vec r = cc.newVecD("r"); + a64::Gp fn = cc.newUIntPtr("fn"); funcNode->setArg(0, x); funcNode->setArg(1, y); cc.mov(fn, (uint64_t)calledFunc); InvokeNode* invokeNode; - cc.invoke(&invokeNode, fn, FuncSignatureT(CallConvId::kHost)); + cc.invoke(&invokeNode, fn, FuncSignature::build()); invokeNode->setArg(0, y); invokeNode->setArg(1, x); invokeNode->setRet(0, r); @@ -583,14 +580,14 @@ public: } virtual void compile(a64::Compiler& cc) { - FuncNode* funcNode = cc.addFunc(FuncSignatureT()); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); - arm::Vec a = cc.newVecS("a"); - arm::Vec b = cc.newVecS("b"); - arm::Gp op = cc.newUInt32("op"); + a64::Vec a = cc.newVecS("a"); + a64::Vec b = cc.newVecS("b"); + a64::Gp op = cc.newUInt32("op"); - arm::Gp target = cc.newIntPtr("target"); - arm::Gp offset = cc.newIntPtr("offset"); + a64::Gp target = cc.newIntPtr("target"); + a64::Gp offset = cc.newIntPtr("offset"); Label L_End = cc.newLabel(); @@ -605,7 +602,7 @@ public: funcNode->setArg(2, op); cc.adr(target, L_Table); - cc.ldrsw(offset, arm::ptr(target, op, arm::sxtw(2))); + cc.ldrsw(offset, a64::ptr(target, op, a64::sxtw(2))); cc.add(target, target, offset); // JumpAnnotation allows to annotate all possible jump targets of diff --git a/deps/asmjit/test/asmjit_test_compiler_x86.cpp b/deps/asmjit/test/asmjit_test_compiler_x86.cpp index 2539d167..cae7c7ad 100644 --- a/deps/asmjit/test/asmjit_test_compiler_x86.cpp +++ b/deps/asmjit/test/asmjit_test_compiler_x86.cpp @@ -67,7 +67,7 @@ public: uint32_t i; uint32_t argCount = _argCount; - FuncSignatureBuilder signature(CallConvId::kHost); + FuncSignature signature(CallConvId::kCDecl); signature.setRetT(); for (i = 0; i < argCount; i++) signature.addArgT(); @@ -203,7 +203,7 @@ public: result.assignFormat("ret={%u, %u}", resultRet >> 28, resultRet & 0x0FFFFFFFu); expect.assignFormat("ret={%u, %u}", expectRet >> 28, expectRet & 0x0FFFFFFFu); - return resultRet == expectRet; + return result == expect; } uint32_t _argCount; @@ -223,7 +223,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); cc.endFunc(); } @@ -238,8 +238,8 @@ public: } }; -// x86::Compiler - X86Test_AlignNone -// ================================= +// x86::Compiler - X86Test_NoAlign +// =============================== class X86Test_NoAlign : public X86TestCase { public: @@ -250,7 +250,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); cc.align(AlignMode::kCode, 0); cc.align(AlignMode::kCode, 1); cc.endFunc(); @@ -267,6 +267,35 @@ public: } }; +// x86::Compiler - X86Test_IndirectBranchProtection +// ================================================ + +class X86Test_IndirectBranchProtection : public X86TestCase { +public: + X86Test_IndirectBranchProtection() : X86TestCase("IndirectBranchProtection") {} + + static void add(TestApp& app) { + app.add(new X86Test_IndirectBranchProtection()); + } + + virtual void compile(x86::Compiler& cc) { + FuncNode* func = cc.addFunc(FuncSignature::build()); + func->addAttributes(FuncAttributes::kIndirectBranchProtection); + cc.endFunc(); + } + + virtual bool run(void* _func, String& result, String& expect) { + DebugUtils::unused(result, expect); + + typedef void (*Func)(void); + Func func = ptr_as_func(_func); + + func(); + return true; + } +}; + + // x86::Compiler - X86Test_JumpMerge // ================================= @@ -287,7 +316,7 @@ public: x86::Gp dst = cc.newIntPtr("dst"); x86::Gp val = cc.newInt32("val"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, dst); funcNode->setArg(1, val); @@ -343,7 +372,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); Label L1 = cc.newLabel(); Label L2 = cc.newLabel(); @@ -384,7 +413,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); for (uint32_t i = 0; i < 1000; i++) { Label L = cc.newLabel(); cc.jmp(L); @@ -408,7 +437,7 @@ public: result.assignFormat("ret={%d}", resultRet); expect.assignFormat("ret={%d}", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -424,7 +453,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); Label L_1 = cc.newLabel(); Label L_2 = cc.newLabel(); @@ -486,7 +515,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); Label L_1 = cc.newLabel(); Label L_2 = cc.newLabel(); @@ -559,7 +588,7 @@ public: Label L_Div = cc.newLabel(); Label L_End = cc.newLabel(); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, a); funcNode->setArg(1, b); funcNode->setArg(2, op); @@ -660,7 +689,7 @@ public: Label L_Case1 = cc.newLabel(); Label L_End = cc.newLabel(); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, value); cc.bind(L_Begin); @@ -730,7 +759,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); Label L_Target = cc.newLabel(); x86::Gp target = cc.newUIntPtr("target"); @@ -778,7 +807,7 @@ public: x86::Gp result = cc.newUInt32("result"); x86::Gp condition = cc.newUInt32("condition"); - FuncNode* func = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* func = cc.addFunc(FuncSignature::build()); func->setArg(0, condition); Label L_NonZero = cc.newLabel(); @@ -849,7 +878,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); x86::Gp v0 = cc.newInt32("v0"); x86::Gp v1 = cc.newInt32("v1"); @@ -883,7 +912,7 @@ public: result.assignFormat("ret=%d", resultRet); expect.assignFormat("ret=%d", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -904,7 +933,7 @@ public: x86::Gp a0 = cc.newIntPtr("a0"); x86::Gp a1 = cc.newIntPtr("a1"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, a0); funcNode->setArg(1, a1); @@ -942,8 +971,8 @@ public: typedef void (*Func)(int*, int*); Func func = ptr_as_func(_func); - int resultX; - int resultY; + int resultX = 0; + int resultY = 0; int expectX = 36; int expectY = -36; @@ -972,7 +1001,7 @@ public: x86::Gp a = cc.newIntPtr("a"); x86::Gp v[32]; - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, a); for (uint32_t i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) v[i] = cc.newInt32("v%d", i); @@ -997,8 +1026,8 @@ public: Func func = ptr_as_func(_func); uint32_t i; - uint32_t resultBuf[32]; - uint32_t expectBuf[32]; + uint32_t resultBuf[32] {}; + uint32_t expectBuf[32] {}; for (i = 0; i < ASMJIT_ARRAY_SIZE(resultBuf); i++) expectBuf[i] = i * 32; @@ -1037,7 +1066,7 @@ public: x86::Gp vLo = cc.newInt32("vLo"); x86::Gp src = cc.newInt32("src"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, dstHi); funcNode->setArg(1, dstLo); funcNode->setArg(2, vLo); @@ -1056,8 +1085,8 @@ public: int v0 = 4; int v1 = 4; - int resultHi; - int resultLo; + int resultHi = 0; + int resultLo = 0; int expectHi = 0; int expectLo = v0 * v1; @@ -1086,7 +1115,7 @@ public: x86::Gp dst = cc.newIntPtr("dst"); x86::Gp src = cc.newIntPtr("src"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, dst); funcNode->setArg(1, src); @@ -1139,7 +1168,7 @@ public: x86::Gp b = cc.newInt32("b"); x86::Gp dummy = cc.newInt32("dummy"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, a); funcNode->setArg(1, b); @@ -1163,7 +1192,7 @@ public: result.assignFormat("result=%d", resultRet); expect.assignFormat("result=%d", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -1183,7 +1212,7 @@ public: x86::Gp src1 = cc.newInt32("src1"); x86::Gp dst0 = cc.newIntPtr("dst0"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, src0); funcNode->setArg(1, src1); funcNode->setArg(2, dst0); @@ -1198,7 +1227,7 @@ public: typedef void (*Func)(int, int, char*); Func func = ptr_as_func(_func); - char resultBuf[4]; + char resultBuf[4] {}; char expectBuf[4] = { 1, 0, 0, 1 }; func(0, 0, &resultBuf[0]); // We are expecting 1 (0 == 0). @@ -1233,7 +1262,7 @@ public: x86::Gp vShlParam = cc.newInt32("vShlParam"); x86::Gp vRorParam = cc.newInt32("vRorParam"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, dst); funcNode->setArg(1, var); funcNode->setArg(2, vShlParam); @@ -1251,7 +1280,7 @@ public: int v0 = 0x000000FF; - int resultRet; + int resultRet = 0; int expectRet = 0x0000FF00; func(&resultRet, v0, 16, 8); @@ -1259,7 +1288,7 @@ public: result.assignFormat("ret=%d", resultRet); expect.assignFormat("ret=%d", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -1281,7 +1310,7 @@ public: x86::Gp rSum = cc.newUInt32("rSum"); x86::Gp x[kCount]; - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, rPtr); for (uint32_t i = 0; i < kCount; i++) { @@ -1318,10 +1347,9 @@ public: uint32_t i; uint32_t buf[kCount]; - uint32_t resultRet; - uint32_t expectRet; + uint32_t resultRet = 0; + uint32_t expectRet = 0; - expectRet = 0; for (i = 0; i < kCount; i++) { buf[i] = 1; } @@ -1345,7 +1373,7 @@ public: result.assignFormat("ret=%d", resultRet); expect.assignFormat("ret=%d", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -1363,7 +1391,7 @@ public: virtual void compile(x86::Compiler& cc) { x86::Gp v = cc.newUInt32("v"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, v); cc.mov(v.r8(), 0xFF); @@ -1381,7 +1409,7 @@ public: result.assignFormat("ret=%d", resultRet); expect.assignFormat("ret=%d", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -1401,7 +1429,7 @@ public: x86::Gp src = cc.newIntPtr("src"); x86::Gp cnt = cc.newIntPtr("cnt"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, dst); funcNode->setArg(1, src); funcNode->setArg(2, cnt); @@ -1443,7 +1471,7 @@ public: Label L_1 = cc.newLabel(); Label L_2 = cc.newLabel(); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, v1); funcNode->setArg(1, v2); @@ -1495,7 +1523,7 @@ public: Label L_3 = cc.newLabel(); Label L_4 = cc.newLabel(); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, v1); funcNode->setArg(1, v2); @@ -1554,7 +1582,7 @@ public: Label L_Loop = cc.newLabel(); Label L_Exit = cc.newLabel(); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, v1); funcNode->setArg(1, v2); @@ -1614,7 +1642,7 @@ public: Label L_Loop2 = cc.newLabel(); Label L_Exit = cc.newLabel(); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, v1); funcNode->setArg(1, v2); @@ -1671,7 +1699,7 @@ public: x86::Gp x = cc.newInt8("x"); x86::Gp y = cc.newInt32("y"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, x); cc.movsx(y, x); @@ -1681,10 +1709,10 @@ public: } virtual bool run(void* _func, String& result, String& expect) { - typedef int (*Func)(char); + typedef int (*Func)(int8_t); Func func = ptr_as_func(_func); - int resultRet = func(-13); + int resultRet = func(int8_t(-13)); int expectRet = -13; result.assignFormat("ret=%d", resultRet); @@ -1708,7 +1736,7 @@ public: virtual void compile(x86::Compiler& cc) { x86::Gp x = cc.newInt32("x"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(2, x); cc.ret(x); @@ -1741,7 +1769,7 @@ public: } virtual void compile(x86::Compiler& cc) { - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); x86::Gp var[8]; for (uint32_t i = 0; i < 8; i++) { @@ -1797,7 +1825,7 @@ public: } virtual void compile(x86::Compiler& cc) { - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); x86::Gp p = cc.newIntPtr("p"); x86::Xmm xv[7]; @@ -1824,7 +1852,7 @@ public: typedef void (*Func)(float, float, float, float, float, float, float, float*); Func func = ptr_as_func(_func); - float resultRet; + float resultRet = 0; float expectRet = 1.0f + 2.0f + 3.0f + 4.0f + 5.0f + 6.0f + 7.0f; func(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, &resultRet); @@ -1832,7 +1860,7 @@ public: result.assignFormat("ret={%g}", resultRet); expect.assignFormat("ret={%g}", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -1848,7 +1876,7 @@ public: } virtual void compile(x86::Compiler& cc) { - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); x86::Gp p = cc.newIntPtr("p"); x86::Xmm xv[7]; @@ -1875,7 +1903,7 @@ public: typedef void (*Func)(double, double, double, double, double, double, double, double*); Func func = ptr_as_func(_func); - double resultRet; + double resultRet = 0; double expectRet = 1.0 + 2.0 + 3.0 + 4.0 + 5.0 + 6.0 + 7.0; func(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, &resultRet); @@ -1883,7 +1911,7 @@ public: result.assignFormat("ret={%g}", resultRet); expect.assignFormat("ret={%g}", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -1908,7 +1936,7 @@ public: x86::Xmm a = cc.newXmm("aXmm"); x86::Xmm b = cc.newXmm("bXmm"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, a); funcNode->setArg(1, b); @@ -1925,7 +1953,7 @@ public: uint8_t aData[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; uint8_t bData[16] = { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; - uint8_t rData[16]; + uint8_t rData[16] {}; uint8_t eData[16] = { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 }; __m128i aVec = _mm_loadu_si128(reinterpret_cast(aData)); @@ -1956,7 +1984,7 @@ public: virtual void compile(x86::Compiler& cc) { x86::Xmm x = cc.newXmmSs("x"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, x); cc.ret(x); @@ -1973,7 +2001,7 @@ public: result.assignFormat("ret={%g}", resultRet); expect.assignFormat("ret={%g}", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -1992,7 +2020,7 @@ public: x86::Xmm x = cc.newXmmSs("x"); x86::Xmm y = cc.newXmmSs("y"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, x); funcNode->setArg(1, y); @@ -2012,7 +2040,7 @@ public: result.assignFormat("ret={%g}", resultRet); expect.assignFormat("ret={%g}", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -2030,7 +2058,7 @@ public: virtual void compile(x86::Compiler& cc) { x86::Xmm x = cc.newXmmSd("x"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, x); cc.ret(x); @@ -2047,7 +2075,7 @@ public: result.assignFormat("ret={%g}", resultRet); expect.assignFormat("ret={%g}", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -2066,7 +2094,7 @@ public: x86::Xmm x = cc.newXmmSd("x"); x86::Xmm y = cc.newXmmSd("y"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, x); funcNode->setArg(1, y); @@ -2086,7 +2114,7 @@ public: result.assignFormat("ret={%g}", resultRet); expect.assignFormat("ret={%g}", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -2104,7 +2132,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); x86::Mem stack = cc.newStack(kSize, 1); stack.setSize(1); @@ -2153,7 +2181,7 @@ public: result.assignInt(resultRet); expect.assignInt(expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -2178,7 +2206,7 @@ public: Label L_Loop = cc.newLabel(); // Create base labels we use Label L_Exit = cc.newLabel(); // in our function. - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, dst); funcNode->setArg(1, src); funcNode->setArg(2, cnt); @@ -2255,7 +2283,7 @@ public: x86::Gp a = cc.newInt32("a"); x86::Gp b = cc.newInt32("b"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, cond); funcNode->setArg(1, a); funcNode->setArg(2, b); @@ -2378,6 +2406,47 @@ public: } }; +// x86::Compiler - X86Test_FuncArgInt8 +// =================================== + +class X86Test_FuncArgInt8 : public X86TestCase { +public: + X86Test_FuncArgInt8() : X86TestCase("FuncArgInt8") {} + + static void add(TestApp& app) { + app.add(new X86Test_FuncArgInt8()); + } + + virtual void compile(x86::Compiler& cc) { + x86::Gp v0 = cc.newUInt32("v0"); + x86::Gp v1 = cc.newUInt32("v1"); + + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); + funcNode->setArg(0, v0); + funcNode->setArg(1, v1); + + cc.add(v0, v1); + + cc.ret(v0); + cc.endFunc(); + } + + virtual bool run(void* _func, String& result, String& expect) { + typedef uint32_t (*Func)(uint8_t, uint8_t, uint32_t); + Func func = ptr_as_func(_func); + + uint32_t arg = uint32_t(uintptr_t(_func) & 0xFFFFFFFF); + + unsigned resultRet = func(uint8_t(arg & 0xFF), uint8_t(arg & 0xFF), arg); + unsigned expectRet = (arg & 0xFF) * 2; + + result.assignFormat("ret=%u", resultRet); + expect.assignFormat("ret=%u", expectRet); + + return result == expect; + } +}; + // x86::Compiler - X86Test_FuncCallBase1 // ===================================== @@ -2394,7 +2463,7 @@ public: x86::Gp v1 = cc.newInt32("v1"); x86::Gp v2 = cc.newInt32("v2"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, v0); funcNode->setArg(1, v1); funcNode->setArg(2, v2); @@ -2406,7 +2475,7 @@ public: // Call a function. InvokeNode* invokeNode; - cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT(CallConvId::kHost)); + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignature::build()); invokeNode->setArg(0, v2); invokeNode->setArg(1, v1); invokeNode->setArg(2, v0); @@ -2426,7 +2495,7 @@ public: result.assignFormat("ret=%d", resultRet); expect.assignFormat("ret=%d", expectRet); - return resultRet == expectRet; + return result == expect; } static int calledFunc(int a, int b, int c) { return (a + b) * c; } @@ -2446,7 +2515,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); const int kTokenSize = 32; @@ -2466,19 +2535,19 @@ public: cc.lea(p2, s2); // Try to corrupt the stack if wrongly allocated. - cc.invoke(&invokeNode, imm((void*)memcpy), FuncSignatureT(CallConvId::kCDecl)); + cc.invoke(&invokeNode, imm((void*)memcpy), FuncSignature::build()); invokeNode->setArg(0, p1); invokeNode->setArg(1, imm(token)); invokeNode->setArg(2, imm(kTokenSize)); invokeNode->setRet(0, p1); - cc.invoke(&invokeNode, imm((void*)memcpy), FuncSignatureT(CallConvId::kCDecl)); + cc.invoke(&invokeNode, imm((void*)memcpy), FuncSignature::build()); invokeNode->setArg(0, p2); invokeNode->setArg(1, imm(token)); invokeNode->setArg(2, imm(kTokenSize)); invokeNode->setRet(0, p2); - cc.invoke(&invokeNode, imm((void*)memcmp), FuncSignatureT(CallConvId::kCDecl)); + cc.invoke(&invokeNode, imm((void*)memcmp), FuncSignature::build()); invokeNode->setArg(0, p1); invokeNode->setArg(1, p2); invokeNode->setArg(2, imm(kTokenSize)); @@ -2509,7 +2578,7 @@ public: result.assignInt(resultRet); expect.assignInt(expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -2529,7 +2598,7 @@ public: x86::Gp y = cc.newInt32("y"); x86::Gp z = cc.newInt32("z"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, x); funcNode->setArg(1, y); funcNode->setArg(2, z); @@ -2537,7 +2606,7 @@ public: InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)calledFunc), - FuncSignatureT(CallConvId::kStdCall)); + FuncSignature::build(CallConvId::kStdCall)); invokeNode->setArg(0, x); invokeNode->setArg(1, y); invokeNode->setArg(2, z); @@ -2557,7 +2626,7 @@ public: result.assignFormat("ret=%d", resultRet); expect.assignFormat("ret=%d", expectRet); - return resultRet == expectRet; + return result == expect; } // STDCALL function that is called inside the generated one. @@ -2580,16 +2649,16 @@ public: virtual void compile(x86::Compiler& cc) { x86::Gp var = cc.newInt32("var"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, var); InvokeNode* invokeNode; - cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT(CallConvId::kFastCall)); + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignature::build(CallConvId::kFastCall)); invokeNode->setArg(0, var); invokeNode->setRet(0, var); - cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT(CallConvId::kFastCall)); + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignature::build(CallConvId::kFastCall)); invokeNode->setArg(0, var); invokeNode->setRet(0, var); @@ -2607,7 +2676,7 @@ public: result.assignFormat("ret=%d", resultRet); expect.assignFormat("ret=%d", expectRet); - return resultRet == expectRet; + return result == expect; } // FASTCALL function that is called inside the generated one. @@ -2638,7 +2707,7 @@ public: } virtual void compile(x86::Compiler& cc) { - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); x86::Gp resultPtr = cc.newIntPtr("resultPtr"); x86::Gp aPtr = cc.newIntPtr("aPtr"); @@ -2667,7 +2736,7 @@ public: cc.movdqu(bXmm, x86::ptr(bPtr)); InvokeNode* invokeNode; - cc.invoke(&invokeNode, pFn, FuncSignatureT(ccId)); + cc.invoke(&invokeNode, pFn, FuncSignature::build(ccId)); invokeNode->setArg(0, aXmm); invokeNode->setArg(1, bXmm); @@ -2685,7 +2754,7 @@ public: uint8_t aData[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; uint8_t bData[16] = { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; - uint8_t rData[16]; + uint8_t rData[16] {}; uint8_t eData[16] = { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 }; func(rData, aData, bData); @@ -2720,8 +2789,8 @@ public: } virtual void compile(x86::Compiler& cc) { - FuncSignatureT f1Sig(CallConvId::kCDecl); - FuncSignatureT f2Sig(CallConvId::kLightCall2); + FuncSignature f1Sig = FuncSignature::build(); + FuncSignature f2Sig = FuncSignature::build(CallConvId::kLightCall2); FuncNode* f1Node = cc.newFunc(f1Sig); FuncNode* f2Node = cc.newFunc(f2Sig); @@ -2794,7 +2863,7 @@ public: int16_t c[8] = { 1, 3, 9, 7, 5, 4, 2, 1 }; int16_t d[8] = { 2, 0,-6,-4,-2,-1, 1, 2 }; - int16_t o[8]; + int16_t o[8] {}; int oExp = 7 * 3; func(a, b, c, d, o); @@ -2822,7 +2891,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); // Prepare. x86::Gp va = cc.newInt32("va"); @@ -2851,7 +2920,7 @@ public: InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)calledFunc), - FuncSignatureT(CallConvId::kHost)); + FuncSignature::build()); invokeNode->setArg(0, va); invokeNode->setArg(1, vb); invokeNode->setArg(2, vc); @@ -2878,7 +2947,7 @@ public: result.assignFormat("ret=%d", resultRet); expect.assignFormat("ret=%d", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -2898,7 +2967,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); // Prepare. x86::Gp a = cc.newInt32("a"); @@ -2908,7 +2977,7 @@ public: InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)calledFunc), - FuncSignatureT(CallConvId::kHost)); + FuncSignature::build()); invokeNode->setArg(0, a); invokeNode->setArg(1, a); invokeNode->setArg(2, a); @@ -2935,7 +3004,7 @@ public: result.assignFormat("ret=%d", resultRet); expect.assignFormat("ret=%d", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -2951,7 +3020,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); // Prepare. x86::Gp rv = cc.newInt32("rv"); @@ -2960,7 +3029,7 @@ public: InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)X86Test_FuncCallManyArgs::calledFunc), - FuncSignatureT(CallConvId::kHost)); + FuncSignature::build()); invokeNode->setArg(0, imm(0x03)); invokeNode->setArg(1, imm(0x12)); @@ -2988,7 +3057,7 @@ public: result.assignFormat("ret=%d", resultRet); expect.assignFormat("ret=%d", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -3017,7 +3086,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); // Prepare. x86::Gp rv = cc.newInt32("rv"); @@ -3026,7 +3095,7 @@ public: InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)calledFunc), - FuncSignatureT(CallConvId::kHost)); + FuncSignature::build()); invokeNode->setArg(0, imm(0x01)); invokeNode->setArg(1, imm(0x02)); @@ -3054,7 +3123,7 @@ public: result.assignFormat("ret=%d", resultRet); expect.assignFormat("ret=%d", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -3078,7 +3147,7 @@ public: } virtual void compile(x86::Compiler& cc) { - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); // Prepare. x86::Gp arg1 = cc.newInt32(); @@ -3096,7 +3165,7 @@ public: InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)calledFunc), - FuncSignatureT(CallConvId::kHost)); + FuncSignature::build()); invokeNode->setArg(0, arg1); invokeNode->setArg(1, arg2); @@ -3120,7 +3189,7 @@ public: result.assignFormat("ret={%08X %08X %08X %08X %08X}", resultRet, inputs[0], inputs[1], inputs[2], inputs[3]); expect.assignFormat("ret={%08X %08X %08X %08X %08X}", expectRet, outputs[0], outputs[1], outputs[2], outputs[3]); - return resultRet == expectRet; + return result == expect; } }; @@ -3140,7 +3209,7 @@ public: } virtual void compile(x86::Compiler& cc) { - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); x86::Xmm a = cc.newXmmSs("a"); x86::Xmm b = cc.newXmmSs("b"); @@ -3151,7 +3220,7 @@ public: // Call function. InvokeNode* invokeNode; - cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT(CallConvId::kHost)); + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignature::build()); invokeNode->setArg(0, a); invokeNode->setArg(1, b); invokeNode->setRet(0, ret); @@ -3170,7 +3239,7 @@ public: result.assignFormat("ret=%g", resultRet); expect.assignFormat("ret=%g", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -3190,7 +3259,7 @@ public: } virtual void compile(x86::Compiler& cc) { - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); x86::Xmm a = cc.newXmmSd("a"); x86::Xmm b = cc.newXmmSd("b"); @@ -3200,7 +3269,7 @@ public: funcNode->setArg(1, b); InvokeNode* invokeNode; - cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT(CallConvId::kHost)); + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignature::build()); invokeNode->setArg(0, a); invokeNode->setArg(1, b); invokeNode->setRet(0, ret); @@ -3219,7 +3288,7 @@ public: result.assignFormat("ret=%g", resultRet); expect.assignFormat("ret=%g", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -3242,7 +3311,7 @@ public: InvokeNode* invokeNode; x86::Gp result; - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, x); funcNode->setArg(1, y); funcNode->setArg(2, op); @@ -3262,7 +3331,7 @@ public: cc.bind(opAdd); result = cc.newInt32("result_1"); - cc.invoke(&invokeNode, (uint64_t)calledFuncAdd, FuncSignatureT(CallConvId::kHost)); + cc.invoke(&invokeNode, (uint64_t)calledFuncAdd, FuncSignature::build()); invokeNode->setArg(0, x); invokeNode->setArg(1, y); invokeNode->setRet(0, result); @@ -3271,7 +3340,7 @@ public: cc.bind(opMul); result = cc.newInt32("result_2"); - cc.invoke(&invokeNode, (uint64_t)calledFuncMul, FuncSignatureT(CallConvId::kHost)); + cc.invoke(&invokeNode, (uint64_t)calledFuncMul, FuncSignature::build()); invokeNode->setArg(0, x); invokeNode->setArg(1, y); invokeNode->setRet(0, result); @@ -3325,7 +3394,7 @@ public: x86::Gp acc0 = cc.newInt32("acc0"); x86::Gp acc1 = cc.newInt32("acc1"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, buf); cc.mov(acc0, 0); @@ -3340,7 +3409,7 @@ public: cc.mov(ptr, buf); cc.mov(idx, int(i)); - cc.invoke(&invokeNode, (uint64_t)calledFunc, FuncSignatureT(CallConvId::kFastCall)); + cc.invoke(&invokeNode, (uint64_t)calledFunc, FuncSignature::build(CallConvId::kFastCall)); invokeNode->setArg(0, ptr); invokeNode->setArg(1, idx); invokeNode->setRet(0, ret); @@ -3350,7 +3419,7 @@ public: cc.mov(ptr, buf); cc.mov(idx, int(i)); - cc.invoke(&invokeNode, (uint64_t)calledFunc, FuncSignatureT(CallConvId::kFastCall)); + cc.invoke(&invokeNode, (uint64_t)calledFunc, FuncSignature::build(CallConvId::kFastCall)); invokeNode->setArg(0, ptr); invokeNode->setArg(1, idx); invokeNode->setRet(0, ret); @@ -3375,7 +3444,7 @@ public: result.assignFormat("ret=%d", resultRet); expect.assignFormat("ret=%d", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -3394,7 +3463,7 @@ public: x86::Gp val = cc.newInt32("val"); Label skip = cc.newLabel(); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, val); cc.cmp(val, 1); @@ -3406,7 +3475,7 @@ public: InvokeNode* invokeNode; - cc.invoke(&invokeNode, funcNode->label(), FuncSignatureT(CallConvId::kHost)); + cc.invoke(&invokeNode, funcNode->label(), FuncSignature::build()); invokeNode->setArg(0, tmp); invokeNode->setRet(0, tmp); cc.mul(cc.newInt32(), val, tmp); @@ -3426,7 +3495,7 @@ public: result.assignFormat("ret=%d", resultRet); expect.assignFormat("ret=%d", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -3442,7 +3511,7 @@ public: } virtual void compile(x86::Compiler& cc) { - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); x86::Gp a0 = cc.newInt32("a0"); x86::Gp a1 = cc.newInt32("a1"); @@ -3460,7 +3529,7 @@ public: InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)calledFunc), - FuncSignatureT(CallConvId::kHost, 1)); + FuncSignature::build(CallConvId::kCDecl, 1)); invokeNode->setArg(0, imm(4)); invokeNode->setArg(1, a0); invokeNode->setArg(2, a1); @@ -3482,7 +3551,7 @@ public: result.assignFormat("ret=%d", resultRet); expect.assignFormat("ret=%d", expectRet); - return resultRet == expectRet; + return result == expect; } static int calledFunc(size_t n, ...) { @@ -3510,7 +3579,7 @@ public: } virtual void compile(x86::Compiler& cc) { - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); x86::Xmm a0 = cc.newXmmSd("a0"); x86::Xmm a1 = cc.newXmmSd("a1"); @@ -3528,7 +3597,7 @@ public: InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)calledFunc), - FuncSignatureT(CallConvId::kHost, 1)); + FuncSignature::build(CallConvId::kCDecl, 1)); invokeNode->setArg(0, imm(4)); invokeNode->setArg(1, a0); invokeNode->setArg(2, a1); @@ -3550,7 +3619,7 @@ public: result.assignFormat("ret=%f", resultRet); expect.assignFormat("ret=%f", expectRet); - return resultRet == expectRet; + return result == expect; } static double calledFunc(size_t n, ...) { @@ -3578,7 +3647,7 @@ public: } virtual void compile(x86::Compiler& cc) { - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); if (cc.is64Bit()) { x86::Gp reg = cc.newUInt64(); @@ -3611,7 +3680,7 @@ public: result.assignFormat("ret=%llu", (unsigned long long)resultRet); expect.assignFormat("ret=%llu", (unsigned long long)expectRet); - return resultRet == expectRet; + return result == expect; } static double calledFunc(size_t n, ...) { @@ -3641,7 +3710,7 @@ public: static void dummy(int, int) {} virtual void compile(x86::Compiler& cc) { - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); x86::Gp a = cc.newInt32("a"); x86::Gp b = cc.newInt32("b"); @@ -3653,7 +3722,7 @@ public: InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)dummy), - FuncSignatureT(CallConvId::kHost)); + FuncSignature::build()); invokeNode->setArg(0, a); invokeNode->setArg(1, b); @@ -3673,7 +3742,7 @@ public: result.assignFormat("ret=%d", resultRet); expect.assignFormat("ret=%d", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -3689,7 +3758,7 @@ public: } virtual void compile(x86::Compiler& cc) { - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); x86::Gp p = cc.newIntPtr("p"); x86::Xmm arg = cc.newXmmSd("arg"); @@ -3701,7 +3770,7 @@ public: InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)op), - FuncSignatureT(CallConvId::kHost)); + FuncSignature::build()); invokeNode->setArg(0, arg); invokeNode->setRet(0, ret); @@ -3721,7 +3790,7 @@ public: result.assignFormat("ret=%g", resultRet); expect.assignFormat("ret=%g", expectRet); - return resultRet == expectRet; + return result == expect; } static double op(double a) { return a * a; } @@ -3739,7 +3808,7 @@ public: } virtual void compile(x86::Compiler& cc) { - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); x86::Gp p = cc.newIntPtr("p"); x86::Xmm arg = cc.newXmmSd("arg"); @@ -3751,7 +3820,7 @@ public: InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)op), - FuncSignatureT(CallConvId::kHost)); + FuncSignature::build()); invokeNode->setArg(0, arg); invokeNode->setRet(0, ret); @@ -3774,7 +3843,7 @@ public: result.assignFormat("ret=%g", resultRet); expect.assignFormat("ret=%g", expectRet); - return resultRet == expectRet; + return result == expect; } static double op(double a) { return a * a; } @@ -3794,13 +3863,13 @@ public: virtual void compile(x86::Compiler& cc) { InvokeNode* invokeNode; - FuncSignatureBuilder funcSignature; - funcSignature.setCallConvId(CallConvId::kHost); + FuncSignature funcSignature; + funcSignature.setCallConvId(CallConvId::kCDecl); funcSignature.setRet(TypeId::kFloat64); cc.addFunc(funcSignature); - FuncSignatureBuilder invokeSignature; - invokeSignature.setCallConvId(CallConvId::kHost); + FuncSignature invokeSignature; + invokeSignature.setCallConvId(CallConvId::kCDecl); invokeSignature.setRet(TypeId::kFloat64); cc.invoke(&invokeNode, imm((void*)calledFunc), invokeSignature); @@ -3821,7 +3890,7 @@ public: result.assignFormat("ret=%g", resultRet); expect.assignFormat("ret=%g", expectRet); - return resultRet == expectRet; + return result == expect; } static double calledFunc() { return 3.14; } @@ -3840,7 +3909,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); x86::Gp pFn = cc.newIntPtr("pFn"); x86::Gp vars[16]; @@ -3859,7 +3928,7 @@ public: } InvokeNode* invokeNode; - cc.invoke(&invokeNode, pFn, FuncSignatureT(CallConvId::kHost)); + cc.invoke(&invokeNode, pFn, FuncSignature::build()); for (i = 1; i < regCount; i++) if (vars[i].isValid()) @@ -3879,7 +3948,7 @@ public: result.assignFormat("ret=%d", resultRet); expect.assignFormat("ret=%d", expectRet); - return resultRet == expectRet; + return result == expect; } static void calledFunc() {} @@ -3897,7 +3966,7 @@ public: } virtual void compile(x86::Compiler& cc) { - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); constexpr uint32_t kCount = 16; @@ -3913,7 +3982,7 @@ public: v[i] = cc.newUInt32("v%u", i); InvokeNode* invokeNode; - cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT(CallConvId::kHost)); + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignature::build()); invokeNode->setArg(0, argVal); invokeNode->setRet(0, retVal); @@ -3939,7 +4008,7 @@ public: result.assignFormat("ret=%u", resultRet); expect.assignFormat("ret=%u", expectRet); - return resultRet == expectRet; + return result == expect; } static uint32_t calledFunc(uint32_t x) { return x + 1; } @@ -3960,12 +4029,12 @@ public: } virtual void compile(x86::Compiler& cc) { - FuncNode* mainFunc = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* mainFunc = cc.addFunc(FuncSignature::build()); mainFunc->frame().setAvxEnabled(); mainFunc->frame().setAvxCleanup(); // We need a Windows calling convention to test this properly also on a non-Windows machine. - FuncNode* helperFunc = cc.newFunc(FuncSignatureT(CallConvId::kX64Windows)); + FuncNode* helperFunc = cc.newFunc(FuncSignature::build(CallConvId::kX64Windows)); helperFunc->frame().setAvxEnabled(); helperFunc->frame().setAvxCleanup(); @@ -3992,7 +4061,7 @@ public: InvokeNode* invokeNode; cc.invoke(&invokeNode, helperFunc->label(), - FuncSignatureT(CallConvId::kX64Windows)); + FuncSignature::build(CallConvId::kX64Windows)); invokeNode->setArg(0, tPtr); invokeNode->setArg(1, bPtr); @@ -4037,8 +4106,8 @@ public: static const uint32_t aData[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; static const uint32_t bData[8] = { 6, 3, 5, 9, 1, 8, 7, 2 }; - uint32_t resultData[8]; - uint32_t expectData[8]; + uint32_t resultData[8] {}; + uint32_t expectData[8] {}; for (i = 0; i < 8; i++) expectData[i] = aData[i] * 8 + bData[i] + 1; @@ -4063,6 +4132,60 @@ public: } }; +// x86::Compiler - X86Test_VecToScalar +// =================================== + +class X86Test_VecToScalar : public X86TestCase { +public: + static constexpr uint32_t kVecCount = 64; + + X86Test_VecToScalar() : X86TestCase("VecToScalar") {} + + static void add(TestApp& app) { + app.add(new X86Test_VecToScalar()); + } + + virtual void compile(x86::Compiler& cc) { + FuncNode* func = cc.addFunc(FuncSignature::build()); + + x86::Gp x = cc.newInt32("x"); + x86::Gp t = cc.newInt32("t"); + x86::Xmm v[kVecCount]; + + func->setArg(0, x); + + for (size_t i = 0; i < kVecCount; i++) { + v[i] = cc.newXmm("v%d", i); + if (i != 0) + cc.add(x, 1); + cc.movd(v[i], x); + } + + cc.xor_(x, x); + + for (size_t i = 0; i < kVecCount; i++) { + cc.movd(t, v[i]); + cc.add(x, t); + } + + cc.ret(x); + cc.endFunc(); + } + + virtual bool run(void* _func, String& result, String& expect) { + typedef uint32_t (*Func)(uint32_t); + Func func = ptr_as_func(_func); + + uint32_t resultRet = func(1); + uint32_t expectRet = 2080; // 1 + 2 + 3 + ... + 64 + + result.assignFormat("ret=%d", resultRet); + expect.assignFormat("ret=%d", expectRet); + + return result == expect; + } +}; + // x86::Compiler - X86Test_MiscLocalConstPool // ========================================== @@ -4075,7 +4198,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); x86::Gp v0 = cc.newInt32("v0"); x86::Gp v1 = cc.newInt32("v1"); @@ -4101,7 +4224,7 @@ public: result.assignFormat("ret=%d", resultRet); expect.assignFormat("ret=%d", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -4117,7 +4240,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); x86::Gp v0 = cc.newInt32("v0"); x86::Gp v1 = cc.newInt32("v1"); @@ -4143,7 +4266,7 @@ public: result.assignFormat("ret=%d", resultRet); expect.assignFormat("ret=%d", expectRet); - return resultRet == expectRet; + return result == expect; } }; @@ -4158,7 +4281,7 @@ struct X86Test_MiscMultiRet : public X86TestCase { } virtual void compile(x86::Compiler& cc) { - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); x86::Gp op = cc.newInt32("op"); x86::Gp a = cc.newInt32("a"); @@ -4234,7 +4357,7 @@ struct X86Test_MiscMultiRet : public X86TestCase { result.assignFormat("ret={%d %d %d %d}", r0, r1, r2, r3); expect.assignFormat("ret={%d %d %d %d}", e0, e1, e2, e3); - return result.eq(expect); + return result == expect; } }; @@ -4250,8 +4373,8 @@ public: } virtual void compile(x86::Compiler& cc) { - FuncNode* f1Node = cc.newFunc(FuncSignatureT(CallConvId::kHost)); - FuncNode* f2Node = cc.newFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* f1Node = cc.newFunc(FuncSignature::build()); + FuncNode* f2Node = cc.newFunc(FuncSignature::build()); { x86::Gp a = cc.newInt32("a"); @@ -4262,7 +4385,7 @@ public: f1Node->setArg(1, b); InvokeNode* invokeNode; - cc.invoke(&invokeNode, f2Node->label(), FuncSignatureT(CallConvId::kHost)); + cc.invoke(&invokeNode, f2Node->label(), FuncSignature::build()); invokeNode->setArg(0, a); invokeNode->setArg(1, b); invokeNode->setRet(0, a); @@ -4296,7 +4419,7 @@ public: result.assignFormat("ret=%d", resultRet); expect.assignFormat("ret=%d", expectRet); - return result.eq(expect); + return result == expect; } }; @@ -4321,7 +4444,7 @@ public: x86::Gp b = cc.newIntPtr("b"); Label tramp = cc.newLabel(); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kFastCall)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build(CallConvId::kFastCall)); funcNode->setArg(0, a); funcNode->setArg(1, b); @@ -4349,7 +4472,7 @@ public: result.assignFormat("ret={%d}", resultRet); expect.assignFormat("ret={%d}", expectRet); - return resultRet == expectRet; + return result == expect; } static void ASMJIT_FASTCALL handler() { longjmp(globalJmpBuf, 1); } @@ -4362,6 +4485,7 @@ void compiler_add_x86_tests(TestApp& app) { // Base tests. app.addT(); app.addT(); + app.addT(); app.addT(); // Jump tests. @@ -4408,6 +4532,9 @@ void compiler_add_x86_tests(TestApp& app) { app.addT(); app.addT(); + // Function arguments handling tests. + app.addT(); + // Function call tests. app.addT(); app.addT(); @@ -4439,6 +4566,7 @@ void compiler_add_x86_tests(TestApp& app) { app.addT(); // Miscellaneous tests. + app.addT(); app.addT(); app.addT(); app.addT(); diff --git a/deps/asmjit/test/asmjit_test_emitters.cpp b/deps/asmjit/test/asmjit_test_emitters.cpp index 7436bf5b..47fcaff3 100644 --- a/deps/asmjit/test/asmjit_test_emitters.cpp +++ b/deps/asmjit/test/asmjit_test_emitters.cpp @@ -5,8 +5,24 @@ #include -#if ASMJIT_ARCH_X86 && !defined(ASMJIT_NO_X86) && !defined(ASMJIT_NO_JIT) +static void printInfo() noexcept { + printf("AsmJit Emitters Test-Suite v%u.%u.%u\n", + unsigned((ASMJIT_LIBRARY_VERSION >> 16) ), + unsigned((ASMJIT_LIBRARY_VERSION >> 8) & 0xFF), + unsigned((ASMJIT_LIBRARY_VERSION ) & 0xFF)); +} + +#if !defined(ASMJIT_NO_JIT) && ( \ + (ASMJIT_ARCH_X86 != 0 && !defined(ASMJIT_NO_X86 )) || \ + (ASMJIT_ARCH_ARM == 64 && !defined(ASMJIT_NO_AARCH64)) ) + +#if ASMJIT_ARCH_X86 != 0 #include +#endif + +#if ASMJIT_ARCH_ARM == 64 +#include +#endif #include #include @@ -17,9 +33,13 @@ using namespace asmjit; // Signature of the generated function. typedef void (*SumIntsFunc)(int* dst, const int* a, const int* b); +// X86 Backend +// ----------- + +#if ASMJIT_ARCH_X86 != 0 // This function works with both x86::Assembler and x86::Builder. It shows how // `x86::Emitter` can be used to make your code more generic. -static void makeRawFunc(x86::Emitter* emitter) noexcept { +static void generateFuncWithEmitter(x86::Emitter* emitter) noexcept { // Decide which registers will be mapped to function arguments. Try changing // registers of `dst`, `src_a`, and `src_b` and see what happens in function's // prolog and epilog. @@ -34,13 +54,13 @@ static void makeRawFunc(x86::Emitter* emitter) noexcept { // Create and initialize `FuncDetail` and `FuncFrame`. FuncDetail func; - func.init(FuncSignatureT(CallConvId::kHost), emitter->environment()); + func.init(FuncSignature::build(), emitter->environment()); FuncFrame frame; frame.init(func); - // Make XMM0 and XMM1 dirty. VEC group includes XMM|YMM|ZMM registers. - frame.addDirtyRegs(x86::xmm0, x86::xmm1); + // Make or registers dirty. + frame.addDirtyRegs(vec0, vec1); FuncArgsAssignment args(&func); // Create arguments assignment context. args.assignAll(dst, src_a, src_b); // Assign our registers to arguments. @@ -63,14 +83,14 @@ static void makeRawFunc(x86::Emitter* emitter) noexcept { #ifndef ASMJIT_NO_COMPILER // This function works with x86::Compiler, provided for comparison. -static void makeCompiledFunc(x86::Compiler* cc) noexcept { +static void generateFuncWithCompiler(x86::Compiler* cc) noexcept { x86::Gp dst = cc->newIntPtr("dst"); x86::Gp src_a = cc->newIntPtr("src_a"); x86::Gp src_b = cc->newIntPtr("src_b"); x86::Xmm vec0 = cc->newXmm("vec0"); x86::Xmm vec1 = cc->newXmm("vec1"); - FuncNode* funcNode = cc->addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc->addFunc(FuncSignature::build()); funcNode->setArg(0, dst); funcNode->setArg(1, src_a); funcNode->setArg(2, src_b); @@ -83,6 +103,154 @@ static void makeCompiledFunc(x86::Compiler* cc) noexcept { } #endif +static Error generateFunc(CodeHolder& code, EmitterType emitterType) noexcept { + switch (emitterType) { + case EmitterType::kAssembler: { + printf("Using x86::Assembler:\n"); + x86::Assembler a(&code); + generateFuncWithEmitter(a.as()); + return kErrorOk; + } + +#ifndef ASMJIT_NO_BUILDER + case EmitterType::kBuilder: { + printf("Using x86::Builder:\n"); + x86::Builder cb(&code); + generateFuncWithEmitter(cb.as()); + + return cb.finalize(); + } +#endif + +#ifndef ASMJIT_NO_COMPILER + case EmitterType::kCompiler: { + printf("Using x86::Compiler:\n"); + x86::Compiler cc(&code); + generateFuncWithCompiler(&cc); + + return cc.finalize(); + } +#endif + + default: { + printf("** FAILURE: No emitter to use **\n"); + exit(1); + } + } +} +#endif + +// AArch64 Backend +// --------------- + +#if ASMJIT_ARCH_ARM == 64 +// This function works with both a64::Assembler and a64::Builder. It shows how +// `a64::Emitter` can be used to make your code more generic. +static void generateFuncWithEmitter(a64::Emitter* emitter) noexcept { + // Decide which registers will be mapped to function arguments. Try changing + // registers of `dst`, `src_a`, and `src_b` and see what happens in function's + // prolog and epilog. + a64::Gp dst = a64::x0; + a64::Gp src_a = a64::x1; + a64::Gp src_b = a64::x2; + + // Decide which vector registers to use. We use these to keep the code generic, + // you can switch to any other registers when needed. + a64::Vec vec0 = a64::v0; + a64::Vec vec1 = a64::v1; + a64::Vec vec2 = a64::v2; + + // Create and initialize `FuncDetail` and `FuncFrame`. + FuncDetail func; + func.init(FuncSignature::build(), emitter->environment()); + + FuncFrame frame; + frame.init(func); + + // Make XMM0 and XMM1 dirty. VEC group includes XMM|YMM|ZMM registers. + frame.addDirtyRegs(vec0, vec1, vec2); + + FuncArgsAssignment args(&func); // Create arguments assignment context. + args.assignAll(dst, src_a, src_b); // Assign our registers to arguments. + args.updateFuncFrame(frame); // Reflect our args in FuncFrame. + frame.finalize(); + + // Emit prolog and allocate arguments to registers. + emitter->emitProlog(frame); + emitter->emitArgsAssignment(frame, args); + + emitter->ld1(vec0.b16(), a64::ptr(src_a)); // Load 4 ints from [src_a] to vec0. + emitter->ld1(vec1.b16(), a64::ptr(src_b)); // Load 4 ints from [src_b] to vec1. + emitter->add(vec2.s4(), vec0.s4(), vec1.s4()); // Add 4 ints of vec0 and vec1 and store to vec2. + emitter->st1(vec2.b16(), a64::ptr(dst)); // Store the result (vec2) to [dst]. + + // Emit epilog and return. + emitter->emitEpilog(frame); +} + +#ifndef ASMJIT_NO_COMPILER +// This function works with x86::Compiler, provided for comparison. +static void generateFuncWithCompiler(a64::Compiler* cc) noexcept { + a64::Gp dst = cc->newIntPtr("dst"); + a64::Gp src_a = cc->newIntPtr("src_a"); + a64::Gp src_b = cc->newIntPtr("src_b"); + a64::Vec vec0 = cc->newVecQ("vec0"); + a64::Vec vec1 = cc->newVecQ("vec1"); + a64::Vec vec2 = cc->newVecQ("vec2"); + + FuncNode* funcNode = cc->addFunc(FuncSignature::build()); + funcNode->setArg(0, dst); + funcNode->setArg(1, src_a); + funcNode->setArg(2, src_b); + + cc->ld1(vec0.b16(), a64::ptr(src_a)); // Load 4 ints from [src_a] to vec0. + cc->ld1(vec1.b16(), a64::ptr(src_b)); // Load 4 ints from [src_b] to vec1. + cc->add(vec2.s4(), vec0.s4(), vec1.s4()); // Add 4 ints of vec0 and vec1 and store to vec2. + cc->st1(vec2.b16(), a64::ptr(dst)); // Store the result (vec2) to [dst]. + cc->endFunc(); +} +#endif + +static Error generateFunc(CodeHolder& code, EmitterType emitterType) noexcept { + switch (emitterType) { + case EmitterType::kAssembler: { + printf("Using a64::Assembler:\n"); + a64::Assembler a(&code); + generateFuncWithEmitter(a.as()); + return kErrorOk; + } + +#ifndef ASMJIT_NO_BUILDER + case EmitterType::kBuilder: { + printf("Using a64::Builder:\n"); + a64::Builder cb(&code); + generateFuncWithEmitter(cb.as()); + + return cb.finalize(); + } +#endif + +#ifndef ASMJIT_NO_COMPILER + case EmitterType::kCompiler: { + printf("Using a64::Compiler:\n"); + a64::Compiler cc(&code); + generateFuncWithCompiler(&cc); + + return cc.finalize(); + } +#endif + + default: { + printf("** FAILURE: No emitter to use **\n"); + exit(1); + } + } +} +#endif + +// Testing +// ------- + static uint32_t testFunc(JitRuntime& rt, EmitterType emitterType) noexcept { #ifndef ASMJIT_NO_LOGGING FileLogger logger(stdout); @@ -96,48 +264,10 @@ static uint32_t testFunc(JitRuntime& rt, EmitterType emitterType) noexcept { code.setLogger(&logger); #endif - Error err = kErrorOk; - switch (emitterType) { - case EmitterType::kNone: { - break; - } - - case EmitterType::kAssembler: { - printf("Using x86::Assembler:\n"); - x86::Assembler a(&code); - makeRawFunc(a.as()); - break; - } - -#ifndef ASMJIT_NO_BUILDER - case EmitterType::kBuilder: { - printf("Using x86::Builder:\n"); - x86::Builder cb(&code); - makeRawFunc(cb.as()); - - err = cb.finalize(); - if (err) { - printf("** FAILURE: x86::Builder::finalize() failed (%s) **\n", DebugUtils::errorAsString(err)); - return 1; - } - break; - } -#endif - -#ifndef ASMJIT_NO_COMPILER - case EmitterType::kCompiler: { - printf("Using x86::Compiler:\n"); - x86::Compiler cc(&code); - makeCompiledFunc(&cc); - - err = cc.finalize(); - if (err) { - printf("** FAILURE: x86::Compiler::finalize() failed (%s) **\n", DebugUtils::errorAsString(err)); - return 1; - } - break; - } -#endif + Error err = generateFunc(code, emitterType); + if (err) { + printf("** FAILURE: Failed to generate a function: %s **\n", DebugUtils::errorAsString(err)); + return 1; } // Add the code generated to the runtime. @@ -145,41 +275,38 @@ static uint32_t testFunc(JitRuntime& rt, EmitterType emitterType) noexcept { err = rt.add(&fn, &code); if (err) { - printf("** FAILURE: JitRuntime::add() failed (%s) **\n", DebugUtils::errorAsString(err)); + printf("** FAILURE: JitRuntime::add() failed: %s **\n", DebugUtils::errorAsString(err)); return 1; } // Execute the generated function. - int inA[4] = { 4, 3, 2, 1 }; - int inB[4] = { 1, 5, 2, 8 }; - int out[4]; + static const int inA[4] = { 4, 3, 2, 1 }; + static const int inB[4] = { 1, 5, 2, 8 }; + int out[4] {}; fn(out, inA, inB); // Should print {5 8 4 9}. printf("Result = { %d %d %d %d }\n\n", out[0], out[1], out[2], out[3]); rt.release(fn); - return !(out[0] == 5 && out[1] == 8 && out[2] == 4 && out[3] == 9); + return out[0] == 5 && out[1] == 8 && out[2] == 4 && out[3] == 9; } int main() { - printf("AsmJit Emitters Test-Suite v%u.%u.%u\n", - unsigned((ASMJIT_LIBRARY_VERSION >> 16) ), - unsigned((ASMJIT_LIBRARY_VERSION >> 8) & 0xFF), - unsigned((ASMJIT_LIBRARY_VERSION ) & 0xFF)); + printInfo(); printf("\n"); JitRuntime rt; unsigned nFailed = 0; - nFailed += testFunc(rt, EmitterType::kAssembler); + nFailed += !testFunc(rt, EmitterType::kAssembler); #ifndef ASMJIT_NO_BUILDER - nFailed += testFunc(rt, EmitterType::kBuilder); + nFailed += !testFunc(rt, EmitterType::kBuilder); #endif #ifndef ASMJIT_NO_COMPILER - nFailed += testFunc(rt, EmitterType::kCompiler); + nFailed += !testFunc(rt, EmitterType::kCompiler); #endif if (!nFailed) @@ -191,7 +318,8 @@ int main() { } #else int main() { - printf("AsmJit X86 Emitter Test is disabled on non-x86 hosts or when compiled with ASMJIT_NO_JIT option\n\n"); + printInfo(); + printf("\nThis test is currently disabled - no JIT or no support for the target architecture\n"); return 0; } #endif // ASMJIT_ARCH_X86 && !ASMJIT_NO_X86 && !ASMJIT_NO_JIT diff --git a/deps/asmjit/test/asmjit_test_execute.cpp b/deps/asmjit/test/asmjit_test_execute.cpp new file mode 100644 index 00000000..ce002dc5 --- /dev/null +++ b/deps/asmjit/test/asmjit_test_execute.cpp @@ -0,0 +1,103 @@ +// This file is part of AsmJit project +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#include + +static void printInfo() noexcept { + printf("AsmJit Execute Test-Suite v%u.%u.%u\n", + unsigned((ASMJIT_LIBRARY_VERSION >> 16) ), + unsigned((ASMJIT_LIBRARY_VERSION >> 8) & 0xFF), + unsigned((ASMJIT_LIBRARY_VERSION ) & 0xFF)); +} + +#if !defined(ASMJIT_NO_JIT) && ( \ + (ASMJIT_ARCH_X86 != 0 && !defined(ASMJIT_NO_X86 )) || \ + (ASMJIT_ARCH_ARM == 64 && !defined(ASMJIT_NO_AARCH64)) ) + +#if ASMJIT_ARCH_X86 != 0 +#include +#endif + +#if ASMJIT_ARCH_ARM == 64 +#include +#endif + +#include +#include +#include + +using namespace asmjit; + +// Signature of the generated function. +typedef void (*EmptyFunc)(void); + +// Generate Empty Function +// ----------------------- + +#if ASMJIT_ARCH_X86 != 0 +static void generateEmptyFunc(CodeHolder& code) noexcept { + x86::Assembler a(&code); + a.ret(); +} +#endif + +#if ASMJIT_ARCH_ARM == 64 +static void generateEmptyFunc(CodeHolder& code) noexcept { + a64::Assembler a(&code); + a.ret(a64::x30); +} +#endif + +// Testing +// ------- + +static void executeEmptyFunc(JitRuntime& rt) noexcept { + CodeHolder code; + code.init(rt.environment(), rt.cpuFeatures()); + + EmptyFunc fn; + + generateEmptyFunc(code); + Error err = rt.add(&fn, &code); + + if (err) { + printf("** FAILURE: JitRuntime::add() failed: %s **\n", DebugUtils::errorAsString(err)); + exit(1); + } + + fn(); + + rt.release(&fn); +} + +int main() { + printInfo(); + printf("\n"); + + { + printf("Trying to execute empty function with JitRuntime (default settings)\n"); + JitRuntime rt; + executeEmptyFunc(rt); + } + + if (VirtMem::hardenedRuntimeInfo().hasFlag(VirtMem::HardenedRuntimeFlags::kDualMapping)) { + printf("Trying to execute empty function with JitRuntime (dual-mapped)\n"); + JitAllocator::CreateParams params {}; + params.options |= JitAllocatorOptions::kUseDualMapping; + JitRuntime rt; + executeEmptyFunc(rt); + } + + // If we are here we were successful, otherwise the process would crash. + printf("** SUCCESS **\n"); + return 0; +} +#else +int main() { + printInfo(); + printf("\nThis test is currently disabled - no JIT or no support for the target architecture\n"); + return 0; +} +#endif // ASMJIT_ARCH_X86 && !ASMJIT_NO_X86 && !ASMJIT_NO_JIT diff --git a/deps/asmjit/test/asmjit_test_instinfo.cpp b/deps/asmjit/test/asmjit_test_instinfo.cpp index 3d51edca..466d8a55 100644 --- a/deps/asmjit/test/asmjit_test_instinfo.cpp +++ b/deps/asmjit/test/asmjit_test_instinfo.cpp @@ -13,6 +13,9 @@ using namespace asmjit; +namespace { + +#if !defined(ASMJIT_NO_X86) static char accessLetter(bool r, bool w) noexcept { return r && w ? 'X' : r ? 'R' : w ? 'W' : '_'; } @@ -140,6 +143,7 @@ static void printInfoExtra(Arch arch, InstId instId, InstOptions options, const Operand_ opArray[] = { std::forward(args)... }; printInfo(arch, inst, opArray, sizeof...(args)); } +#endif // !ASMJIT_NO_X86 static void testX86Arch() { #if !defined(ASMJIT_NO_X86) @@ -165,9 +169,11 @@ static void testX86Arch() { printInfoExtra(arch, Inst::kIdVaddpd, InstOptions::kNone, k1, zmm0, zmm1, zmm2); printInfoExtra(arch, Inst::kIdVaddpd, InstOptions::kX86_ZMask, k1, zmm0, zmm1, zmm2); -#endif +#endif // !ASMJIT_NO_X86 } +} // {anonymous} + int main() { printf("AsmJit Instruction Info Test-Suite v%u.%u.%u\n", unsigned((ASMJIT_LIBRARY_VERSION >> 16) ), diff --git a/deps/asmjit/test/asmjit_test_misc.h b/deps/asmjit/test/asmjit_test_misc.h index 0839d30a..6231971f 100644 --- a/deps/asmjit/test/asmjit_test_misc.h +++ b/deps/asmjit/test/asmjit_test_misc.h @@ -170,7 +170,7 @@ static void generateSseAlphaBlend(asmjit::BaseEmitter& emitter, bool emitPrologE if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT(CallConvId::kHost), cc.environment()); + func.init(FuncSignature::build(), cc.environment()); FuncFrame frame; frame.init(func); @@ -202,7 +202,7 @@ static void generateSseAlphaBlend(asmjit::BaseEmitter& emitter, bool emitPrologE if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT(CallConvId::kHost), cc.environment()); + func.init(FuncSignature::build(), cc.environment()); FuncFrame frame; frame.init(func); @@ -242,7 +242,7 @@ static void generateSseAlphaBlend(asmjit::BaseEmitter& emitter, bool emitPrologE Xmm v6 = cc.newXmm("v6"); Xmm v7 = cc.newXmm("v7"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignature::build()); funcNode->setArg(0, dst); funcNode->setArg(1, src); funcNode->setArg(2, i); diff --git a/deps/asmjit/test/asmjit_test_perf.cpp b/deps/asmjit/test/asmjit_test_perf.cpp index 20fbbf47..98353fd1 100644 --- a/deps/asmjit/test/asmjit_test_perf.cpp +++ b/deps/asmjit/test/asmjit_test_perf.cpp @@ -40,7 +40,7 @@ int main(int argc, char* argv[]) { printf(" --arch=x86 32-bit X86 architecture (X86)\n"); printf(" --arch=x64 64-bit X86 architecture (X86_64)\n"); #endif -#if !defined(ASMJIT_AARCH64) +#if !defined(ASMJIT_NO_AARCH64) printf(" --arch=aarch64 64-bit ARM architecture (AArch64)\n"); #endif printf("\n"); diff --git a/deps/asmjit/test/asmjit_test_perf_a64.cpp b/deps/asmjit/test/asmjit_test_perf_a64.cpp index 054959b5..36d23a42 100644 --- a/deps/asmjit/test/asmjit_test_perf_a64.cpp +++ b/deps/asmjit/test/asmjit_test_perf_a64.cpp @@ -582,7 +582,7 @@ static void generateGpSequence(BaseEmitter& emitter, bool emitPrologEpilog) { if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT(CallConvId::kHost), cc.environment()); + func.init(FuncSignature::build(), cc.environment()); FuncFrame frame; frame.init(func); @@ -608,7 +608,7 @@ static void generateGpSequence(BaseEmitter& emitter, bool emitPrologEpilog) { if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT(CallConvId::kHost), cc.environment()); + func.init(FuncSignature::build(), cc.environment()); FuncFrame frame; frame.init(func); @@ -633,7 +633,7 @@ static void generateGpSequence(BaseEmitter& emitter, bool emitPrologEpilog) { a64::Gp c = cc.newIntPtr("c"); a64::Gp d = cc.newIntPtr("d"); - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); generateGpSequenceInternal(cc, a, b, c, d); cc.endFunc(); } diff --git a/deps/asmjit/test/asmjit_test_perf_x86.cpp b/deps/asmjit/test/asmjit_test_perf_x86.cpp index 462a0b34..4ff74818 100644 --- a/deps/asmjit/test/asmjit_test_perf_x86.cpp +++ b/deps/asmjit/test/asmjit_test_perf_x86.cpp @@ -335,7 +335,7 @@ static void generateGpSequence(BaseEmitter& emitter, InstForm form, bool emitPro if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT(CallConvId::kHost), cc.environment()); + func.init(FuncSignature::build(), cc.environment()); FuncFrame frame; frame.init(func); @@ -361,7 +361,7 @@ static void generateGpSequence(BaseEmitter& emitter, InstForm form, bool emitPro if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT(CallConvId::kHost), cc.environment()); + func.init(FuncSignature::build(), cc.environment()); FuncFrame frame; frame.init(func); @@ -386,7 +386,7 @@ static void generateGpSequence(BaseEmitter& emitter, InstForm form, bool emitPro Gp c = cc.newIntPtr("c"); Gp d = cc.newIntPtr("d"); - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); generateGpSequenceInternal(cc, form, a, b, c, d); cc.endFunc(); } @@ -927,7 +927,7 @@ static void generateSseSequence(BaseEmitter& emitter, InstForm form, bool emitPr if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT(CallConvId::kHost), cc.environment()); + func.init(FuncSignature::build(), cc.environment()); FuncFrame frame; frame.init(func); @@ -948,7 +948,7 @@ static void generateSseSequence(BaseEmitter& emitter, InstForm form, bool emitPr if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT(CallConvId::kHost), cc.environment()); + func.init(FuncSignature::build(), cc.environment()); FuncFrame frame; frame.init(func); @@ -974,7 +974,7 @@ static void generateSseSequence(BaseEmitter& emitter, InstForm form, bool emitPr Xmm c = cc.newXmm("c"); Xmm d = cc.newXmm("d"); - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); generateSseSequenceInternal(cc, form, gp, a, b, c, d); cc.endFunc(); } @@ -2134,7 +2134,7 @@ static void generateAvxSequence(BaseEmitter& emitter, InstForm form, bool emitPr if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT(CallConvId::kHost), cc.environment()); + func.init(FuncSignature::build(), cc.environment()); FuncFrame frame; frame.init(func); @@ -2155,7 +2155,7 @@ static void generateAvxSequence(BaseEmitter& emitter, InstForm form, bool emitPr if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT(CallConvId::kHost), cc.environment()); + func.init(FuncSignature::build(), cc.environment()); FuncFrame frame; frame.init(func); @@ -2181,7 +2181,7 @@ static void generateAvxSequence(BaseEmitter& emitter, InstForm form, bool emitPr Ymm c = cc.newYmm("c"); Ymm d = cc.newYmm("d"); - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); generateAvxSequenceInternal(cc, form, gp, a, b, c, d); cc.endFunc(); } @@ -4928,7 +4928,7 @@ static void generateAvx512Sequence(BaseEmitter& emitter, InstForm form, bool emi if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT(CallConvId::kHost), cc.environment()); + func.init(FuncSignature::build(), cc.environment()); FuncFrame frame; frame.init(func); @@ -4949,7 +4949,7 @@ static void generateAvx512Sequence(BaseEmitter& emitter, InstForm form, bool emi if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT(CallConvId::kHost), cc.environment()); + func.init(FuncSignature::build(), cc.environment()); FuncFrame frame; frame.init(func); @@ -4979,7 +4979,7 @@ static void generateAvx512Sequence(BaseEmitter& emitter, InstForm form, bool emi KReg kB = cc.newKq("kB"); KReg kC = cc.newKq("kC"); - cc.addFunc(FuncSignatureT(CallConvId::kHost)); + cc.addFunc(FuncSignature::build()); generateAvx512SequenceInternal(cc, form, gp, kA, kB, kC, vecA, vecB, vecC, vecD); cc.endFunc(); } diff --git a/deps/asmjit/test/asmjit_test_unit.cpp b/deps/asmjit/test/asmjit_test_unit.cpp index 5658ebc1..86d1f1a9 100644 --- a/deps/asmjit/test/asmjit_test_unit.cpp +++ b/deps/asmjit/test/asmjit_test_unit.cpp @@ -109,7 +109,8 @@ static void dumpSizeOf(void) noexcept { DUMP_TYPE(BaseBuilder); DUMP_TYPE(BaseNode); DUMP_TYPE(InstNode); - DUMP_TYPE(InstExNode); + DUMP_TYPE(InstNodeWithOperands); + DUMP_TYPE(InstNodeWithOperands); DUMP_TYPE(AlignNode); DUMP_TYPE(LabelNode); DUMP_TYPE(EmbedDataNode); diff --git a/deps/asmjit/test/asmjit_test_x86_sections.cpp b/deps/asmjit/test/asmjit_test_x86_sections.cpp index 31a88ab1..df763224 100644 --- a/deps/asmjit/test/asmjit_test_x86_sections.cpp +++ b/deps/asmjit/test/asmjit_test_x86_sections.cpp @@ -70,7 +70,7 @@ int main() { Label data = a.newLabel(); FuncDetail func; - func.init(FuncSignatureT(CallConvId::kHost), code.environment()); + func.init(FuncSignature::build(), code.environment()); FuncFrame frame; frame.init(func); diff --git a/deps/asmjit/test/asmjitutils.h b/deps/asmjit/test/asmjitutils.h index 525227e3..28880153 100644 --- a/deps/asmjit/test/asmjitutils.h +++ b/deps/asmjit/test/asmjitutils.h @@ -8,8 +8,10 @@ #include +namespace { + ASMJIT_MAYBE_UNUSED -static const char* asmjitArchAsString(asmjit::Arch arch) noexcept { +static inline const char* asmjitArchAsString(asmjit::Arch arch) noexcept { switch (arch) { case asmjit::Arch::kX86 : return "X86"; case asmjit::Arch::kX64 : return "X64"; @@ -37,7 +39,7 @@ static const char* asmjitArchAsString(asmjit::Arch arch) noexcept { } ASMJIT_MAYBE_UNUSED -static void printIndented(const char* str, size_t indent) noexcept { +static inline void printIndented(const char* str, size_t indent) noexcept { const char* start = str; while (*str) { if (*str == '\n') { @@ -53,4 +55,6 @@ static void printIndented(const char* str, size_t indent) noexcept { printf("%*s%.*s\n", int(indent), "", int(size), start); } +} // {anonymous} + #endif // ASMJITUTILS_H_INCLUDED diff --git a/deps/asmjit/tools/configure-sanitizers.sh b/deps/asmjit/tools/configure-sanitizers.sh index a9f64969..d35b9a4c 100644 --- a/deps/asmjit/tools/configure-sanitizers.sh +++ b/deps/asmjit/tools/configure-sanitizers.sh @@ -11,3 +11,7 @@ echo "" echo "== [Configuring Build - Release_UBSAN] ==" eval cmake "${CURRENT_DIR}/.." -B "${BUILD_DIR}/Release_UBSAN" ${BUILD_OPTIONS} -DCMAKE_BUILD_TYPE=Release -DASMJIT_SANITIZE=undefined echo "" + +echo "== [Configuring Build - Release_MSAN] ==" +eval cmake "${CURRENT_DIR}/.." -B "${BUILD_DIR}/Release_MSAN" ${BUILD_OPTIONS} -DCMAKE_BUILD_TYPE=Release -DASMJIT_SANITIZE=memory +echo "" diff --git a/deps/asmjit/tools/gencommons.js b/deps/asmjit/tools/gencommons.js deleted file mode 100644 index 569fbf69..00000000 --- a/deps/asmjit/tools/gencommons.js +++ /dev/null @@ -1,23 +0,0 @@ -// This file is part of AsmJit project -// -// See asmjit.h or LICENSE.md for license and copyright information -// SPDX-License-Identifier: Zlib - -let VERBOSE = false; - -function DEBUG(msg) { - if (VERBOSE) - console.log(msg); -} -exports.DEBUG = DEBUG; - -function WARN(msg) { - console.log(msg); -} -exports.WARN = WARN; - -function FATAL(msg) { - console.log(`FATAL ERROR: ${msg}`); - throw new Error(msg); -} -exports.FATAL = FATAL; diff --git a/deps/asmjit/tools/generator-commons.js b/deps/asmjit/tools/generator-commons.js new file mode 100644 index 00000000..eb3a0721 --- /dev/null +++ b/deps/asmjit/tools/generator-commons.js @@ -0,0 +1,592 @@ +// This file is part of AsmJit project +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +const hasOwn = Object.prototype.hasOwnProperty; +function nop(x) { return x; } + +// Generator - Constants +// --------------------- + +const kIndent = " "; +exports.kIndent = kIndent; + +const kLineWidth = 120; + +// Generator - Logging +// ------------------- + +let VERBOSE = false; + +function setDebugVerbosity(value) { + VERBOSE = value; +} +exports.setDebugVerbosity = setDebugVerbosity; + +function DEBUG(msg) { + if (VERBOSE) + console.log(msg); +} +exports.DEBUG = DEBUG; + +function WARN(msg) { + console.log(msg); +} +exports.WARN = WARN; + +function FATAL(msg) { + console.log(`FATAL: ${msg}`); + throw new Error(msg); +} +exports.FATAL = FATAL; + +// Generator - Object Utilities +// ---------------------------- + +class ObjectUtils { + static clone(map) { + return Object.assign(Object.create(null), map); + } + + static merge(a, b) { + if (a === b) + return a; + + for (let k in b) { + let av = a[k]; + let bv = b[k]; + + if (typeof av === "object" && typeof bv === "object") + ObjectUtils.merge(av, bv); + else + a[k] = bv; + } + + return a; + } + + static equals(a, b) { + if (a === b) + return true; + + if (typeof a !== typeof b) + return false; + + if (typeof a !== "object") + return a === b; + + if (Array.isArray(a) || Array.isArray(b)) { + if (Array.isArray(a) !== Array.isArray(b)) + return false; + + const len = a.length; + if (b.length !== len) + return false; + + for (let i = 0; i < len; i++) + if (!ObjectUtils.equals(a[i], b[i])) + return false; + } + else { + if (a === null || b === null) + return a === b; + + for (let k in a) + if (!hasOwn.call(b, k) || !ObjectUtils.equals(a[k], b[k])) + return false; + + for (let k in b) + if (!hasOwn.call(a, k)) + return false; + } + + return true; + } + + static equalsExcept(a, b, except) { + if (a === b) + return true; + + if (typeof a !== "object" || typeof b !== "object" || Array.isArray(a) || Array.isArray(b)) + return ObjectUtils.equals(a, b); + + for (let k in a) + if (!hasOwn.call(except, k) && (!hasOwn.call(b, k) || !ObjectUtils.equals(a[k], b[k]))) + return false; + + for (let k in b) + if (!hasOwn.call(except, k) && !hasOwn.call(a, k)) + return false; + + return true; + } + + static findKey(map, keys) { + for (let key in keys) + if (hasOwn.call(map, key)) + return key; + return undefined; + } + + static hasAny(map, keys) { + for (let key in keys) + if (hasOwn.call(map, key)) + return true; + return false; + } + + static and(a, b) { + const out = Object.create(null); + for (let k in a) + if (hasOwn.call(b, k)) + out[k] = true; + return out; + } + + static xor(a, b) { + const out = Object.create(null); + for (let k in a) if (!hasOwn.call(b, k)) out[k] = true; + for (let k in b) if (!hasOwn.call(a, k)) out[k] = true; + return out; + } +} +exports.ObjectUtils = ObjectUtils; + +// Generator - Array Utilities +// --------------------------- + +class ArrayUtils { + static min(arr, fn) { + if (!arr.length) + return null; + + if (!fn) + fn = nop; + + let v = fn(arr[0]); + for (let i = 1; i < arr.length; i++) + v = Math.min(v, fn(arr[i])); + return v; + } + + static max(arr, fn) { + if (!arr.length) + return null; + + if (!fn) + fn = nop; + + let v = fn(arr[0]); + for (let i = 1; i < arr.length; i++) + v = Math.max(v, fn(arr[i])); + return v; + } + + static sorted(obj, cmp) { + const out = Array.isArray(obj) ? obj.slice() : Object.getOwnPropertyNames(obj); + out.sort(cmp); + return out; + } + + static deepIndexOf(arr, what) { + for (let i = 0; i < arr.length; i++) + if (ObjectUtils.equals(arr[i], what)) + return i; + return -1; + } + + static toDict(arr, value) { + if (value === undefined) + value = true; + + const out = Object.create(null); + for (let i = 0; i < arr.length; i++) + out[arr[i]] = value; + return out; + } +} +exports.ArrayUtils = ArrayUtils; + + +// Generator - String Utilities +// ---------------------------- + +class StringUtils { + static asString(x) { return String(x); } + + static countOf(s, pattern) { + if (!pattern) + FATAL(`Pattern cannot be empty`); + + let n = 0; + let pos = 0; + + while ((pos = s.indexOf(pattern, pos)) >= 0) { + n++; + pos += pattern.length; + } + + return n; + } + + static trimLeft(s) { return s.replace(/^\s+/, ""); } + static trimRight(s) { return s.replace(/\s+$/, ""); } + + static upFirst(s) { + if (!s) return ""; + return s[0].toUpperCase() + s.substr(1); + } + + static decToHex(n, nPad) { + let hex = Number(n < 0 ? 0x100000000 + n : n).toString(16); + while (nPad > hex.length) + hex = "0" + hex; + return "0x" + hex.toUpperCase(); + } + + static format(array, indent, showIndex, mapFn) { + if (!mapFn) + mapFn = StringUtils.asString; + + let s = ""; + let threshold = 80; + + if (showIndex === -1) + s += indent; + + for (let i = 0; i < array.length; i++) { + const item = array[i]; + const last = i === array.length - 1; + + if (showIndex !== -1) + s += indent; + + s += mapFn(item); + if (showIndex > 0) { + s += `${last ? " " : ","} // #${i}`; + if (typeof array.refCountOf === "function") + s += ` [ref=${array.refCountOf(item)}x]`; + } + else if (!last) { + s += ","; + } + + if (showIndex === -1) { + if (s.length >= threshold - 1 && !last) { + s += "\n" + indent; + threshold += 80; + } + else { + if (!last) s += " "; + } + } + else { + if (!last) s += "\n"; + } + } + + return s; + } + + static makeCxxArray(array, code, indent) { + if (typeof indent !== "string") + indent = kIndent; + + return `${code} = {\n${indent}` + array.join(`,\n${indent}`) + `\n};\n`; + } + + static makeCxxArrayWithComment(array, code, indent) { + if (typeof indent !== "string") + indent = kIndent; + + let s = ""; + for (let i = 0; i < array.length; i++) { + const last = i === array.length - 1; + s += indent + array[i].data + + (last ? " // " : ", // ") + (array[i].refs ? "#" + String(i) : "").padEnd(5) + array[i].comment + "\n"; + } + return `${code} = {\n${s}};\n`; + } + + static formatCppStruct(...args) { + return "{ " + args.join(", ") + " }"; + } + + static formatCppFlags(obj, fn, none) { + if (none == null) + none = "0"; + + if (!fn) + fn = nop; + + let out = ""; + for (let k in obj) { + if (obj[k]) + out += (out ? " | " : "") + fn(k); + } + return out ? out : none; + } + + static formatRecords(array, indent, fn) { + if (typeof indent !== "string") + indent = kIndent; + + if (!fn) + fn = nop; + + let s = ""; + let line = ""; + for (let i = 0; i < array.length; i++) { + const item = fn(array[i]); + const combined = line ? line + ", " + item : item; + + if (combined.length >= kLineWidth) { + s = s ? s + ",\n" + line : line; + line = item; + } + else { + line = combined; + } + } + + if (line) { + s = s ? s + ",\n" + line : line; + } + + return StringUtils.indent(s, indent); + } + + static disclaimer(s) { + return "// ------------------- Automatically generated, do not edit -------------------\n" + + s + + "// ----------------------------------------------------------------------------\n"; + } + + static indent(s, indentation) { + if (typeof indentation === "number") + indentation = " ".repeat(indentation); + + let lines = s.split(/\r?\n/g); + if (indentation) { + for (let i = 0; i < lines.length; i++) { + let line = lines[i]; + if (line) + lines[i] = indentation + line; + } + } + + return lines.join("\n"); + } + + static extract(s, start, end) { + const iStart = s.indexOf(start); + const iEnd = s.indexOf(end); + + if (iStart === -1) + FATAL(`StringUtils.extract(): Couldn't locate start mark '${start}'`); + + if (iEnd === -1) + FATAL(`StringUtils.extract(): Couldn't locate end mark '${end}'`); + + return s.substring(iStart + start.length, iEnd).trim(); + } + + static inject(s, start, end, code) { + let iStart = s.indexOf(start); + let iEnd = s.indexOf(end); + + if (iStart === -1) + FATAL(`StringUtils.inject(): Couldn't locate start mark '${start}'`); + + if (iEnd === -1) + FATAL(`StringUtils.inject(): Couldn't locate end mark '${end}'`); + + let nIndent = 0; + while (iStart > 0 && s[iStart-1] === " ") { + iStart--; + nIndent++; + } + + if (nIndent) { + const indentation = " ".repeat(nIndent); + code = StringUtils.indent(code, indentation) + indentation; + } + + return s.substr(0, iStart + start.length + nIndent) + code + s.substr(iEnd); + } + + static makePriorityCompare(priorityArray) { + const map = Object.create(null); + priorityArray.forEach((str, index) => { map[str] = index; }); + + return function(a, b) { + const ax = hasOwn.call(map, a) ? map[a] : Infinity; + const bx = hasOwn.call(map, b) ? map[b] : Infinity; + return ax != bx ? ax - bx : a < b ? -1 : a > b ? 1 : 0; + } + } +} +exports.StringUtils = StringUtils; + +// Generator - Indexed Array +// ========================= + +// IndexedArray is an Array replacement that allows to index each item inserted to it. Its main purpose +// is to avoid data duplication, if an item passed to `addIndexed()` is already within the Array then +// it's not inserted and the existing index is returned instead. +function IndexedArray_keyOf(item) { + return typeof item === "string" ? item : JSON.stringify(item); +} + +class IndexedArray extends Array { + constructor() { + super(); + this._index = Object.create(null); + } + + refCountOf(item) { + const key = IndexedArray_keyOf(item); + const idx = this._index[key]; + + return idx !== undefined ? idx.refCount : 0; + } + + addIndexed(item) { + const key = IndexedArray_keyOf(item); + let idx = this._index[key]; + + if (idx !== undefined) { + idx.refCount++; + return idx.data; + } + + idx = this.length; + this._index[key] = { + data: idx, + refCount: 1 + }; + this.push(item); + return idx; + } +} +exports.IndexedArray = IndexedArray; + +// Generator - Indexed String +// ========================== + +// IndexedString is mostly used to merge all instruction names into a single string with external +// index. It's designed mostly for generating C++ tables. Consider the following cases in C++: +// +// a) static const char* const* instNames = { "add", "mov", "vpunpcklbw" }; +// +// b) static const char instNames[] = { "add\0" "mov\0" "vpunpcklbw\0" }; +// static const uint16_t instNameIndex[] = { 0, 4, 8 }; +// +// The latter (b) has an advantage that it doesn't have to be relocated by the linker, which saves +// a lot of space in the resulting binary and a lot of CPU cycles (and memory) when the linker loads +// it. AsmJit supports thousands of instructions so each optimization like this makes it smaller and +// faster to load. +class IndexedString { + constructor() { + this.map = Object.create(null); + this.array = []; + this.size = -1; + } + + add(s) { + this.map[s] = -1; + } + + index() { + const map = this.map; + const array = this.array; + const partialMap = Object.create(null); + + let k, kp; + let i, len; + + // Create a map that will contain all keys and partial keys. + for (k in map) { + if (!k) { + partialMap[k] = k; + } + else { + for (i = 0, len = k.length; i < len; i++) { + kp = k.substr(i); + if (!hasOwn.call(partialMap, kp) || partialMap[kp].length < len) + partialMap[kp] = k; + } + } + } + + // Create an array that will only contain keys that are needed. + for (k in map) + if (partialMap[k] === k) + array.push(k); + array.sort(); + + // Create valid offsets to the `array`. + let offMap = Object.create(null); + let offset = 0; + + for (i = 0, len = array.length; i < len; i++) { + k = array[i]; + + offMap[k] = offset; + offset += k.length + 1; + } + this.size = offset; + + // Assign valid offsets to `map`. + for (kp in map) { + k = partialMap[kp]; + map[kp] = offMap[k] + k.length - kp.length; + } + } + + format(indent, justify) { + if (this.size === -1) + FATAL(`IndexedString.format(): not indexed yet, call index()`); + + const array = this.array; + if (!justify) justify = 0; + + let i; + let s = ""; + let line = ""; + + for (i = 0; i < array.length; i++) { + const item = "\"" + array[i] + ((i !== array.length - 1) ? "\\0\"" : "\";"); + const newl = line + (line ? " " : indent) + item; + + if (newl.length <= justify) { + line = newl; + continue; + } + else { + s += line + "\n"; + line = indent + item; + } + } + + return s + line; + } + + getSize() { + if (this.size === -1) + FATAL(`IndexedString.getSize(): Not indexed yet, call index()`); + return this.size; + } + + getIndex(k) { + if (this.size === -1) + FATAL(`IndexedString.getIndex(): Not indexed yet, call index()`); + + if (!hasOwn.call(this.map, k)) + FATAL(`IndexedString.getIndex(): Key '${k}' not found.`); + + return this.map[k]; + } +} +exports.IndexedString = IndexedString; diff --git a/deps/asmjit/tools/gencxx.js b/deps/asmjit/tools/generator-cxx.js similarity index 99% rename from deps/asmjit/tools/gencxx.js rename to deps/asmjit/tools/generator-cxx.js index f1a2b576..b1b1d946 100644 --- a/deps/asmjit/tools/gencxx.js +++ b/deps/asmjit/tools/generator-cxx.js @@ -4,7 +4,7 @@ // SPDX-License-Identifier: Zlib // C++ code generation helpers. -const commons = require("./gencommons.js"); +const commons = require("./generator-commons.js"); const FATAL = commons.FATAL; // Utilities to convert primitives to C++ code. diff --git a/deps/asmjit/tools/tablegen-a64.js b/deps/asmjit/tools/tablegen-a64.js index d24369ec..1466fc63 100644 --- a/deps/asmjit/tools/tablegen-a64.js +++ b/deps/asmjit/tools/tablegen-a64.js @@ -6,13 +6,13 @@ "use strict"; const core = require("./tablegen.js"); -const commons = require("./gencommons.js"); +const commons = require("./generator-commons.js"); const hasOwn = Object.prototype.hasOwnProperty; const asmdb = core.asmdb; -const kIndent = core.kIndent; -const IndexedArray = core.IndexedArray; -const StringUtils = core.StringUtils; +const kIndent = commons.kIndent; +const IndexedArray = commons.IndexedArray; +const StringUtils = commons.StringUtils; const FATAL = commons.FATAL; @@ -20,13 +20,10 @@ const FATAL = commons.FATAL; // [ArmDB] // ============================================================================ -// Create ARM ISA. -const isa = new asmdb.arm.ISA(); - -// ============================================================================ -// [tablegen.arm.GenUtils] -// ============================================================================ +// Create AArch64 ISA. +const isa = new asmdb.aarch64.ISA(); +/* class GenUtils { // Get a list of instructions based on `name` and optional `mode`. static query(name, mode) { @@ -71,6 +68,7 @@ class GenUtils { return arr; } } +*/ // ============================================================================ // [tablegen.arm.ArmTableGen] diff --git a/deps/asmjit/tools/tablegen-x86.js b/deps/asmjit/tools/tablegen-x86.js index 89872fc9..377a7104 100644 --- a/deps/asmjit/tools/tablegen-x86.js +++ b/deps/asmjit/tools/tablegen-x86.js @@ -8,25 +8,22 @@ const fs = require("fs"); const path = require("path"); -const cxx = require("./gencxx.js"); -const commons = require("./gencommons.js"); +const commons = require("./generator-commons.js"); +const cxx = require("./generator-cxx.js"); const core = require("./tablegen.js"); const asmdb = core.asmdb; -const kIndent = core.kIndent; - -const Lang = core.Lang; -const CxxUtils = core.CxxUtils; -const MapUtils = core.MapUtils; -const ArrayUtils = core.ArrayUtils; -const StringUtils = core.StringUtils; -const IndexedArray = core.IndexedArray; - -const hasOwn = Object.prototype.hasOwnProperty; -const disclaimer = StringUtils.disclaimer; const DEBUG = commons.DEBUG; const FATAL = commons.FATAL; +const kIndent = commons.kIndent; +const ArrayUtils = commons.ArrayUtils; +const IndexedArray = commons.IndexedArray; +const ObjectUtils = commons.ObjectUtils; +const StringUtils = commons.StringUtils; + +const hasOwn = Object.prototype.hasOwnProperty; +const disclaimer = StringUtils.disclaimer; const decToHex = StringUtils.decToHex; @@ -37,10 +34,6 @@ function readJSON(fileName) { const x86data = readJSON(path.join(__dirname, "..", "db", asmdb.x86.dbName)); -// TODO: Fix these regressions: -// cvtsi2ss -// enqcmd - // ============================================================================ // [tablegen.x86.x86isa] // ============================================================================ @@ -559,7 +552,7 @@ class X86TableGen extends core.TableGen { // -------------------------------------------------------------------------- printMissing() { - const ignored = MapUtils.arrayToMap([ + const ignored = ArrayUtils.toDict([ "cmpsb", "cmpsw", "cmpsd", "cmpsq", "lodsb", "lodsw", "lodsd", "lodsq", "movsb", "movsw", "movsd", "movsq", @@ -994,8 +987,8 @@ class AltOpcodeTable extends core.Task { // [tablegen.x86.InstSignatureTable] // ============================================================================ -const RegOp = MapUtils.arrayToMap(["al", "ah", "ax", "eax", "rax", "cl", "r8lo", "r8hi", "r16", "r32", "r64", "xmm", "ymm", "zmm", "mm", "k", "sreg", "creg", "dreg", "st", "bnd"]); -const MemOp = MapUtils.arrayToMap(["m8", "m16", "m32", "m48", "m64", "m80", "m128", "m256", "m512", "m1024"]); +const RegOp = ArrayUtils.toDict(["al", "ah", "ax", "eax", "rax", "cl", "r8lo", "r8hi", "r16", "r32", "r64", "xmm", "ymm", "zmm", "mm", "k", "sreg", "creg", "dreg", "st", "bnd"]); +const MemOp = ArrayUtils.toDict(["m8", "m16", "m32", "m48", "m64", "m80", "m128", "m256", "m512", "m1024"]); const cmpOp = StringUtils.makePriorityCompare([ "RegGpbLo", "RegGpbHi", "RegGpw", "RegGpd", "RegGpq", "RegXmm", "RegYmm", "RegZmm", "RegMm", "RegKReg", "RegSReg", "RegCReg", "RegDReg", "RegSt", "RegBnd", "RegTmm", @@ -1034,11 +1027,11 @@ class OSignature { } equals(other) { - return MapUtils.equals(this.flags, other.flags); + return ObjectUtils.equals(this.flags, other.flags); } xor(other) { - const result = MapUtils.xor(this.flags, other.flags); + const result = ObjectUtils.xor(this.flags, other.flags); return Object.getOwnPropertyNames(result).length === 0 ? null : result; } @@ -1286,7 +1279,7 @@ class SignatureArray extends Array { for (var i = 0; i < inst.length; i++) { const op = inst[i]; if (regOps & (1 << i)) - s += "{" + ArrayUtils.sorted(MapUtils.and(op.flags, RegOp)).join("|") + "}"; + s += "{" + ArrayUtils.sorted(ObjectUtils.and(op.flags, RegOp)).join("|") + "}"; } return s || "?"; } @@ -1305,7 +1298,7 @@ class SignatureArray extends Array { // Check if this instruction signature has a memory operand of explicit size. for (i = 0; i < len; i++) { const aOp = aInst[i]; - const mem = MapUtils.firstOf(aOp.flags, MemOp); + const mem = ObjectUtils.findKey(aOp.flags, MemOp); if (mem) { // Stop if the memory operand has implicit-size or if there is more than one. @@ -1318,7 +1311,7 @@ class SignatureArray extends Array { memPos = i; } } - else if (MapUtils.anyOf(aOp.flags, RegOp)) { + else if (ObjectUtils.hasAny(aOp.flags, RegOp)) { // Doesn't consider 'r/m' as we already checked 'm'. regOps |= (1 << i); } @@ -1343,7 +1336,7 @@ class SignatureArray extends Array { for (i = 0; i < len; i++) { if (i === memPos) continue; - const reg = MapUtils.anyOf(bInst[i].flags, RegOp); + const reg = ObjectUtils.hasAny(bInst[i].flags, RegOp); if (regOps & (1 << i)) hasMatch &= reg; else if (reg) @@ -1354,7 +1347,7 @@ class SignatureArray extends Array { const bOp = bInst[memPos]; if (bOp.flags.mem) continue; - const mem = MapUtils.firstOf(bOp.flags, MemOp); + const mem = ObjectUtils.findKey(bOp.flags, MemOp); if (mem === memOp) { sameSizeSet.push(bInst); } @@ -1816,7 +1809,7 @@ class AdditionalInfoTable extends core.Task { break; } - const instFlagsIndex = instFlagsTable.addIndexed("InstRWFlags(" + CxxUtils.flags(instFlags, (f) => { return `FLAG(${f})`; }, "FLAG(None)") + ")"); + const instFlagsIndex = instFlagsTable.addIndexed("InstRWFlags(" + StringUtils.formatCppFlags(instFlags, (f) => { return `FLAG(${f})`; }, "FLAG(None)") + ")"); const rwInfoIndex = rwInfoTable.addIndexed(`{ ${rData}, ${wData} }`); inst.additionalInfoIndex = additionaInfoTable.addIndexed(`{ ${instFlagsIndex}, ${rwInfoIndex}, { ${features} } }`); @@ -1901,7 +1894,7 @@ class AdditionalInfoTable extends core.Task { // [tablegen.x86.InstRWInfoTable] // ============================================================================ -const NOT_MEM_AMBIGUOUS = MapUtils.arrayToMap([ +const NOT_MEM_AMBIGUOUS = ArrayUtils.toDict([ "call", "movq" ]); @@ -1974,20 +1967,20 @@ class InstRWInfoTable extends core.Task { run() { const insts = this.ctx.insts; - const noRmInfo = CxxUtils.struct( + const noRmInfo = StringUtils.formatCppStruct( "InstDB::RWInfoRm::kCategory" + "None".padEnd(10), StringUtils.decToHex(0, 2), String(0).padEnd(2), - CxxUtils.flags({}), + StringUtils.formatCppFlags({}), "0" ); - const noOpInfo = CxxUtils.struct( + const noOpInfo = StringUtils.formatCppStruct( "0x0000000000000000u", "0x0000000000000000u", "0xFF", "0", - CxxUtils.struct(0), + StringUtils.formatCppStruct(0), "OpRWFlags::kNone" ); @@ -2026,7 +2019,7 @@ class InstRWInfoTable extends core.Task { if (opAcc === "R") flags.Read = true; if (opAcc === "W") flags.Write = true; if (opAcc === "X") flags.RW = true; - Lang.merge(flags, op.flags); + ObjectUtils.merge(flags, op.flags); const rIndex = opAcc === "X" || opAcc === "R" ? op.index : -1; const rWidth = opAcc === "X" || opAcc === "R" ? op.width : -1; @@ -2035,23 +2028,23 @@ class InstRWInfoTable extends core.Task { const consecutiveLeadCount = op.clc; - const opData = CxxUtils.struct( + const opData = StringUtils.formatCppStruct( this.byteMaskFromBitRanges([{ start: rIndex, end: rIndex + rWidth - 1 }]) + "u", this.byteMaskFromBitRanges([{ start: wIndex, end: wIndex + wWidth - 1 }]) + "u", StringUtils.decToHex(op.fixed === -1 ? 0xFF : op.fixed, 2), String(consecutiveLeadCount), - CxxUtils.struct(0), - CxxUtils.flags(flags, function(flag) { return "OpRWFlags::k" + flag; }, "OpRWFlags::kNone") + StringUtils.formatCppStruct(0), + StringUtils.formatCppFlags(flags, function(flag) { return "OpRWFlags::k" + flag; }, "OpRWFlags::kNone") ); rwOpsIndex.push(this.opInfoTable.addIndexed(opData)); } - const rmData = CxxUtils.struct( + const rmData = StringUtils.formatCppStruct( "InstDB::RWInfoRm::kCategory" + rmInfo.category.padEnd(10), StringUtils.decToHex(rmInfo.rmIndexes, 2), String(Math.max(rmInfo.memFixed, 0)).padEnd(2), - CxxUtils.flags({ + StringUtils.formatCppFlags({ "InstDB::RWInfoRm::kFlagAmbiguous": Boolean(rmInfo.memAmbiguous), "InstDB::RWInfoRm::kFlagMovssMovsd": Boolean(inst.name === "movss" || inst.name === "movsd"), "InstDB::RWInfoRm::kFlagPextrw": Boolean(inst.name === "pextrw"), @@ -2060,10 +2053,10 @@ class InstRWInfoTable extends core.Task { rmInfo.memExtension === "None" ? "0" : "uint32_t(CpuFeatures::X86::k" + rmInfo.memExtension + ")" ); - const rwData = CxxUtils.struct( + const rwData = StringUtils.formatCppStruct( "InstDB::RWInfo::kCategory" + rwInfo.category.padEnd(10), String(this.rmInfoTable.addIndexed(rmData)).padEnd(2), - CxxUtils.struct(...(rwOpsIndex.map(function(item) { return String(item).padEnd(2); }))) + StringUtils.formatCppStruct(...(rwOpsIndex.map(function(item) { return String(item).padEnd(2); }))) ); if (i == 0) @@ -2218,12 +2211,12 @@ class InstRWInfoTable extends core.Task { rwOps[j] = d; } else { - if (!Lang.deepEqExcept(rwOps[j], d, { "fixed": true, "flags": true })) + if (!ObjectUtils.equalsExcept(rwOps[j], d, { "fixed": true, "flags": true })) return null; if (rwOps[j].fixed === -1) rwOps[j].fixed = d.fixed; - Lang.merge(rwOps[j].flags, d.flags); + ObjectUtils.merge(rwOps[j].flags, d.flags); } } } @@ -2252,7 +2245,7 @@ class InstRWInfoTable extends core.Task { var match = 0; for (var j = 0; j < rwOpsArray.length; j++) - match |= Lang.deepEq(rwOps, rwOpsArray[j]); + match |= ObjectUtils.equals(rwOps, rwOpsArray[j]); if (!match) return false; @@ -2309,7 +2302,7 @@ class InstRWInfoTable extends core.Task { } rwOpFlagsForInstruction(instName, opIndex) { - const toMap = MapUtils.arrayToMap; + const toMap = ArrayUtils.toDict; // TODO: We should be able to get this information from asmdb. switch (instName + "@" + opIndex) { diff --git a/deps/asmjit/tools/tablegen.js b/deps/asmjit/tools/tablegen.js index 98faa36e..a1518056 100644 --- a/deps/asmjit/tools/tablegen.js +++ b/deps/asmjit/tools/tablegen.js @@ -18,8 +18,8 @@ const fs = require("fs"); -const commons = require("./gencommons.js"); -const cxx = require("./gencxx.js"); +const commons = require("./generator-commons.js"); +const cxx = require("./generator-cxx.js"); const asmdb = require("../db"); exports.asmdb = asmdb; @@ -28,528 +28,11 @@ exports.exp = asmdb.base.exp; const hasOwn = Object.prototype.hasOwnProperty; const FATAL = commons.FATAL; +const StringUtils = commons.StringUtils; -// ============================================================================ -// [Constants] -// ============================================================================ - -const kIndent = " "; -const kJustify = 119; const kAsmJitRoot = ".."; - -exports.kIndent = kIndent; -exports.kJustify = kJustify; exports.kAsmJitRoot = kAsmJitRoot; -// ============================================================================ -// [Lang] -// ============================================================================ - -function nop(x) { return x; } - -class Lang { - static merge(a, b) { - if (a === b) - return a; - - for (var k in b) { - var av = a[k]; - var bv = b[k]; - - if (typeof av === "object" && typeof bv === "object") - Lang.merge(av, bv); - else - a[k] = bv; - } - - return a; - } - - static deepEq(a, b) { - if (a === b) - return true; - - if (typeof a !== typeof b) - return false; - - if (typeof a !== "object") - return a === b; - - if (Array.isArray(a) || Array.isArray(b)) { - if (Array.isArray(a) !== Array.isArray(b)) - return false; - - const len = a.length; - if (b.length !== len) - return false; - - for (var i = 0; i < len; i++) - if (!Lang.deepEq(a[i], b[i])) - return false; - } - else { - if (a === null || b === null) - return a === b; - - for (var k in a) - if (!hasOwn.call(b, k) || !Lang.deepEq(a[k], b[k])) - return false; - - for (var k in b) - if (!hasOwn.call(a, k)) - return false; - } - - return true; - } - - static deepEqExcept(a, b, except) { - if (a === b) - return true; - - if (typeof a !== "object" || typeof b !== "object" || Array.isArray(a) || Array.isArray(b)) - return Lang.deepEq(a, b); - - for (var k in a) - if (!hasOwn.call(except, k) && (!hasOwn.call(b, k) || !Lang.deepEq(a[k], b[k]))) - return false; - - for (var k in b) - if (!hasOwn.call(except, k) && !hasOwn.call(a, k)) - return false; - - return true; - } -} -exports.Lang = Lang; - -// ============================================================================ -// [StringUtils] -// ============================================================================ - -class StringUtils { - static asString(x) { return String(x); } - - static countOf(s, pattern) { - if (!pattern) - FATAL(`Pattern cannot be empty`); - - var n = 0; - var pos = 0; - - while ((pos = s.indexOf(pattern, pos)) >= 0) { - n++; - pos += pattern.length; - } - - return n; - } - - static trimLeft(s) { return s.replace(/^\s+/, ""); } - static trimRight(s) { return s.replace(/\s+$/, ""); } - - static upFirst(s) { - if (!s) return ""; - return s[0].toUpperCase() + s.substr(1); - } - - static decToHex(n, nPad) { - var hex = Number(n < 0 ? 0x100000000 + n : n).toString(16); - while (nPad > hex.length) - hex = "0" + hex; - return "0x" + hex.toUpperCase(); - } - - static format(array, indent, showIndex, mapFn) { - if (!mapFn) - mapFn = StringUtils.asString; - - var s = ""; - var threshold = 80; - - if (showIndex === -1) - s += indent; - - for (var i = 0; i < array.length; i++) { - const item = array[i]; - const last = i === array.length - 1; - - if (showIndex !== -1) - s += indent; - - s += mapFn(item); - if (showIndex > 0) { - s += `${last ? " " : ","} // #${i}`; - if (typeof array.refCountOf === "function") - s += ` [ref=${array.refCountOf(item)}x]`; - } - else if (!last) { - s += ","; - } - - if (showIndex === -1) { - if (s.length >= threshold - 1 && !last) { - s += "\n" + indent; - threshold += 80; - } - else { - if (!last) s += " "; - } - } - else { - if (!last) s += "\n"; - } - } - - return s; - } - - static makeCxxArray(array, code, indent) { - if (!indent) indent = kIndent; - return `${code} = {\n${indent}` + array.join(`,\n${indent}`) + `\n};\n`; - } - - static makeCxxArrayWithComment(array, code, indent) { - if (!indent) indent = kIndent; - var s = ""; - for (var i = 0; i < array.length; i++) { - const last = i === array.length - 1; - s += indent + array[i].data + - (last ? " // " : ", // ") + (array[i].refs ? "#" + String(i) : "").padEnd(5) + array[i].comment + "\n"; - } - return `${code} = {\n${s}};\n`; - } - - static disclaimer(s) { - return "// ------------------- Automatically generated, do not edit -------------------\n" + - s + - "// ----------------------------------------------------------------------------\n"; - } - - static indent(s, indentation) { - if (typeof indentation === "number") - indentation = " ".repeat(indentation); - - var lines = s.split(/\r?\n/g); - if (indentation) { - for (var i = 0; i < lines.length; i++) { - var line = lines[i]; - if (line) - lines[i] = indentation + line; - } - } - - return lines.join("\n"); - } - - static extract(s, start, end) { - var iStart = s.indexOf(start); - var iEnd = s.indexOf(end); - - if (iStart === -1) - FATAL(`StringUtils.extract(): Couldn't locate start mark '${start}'`); - - if (iEnd === -1) - FATAL(`StringUtils.extract(): Couldn't locate end mark '${end}'`); - - return s.substring(iStart + start.length, iEnd).trim(); - } - - static inject(s, start, end, code) { - var iStart = s.indexOf(start); - var iEnd = s.indexOf(end); - - if (iStart === -1) - FATAL(`StringUtils.inject(): Couldn't locate start mark '${start}'`); - - if (iEnd === -1) - FATAL(`StringUtils.inject(): Couldn't locate end mark '${end}'`); - - var nIndent = 0; - while (iStart > 0 && s[iStart-1] === " ") { - iStart--; - nIndent++; - } - - if (nIndent) { - const indentation = " ".repeat(nIndent); - code = StringUtils.indent(code, indentation) + indentation; - } - - return s.substr(0, iStart + start.length + nIndent) + code + s.substr(iEnd); - } - - static makePriorityCompare(priorityArray) { - const map = Object.create(null); - priorityArray.forEach((str, index) => { map[str] = index; }); - - return function(a, b) { - const ax = hasOwn.call(map, a) ? map[a] : Infinity; - const bx = hasOwn.call(map, b) ? map[b] : Infinity; - return ax != bx ? ax - bx : a < b ? -1 : a > b ? 1 : 0; - } - } -} -exports.StringUtils = StringUtils; - -// ============================================================================ -// [ArrayUtils] -// ============================================================================ - -class ArrayUtils { - static min(arr, fn) { - if (!arr.length) - return null; - - if (!fn) - fn = nop; - - var v = fn(arr[0]); - for (var i = 1; i < arr.length; i++) - v = Math.min(v, fn(arr[i])); - return v; - } - - static max(arr, fn) { - if (!arr.length) - return null; - - if (!fn) - fn = nop; - - var v = fn(arr[0]); - for (var i = 1; i < arr.length; i++) - v = Math.max(v, fn(arr[i])); - return v; - } - - static sorted(obj, cmp) { - const out = Array.isArray(obj) ? obj.slice() : Object.getOwnPropertyNames(obj); - out.sort(cmp); - return out; - } - - static deepIndexOf(arr, what) { - for (var i = 0; i < arr.length; i++) - if (Lang.deepEq(arr[i], what)) - return i; - return -1; - } -} -exports.ArrayUtils = ArrayUtils; - -// ============================================================================ -// [MapUtils] -// ============================================================================ - -class MapUtils { - static clone(map) { - return Object.assign(Object.create(null), map); - } - - static arrayToMap(arr, value) { - if (value === undefined) - value = true; - - const out = Object.create(null); - for (var i = 0; i < arr.length; i++) - out[arr[i]] = value; - return out; - } - - static equals(a, b) { - for (var k in a) if (!hasOwn.call(b, k)) return false; - for (var k in b) if (!hasOwn.call(a, k)) return false; - return true; - } - - static firstOf(map, flags) { - for (var k in flags) - if (hasOwn.call(map, k)) - return k; - return undefined; - } - - static anyOf(map, flags) { - for (var k in flags) - if (hasOwn.call(map, k)) - return true; - return false; - } - - static add(a, b) { - for (var k in b) - a[k] = b[k]; - return a; - } - - static and(a, b) { - const out = Object.create(null); - for (var k in a) - if (hasOwn.call(b, k)) - out[k] = true; - return out; - } - - static xor(a, b) { - const out = Object.create(null); - for (var k in a) if (!hasOwn.call(b, k)) out[k] = true; - for (var k in b) if (!hasOwn.call(a, k)) out[k] = true; - return out; - } -}; -exports.MapUtils = MapUtils; - -// ============================================================================ -// [CxxUtils] -// ============================================================================ - -class CxxUtils { - static flags(obj, fn, none) { - if (none == null) - none = "0"; - - if (!fn) - fn = nop; - - let out = ""; - for (let k in obj) { - if (obj[k]) - out += (out ? " | " : "") + fn(k); - } - return out ? out : none; - } - - static struct(...args) { - return "{ " + args.join(", ") + " }"; - } -}; -exports.CxxUtils = CxxUtils; - -// ============================================================================ -// [IndexedString] -// ============================================================================ - -// IndexedString is mostly used to merge all instruction names into a single -// string with external index. It's designed mostly for generating C++ tables. -// -// Consider the following cases in C++: -// -// a) static const char* const* instNames = { "add", "mov", "vpunpcklbw" }; -// -// b) static const char instNames[] = { "add\0" "mov\0" "vpunpcklbw\0" }; -// static const uint16_t instNameIndex[] = { 0, 4, 8 }; -// -// The latter (b) has an advantage that it doesn't have to be relocated by the -// linker, which saves a lot of space in the resulting binary and a lot of CPU -// cycles (and memory) when the linker loads it. AsmJit supports thousands of -// instructions so each optimization like this makes it smaller and faster to -// load. -class IndexedString { - constructor() { - this.map = Object.create(null); - this.array = []; - this.size = -1; - } - - add(s) { - this.map[s] = -1; - } - - index() { - const map = this.map; - const array = this.array; - const partialMap = Object.create(null); - - var k, kp; - var i, len; - - // Create a map that will contain all keys and partial keys. - for (k in map) { - if (!k) { - partialMap[k] = k; - } - else { - for (i = 0, len = k.length; i < len; i++) { - kp = k.substr(i); - if (!hasOwn.call(partialMap, kp) || partialMap[kp].length < len) - partialMap[kp] = k; - } - } - } - - // Create an array that will only contain keys that are needed. - for (k in map) - if (partialMap[k] === k) - array.push(k); - array.sort(); - - // Create valid offsets to the `array`. - var offMap = Object.create(null); - var offset = 0; - - for (i = 0, len = array.length; i < len; i++) { - k = array[i]; - - offMap[k] = offset; - offset += k.length + 1; - } - this.size = offset; - - // Assign valid offsets to `map`. - for (kp in map) { - k = partialMap[kp]; - map[kp] = offMap[k] + k.length - kp.length; - } - } - - format(indent, justify) { - if (this.size === -1) - FATAL(`IndexedString.format(): not indexed yet, call index()`); - - const array = this.array; - if (!justify) justify = 0; - - var i; - var s = ""; - var line = ""; - - for (i = 0; i < array.length; i++) { - const item = "\"" + array[i] + ((i !== array.length - 1) ? "\\0\"" : "\";"); - const newl = line + (line ? " " : indent) + item; - - if (newl.length <= justify) { - line = newl; - continue; - } - else { - s += line + "\n"; - line = indent + item; - } - } - - return s + line; - } - - getSize() { - if (this.size === -1) - FATAL(`IndexedString.getSize(): Not indexed yet, call index()`); - return this.size; - } - - getIndex(k) { - if (this.size === -1) - FATAL(`IndexedString.getIndex(): Not indexed yet, call index()`); - - if (!hasOwn.call(this.map, k)) - FATAL(`IndexedString.getIndex(): Key '${k}' not found.`); - - return this.map[k]; - } -} -exports.IndexedString = IndexedString; - - // ============================================================================ // [InstructionNameData] // ============================================================================ @@ -664,7 +147,7 @@ class InstructionNameData { suffix = name.substring(longestPrefix); } else if (longestSuffix) { - const splitAt = Math.min(name.length - longestSuffix, kMaxPrefixSize);; + const splitAt = Math.min(name.length - longestSuffix, kMaxPrefixSize); prefix = name.substring(0, splitAt); suffix = name.substring(splitAt); } @@ -751,51 +234,6 @@ class InstructionNameData { } exports.InstructionNameData = InstructionNameData; -// ============================================================================ -// [IndexedArray] -// ============================================================================ - -// IndexedArray is an Array replacement that allows to index each item inserted -// to it. Its main purpose is to avoid data duplication, if an item passed to -// `addIndexed()` is already within the Array then it's not inserted and the -// existing index is returned instead. -function IndexedArray_keyOf(item) { - return typeof item === "string" ? item : JSON.stringify(item); -} - -class IndexedArray extends Array { - constructor() { - super(); - this._index = Object.create(null); - } - - refCountOf(item) { - const key = IndexedArray_keyOf(item); - const idx = this._index[key]; - - return idx !== undefined ? idx.refCount : 0; - } - - addIndexed(item) { - const key = IndexedArray_keyOf(item); - var idx = this._index[key]; - - if (idx !== undefined) { - idx.refCount++; - return idx.data; - } - - idx = this.length; - this._index[key] = { - data: idx, - refCount: 1 - }; - this.push(item); - return idx; - } -} -exports.IndexedArray = IndexedArray; - // ============================================================================ // [Task] // ============================================================================ @@ -823,29 +261,12 @@ exports.Task = Task; // [TableGen] // ============================================================================ -// Main context used to load, generate, and store instruction tables. The idea -// is to be extensible, so it stores 'Task's to be executed with minimal deps -// management. -class TableGen { - constructor(arch) { - this.arch = arch; +class Injector { + constructor() { this.files = Object.create(null); this.tableSizes = Object.create(null); - - this.tasks = []; - this.taskMap = Object.create(null); - - this.insts = []; - this.instMap = Object.create(null); - - this.aliases = []; - this.aliasMem = Object.create(null); } - // -------------------------------------------------------------------------- - // [File Management] - // -------------------------------------------------------------------------- - load(fileList) { for (var i = 0; i < fileList.length; i++) { const file = fileList[i]; @@ -905,6 +326,42 @@ class TableGen { return this; } + dumpTableSizes() { + const sizes = this.tableSizes; + + var pad = 26; + var total = 0; + + for (var name in sizes) { + const size = sizes[name]; + total += size; + console.log(("Size of " + name).padEnd(pad) + ": " + size); + } + + console.log("Size of all tables".padEnd(pad) + ": " + total); + } +} +exports.Injector = Injector; + +// Main context used to load, generate, and store instruction tables. The idea +// is to be extensible, so it stores 'Task's to be executed with minimal deps +// management. +class TableGen extends Injector{ + constructor(arch) { + super(); + + this.arch = arch; + + this.tasks = []; + this.taskMap = Object.create(null); + + this.insts = []; + this.instMap = Object.create(null); + + this.aliases = []; + this.aliasMem = Object.create(null); + } + // -------------------------------------------------------------------------- // [Task Management] // -------------------------------------------------------------------------- @@ -989,25 +446,6 @@ class TableGen { this.onAfterRun(); } - // -------------------------------------------------------------------------- - // [Other] - // -------------------------------------------------------------------------- - - dumpTableSizes() { - const sizes = this.tableSizes; - - var pad = 26; - var total = 0; - - for (var name in sizes) { - const size = sizes[name]; - total += size; - console.log(("Size of " + name).padEnd(pad) + ": " + size); - } - - console.log("Size of all tables".padEnd(pad) + ": " + total); - } - // -------------------------------------------------------------------------- // [Hooks] // -------------------------------------------------------------------------- @@ -1056,59 +494,75 @@ exports.IdEnum = IdEnum; // [NameTable] // ============================================================================ +class Output { + constructor() { + this.content = Object.create(null); + this.tableSize = Object.create(null); + } + + add(id, content, tableSize) { + this.content[id] = content; + this.tableSize[id] = typeof tableSize === "number" ? tableSize : 0; + } +}; +exports.Output = Output; + +function generateNameData(out, instructions) { + const none = "Inst::kIdNone"; + + const instFirst = new Array(26); + const instLast = new Array(26); + const instNameData = new InstructionNameData(); + + for (let i = 0; i < instructions.length; i++) + instNameData.add(instructions[i].displayName); + instNameData.index(); + + for (let i = 0; i < instructions.length; i++) { + const inst = instructions[i]; + const displayName = inst.displayName; + const alphaIndex = displayName.charCodeAt(0) - 'a'.charCodeAt(0); + + if (alphaIndex < 0 || alphaIndex >= 26) + FATAL(`generateNameData(): Invalid lookup character '${displayName[0]}' of '${displayName}'`); + + if (instFirst[alphaIndex] === undefined) + instFirst[alphaIndex] = `Inst::kId${inst.enum}`; + instLast[alphaIndex] = `Inst::kId${inst.enum}`; + } + + var s = ""; + s += `const InstNameIndex InstDB::instNameIndex = {{\n`; + for (var i = 0; i < instFirst.length; i++) { + const firstId = instFirst[i] || none; + const lastId = instLast[i] || none; + + s += ` { ${String(firstId).padEnd(22)}, ${String(lastId).padEnd(22)} + 1 }`; + if (i !== 26 - 1) + s += `,`; + s += `\n`; + } + s += `}, uint16_t(${instNameData.maxNameLength})};\n`; + s += `\n`; + s += instNameData.formatStringTable("InstDB::_instNameStringTable"); + s += `\n`; + s += instNameData.formatIndexTable("InstDB::_instNameIndexTable"); + + const dataSize = instNameData.getSize() + 26 * 4; + out.add("NameData", StringUtils.disclaimer(s), dataSize); + return out; +} +exports.generateNameData = generateNameData; + class NameTable extends Task { constructor(name, deps) { super(name || "NameTable", deps); } run() { - const none = "Inst::kIdNone"; - const insts = this.ctx.insts; - - const instFirst = new Array(26); - const instLast = new Array(26); - - const instNameData = new InstructionNameData(); - - for (let i = 0; i < insts.length; i++) - instNameData.add(insts[i].displayName); - instNameData.index(); - - for (let i = 0; i < insts.length; i++) { - const inst = insts[i]; - const name = inst.displayName; - const index = name.charCodeAt(0) - 'a'.charCodeAt(0); - - if (index < 0 || index >= 26) - FATAL(`TableGen.generateNameData(): Invalid lookup character '${name[0]}' of '${name}'`); - - if (instFirst[index] === undefined) - instFirst[index] = `Inst::kId${inst.enum}`; - instLast[index] = `Inst::kId${inst.enum}`; - } - - var s = ""; - s += instNameData.formatIndexTable("InstDB::_instNameIndexTable"); - s += `\n`; - s += instNameData.formatStringTable("InstDB::_instNameStringTable"); - s += `\n`; - - s += `const InstDB::InstNameIndex InstDB::instNameIndex[26] = {\n`; - for (var i = 0; i < instFirst.length; i++) { - const firstId = instFirst[i] || none; - const lastId = instLast[i] || none; - - s += ` { ${String(firstId).padEnd(22)}, ${String(lastId).padEnd(22)} + 1 }`; - if (i !== 26 - 1) - s += `,`; - s += `\n`; - } - s += `};\n`; - - this.ctx.inject("NameLimits", - StringUtils.disclaimer(`enum : uint32_t { kMaxNameSize = ${instNameData.maxNameLength} };\n`)); - - return this.ctx.inject("NameData", StringUtils.disclaimer(s), instNameData.getSize() + 26 * 4); + const output = new Output(); + generateNameData(output, this.ctx.insts); + this.ctx.inject("NameData", output.content["NameData"], output.tableSize["NameData"]); } } exports.NameTable = NameTable; diff --git a/deps/asmjit/tools/tablegen.sh b/deps/asmjit/tools/tablegen.sh index bd835c76..0ef1e580 100644 --- a/deps/asmjit/tools/tablegen.sh +++ b/deps/asmjit/tools/tablegen.sh @@ -1,4 +1,5 @@ #!/usr/bin/env sh set -e +node ./tablegen-a32.js $@ node ./tablegen-a64.js $@ node ./tablegen-x86.js $@ diff --git a/deps/curl/.cirrus.yml b/deps/curl/.cirrus.yml index 27b4659b..ae7d8591 100644 --- a/deps/curl/.cirrus.yml +++ b/deps/curl/.cirrus.yml @@ -43,9 +43,9 @@ freebsd_task: name: FreeBSD matrix: - - name: FreeBSD 14.0 + - name: FreeBSD 13.2 freebsd_instance: - image_family: freebsd-14-0 + image_family: freebsd-13-2 env: CIRRUS_CLONE_DEPTH: 10 @@ -54,7 +54,7 @@ freebsd_task: pkginstall_script: - pkg update -f - - pkg install -y autoconf automake libtool pkgconf brotli openldap26-client heimdal libpsl libssh2 libidn2 librtmp libnghttp2 nghttp2 stunnel py39-openssl py39-impacket py39-cryptography + - pkg install -y autoconf automake libtool pkgconf brotli openldap26-client heimdal libpsl libssh2 openssh-portable libidn2 librtmp libnghttp2 nghttp2 stunnel py39-openssl py39-impacket py39-cryptography - pkg delete -y curl configure_script: - autoreconf -fi diff --git a/deps/curl/.github/scripts/codespell-ignore.txt b/deps/curl/.github/scripts/codespell-ignore.txt deleted file mode 100644 index 3832cec4..00000000 --- a/deps/curl/.github/scripts/codespell-ignore.txt +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (C) Daniel Stenberg, , et al. -# -# SPDX-License-Identifier: curl -clen -te -wont -statics -nome -wast -numer -anull -inout -msdos -ba -fo diff --git a/deps/curl/.github/scripts/spellcheck.words b/deps/curl/.github/scripts/spellcheck.words index 4bee9bf6..8856afc3 100644 --- a/deps/curl/.github/scripts/spellcheck.words +++ b/deps/curl/.github/scripts/spellcheck.words @@ -898,7 +898,6 @@ winssl Wireshark wolfSSH wolfSSL -ws WS WSS www diff --git a/deps/curl/.github/scripts/verify-synopsis.pl b/deps/curl/.github/scripts/verify-synopsis.pl deleted file mode 100644 index 34f15a8e..00000000 --- a/deps/curl/.github/scripts/verify-synopsis.pl +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env perl -#*************************************************************************** -# _ _ ____ _ -# Project ___| | | | _ \| | -# / __| | | | |_) | | -# | (__| |_| | _ <| |___ -# \___|\___/|_| \_\_____| -# -# Copyright (C) Daniel Stenberg, , et al. -# -# This software is licensed as described in the file COPYING, which -# you should have received as part of this distribution. The terms -# are also available at https://curl.se/docs/copyright.html. -# -# You may opt to use, copy, modify, merge, publish, distribute and/or sell -# copies of the Software, and permit persons to whom the Software is -# furnished to do so, under the terms of the COPYING file. -# -# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -# KIND, either express or implied. -# -# SPDX-License-Identifier: curl -# -########################################################################### - -my @files = @ARGV; -my $cfile = "test.c"; - -if($files[0] eq "-h") { - print "Usage: verify-synopsis [man pages]\n"; - exit; -} - -sub testcompile { - my $rc = system("gcc -c test.c -DCURL_DISABLE_TYPECHECK -DCURL_ALLOW_OLD_MULTI_SOCKET -I include") >> 8; - return $rc; -} - - -sub extract { - my($f) = @_; - my $syn = 0; - my $l = 0; - my $iline = 0; - open(F, "<$f"); - open(O, ">$cfile"); - while() { - $iline++; - if(/^.SH SYNOPSIS/) { - $syn = 1 - } - elsif($syn == 1) { - if(/^.nf/) { - $syn++; - print O "#line $iline \"$f\"\n"; - } - } - elsif($syn == 2) { - if(/^.fi/) { - last; - } - # turn the vararg argument into vararg - $_ =~ s/, parameter\)\;/, ...);/; - print O $_; - $l++; - } - } - close(F); - close(O); - - return 0; -} - -my $error; -for my $m (@files) { - print "Verify $m\n"; - extract($m); - $error |= testcompile($m); -} -exit $error; - diff --git a/deps/curl/.github/workflows/codespell.yml b/deps/curl/.github/workflows/codespell.yml deleted file mode 100644 index 405d6391..00000000 --- a/deps/curl/.github/workflows/codespell.yml +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (C) Daniel Stenberg, , et al. -# -# SPDX-License-Identifier: curl - -name: Codespell - -on: - push: - branches: - - master - - '*/ci' - paths: - - 'lib/**' - - 'src/**' - - 'include/**' - pull_request: - branches: - - master - - 'lib/**' - - 'src/**' - - 'include/**' - -jobs: - codespell: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: install - run: | - sudo apt-get update - sudo apt-get install codespell - - - name: spellcheck - run: codespell --skip src/tool_hugehelp.c -I .github/scripts/codespell-ignore.txt include src lib diff --git a/deps/curl/.github/workflows/distcheck.yml b/deps/curl/.github/workflows/distcheck.yml index 26c4da2b..a63091bd 100644 --- a/deps/curl/.github/workflows/distcheck.yml +++ b/deps/curl/.github/workflows/distcheck.yml @@ -81,27 +81,6 @@ jobs: rm -rf curl-99.98.97 name: 'verify out-of-tree configure build including docs' - verify-out-of-tree-autotools-debug: - runs-on: ubuntu-latest - timeout-minutes: 30 - needs: maketgz-and-verify-in-tree - steps: - - uses: actions/download-artifact@v3 - with: - name: 'release-tgz' - - - run: | - echo "::stop-commands::$(uuidgen)" - tar xvf curl-99.98.97.tar.gz - pushd curl-99.98.97 - mkdir build - pushd build - ../configure --without-ssl --enable-debug "--prefix=${PWD}/pkg" - make -j3 - make -j3 TFLAGS=1279 test - make -j3 install - name: 'verify out-of-tree autotools debug build' - verify-out-of-tree-cmake: runs-on: ubuntu-latest timeout-minutes: 30 diff --git a/deps/curl/.github/workflows/linux.yml b/deps/curl/.github/workflows/linux.yml index aaa8abc0..9cb9d16b 100644 --- a/deps/curl/.github/workflows/linux.yml +++ b/deps/curl/.github/workflows/linux.yml @@ -44,10 +44,10 @@ env: bearssl-version: 0.6 libressl-version: v3.7.3 mbedtls-version: v3.5.0 - mod_h2-version: v2.0.25 + mod_h2-version: v2.0.21 msh3-version: v0.6.0 openssl3-version: openssl-3.1.3 - quictls-version: 3.1.4+quic + quictls-version: OpenSSL_1_1_1w+quic rustls-version: v0.10.0 jobs: @@ -105,7 +105,7 @@ jobs: - name: openssl3 install_packages: zlib1g-dev valgrind install_steps: gcc-11 openssl3 pytest - configure: CFLAGS=-std=gnu89 LDFLAGS="-Wl,-rpath,$HOME/openssl3/lib64" --with-openssl=$HOME/openssl3 --enable-debug --enable-websockets + configure: LDFLAGS="-Wl,-rpath,$HOME/openssl3/lib64" --with-openssl=$HOME/openssl3 --enable-debug --enable-websockets singleuse: --unit - name: openssl3-O3 @@ -295,9 +295,9 @@ jobs: - name: 'build quictls' if: contains(matrix.build.install_steps, 'quictls') && steps.cache-quictls.outputs.cache-hit != 'true' run: | - git clone --quiet --depth=1 -b openssl-${{ env.quictls-version }} https://github.com/quictls/openssl + git clone --quiet --depth=1 -b ${{ env.quictls-version }} https://github.com/quictls/openssl cd openssl - ./config enable-tls1_3 --prefix=$HOME/quictls --libdir=$HOME/quictls/lib + ./config enable-tls1_3 --prefix=$HOME/quictls make -j1 install_sw - name: cache msh3 diff --git a/deps/curl/.github/workflows/ngtcp2-linux.yml b/deps/curl/.github/workflows/ngtcp2-linux.yml index 8b7a7f2e..0bc230aa 100644 --- a/deps/curl/.github/workflows/ngtcp2-linux.yml +++ b/deps/curl/.github/workflows/ngtcp2-linux.yml @@ -46,13 +46,13 @@ permissions: {} env: MAKEFLAGS: -j 3 - quictls-version: 3.1.4+quic + quictls-version: 3.0.10+quic gnutls-version: 3.8.0 wolfssl-version: master - nghttp3-version: v1.0.0 - ngtcp2-version: v1.0.1 - nghttp2-version: v1.58.0 - mod_h2-version: v2.0.25 + nghttp3-version: v0.15.0 + ngtcp2-version: v0.19.1 + nghttp2-version: v1.56.0 + mod_h2-version: v2.0.21 jobs: autotools: @@ -66,7 +66,7 @@ jobs: - name: quictls configure: >- PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" LDFLAGS="-Wl,-rpath,$HOME/nghttpx/lib" - --with-ngtcp2=$HOME/nghttpx --enable-warnings --enable-werror --enable-debug --disable-ntlm + --with-ngtcp2=$HOME/nghttpx --enable-warnings --enable-werror --enable-debug --with-test-nghttpx="$HOME/nghttpx/bin/nghttpx" --with-openssl=$HOME/nghttpx - name: gnutls @@ -95,19 +95,19 @@ jobs: - name: cache quictls uses: actions/cache@v3 - id: cache-quictls-no-deprecated + id: cache-quictls env: - cache-name: cache-quictls-no-deprecated + cache-name: cache-quictls with: path: /home/runner/quictls key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.quictls-version }} - - if: steps.cache-quictls-no-deprecated.outputs.cache-hit != 'true' + - if: steps.cache-quictls.outputs.cache-hit != 'true' run: | cd $HOME git clone --quiet --depth=1 -b openssl-${{ env.quictls-version }} https://github.com/quictls/openssl quictls cd quictls - ./config no-deprecated --prefix=$HOME/nghttpx --libdir=$HOME/nghttpx/lib + ./config --prefix=$HOME/nghttpx --libdir=$HOME/nghttpx/lib make name: 'build quictls' diff --git a/deps/curl/.github/workflows/quiche-linux.yml b/deps/curl/.github/workflows/quiche-linux.yml index cc6222ef..90dec5e3 100644 --- a/deps/curl/.github/workflows/quiche-linux.yml +++ b/deps/curl/.github/workflows/quiche-linux.yml @@ -47,11 +47,11 @@ permissions: {} env: MAKEFLAGS: -j 3 openssl-version: 3.0.10+quic - nghttp3-version: v1.0.0 - ngtcp2-version: v1.0.1 - nghttp2-version: v1.58.0 - quiche-version: 0.19.0 - mod_h2-version: v2.0.25 + nghttp3-version: v0.15.0 + ngtcp2-version: v0.19.1 + nghttp2-version: v1.56.0 + quiche-version: 0.17.2 + mod_h2-version: v2.0.21 jobs: autotools: diff --git a/deps/curl/.github/workflows/synopsis.yml b/deps/curl/.github/workflows/synopsis.yml deleted file mode 100644 index 948a83ac..00000000 --- a/deps/curl/.github/workflows/synopsis.yml +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (C) Daniel Stenberg, , et al. -# -# SPDX-License-Identifier: curl - -name: SYNOPSIS - -on: - push: - branches: - - master - - '*/ci' - paths: - - 'docs/libcurl/curl_*.3' - pull_request: - branches: - - master - paths: - - 'docs/libcurl/curl_*.3' - -jobs: - verify: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: verify-synopsis - run: ./.github/scripts/verify-synopsis.pl docs/libcurl/curl*.3 diff --git a/deps/curl/CMake/CurlTests.c b/deps/curl/CMake/CurlTests.c index e5462862..ea80ec89 100644 --- a/deps/curl/CMake/CurlTests.c +++ b/deps/curl/CMake/CurlTests.c @@ -23,6 +23,7 @@ ***************************************************************************/ #ifdef HAVE_FCNTL_O_NONBLOCK + /* headers for FCNTL_O_NONBLOCK test */ #include #include @@ -44,13 +45,14 @@ #error "O_NONBLOCK does not work on this platform" #endif -int main(void) +int +main () { - /* O_NONBLOCK source test */ - int flags = 0; - if(0 != fcntl(0, F_SETFL, flags | O_NONBLOCK)) - return 1; - return 0; + /* O_NONBLOCK source test */ + int flags = 0; + if(0 != fcntl(0, F_SETFL, flags | O_NONBLOCK)) + return 1; + return 0; } #endif @@ -106,16 +108,36 @@ int main(void) } #endif +#ifdef HAVE_SOCKLEN_T +#ifdef _WIN32 +#include +#else +#include +#include +#endif +int +main () +{ +if ((socklen_t *) 0) + return 0; +if (sizeof (socklen_t)) + return 0; + ; + return 0; +} +#endif #ifdef HAVE_IN_ADDR_T #include #include #include -int main(void) + +int +main () { - if((in_addr_t *) 0) - return 0; - if(sizeof(in_addr_t)) - return 0; +if ((in_addr_t *) 0) + return 0; +if (sizeof (in_addr_t)) + return 0; ; return 0; } @@ -128,10 +150,11 @@ int main(void) #ifdef HAVE_STDBOOL_H #include #endif -int main(void) +int +main () { - if(sizeof(bool *)) - return 0; +if (sizeof (bool *) ) + return 0; ; return 0; } @@ -142,9 +165,8 @@ int main(void) #include #include #include -int main(void) { return 0; } +int main() { return 0; } #endif - #ifdef HAVE_FILE_OFFSET_BITS #ifdef _FILE_OFFSET_BITS #undef _FILE_OFFSET_BITS @@ -159,95 +181,104 @@ int main(void) { return 0; } int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; -int main(void) { ; return 0; } +int main () { ; return 0; } #endif - #ifdef HAVE_IOCTLSOCKET /* includes start */ #ifdef HAVE_WINDOWS_H # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN # endif +# include # ifdef HAVE_WINSOCK2_H # include # endif -# include #endif -int main(void) + +int +main () { - /* ioctlsocket source code */ - int socket; - unsigned long flags = ioctlsocket(socket, FIONBIO, &flags); + +/* ioctlsocket source code */ + int socket; + unsigned long flags = ioctlsocket(socket, FIONBIO, &flags); + ; return 0; } #endif - #ifdef HAVE_IOCTLSOCKET_CAMEL /* includes start */ #ifdef HAVE_WINDOWS_H # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN # endif +# include # ifdef HAVE_WINSOCK2_H # include # endif -# include #endif -int main(void) + +int +main () { - /* IoctlSocket source code */ - if(0 != IoctlSocket(0, 0, 0)) - return 1; + +/* IoctlSocket source code */ + if(0 != IoctlSocket(0, 0, 0)) + return 1; ; return 0; } #endif - #ifdef HAVE_IOCTLSOCKET_CAMEL_FIONBIO /* includes start */ #ifdef HAVE_WINDOWS_H # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN # endif +# include # ifdef HAVE_WINSOCK2_H # include # endif -# include #endif -int main(void) + +int +main () { - /* IoctlSocket source code */ - long flags = 0; - if(0 != IoctlSocket(0, FIONBIO, &flags)) - return 1; + +/* IoctlSocket source code */ + long flags = 0; + if(0 != IoctlSocket(0, FIONBIO, &flags)) + return 1; ; return 0; } #endif - #ifdef HAVE_IOCTLSOCKET_FIONBIO /* includes start */ #ifdef HAVE_WINDOWS_H # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN # endif +# include # ifdef HAVE_WINSOCK2_H # include # endif -# include #endif -int main(void) + +int +main () { - int flags = 0; - if(0 != ioctlsocket(0, FIONBIO, &flags)) - return 1; + + int flags = 0; + if(0 != ioctlsocket(0, FIONBIO, &flags)) + return 1; + ; return 0; } #endif - #ifdef HAVE_IOCTL_FIONBIO /* headers for FIONBIO test */ /* includes start */ @@ -266,16 +297,19 @@ int main(void) #ifdef HAVE_STROPTS_H # include #endif -int main(void) + +int +main () { - int flags = 0; - if(0 != ioctl(0, FIONBIO, &flags)) - return 1; + + int flags = 0; + if(0 != ioctl(0, FIONBIO, &flags)) + return 1; + ; return 0; } #endif - #ifdef HAVE_IOCTL_SIOCGIFADDR /* headers for FIONBIO test */ /* includes start */ @@ -295,26 +329,28 @@ int main(void) # include #endif #include -int main(void) + +int +main () { - struct ifreq ifr; - if(0 != ioctl(0, SIOCGIFADDR, &ifr)) - return 1; + struct ifreq ifr; + if(0 != ioctl(0, SIOCGIFADDR, &ifr)) + return 1; + ; return 0; } #endif - #ifdef HAVE_SETSOCKOPT_SO_NONBLOCK /* includes start */ #ifdef HAVE_WINDOWS_H # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN # endif +# include # ifdef HAVE_WINSOCK2_H # include # endif -# include #endif /* includes start */ #ifdef HAVE_SYS_TYPES_H @@ -324,30 +360,30 @@ int main(void) # include #endif /* includes end */ -int main(void) + +int +main () { - if(0 != setsockopt(0, SOL_SOCKET, SO_NONBLOCK, 0, 0)) - return 1; + if(0 != setsockopt(0, SOL_SOCKET, SO_NONBLOCK, 0, 0)) + return 1; ; return 0; } #endif - #ifdef HAVE_GLIBC_STRERROR_R #include #include void check(char c) {} -int main(void) -{ +int +main () { char buffer[1024]; /* This will not compile if strerror_r does not return a char* */ check(strerror_r(EACCES, buffer, sizeof(buffer))[0]); return 0; } #endif - #ifdef HAVE_POSIX_STRERROR_R #include #include @@ -355,51 +391,92 @@ int main(void) /* float, because a pointer can't be implicitly cast to float */ void check(float f) {} -int main(void) -{ +int +main () { char buffer[1024]; /* This will not compile if strerror_r does not return an int */ check(strerror_r(EACCES, buffer, sizeof(buffer))); return 0; } #endif - #ifdef HAVE_FSETXATTR_6 #include /* header from libc, not from libattr */ -int main(void) -{ +int +main() { fsetxattr(0, 0, 0, 0, 0, 0); return 0; } #endif - #ifdef HAVE_FSETXATTR_5 #include /* header from libc, not from libattr */ -int main(void) -{ +int +main() { fsetxattr(0, 0, 0, 0, 0); return 0; } #endif - #ifdef HAVE_CLOCK_GETTIME_MONOTONIC #include -int main(void) -{ +int +main() { struct timespec ts = {0, 0}; clock_gettime(CLOCK_MONOTONIC, &ts); return 0; } #endif - #ifdef HAVE_BUILTIN_AVAILABLE -int main(void) -{ +int +main() { if(__builtin_available(macOS 10.12, *)) {} return 0; } #endif +#ifdef HAVE_VARIADIC_MACROS_C99 +#define c99_vmacro3(first, ...) fun3(first, __VA_ARGS__) +#define c99_vmacro2(first, ...) fun2(first, __VA_ARGS__) +int fun3(int arg1, int arg2, int arg3); +int fun2(int arg1, int arg2); + +int fun3(int arg1, int arg2, int arg3) { + return arg1 + arg2 + arg3; +} +int fun2(int arg1, int arg2) { + return arg1 + arg2; +} + +int +main() { + int res3 = c99_vmacro3(1, 2, 3); + int res2 = c99_vmacro2(1, 2); + (void)res3; + (void)res2; + return 0; +} +#endif +#ifdef HAVE_VARIADIC_MACROS_GCC +#define gcc_vmacro3(first, args...) fun3(first, args) +#define gcc_vmacro2(first, args...) fun2(first, args) + +int fun3(int arg1, int arg2, int arg3); +int fun2(int arg1, int arg2); + +int fun3(int arg1, int arg2, int arg3) { + return arg1 + arg2 + arg3; +} +int fun2(int arg1, int arg2) { + return arg1 + arg2; +} + +int +main() { + int res3 = gcc_vmacro3(1, 2, 3); + int res2 = gcc_vmacro2(1, 2); + (void)res3; + (void)res2; + return 0; +} +#endif #ifdef HAVE_ATOMIC /* includes start */ #ifdef HAVE_SYS_TYPES_H @@ -413,24 +490,17 @@ int main(void) #endif /* includes end */ -int main(void) -{ +int +main() { _Atomic int i = 1; i = 0; /* Force an atomic-write operation. */ return i; } #endif - #ifdef HAVE_WIN32_WINNT /* includes start */ -#ifdef _WIN32 -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -# ifndef NOGDI -# define NOGDI -# endif -# include +#ifdef WIN32 +# include "../lib/setup-win32.h" #endif /* includes end */ @@ -438,8 +508,8 @@ int main(void) #define expand(x) enquote(x) #pragma message("_WIN32_WINNT=" expand(_WIN32_WINNT)) -int main(void) -{ +int +main() { return 0; } #endif diff --git a/deps/curl/CMake/FindZstd.cmake b/deps/curl/CMake/FindZstd.cmake index 0ea9e0c8..973e6ad4 100644 --- a/deps/curl/CMake/FindZstd.cmake +++ b/deps/curl/CMake/FindZstd.cmake @@ -56,18 +56,11 @@ find_library(Zstd_LIBRARY NAMES zstd ${PC_Zstd_LIBRARY_DIRS} ) -if(Zstd_INCLUDE_DIR) - file(READ "${Zstd_INCLUDE_DIR}/zstd.h" _zstd_header) - string(REGEX MATCH ".*define ZSTD_VERSION_MAJOR *([0-9]+).*define ZSTD_VERSION_MINOR *([0-9]+).*define ZSTD_VERSION_RELEASE *([0-9]+)" _zstd_ver "${_zstd_header}") - set(Zstd_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}") -endif() - include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Zstd REQUIRED_VARS Zstd_LIBRARY Zstd_INCLUDE_DIR - VERSION_VAR Zstd_VERSION ) if(Zstd_FOUND) diff --git a/deps/curl/CMake/Macros.cmake b/deps/curl/CMake/Macros.cmake index 7ad2f5c4..e12bf303 100644 --- a/deps/curl/CMake/Macros.cmake +++ b/deps/curl/CMake/Macros.cmake @@ -23,6 +23,19 @@ ########################################################################### #File defines convenience macros for available feature testing +# This macro checks if the symbol exists in the library and if it +# does, it prepends library to the list. It is intended to be called +# multiple times with a sequence of possibly dependent libraries in +# order of least-to-most-dependent. Some libraries depend on others +# to link correctly. +macro(check_library_exists_concat LIBRARY SYMBOL VARIABLE) + check_library_exists("${LIBRARY};${CURL_LIBS}" ${SYMBOL} "${CMAKE_LIBRARY_PATH}" + ${VARIABLE}) + if(${VARIABLE}) + set(CURL_LIBS ${LIBRARY} ${CURL_LIBS}) + endif() +endmacro() + # Check if header file exists and add it to the list. # This macro is intended to be called multiple times with a sequence of # possibly dependent header files. Some headers depend on others to be diff --git a/deps/curl/CMake/OtherTests.cmake b/deps/curl/CMake/OtherTests.cmake index a613f6ec..d67a9059 100644 --- a/deps/curl/CMake/OtherTests.cmake +++ b/deps/curl/CMake/OtherTests.cmake @@ -35,13 +35,13 @@ endmacro() set(signature_call_conv) if(HAVE_WINDOWS_H) - set(_source_epilogue - "${_source_epilogue}\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif") add_header_include(HAVE_WINSOCK2_H "winsock2.h") add_header_include(HAVE_WINDOWS_H "windows.h") + set(_source_epilogue + "${_source_epilogue}\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif") set(signature_call_conv "PASCAL") if(WIN32) - set(CMAKE_REQUIRED_LIBRARIES "ws2_32") + set(CMAKE_REQUIRED_LIBRARIES ws2_32) endif() else() add_header_include(HAVE_SYS_TYPES_H "sys/types.h") @@ -71,11 +71,11 @@ int main(void) { }" HAVE_STRUCT_TIMEVAL) if(HAVE_WINDOWS_H) - set(CMAKE_EXTRA_INCLUDE_FILES "winsock2.h") + set(CMAKE_EXTRA_INCLUDE_FILES winsock2.h) else() set(CMAKE_EXTRA_INCLUDE_FILES) if(HAVE_SYS_SOCKET_H) - set(CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h") + set(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h) endif() endif() @@ -172,7 +172,7 @@ if(NOT DEFINED HAVE_GETADDRINFO_THREADSAFE) }" HAVE_H_ERRNO) if(NOT HAVE_H_ERRNO) - check_c_source_compiles("${_source_epilogue} + check_c_source_runs("${_source_epilogue} int main(void) { h_errno = 2; @@ -201,7 +201,7 @@ if(NOT DEFINED HAVE_GETADDRINFO_THREADSAFE) set(_source_epilogue "${_save_epilogue}") endif() -if(NOT WIN32 AND NOT DEFINED HAVE_CLOCK_GETTIME_MONOTONIC_RAW) +if(NOT DEFINED HAVE_CLOCK_GETTIME_MONOTONIC_RAW) set(_save_epilogue "${_source_epilogue}") set(_source_epilogue "#undef inline") diff --git a/deps/curl/CMake/PickyWarnings.cmake b/deps/curl/CMake/PickyWarnings.cmake index 5a0d1560..1310cb4f 100644 --- a/deps/curl/CMake/PickyWarnings.cmake +++ b/deps/curl/CMake/PickyWarnings.cmake @@ -52,8 +52,8 @@ if(PICKY_COMPILER) # Assume these options always exist with both clang and gcc. # Require clang 3.0 / gcc 2.95 or later. list(APPEND WPICKY_ENABLE - -Wbad-function-cast # clang 2.7 gcc 2.95 - -Wconversion # clang 2.7 gcc 2.95 + -Wbad-function-cast # clang 3.0 gcc 2.95 + -Wconversion # clang 3.0 gcc 2.95 -Winline # clang 1.0 gcc 1.0 -Wmissing-declarations # clang 1.0 gcc 2.7 -Wmissing-prototypes # clang 1.0 gcc 1.0 @@ -70,37 +70,23 @@ if(PICKY_COMPILER) # Always enable with clang, version dependent with gcc set(WPICKY_COMMON_OLD - -Waddress # clang 2.7 gcc 4.3 - -Wattributes # clang 2.7 gcc 4.1 -Wcast-align # clang 1.0 gcc 4.2 -Wdeclaration-after-statement # clang 1.0 gcc 3.4 - -Wdiv-by-zero # clang 2.7 gcc 4.1 - -Wempty-body # clang 2.7 gcc 4.3 + -Wempty-body # clang 3.0 gcc 4.3 -Wendif-labels # clang 1.0 gcc 3.3 -Wfloat-equal # clang 1.0 gcc 2.96 (3.0) - -Wformat-security # clang 2.7 gcc 4.1 - -Wignored-qualifiers # clang 2.8 gcc 4.3 - -Wmissing-field-initializers # clang 2.7 gcc 4.1 - -Wmissing-noreturn # clang 2.7 gcc 4.1 + -Wignored-qualifiers # clang 3.0 gcc 4.3 -Wno-format-nonliteral # clang 1.0 gcc 2.96 (3.0) - -Wno-sign-conversion # clang 2.9 gcc 4.3 + -Wno-sign-conversion # clang 3.0 gcc 4.3 -Wno-system-headers # clang 1.0 gcc 3.0 - # -Wpadded # clang 2.9 gcc 4.1 # Not used because we cannot change public structs - -Wredundant-decls # clang 2.7 gcc 4.1 - -Wold-style-definition # clang 2.7 gcc 3.4 -Wstrict-prototypes # clang 1.0 gcc 3.3 - # -Wswitch-enum # clang 2.7 gcc 4.1 # Not used because this basically disallows default case - -Wtype-limits # clang 2.7 gcc 4.3 - -Wunreachable-code # clang 2.7 gcc 4.1 - # -Wunused-macros # clang 2.7 gcc 4.1 # Not practical - -Wunused-parameter # clang 2.7 gcc 4.1 + -Wtype-limits # clang 3.0 gcc 4.3 -Wvla # clang 2.8 gcc 4.3 ) set(WPICKY_COMMON -Wdouble-promotion # clang 3.6 gcc 4.6 appleclang 6.3 -Wenum-conversion # clang 3.2 gcc 10.0 appleclang 4.6 g++ 11.0 - -Wpragmas # clang 3.5 gcc 4.1 appleclang 6.0 -Wunused-const-variable # clang 3.4 gcc 6.0 appleclang 5.1 ) @@ -109,16 +95,12 @@ if(PICKY_COMPILER) ${WPICKY_COMMON_OLD} -Wshift-sign-overflow # clang 2.9 -Wshorten-64-to-32 # clang 1.0 - -Wlanguage-extension-token # clang 3.0 ) # Enable based on compiler version if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.6) OR (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 6.3)) list(APPEND WPICKY_ENABLE ${WPICKY_COMMON} - -Wunreachable-code-break # clang 3.5 appleclang 6.0 - -Wheader-guard # clang 3.4 appleclang 5.1 - -Wsometimes-uninitialized # clang 3.2 appleclang 4.6 ) endif() if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.9) OR @@ -143,7 +125,6 @@ if(PICKY_COMPILER) if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.3) list(APPEND WPICKY_ENABLE ${WPICKY_COMMON_OLD} - -Wclobbered # gcc 4.3 -Wmissing-parameter-type # gcc 4.3 -Wold-style-declaration # gcc 4.3 -Wstrict-aliasing=3 # gcc 4.0 @@ -178,7 +159,7 @@ if(PICKY_COMPILER) -Walloc-zero # gcc 7.0 -Wduplicated-branches # gcc 7.0 -Wformat-overflow=2 # gcc 7.0 - -Wformat-truncation=2 # gcc 7.0 + -Wformat-truncation=1 # gcc 7.0 -Wrestrict # gcc 7.0 ) endif() @@ -193,11 +174,11 @@ if(PICKY_COMPILER) unset(WPICKY) - foreach(_CCOPT IN LISTS WPICKY_ENABLE) + foreach(_CCOPT ${WPICKY_ENABLE}) set(WPICKY "${WPICKY} ${_CCOPT}") endforeach() - foreach(_CCOPT IN LISTS WPICKY_DETECT) + foreach(_CCOPT ${WPICKY_DETECT}) # surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new # test result in. string(MAKE_C_IDENTIFIER "OPT${_CCOPT}" _optvarname) diff --git a/deps/curl/CMake/Platforms/WindowsCache.cmake b/deps/curl/CMake/Platforms/WindowsCache.cmake index ec09fd4b..5daec0e1 100644 --- a/deps/curl/CMake/Platforms/WindowsCache.cmake +++ b/deps/curl/CMake/Platforms/WindowsCache.cmake @@ -21,167 +21,113 @@ # SPDX-License-Identifier: curl # ########################################################################### -if(NOT WIN32) - message(FATAL_ERROR "This file should be included on Windows platform only") -endif() +if(NOT UNIX) + if(WIN32) -set(HAVE_LOCALE_H 1) + set(HAVE_WINDOWS_H 1) + set(HAVE_WS2TCPIP_H 1) + set(HAVE_WINSOCK2_H 1) -if(MINGW) - set(HAVE_SNPRINTF 1) - set(HAVE_UNISTD_H 1) - set(HAVE_LIBGEN_H 1) - set(HAVE_STDDEF_H 1) # detected by CMake internally in check_type_size() - set(HAVE_STDBOOL_H 1) - set(HAVE_BOOL_T "${HAVE_STDBOOL_H}") - set(HAVE_STRTOLL 1) - set(HAVE_BASENAME 1) - set(HAVE_STRCASECMP 1) - set(HAVE_FTRUNCATE 1) - set(HAVE_SYS_PARAM_H 1) - set(HAVE_SYS_TIME_H 1) - set(HAVE_GETTIMEOFDAY 1) -else() - set(HAVE_LIBGEN_H 0) - set(HAVE_STRCASECMP 0) - set(HAVE_FTRUNCATE 0) - set(HAVE_SYS_PARAM_H 0) - set(HAVE_SYS_TIME_H 0) - set(HAVE_GETTIMEOFDAY 0) - if(MSVC) - set(HAVE_UNISTD_H 0) - set(HAVE_LOCALE_H 1) - set(HAVE_STDDEF_H 1) # detected by CMake internally in check_type_size() - set(HAVE_STDATOMIC_H 0) - if(NOT MSVC_VERSION LESS 1800) - set(HAVE_STDBOOL_H 1) - set(HAVE_STRTOLL 1) - else() - set(HAVE_STDBOOL_H 0) - set(HAVE_STRTOLL 0) - endif() - set(HAVE_BOOL_T "${HAVE_STDBOOL_H}") - if(NOT MSVC_VERSION LESS 1900) + if(MINGW) set(HAVE_SNPRINTF 1) - else() - set(HAVE_SNPRINTF 0) + set(HAVE_UNISTD_H 1) + set(HAVE_INTTYPES_H 1) + set(HAVE_STRTOLL 1) + set(HAVE_BASENAME 1) + elseif(MSVC) + if(NOT MSVC_VERSION LESS 1800) + set(HAVE_INTTYPES_H 1) + set(HAVE_STRTOLL 1) + else() + set(HAVE_INTTYPES_H 0) + set(HAVE_STRTOLL 0) + endif() + if(NOT MSVC_VERSION LESS 1900) + set(HAVE_SNPRINTF 1) + else() + set(HAVE_SNPRINTF 0) + endif() + set(HAVE_BASENAME 0) endif() - set(HAVE_BASENAME 0) - set(HAVE_STRTOK_R 0) - set(HAVE_FILE_OFFSET_BITS 0) - set(HAVE_ATOMIC 0) + + set(HAVE_LIBSOCKET 0) + set(HAVE_GETHOSTNAME 1) + set(HAVE_LIBZ 0) + + set(HAVE_ARC4RANDOM 0) + set(HAVE_FNMATCH 0) + set(HAVE_SCHED_YIELD 0) + set(HAVE_ARPA_INET_H 0) + set(HAVE_FCNTL_H 1) + set(HAVE_IFADDRS_H 0) + set(HAVE_IO_H 1) + set(HAVE_NETDB_H 0) + set(HAVE_NETINET_IN_H 0) + set(HAVE_NETINET_TCP_H 0) + set(HAVE_NETINET_UDP_H 0) + set(HAVE_NET_IF_H 0) + set(HAVE_IOCTL_SIOCGIFADDR 0) + set(HAVE_POLL_H 0) + set(HAVE_POLL_FINE 0) + set(HAVE_PWD_H 0) + set(HAVE_STRINGS_H 0) + set(HAVE_SYS_FILIO_H 0) + set(HAVE_SYS_WAIT_H 0) + set(HAVE_SYS_IOCTL_H 0) + set(HAVE_SYS_PARAM_H 0) + set(HAVE_SYS_POLL_H 0) + set(HAVE_SYS_RESOURCE_H 0) + set(HAVE_SYS_SELECT_H 0) + set(HAVE_SYS_SOCKET_H 0) + set(HAVE_SYS_SOCKIO_H 0) + set(HAVE_SYS_STAT_H 1) + set(HAVE_SYS_TIME_H 0) + set(HAVE_SYS_TYPES_H 1) + set(HAVE_SYS_UN_H 0) + set(HAVE_SYS_UTIME_H 1) + set(HAVE_TERMIOS_H 0) + set(HAVE_TERMIO_H 0) + set(HAVE_UTIME_H 0) + + set(HAVE_FSEEKO 0) + set(HAVE__FSEEKI64 1) + set(HAVE_SOCKET 1) + set(HAVE_SELECT 1) + set(HAVE_STRDUP 1) + set(HAVE_STRICMP 1) + set(HAVE_STRCMPI 1) + set(HAVE_MEMRCHR 0) + set(HAVE_GETTIMEOFDAY 0) + set(HAVE_CLOSESOCKET 1) + set(HAVE_SIGSETJMP 0) + set(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1) + set(HAVE_GETPASS_R 0) + set(HAVE_GETPWUID 0) + set(HAVE_GETEUID 0) + set(HAVE_UTIME 1) + set(HAVE_GMTIME_R 0) + set(HAVE_CLOCK_GETTIME_MONOTONIC_RAW 0) + set(HAVE_GETHOSTBYNAME_R 0) + set(HAVE_SIGNAL 1) + set(HAVE_LINUX_TCP_H 0) + set(HAVE_GLIBC_STRERROR_R 0) + set(HAVE_MACH_ABSOLUTE_TIME 0) + set(HAVE_GETIFADDRS 0) + + set(HAVE_GETHOSTBYNAME_R_3 0) + set(HAVE_GETHOSTBYNAME_R_3_REENTRANT 0) + set(HAVE_GETHOSTBYNAME_R_5 0) + set(HAVE_GETHOSTBYNAME_R_5_REENTRANT 0) + set(HAVE_GETHOSTBYNAME_R_6 0) + set(HAVE_GETHOSTBYNAME_R_6_REENTRANT 0) + + set(HAVE_O_NONBLOCK 0) + set(HAVE_IN_ADDR_T 0) + set(STDC_HEADERS 1) + + set(HAVE_SIGACTION 0) + set(HAVE_MACRO_SIGSETJMP 0) + else() + message("This file should be included on Windows platform only") endif() endif() - -# Available in Windows XP and newer -set(HAVE_GETADDRINFO 1) -set(HAVE_FREEADDRINFO 1) - -set(HAVE_FCHMOD 0) -set(HAVE_SOCKETPAIR 0) -set(HAVE_SENDMSG 0) -set(HAVE_ALARM 0) -set(HAVE_FCNTL 0) -set(HAVE_GETPPID 0) -set(HAVE_UTIMES 0) -set(HAVE_GETPWUID_R 0) -set(HAVE_STRERROR_R 0) -set(HAVE_SIGINTERRUPT 0) -set(HAVE_PIPE 0) -set(HAVE_IF_NAMETOINDEX 0) -set(HAVE_GETRLIMIT 0) -set(HAVE_SETRLIMIT 0) -set(HAVE_FSETXATTR 0) -set(HAVE_LIBSOCKET 0) -set(HAVE_SETLOCALE 1) -set(HAVE_SETMODE 1) -set(HAVE_GETPEERNAME 1) -set(HAVE_GETSOCKNAME 1) -set(HAVE_GETHOSTNAME 1) -set(HAVE_LIBZ 0) - -set(HAVE_RECV 1) -set(HAVE_SEND 1) -set(HAVE_STROPTS_H 0) -set(HAVE_SYS_XATTR_H 0) -set(HAVE_ARC4RANDOM 0) -set(HAVE_FNMATCH 0) -set(HAVE_SCHED_YIELD 0) -set(HAVE_ARPA_INET_H 0) -set(HAVE_FCNTL_H 1) -set(HAVE_IFADDRS_H 0) -set(HAVE_IO_H 1) -set(HAVE_NETDB_H 0) -set(HAVE_NETINET_IN_H 0) -set(HAVE_NETINET_TCP_H 0) -set(HAVE_NETINET_UDP_H 0) -set(HAVE_NET_IF_H 0) -set(HAVE_IOCTL_SIOCGIFADDR 0) -set(HAVE_POLL_H 0) -set(HAVE_POLL_FINE 0) -set(HAVE_PWD_H 0) -set(HAVE_STRINGS_H 0) # mingw-w64 has it (wrapper to string.h) -set(HAVE_SYS_FILIO_H 0) -set(HAVE_SYS_WAIT_H 0) -set(HAVE_SYS_IOCTL_H 0) -set(HAVE_SYS_POLL_H 0) -set(HAVE_SYS_RESOURCE_H 0) -set(HAVE_SYS_SELECT_H 0) -set(HAVE_SYS_SOCKET_H 0) -set(HAVE_SYS_SOCKIO_H 0) -set(HAVE_SYS_STAT_H 1) -set(HAVE_SYS_TYPES_H 1) -set(HAVE_SYS_UN_H 0) -set(HAVE_SYS_UTIME_H 1) -set(HAVE_TERMIOS_H 0) -set(HAVE_TERMIO_H 0) -set(HAVE_UTIME_H 0) # mingw-w64 has it (wrapper to sys/utime.h) - -set(HAVE_FSEEKO 0) -set(HAVE__FSEEKI64 1) -set(HAVE_SOCKET 1) -set(HAVE_SELECT 1) -set(HAVE_STRDUP 1) -set(HAVE_STRICMP 1) -set(HAVE_STRCMPI 1) -set(HAVE_MEMRCHR 0) -set(HAVE_CLOSESOCKET 1) -set(HAVE_SIGSETJMP 0) -set(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1) -set(HAVE_GETPASS_R 0) -set(HAVE_GETPWUID 0) -set(HAVE_GETEUID 0) -set(HAVE_UTIME 1) -set(HAVE_GMTIME_R 0) -set(HAVE_GETHOSTBYNAME_R 0) -set(HAVE_SIGNAL 1) -set(HAVE_SIGACTION 0) -set(HAVE_LINUX_TCP_H 0) -set(HAVE_GLIBC_STRERROR_R 0) -set(HAVE_MACH_ABSOLUTE_TIME 0) -set(HAVE_GETIFADDRS 0) -set(HAVE_FCNTL_O_NONBLOCK 0) -set(HAVE_IOCTLSOCKET 1) -set(HAVE_IOCTLSOCKET_CAMEL 0) -set(HAVE_IOCTLSOCKET_CAMEL_FIONBIO 0) -set(HAVE_IOCTLSOCKET_FIONBIO 1) -set(HAVE_IOCTL_FIONBIO 0) -set(HAVE_SETSOCKOPT_SO_NONBLOCK 0) -set(HAVE_POSIX_STRERROR_R 0) -set(HAVE_BUILTIN_AVAILABLE 0) -set(HAVE_MSG_NOSIGNAL 0) -set(HAVE_STRUCT_TIMEVAL 1) - -set(HAVE_GETHOSTBYNAME_R_3 0) -set(HAVE_GETHOSTBYNAME_R_3_REENTRANT 0) -set(HAVE_GETHOSTBYNAME_R_5 0) -set(HAVE_GETHOSTBYNAME_R_5_REENTRANT 0) -set(HAVE_GETHOSTBYNAME_R_6 0) -set(HAVE_GETHOSTBYNAME_R_6_REENTRANT 0) - -set(HAVE_O_NONBLOCK 0) -set(HAVE_IN_ADDR_T 0) -set(STDC_HEADERS 1) - -set(HAVE_SIZEOF_SUSECONDS_T 0) -set(HAVE_SIZEOF_SA_FAMILY_T 0) diff --git a/deps/curl/CMake/curl-config.cmake.in b/deps/curl/CMake/curl-config.cmake.in index 9adb96e0..056907c4 100644 --- a/deps/curl/CMake/curl-config.cmake.in +++ b/deps/curl/CMake/curl-config.cmake.in @@ -35,6 +35,4 @@ include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake") check_required_components("@PROJECT_NAME@") # Alias for either shared or static library -if(NOT TARGET @PROJECT_NAME@::libcurl) - add_library(@PROJECT_NAME@::libcurl ALIAS @PROJECT_NAME@::@LIB_SELECTED@) -endif() +add_library(@PROJECT_NAME@::libcurl ALIAS @PROJECT_NAME@::@LIB_SELECTED@) diff --git a/deps/curl/CMakeLists.txt b/deps/curl/CMakeLists.txt index a54c2fff..1b19c681 100644 --- a/deps/curl/CMakeLists.txt +++ b/deps/curl/CMakeLists.txt @@ -54,13 +54,13 @@ # HAVE_GNUTLS_SRP: `gnutls_srp_verifier` present in GnuTLS # HAVE_SSL_CTX_SET_QUIC_METHOD: `SSL_CTX_set_quic_method` present in OpenSSL/wolfSSL # HAVE_QUICHE_CONN_SET_QLOG_FD: `quiche_conn_set_qlog_fd` present in QUICHE +# HAVE_ZSTD_CREATEDSTREAM: `ZSTD_createDStream` present in Zstd # # For each of the above variables, if the variable is DEFINED (either # to ON or OFF), the symbol detection will be skipped. If the # variable is NOT DEFINED, the symbol detection will be performed. cmake_minimum_required(VERSION 3.7...3.16 FATAL_ERROR) -message(STATUS "Using CMake version ${CMAKE_VERSION}") set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}") include(Utilities) @@ -105,8 +105,6 @@ option(BUILD_SHARED_LIBS "Build shared libraries" ON) option(BUILD_STATIC_LIBS "Build static libraries" OFF) option(BUILD_STATIC_CURL "Build curl executable with static libcurl" OFF) option(ENABLE_ARES "Set to ON to enable c-ares support" OFF) -option(CURL_DISABLE_INSTALL "Set to ON to disable instalation targets" OFF) - if(WIN32) option(CURL_STATIC_CRT "Set to ON to build libcurl with static CRT on Windows (/MT)." OFF) option(ENABLE_UNICODE "Set to ON to use the Unicode version of the Windows API functions" OFF) @@ -222,8 +220,6 @@ option(CURL_DISABLE_GETOPTIONS "disables curl_easy_options API for existing opti mark_as_advanced(CURL_DISABLE_GETOPTIONS) option(CURL_DISABLE_GOPHER "disables Gopher" OFF) mark_as_advanced(CURL_DISABLE_GOPHER) -option(CURL_DISABLE_HEADERS_API "disables headers-api support" OFF) -mark_as_advanced(CURL_DISABLE_HEADERS_API) option(CURL_DISABLE_HSTS "disables HSTS support" OFF) mark_as_advanced(CURL_DISABLE_HSTS) option(CURL_DISABLE_HTTP "disables HTTP" OFF) @@ -241,8 +237,6 @@ mark_as_advanced(CURL_DISABLE_LIBCURL_OPTION) option(CURL_DISABLE_MIME "disables MIME support" OFF) mark_as_advanced(CURL_DISABLE_MIME) option(CURL_DISABLE_MQTT "disables MQTT" OFF) -mark_as_advanced(CURL_DISABLE_BINDLOCAL) -option(CURL_DISABLE_BINDLOCAL "disables local binding support" OFF) mark_as_advanced(CURL_DISABLE_MQTT) option(CURL_DISABLE_NETRC "disables netrc parser" OFF) mark_as_advanced(CURL_DISABLE_NETRC) @@ -368,33 +362,28 @@ include(CheckCSourceCompiles) # On windows preload settings if(WIN32) - set(HAVE_WINDOWS_H 1) - set(HAVE_WS2TCPIP_H 1) - set(HAVE_WINSOCK2_H 1) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_WINSOCKAPI_=) include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Platforms/WindowsCache.cmake) endif() if(ENABLE_THREADED_RESOLVER) + find_package(Threads REQUIRED) if(WIN32) set(USE_THREADS_WIN32 ON) else() - find_package(Threads REQUIRED) set(USE_THREADS_POSIX ${CMAKE_USE_PTHREADS_INIT}) set(HAVE_PTHREAD_H ${CMAKE_USE_PTHREADS_INIT}) - set(CURL_LIBS ${CURL_LIBS} ${CMAKE_THREAD_LIBS_INIT}) endif() + set(CURL_LIBS ${CURL_LIBS} ${CMAKE_THREAD_LIBS_INIT}) endif() # Check for all needed libraries -check_library_exists("socket" "connect" "" HAVE_LIBSOCKET) -if(HAVE_LIBSOCKET) - set(CURL_LIBS "socket;${CURL_LIBS}") -endif() +check_library_exists_concat("socket" connect HAVE_LIBSOCKET) check_function_exists(gethostname HAVE_GETHOSTNAME) if(WIN32) - list(APPEND CURL_LIBS "ws2_32" "bcrypt") + list(APPEND CURL_LIBS "ws2_32") if(USE_LIBRTMP) list(APPEND CURL_LIBS "winmm") endif() @@ -424,7 +413,7 @@ set(openssl_default ON) if(WIN32 OR CURL_USE_SECTRANSP OR CURL_USE_SCHANNEL OR CURL_USE_MBEDTLS OR CURL_USE_WOLFSSL) set(openssl_default OFF) endif() -cmake_dependent_option(CURL_USE_OPENSSL "Enable OpenSSL for SSL/TLS" ${openssl_default} CURL_ENABLE_SSL OFF) +cmake_dependent_option(CURL_USE_OPENSSL "Use OpenSSL code. Experimental" ${openssl_default} CURL_ENABLE_SSL OFF) option(CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG "Disable automatic loading of OpenSSL configuration" OFF) count_true(enabled_ssl_options_count @@ -498,6 +487,11 @@ if(CURL_USE_OPENSSL) include_directories(${OPENSSL_INCLUDE_DIR}) endif() + if(WIN32) + list(APPEND CURL_LIBS "ws2_32") + list(APPEND CURL_LIBS "bcrypt") # for OpenSSL/LibreSSL + endif() + if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "openssl") set(valid_default_ssl_backend TRUE) endif() @@ -610,12 +604,17 @@ option(CURL_ZSTD "Set to ON to enable building curl with zstd support." OFF) set(HAVE_ZSTD OFF) if(CURL_ZSTD) find_package(Zstd REQUIRED) - if(Zstd_FOUND AND NOT Zstd_VERSION VERSION_LESS "1.0.0") + if(NOT DEFINED HAVE_ZSTD_CREATEDSTREAM) + cmake_push_check_state() + set(CMAKE_REQUIRED_INCLUDES ${Zstd_INCLUDE_DIRS}) + set(CMAKE_REQUIRED_LIBRARIES ${Zstd_LIBRARIES}) + check_symbol_exists(ZSTD_createDStream "zstd.h" HAVE_ZSTD_CREATEDSTREAM) + cmake_pop_check_state() + endif() + if(Zstd_FOUND AND HAVE_ZSTD_CREATEDSTREAM) set(HAVE_ZSTD ON) list(APPEND CURL_LIBS ${Zstd_LIBRARIES}) include_directories(${Zstd_INCLUDE_DIRS}) - else() - message(WARNING "zstd v1.0.0 or newer is required, disabling zstd support.") endif() endif() @@ -648,20 +647,6 @@ macro(openssl_check_symbol_exists SYMBOL FILES VARIABLE) cmake_pop_check_state() endmacro() -# Ensure that the OpenSSL fork actually supports QUIC. -macro(openssl_check_quic) - if(NOT DEFINED HAVE_SSL_CTX_SET_QUIC_METHOD) - if(USE_OPENSSL) - openssl_check_symbol_exists(SSL_CTX_set_quic_method "openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD) - elseif(USE_WOLFSSL) - openssl_check_symbol_exists(wolfSSL_set_quic_method "wolfssl/options.h;wolfssl/openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD) - endif() - endif() - if(NOT HAVE_SSL_CTX_SET_QUIC_METHOD) - message(FATAL_ERROR "QUIC support is missing in OpenSSL fork. Try setting -DOPENSSL_ROOT_DIR") - endif() -endmacro() - if(USE_OPENSSL OR USE_WOLFSSL) if(NOT DEFINED HAVE_SSL_SET0_WBIO) openssl_check_symbol_exists(SSL_set0_wbio "openssl/ssl.h" HAVE_SSL_SET0_WBIO) @@ -688,7 +673,18 @@ if(USE_NGTCP2) else() find_package(NGTCP2 REQUIRED quictls) endif() - openssl_check_quic() + + # Be sure that the OpenSSL/wolfSSL library actually supports QUIC. + if(NOT DEFINED HAVE_SSL_CTX_SET_QUIC_METHOD) + if(USE_OPENSSL) + openssl_check_symbol_exists(SSL_CTX_set_quic_method "openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD) + elseif(USE_WOLFSSL) + openssl_check_symbol_exists(wolfSSL_set_quic_method "wolfssl/options.h;wolfssl/openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD) + endif() + endif() + if(NOT HAVE_SSL_CTX_SET_QUIC_METHOD) + message(FATAL_ERROR "QUIC support is missing in OpenSSL/LibreSSL/BoringSSL/wolfSSL. Try setting -DOPENSSL_ROOT_DIR") + endif() elseif(USE_GNUTLS) find_package(NGTCP2 REQUIRED GnuTLS) else() @@ -710,10 +706,7 @@ if(USE_QUICHE) message(FATAL_ERROR "Only one HTTP/3 backend can be selected!") endif() find_package(QUICHE REQUIRED) - if(NOT HAVE_BORINGSSL) - message(FATAL_ERROR "quiche requires BoringSSL") - endif() - openssl_check_quic() + CheckQuicSupportInOpenSSL() set(USE_QUICHE ON) include_directories(${QUICHE_INCLUDE_DIRS}) list(APPEND CURL_LIBS ${QUICHE_LIBRARIES}) @@ -758,12 +751,8 @@ if(NOT CURL_DISABLE_LDAP) if(NOT USE_WIN32_LDAP) # Check for LDAP set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES}) - check_library_exists("${CMAKE_LDAP_LIB}" "ldap_init" "" HAVE_LIBLDAP) - if(HAVE_LIBLDAP) - check_library_exists("${CMAKE_LDAP_LIB};${CMAKE_LBER_LIB}" "ber_init" "" HAVE_LIBLBER) - else() - check_library_exists("${CMAKE_LBER_LIB}" "ber_init" "" HAVE_LIBLBER) - endif() + check_library_exists_concat(${CMAKE_LDAP_LIB} ldap_init HAVE_LIBLDAP) + check_library_exists_concat(${CMAKE_LBER_LIB} ber_init HAVE_LIBLBER) set(CMAKE_REQUIRED_INCLUDES_BAK ${CMAKE_REQUIRED_INCLUDES}) set(CMAKE_LDAP_INCLUDE_DIR "" CACHE STRING "Path to LDAP include directory") @@ -802,10 +791,8 @@ if(NOT CURL_DISABLE_LDAP) list(APPEND CMAKE_REQUIRED_DEFINITIONS -DLDAP_DEPRECATED=1) list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LDAP_LIB}) - set(CURL_LIBS "${CMAKE_LDAP_LIB};${CURL_LIBS}") if(HAVE_LIBLBER) list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LBER_LIB}) - set(CURL_LIBS "${CMAKE_LBER_LIB};${CURL_LIBS}") endif() check_c_source_compiles(" @@ -852,11 +839,7 @@ endif() # Check for idn2 option(USE_LIBIDN2 "Use libidn2 for IDN support" ON) if(USE_LIBIDN2) - check_library_exists("idn2" "idn2_lookup_ul" "" HAVE_LIBIDN2) - if(HAVE_LIBIDN2) - set(CURL_LIBS "idn2;${CURL_LIBS}") - check_include_file_concat("idn2.h" HAVE_IDN2_H) - endif() + check_library_exists_concat("idn2" idn2_lookup_ul HAVE_LIBIDN2) else() set(HAVE_LIBIDN2 OFF) endif() @@ -1069,46 +1052,13 @@ if(CURL_CA_PATH_SET AND endif() # Check for header files -if(WIN32) - check_include_file_concat("winsock2.h" HAVE_WINSOCK2_H) - check_include_file_concat("ws2tcpip.h" HAVE_WS2TCPIP_H) +if(NOT UNIX) check_include_file_concat("windows.h" HAVE_WINDOWS_H) + check_include_file_concat("ws2tcpip.h" HAVE_WS2TCPIP_H) + check_include_file_concat("winsock2.h" HAVE_WINSOCK2_H) endif() -if(WIN32) - # detect actual value of _WIN32_WINNT and store as HAVE_WIN32_WINNT - curl_internal_test(HAVE_WIN32_WINNT) - if(HAVE_WIN32_WINNT) - string(REGEX MATCH ".*_WIN32_WINNT=0x[0-9a-fA-F]+" OUTPUT "${OUTPUT}") - string(REGEX REPLACE ".*_WIN32_WINNT=" "" OUTPUT "${OUTPUT}") - string(REGEX REPLACE "0x([0-9a-f][0-9a-f][0-9a-f])$" "0x0\\1" OUTPUT "${OUTPUT}") # pad to 4 digits - string(TOLOWER "${OUTPUT}" HAVE_WIN32_WINNT) - message(STATUS "Found _WIN32_WINNT=${HAVE_WIN32_WINNT}") - endif() - # avoid storing HAVE_WIN32_WINNT in CMake cache - unset(HAVE_WIN32_WINNT CACHE) - - if(HAVE_WIN32_WINNT) - if(HAVE_WIN32_WINNT STRLESS "0x0501") - # Windows XP is required for freeaddrinfo, getaddrinfo - message(FATAL_ERROR "Building for Windows XP or newer is required.") - endif() - - # pre-fill detection results based on target OS version - if(MINGW OR MSVC) - if(HAVE_WIN32_WINNT STRLESS "0x0600") - set(HAVE_INET_NTOP 0) - set(HAVE_INET_PTON 0) - else() # Windows Vista or newer - set(HAVE_INET_NTOP 1) - set(HAVE_INET_PTON 1) - endif() - unset(HAVE_INET_NTOP CACHE) - unset(HAVE_INET_PTON CACHE) - endif() - endif() -endif() - +check_include_file_concat("inttypes.h" HAVE_INTTYPES_H) check_include_file_concat("sys/filio.h" HAVE_SYS_FILIO_H) check_include_file_concat("sys/wait.h" HAVE_SYS_WAIT_H) check_include_file_concat("sys/ioctl.h" HAVE_SYS_IOCTL_H) @@ -1126,6 +1076,7 @@ check_include_file_concat("sys/utime.h" HAVE_SYS_UTIME_H) check_include_file_concat("sys/xattr.h" HAVE_SYS_XATTR_H) check_include_file_concat("arpa/inet.h" HAVE_ARPA_INET_H) check_include_file_concat("fcntl.h" HAVE_FCNTL_H) +check_include_file_concat("idn2.h" HAVE_IDN2_H) check_include_file_concat("ifaddrs.h" HAVE_IFADDRS_H) check_include_file_concat("io.h" HAVE_IO_H) check_include_file_concat("libgen.h" HAVE_LIBGEN_H) @@ -1141,6 +1092,7 @@ check_include_file_concat("poll.h" HAVE_POLL_H) check_include_file_concat("pwd.h" HAVE_PWD_H) check_include_file_concat("stdatomic.h" HAVE_STDATOMIC_H) check_include_file_concat("stdbool.h" HAVE_STDBOOL_H) +check_include_file_concat("stdint.h" HAVE_STDINT_H) check_include_file_concat("strings.h" HAVE_STRINGS_H) check_include_file_concat("stropts.h" HAVE_STROPTS_H) check_include_file_concat("termio.h" HAVE_TERMIO_H) @@ -1185,6 +1137,7 @@ elseif(HAVE_LIBSOCKET) set(CMAKE_REQUIRED_LIBRARIES socket) endif() +check_symbol_exists(fchmod "${CURL_INCLUDES}" HAVE_FCHMOD) check_symbol_exists(fnmatch "${CURL_INCLUDES};fnmatch.h" HAVE_FNMATCH) check_symbol_exists(basename "${CURL_INCLUDES};string.h" HAVE_BASENAME) check_symbol_exists(socket "${CURL_INCLUDES}" HAVE_SOCKET) @@ -1221,7 +1174,6 @@ check_symbol_exists(gethostbyname_r "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME_R) check_symbol_exists(signal "${CURL_INCLUDES};signal.h" HAVE_SIGNAL) check_symbol_exists(strtoll "${CURL_INCLUDES};stdlib.h" HAVE_STRTOLL) check_symbol_exists(strerror_r "${CURL_INCLUDES};stdlib.h;string.h" HAVE_STRERROR_R) -check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION) check_symbol_exists(siginterrupt "${CURL_INCLUDES};signal.h" HAVE_SIGINTERRUPT) check_symbol_exists(getaddrinfo "${CURL_INCLUDES};stdlib.h;string.h" HAVE_GETADDRINFO) check_symbol_exists(getifaddrs "${CURL_INCLUDES};stdlib.h" HAVE_GETIFADDRS) @@ -1238,10 +1190,6 @@ check_symbol_exists(setlocale "${CURL_INCLUDES}" HAVE_SETLOCALE) check_symbol_exists(setmode "${CURL_INCLUDES}" HAVE_SETMODE) check_symbol_exists(setrlimit "${CURL_INCLUDES}" HAVE_SETRLIMIT) -if(HAVE_FSEEKO) - set(HAVE_DECL_FSEEKO 1) -endif() - if(NOT MSVC OR (MSVC_VERSION GREATER_EQUAL 1900)) # earlier MSVC compilers had faulty snprintf implementations check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF) @@ -1265,11 +1213,20 @@ check_type_size("sa_family_t" SIZEOF_SA_FAMILY_T) set(HAVE_SA_FAMILY_T ${HAVE_SIZEOF_SA_FAMILY_T}) set(CMAKE_EXTRA_INCLUDE_FILES "") -if(WIN32) - set(CMAKE_EXTRA_INCLUDE_FILES "ws2def.h") - check_type_size("ADDRESS_FAMILY" SIZEOF_ADDRESS_FAMILY) - set(HAVE_ADDRESS_FAMILY ${HAVE_SIZEOF_ADDRESS_FAMILY}) - set(CMAKE_EXTRA_INCLUDE_FILES "") +set(CMAKE_EXTRA_INCLUDE_FILES "ws2def.h") +check_type_size("ADDRESS_FAMILY" SIZEOF_ADDRESS_FAMILY) +set(HAVE_ADDRESS_FAMILY ${HAVE_SIZEOF_ADDRESS_FAMILY}) +set(CMAKE_EXTRA_INCLUDE_FILES "") + +# sigaction and sigsetjmp are special. Use special mechanism for +# detecting those, but only if previous attempt failed. +check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION) + +if(NOT HAVE_SIGSETJMP) + check_symbol_exists(sigsetjmp "setjmp.h" HAVE_MACRO_SIGSETJMP) + if(HAVE_MACRO_SIGSETJMP) + set(HAVE_SIGSETJMP 1) + endif() endif() # Do curl specific tests @@ -1293,6 +1250,8 @@ foreach(CURL_TEST HAVE_BOOL_T STDC_HEADERS HAVE_FILE_OFFSET_BITS + HAVE_VARIADIC_MACROS_C99 + HAVE_VARIADIC_MACROS_GCC HAVE_ATOMIC ) curl_internal_test(${CURL_TEST}) @@ -1312,6 +1271,18 @@ set(CMAKE_EXTRA_INCLUDE_FILES "curl/curl.h") check_type_size("curl_socket_t" SIZEOF_CURL_SOCKET_T) set(CMAKE_EXTRA_INCLUDE_FILES "") +if(WIN32) + # detect actual value of _WIN32_WINNT and store as HAVE_WIN32_WINNT + curl_internal_test(HAVE_WIN32_WINNT) + if(HAVE_WIN32_WINNT) + string(REGEX MATCH ".*_WIN32_WINNT=0x[0-9a-fA-F]+" OUTPUT "${OUTPUT}") + string(REGEX REPLACE ".*_WIN32_WINNT=" "" HAVE_WIN32_WINNT "${OUTPUT}") + message(STATUS "Found _WIN32_WINNT=${HAVE_WIN32_WINNT}") + endif() + # avoid storing HAVE_WIN32_WINNT in CMake cache + unset(HAVE_WIN32_WINNT CACHE) +endif() + if(NOT WIN32 AND NOT CMAKE_CROSSCOMPILING) # on not-Windows and not-crosscompiling, check for writable argv[] include(CheckCSourceRuns) @@ -1367,10 +1338,8 @@ if(NEED_REENTRANT) endforeach() endif() -if(NOT WIN32) - # Check clock_gettime(CLOCK_MONOTONIC, x) support - curl_internal_test(HAVE_CLOCK_GETTIME_MONOTONIC) -endif() +# Check clock_gettime(CLOCK_MONOTONIC, x) support +curl_internal_test(HAVE_CLOCK_GETTIME_MONOTONIC) # Check compiler support of __builtin_available() curl_internal_test(HAVE_BUILTIN_AVAILABLE) @@ -1435,6 +1404,8 @@ if(WIN32) if(USE_WIN32_CRYPTO OR USE_SCHANNEL) list(APPEND CURL_LIBS "advapi32" "crypt32") endif() + + list(APPEND CURL_LIBS "bcrypt") endif() if(MSVC) @@ -1521,262 +1492,258 @@ if(BUILD_TESTING) add_subdirectory(tests) endif() -if(NOT CURL_DISABLE_INSTALL) +# Helper to populate a list (_items) with a label when conditions (the remaining +# args) are satisfied +macro(_add_if label) + # needs to be a macro to allow this indirection + if(${ARGN}) + set(_items ${_items} "${label}") + endif() +endmacro() - # Helper to populate a list (_items) with a label when conditions (the remaining - # args) are satisfied - macro(_add_if label) - # needs to be a macro to allow this indirection - if(${ARGN}) - set(_items ${_items} "${label}") +# NTLM support requires crypto function adaptions from various SSL libs +# TODO alternative SSL libs tests for SSP1, GnuTLS, NSS +if(NOT (CURL_DISABLE_NTLM) AND + (USE_OPENSSL OR USE_MBEDTLS OR USE_DARWINSSL OR USE_WIN32_CRYPTO OR USE_GNUTLS)) + set(use_curl_ntlm_core ON) +endif() + +# Clear list and try to detect available features +set(_items) +_add_if("SSL" SSL_ENABLED) +_add_if("IPv6" ENABLE_IPV6) +_add_if("unixsockets" USE_UNIX_SOCKETS) +_add_if("libz" HAVE_LIBZ) +_add_if("brotli" HAVE_BROTLI) +_add_if("zstd" HAVE_ZSTD) +_add_if("AsynchDNS" USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32) +_add_if("IDN" HAVE_LIBIDN2 OR USE_WIN32_IDN) +_add_if("Largefile" (SIZEOF_CURL_OFF_T GREATER 4) AND + ((SIZEOF_OFF_T GREATER 4) OR USE_WIN32_LARGE_FILES)) +# TODO SSP1 (Schannel) check is missing +_add_if("SSPI" USE_WINDOWS_SSPI) +_add_if("GSS-API" HAVE_GSSAPI) +_add_if("alt-svc" NOT CURL_DISABLE_ALTSVC) +_add_if("HSTS" NOT CURL_DISABLE_HSTS) +# TODO SSP1 missing for SPNEGO +_add_if("SPNEGO" NOT CURL_DISABLE_NEGOTIATE_AUTH AND + (HAVE_GSSAPI OR USE_WINDOWS_SSPI)) +_add_if("Kerberos" NOT CURL_DISABLE_KERBEROS_AUTH AND + (HAVE_GSSAPI OR USE_WINDOWS_SSPI)) +# NTLM support requires crypto function adaptions from various SSL libs +# TODO alternative SSL libs tests for SSP1, GnuTLS, NSS +_add_if("NTLM" NOT (CURL_DISABLE_NTLM) AND + (use_curl_ntlm_core OR USE_WINDOWS_SSPI)) +# TODO missing option (autoconf: --enable-ntlm-wb) +_add_if("NTLM_WB" NOT (CURL_DISABLE_NTLM) AND + (use_curl_ntlm_core OR USE_WINDOWS_SSPI) AND + NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED) +_add_if("TLS-SRP" USE_TLS_SRP) +# TODO option --with-nghttp2 tests for nghttp2 lib and nghttp2/nghttp2.h header +_add_if("HTTP2" USE_NGHTTP2) +_add_if("HTTP3" USE_NGTCP2 OR USE_QUICHE) +_add_if("MultiSSL" CURL_WITH_MULTI_SSL) +# TODO wolfSSL only support this from v5.0.0 onwards +_add_if("HTTPS-proxy" SSL_ENABLED AND (USE_OPENSSL OR USE_GNUTLS + OR USE_SCHANNEL OR USE_RUSTLS OR USE_BEARSSL OR + USE_MBEDTLS OR USE_SECTRANSP)) +_add_if("unicode" ENABLE_UNICODE) +_add_if("threadsafe" HAVE_ATOMIC OR (WIN32 AND + HAVE_WIN32_WINNT GREATER_EQUAL 0x600)) +_add_if("PSL" USE_LIBPSL) +string(REPLACE ";" " " SUPPORT_FEATURES "${_items}") +message(STATUS "Enabled features: ${SUPPORT_FEATURES}") + +# Clear list and try to detect available protocols +set(_items) +_add_if("HTTP" NOT CURL_DISABLE_HTTP) +_add_if("HTTPS" NOT CURL_DISABLE_HTTP AND SSL_ENABLED) +_add_if("FTP" NOT CURL_DISABLE_FTP) +_add_if("FTPS" NOT CURL_DISABLE_FTP AND SSL_ENABLED) +_add_if("FILE" NOT CURL_DISABLE_FILE) +_add_if("TELNET" NOT CURL_DISABLE_TELNET) +_add_if("LDAP" NOT CURL_DISABLE_LDAP) +# CURL_DISABLE_LDAP implies CURL_DISABLE_LDAPS +_add_if("LDAPS" NOT CURL_DISABLE_LDAPS AND + ((USE_OPENLDAP AND SSL_ENABLED) OR + (NOT USE_OPENLDAP AND HAVE_LDAP_SSL))) +_add_if("DICT" NOT CURL_DISABLE_DICT) +_add_if("TFTP" NOT CURL_DISABLE_TFTP) +_add_if("GOPHER" NOT CURL_DISABLE_GOPHER) +_add_if("GOPHERS" NOT CURL_DISABLE_GOPHER AND SSL_ENABLED) +_add_if("POP3" NOT CURL_DISABLE_POP3) +_add_if("POP3S" NOT CURL_DISABLE_POP3 AND SSL_ENABLED) +_add_if("IMAP" NOT CURL_DISABLE_IMAP) +_add_if("IMAPS" NOT CURL_DISABLE_IMAP AND SSL_ENABLED) +_add_if("SMB" NOT CURL_DISABLE_SMB AND + use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4)) +_add_if("SMBS" NOT CURL_DISABLE_SMB AND SSL_ENABLED AND + use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4)) +_add_if("SMTP" NOT CURL_DISABLE_SMTP) +_add_if("SMTPS" NOT CURL_DISABLE_SMTP AND SSL_ENABLED) +_add_if("SCP" USE_LIBSSH2 OR USE_LIBSSH) +_add_if("SFTP" USE_LIBSSH2 OR USE_LIBSSH) +_add_if("RTSP" NOT CURL_DISABLE_RTSP) +_add_if("RTMP" USE_LIBRTMP) +_add_if("MQTT" NOT CURL_DISABLE_MQTT) +_add_if("WS" USE_WEBSOCKETS) +_add_if("WSS" USE_WEBSOCKETS) +if(_items) + list(SORT _items) +endif() +string(REPLACE ";" " " SUPPORT_PROTOCOLS "${_items}") +message(STATUS "Enabled protocols: ${SUPPORT_PROTOCOLS}") + +# Clear list and collect SSL backends +set(_items) +_add_if("Schannel" SSL_ENABLED AND USE_SCHANNEL) +_add_if("OpenSSL" SSL_ENABLED AND USE_OPENSSL) +_add_if("Secure Transport" SSL_ENABLED AND USE_SECTRANSP) +_add_if("mbedTLS" SSL_ENABLED AND USE_MBEDTLS) +_add_if("BearSSL" SSL_ENABLED AND USE_BEARSSL) +_add_if("wolfSSL" SSL_ENABLED AND USE_WOLFSSL) +_add_if("GnuTLS" SSL_ENABLED AND USE_GNUTLS) + +if(_items) + list(SORT _items) +endif() +string(REPLACE ";" " " SSL_BACKENDS "${_items}") +message(STATUS "Enabled SSL backends: ${SSL_BACKENDS}") +if(CURL_DEFAULT_SSL_BACKEND) + message(STATUS "Default SSL backend: ${CURL_DEFAULT_SSL_BACKEND}") +endif() + +# curl-config needs the following options to be set. +set(CC "${CMAKE_C_COMPILER}") +# TODO probably put a -D... options here? +set(CONFIGURE_OPTIONS "") +set(CURLVERSION "${CURL_VERSION}") +set(exec_prefix "\${prefix}") +set(includedir "\${prefix}/include") +set(LDFLAGS "${CMAKE_SHARED_LINKER_FLAGS}") +set(LIBCURL_LIBS "") +set(libdir "${CMAKE_INSTALL_PREFIX}/lib") +foreach(_lib ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${CURL_LIBS}) + if(TARGET "${_lib}") + set(_libname "${_lib}") + get_target_property(_imported "${_libname}" IMPORTED) + if(NOT _imported) + # Reading the LOCATION property on non-imported target will error out. + # Assume the user won't need this information in the .pc file. + continue() endif() - endmacro() - - # NTLM support requires crypto function adaptions from various SSL libs - # TODO alternative SSL libs tests for SSP1, GnuTLS, NSS - if(NOT (CURL_DISABLE_NTLM) AND - (USE_OPENSSL OR USE_MBEDTLS OR USE_DARWINSSL OR USE_WIN32_CRYPTO OR USE_GNUTLS)) - set(use_curl_ntlm_core ON) - endif() - - # Clear list and try to detect available features - set(_items) - _add_if("SSL" SSL_ENABLED) - _add_if("IPv6" ENABLE_IPV6) - _add_if("UnixSockets" USE_UNIX_SOCKETS) - _add_if("libz" HAVE_LIBZ) - _add_if("brotli" HAVE_BROTLI) - _add_if("zstd" HAVE_ZSTD) - _add_if("AsynchDNS" USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32) - _add_if("IDN" HAVE_LIBIDN2 OR USE_WIN32_IDN) - _add_if("Largefile" (SIZEOF_CURL_OFF_T GREATER 4) AND - ((SIZEOF_OFF_T GREATER 4) OR USE_WIN32_LARGE_FILES)) - # TODO SSP1 (Schannel) check is missing - _add_if("SSPI" USE_WINDOWS_SSPI) - _add_if("GSS-API" HAVE_GSSAPI) - _add_if("alt-svc" NOT CURL_DISABLE_ALTSVC) - _add_if("HSTS" NOT CURL_DISABLE_HSTS) - # TODO SSP1 missing for SPNEGO - _add_if("SPNEGO" NOT CURL_DISABLE_NEGOTIATE_AUTH AND - (HAVE_GSSAPI OR USE_WINDOWS_SSPI)) - _add_if("Kerberos" NOT CURL_DISABLE_KERBEROS_AUTH AND - (HAVE_GSSAPI OR USE_WINDOWS_SSPI)) - # NTLM support requires crypto function adaptions from various SSL libs - # TODO alternative SSL libs tests for SSP1, GnuTLS, NSS - _add_if("NTLM" NOT (CURL_DISABLE_NTLM) AND - (use_curl_ntlm_core OR USE_WINDOWS_SSPI)) - # TODO missing option (autoconf: --enable-ntlm-wb) - _add_if("NTLM_WB" NOT (CURL_DISABLE_NTLM) AND - (use_curl_ntlm_core OR USE_WINDOWS_SSPI) AND - NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED) - _add_if("TLS-SRP" USE_TLS_SRP) - # TODO option --with-nghttp2 tests for nghttp2 lib and nghttp2/nghttp2.h header - _add_if("HTTP2" USE_NGHTTP2) - _add_if("HTTP3" USE_NGTCP2 OR USE_QUICHE) - _add_if("MultiSSL" CURL_WITH_MULTI_SSL) - # TODO wolfSSL only support this from v5.0.0 onwards - _add_if("HTTPS-proxy" SSL_ENABLED AND (USE_OPENSSL OR USE_GNUTLS - OR USE_SCHANNEL OR USE_RUSTLS OR USE_BEARSSL OR - USE_MBEDTLS OR USE_SECTRANSP)) - _add_if("unicode" ENABLE_UNICODE) - _add_if("threadsafe" HAVE_ATOMIC OR - (USE_THREADS_POSIX AND HAVE_PTHREAD_H) OR - (WIN32 AND HAVE_WIN32_WINNT GREATER_EQUAL 0x600)) - _add_if("PSL" USE_LIBPSL) - string(REPLACE ";" " " SUPPORT_FEATURES "${_items}") - message(STATUS "Enabled features: ${SUPPORT_FEATURES}") - - # Clear list and try to detect available protocols - set(_items) - _add_if("HTTP" NOT CURL_DISABLE_HTTP) - _add_if("HTTPS" NOT CURL_DISABLE_HTTP AND SSL_ENABLED) - _add_if("FTP" NOT CURL_DISABLE_FTP) - _add_if("FTPS" NOT CURL_DISABLE_FTP AND SSL_ENABLED) - _add_if("FILE" NOT CURL_DISABLE_FILE) - _add_if("TELNET" NOT CURL_DISABLE_TELNET) - _add_if("LDAP" NOT CURL_DISABLE_LDAP) - # CURL_DISABLE_LDAP implies CURL_DISABLE_LDAPS - _add_if("LDAPS" NOT CURL_DISABLE_LDAPS AND - ((USE_OPENLDAP AND SSL_ENABLED) OR - (NOT USE_OPENLDAP AND HAVE_LDAP_SSL))) - _add_if("DICT" NOT CURL_DISABLE_DICT) - _add_if("TFTP" NOT CURL_DISABLE_TFTP) - _add_if("GOPHER" NOT CURL_DISABLE_GOPHER) - _add_if("GOPHERS" NOT CURL_DISABLE_GOPHER AND SSL_ENABLED) - _add_if("POP3" NOT CURL_DISABLE_POP3) - _add_if("POP3S" NOT CURL_DISABLE_POP3 AND SSL_ENABLED) - _add_if("IMAP" NOT CURL_DISABLE_IMAP) - _add_if("IMAPS" NOT CURL_DISABLE_IMAP AND SSL_ENABLED) - _add_if("SMB" NOT CURL_DISABLE_SMB AND - use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4)) - _add_if("SMBS" NOT CURL_DISABLE_SMB AND SSL_ENABLED AND - use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4)) - _add_if("SMTP" NOT CURL_DISABLE_SMTP) - _add_if("SMTPS" NOT CURL_DISABLE_SMTP AND SSL_ENABLED) - _add_if("SCP" USE_LIBSSH2 OR USE_LIBSSH) - _add_if("SFTP" USE_LIBSSH2 OR USE_LIBSSH) - _add_if("RTSP" NOT CURL_DISABLE_RTSP) - _add_if("RTMP" USE_LIBRTMP) - _add_if("MQTT" NOT CURL_DISABLE_MQTT) - _add_if("WS" USE_WEBSOCKETS) - _add_if("WSS" USE_WEBSOCKETS) - if(_items) - list(SORT _items) - endif() - string(REPLACE ";" " " SUPPORT_PROTOCOLS "${_items}") - message(STATUS "Enabled protocols: ${SUPPORT_PROTOCOLS}") - - # Clear list and collect SSL backends - set(_items) - _add_if("Schannel" SSL_ENABLED AND USE_SCHANNEL) - _add_if("OpenSSL" SSL_ENABLED AND USE_OPENSSL) - _add_if("Secure Transport" SSL_ENABLED AND USE_SECTRANSP) - _add_if("mbedTLS" SSL_ENABLED AND USE_MBEDTLS) - _add_if("BearSSL" SSL_ENABLED AND USE_BEARSSL) - _add_if("wolfSSL" SSL_ENABLED AND USE_WOLFSSL) - _add_if("GnuTLS" SSL_ENABLED AND USE_GNUTLS) - - if(_items) - list(SORT _items) - endif() - string(REPLACE ";" " " SSL_BACKENDS "${_items}") - message(STATUS "Enabled SSL backends: ${SSL_BACKENDS}") - if(CURL_DEFAULT_SSL_BACKEND) - message(STATUS "Default SSL backend: ${CURL_DEFAULT_SSL_BACKEND}") - endif() - - # curl-config needs the following options to be set. - set(CC "${CMAKE_C_COMPILER}") - # TODO probably put a -D... options here? - set(CONFIGURE_OPTIONS "") - set(CURLVERSION "${CURL_VERSION}") - set(exec_prefix "\${prefix}") - set(includedir "\${prefix}/include") - set(LDFLAGS "${CMAKE_SHARED_LINKER_FLAGS}") - set(LIBCURL_LIBS "") - set(libdir "${CMAKE_INSTALL_PREFIX}/lib") - foreach(_lib ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${CURL_LIBS}) - if(TARGET "${_lib}") - set(_libname "${_lib}") - get_target_property(_imported "${_libname}" IMPORTED) - if(NOT _imported) - # Reading the LOCATION property on non-imported target will error out. - # Assume the user won't need this information in the .pc file. - continue() - endif() - get_target_property(_lib "${_libname}" LOCATION) - if(NOT _lib) - message(WARNING "Bad lib in library list: ${_libname}") - continue() - endif() + get_target_property(_lib "${_libname}" LOCATION) + if(NOT _lib) + message(WARNING "Bad lib in library list: ${_libname}") + continue() endif() - if(_lib MATCHES ".*/.*" OR _lib MATCHES "^-") - set(LIBCURL_LIBS "${LIBCURL_LIBS} ${_lib}") - else() - set(LIBCURL_LIBS "${LIBCURL_LIBS} -l${_lib}") - endif() - endforeach() - if(BUILD_SHARED_LIBS) - set(ENABLE_SHARED "yes") - set(LIBCURL_NO_SHARED "") - set(CPPFLAG_CURL_STATICLIB "") + endif() + if(_lib MATCHES ".*/.*" OR _lib MATCHES "^-") + set(LIBCURL_LIBS "${LIBCURL_LIBS} ${_lib}") else() - set(ENABLE_SHARED "no") - set(LIBCURL_NO_SHARED "${LIBCURL_LIBS}") - set(CPPFLAG_CURL_STATICLIB "-DCURL_STATICLIB") + set(LIBCURL_LIBS "${LIBCURL_LIBS} -l${_lib}") endif() - if(BUILD_STATIC_LIBS) - set(ENABLE_STATIC "yes") - else() - set(ENABLE_STATIC "no") - endif() - # "a" (Linux) or "lib" (Windows) - string(REPLACE "." "" libext "${CMAKE_STATIC_LIBRARY_SUFFIX}") - set(prefix "${CMAKE_INSTALL_PREFIX}") - # Set this to "yes" to append all libraries on which -lcurl is dependent - set(REQUIRE_LIB_DEPS "no") - # SUPPORT_FEATURES - # SUPPORT_PROTOCOLS - set(VERSIONNUM "${CURL_VERSION_NUM}") +endforeach() +if(BUILD_SHARED_LIBS) + set(ENABLE_SHARED "yes") + set(LIBCURL_NO_SHARED "") + set(CPPFLAG_CURL_STATICLIB "") +else() + set(ENABLE_SHARED "no") + set(LIBCURL_NO_SHARED "${LIBCURL_LIBS}") + set(CPPFLAG_CURL_STATICLIB "-DCURL_STATICLIB") +endif() +if(BUILD_STATIC_LIBS) + set(ENABLE_STATIC "yes") +else() + set(ENABLE_STATIC "no") +endif() +# "a" (Linux) or "lib" (Windows) +string(REPLACE "." "" libext "${CMAKE_STATIC_LIBRARY_SUFFIX}") +set(prefix "${CMAKE_INSTALL_PREFIX}") +# Set this to "yes" to append all libraries on which -lcurl is dependent +set(REQUIRE_LIB_DEPS "no") +# SUPPORT_FEATURES +# SUPPORT_PROTOCOLS +set(VERSIONNUM "${CURL_VERSION_NUM}") - # Finally generate a "curl-config" matching this config - # Use: - # * ENABLE_SHARED - # * ENABLE_STATIC - configure_file("${CURL_SOURCE_DIR}/curl-config.in" - "${CURL_BINARY_DIR}/curl-config" @ONLY) - install(FILES "${CURL_BINARY_DIR}/curl-config" - DESTINATION ${CMAKE_INSTALL_BINDIR} - PERMISSIONS - OWNER_READ OWNER_WRITE OWNER_EXECUTE - GROUP_READ GROUP_EXECUTE - WORLD_READ WORLD_EXECUTE) +# Finally generate a "curl-config" matching this config +# Use: +# * ENABLE_SHARED +# * ENABLE_STATIC +configure_file("${CURL_SOURCE_DIR}/curl-config.in" + "${CURL_BINARY_DIR}/curl-config" @ONLY) +install(FILES "${CURL_BINARY_DIR}/curl-config" + DESTINATION ${CMAKE_INSTALL_BINDIR} + PERMISSIONS + OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE) - # Finally generate a pkg-config file matching this config - configure_file("${CURL_SOURCE_DIR}/libcurl.pc.in" - "${CURL_BINARY_DIR}/libcurl.pc" @ONLY) - install(FILES "${CURL_BINARY_DIR}/libcurl.pc" - DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) +# Finally generate a pkg-config file matching this config +configure_file("${CURL_SOURCE_DIR}/libcurl.pc.in" + "${CURL_BINARY_DIR}/libcurl.pc" @ONLY) +install(FILES "${CURL_BINARY_DIR}/libcurl.pc" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) - # install headers - install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/curl" - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - FILES_MATCHING PATTERN "*.h") +# install headers +install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/curl" + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + FILES_MATCHING PATTERN "*.h") - include(CMakePackageConfigHelpers) - write_basic_package_version_file( - "${version_config}" - VERSION ${CURL_VERSION} - COMPATIBILITY SameMajorVersion - ) - file(READ "${version_config}" generated_version_config) - file(WRITE "${version_config}" - "if(NOT PACKAGE_FIND_VERSION_RANGE AND PACKAGE_FIND_VERSION_MAJOR STREQUAL \"7\") - # Version 8 satisfies version 7... requirements - set(PACKAGE_FIND_VERSION_MAJOR 8) - set(PACKAGE_FIND_VERSION_COUNT 1) - endif() - ${generated_version_config}" - ) +include(CMakePackageConfigHelpers) +write_basic_package_version_file( + "${version_config}" + VERSION ${CURL_VERSION} + COMPATIBILITY SameMajorVersion +) +file(READ "${version_config}" generated_version_config) +file(WRITE "${version_config}" +"if(NOT PACKAGE_FIND_VERSION_RANGE AND PACKAGE_FIND_VERSION_MAJOR STREQUAL \"7\") + # Version 8 satisfies version 7... requirements + set(PACKAGE_FIND_VERSION_MAJOR 8) + set(PACKAGE_FIND_VERSION_COUNT 1) +endif() +${generated_version_config}" +) - # Use: - # * TARGETS_EXPORT_NAME - # * PROJECT_NAME - configure_package_config_file(CMake/curl-config.cmake.in - "${project_config}" - INSTALL_DESTINATION ${CURL_INSTALL_CMAKE_DIR} - ) - - if(CURL_ENABLE_EXPORT_TARGET) - install( - EXPORT "${TARGETS_EXPORT_NAME}" - NAMESPACE "${PROJECT_NAME}::" - DESTINATION ${CURL_INSTALL_CMAKE_DIR} - ) - endif() +# Use: +# * TARGETS_EXPORT_NAME +# * PROJECT_NAME +configure_package_config_file(CMake/curl-config.cmake.in + "${project_config}" + INSTALL_DESTINATION ${CURL_INSTALL_CMAKE_DIR} +) +if(CURL_ENABLE_EXPORT_TARGET) install( - FILES ${version_config} ${project_config} + EXPORT "${TARGETS_EXPORT_NAME}" + NAMESPACE "${PROJECT_NAME}::" DESTINATION ${CURL_INSTALL_CMAKE_DIR} ) +endif() - # Workaround for MSVS10 to avoid the Dialog Hell - # FIXME: This could be removed with future version of CMake. - if(MSVC_VERSION EQUAL 1600) - set(CURL_SLN_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/CURL.sln") - if(EXISTS "${CURL_SLN_FILENAME}") - file(APPEND "${CURL_SLN_FILENAME}" "\n# This should be regenerated!\n") - endif() - endif() +install( + FILES ${version_config} ${project_config} + DESTINATION ${CURL_INSTALL_CMAKE_DIR} +) - if(NOT TARGET curl_uninstall) - configure_file( - ${CMAKE_CURRENT_SOURCE_DIR}/CMake/cmake_uninstall.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake - IMMEDIATE @ONLY) - - add_custom_target(curl_uninstall - COMMAND ${CMAKE_COMMAND} -P - ${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake) +# Workaround for MSVS10 to avoid the Dialog Hell +# FIXME: This could be removed with future version of CMake. +if(MSVC_VERSION EQUAL 1600) + set(CURL_SLN_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/CURL.sln") + if(EXISTS "${CURL_SLN_FILENAME}") + file(APPEND "${CURL_SLN_FILENAME}" "\n# This should be regenerated!\n") endif() endif() + +if(NOT TARGET curl_uninstall) + configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/CMake/cmake_uninstall.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake + IMMEDIATE @ONLY) + + add_custom_target(curl_uninstall + COMMAND ${CMAKE_COMMAND} -P + ${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake) +endif() diff --git a/deps/curl/Makefile.am b/deps/curl/Makefile.am index c8afcb50..6c780a84 100644 --- a/deps/curl/Makefile.am +++ b/deps/curl/Makefile.am @@ -53,6 +53,27 @@ CMAKE_DIST = \ CMake/Utilities.cmake \ CMakeLists.txt +VC10_LIBTMPL = projects/Windows/VC10/lib/libcurl.tmpl +VC10_LIBVCXPROJ = projects/Windows/VC10/lib/libcurl.vcxproj.dist +VC10_LIBVCXPROJ_DEPS = $(VC10_LIBTMPL) Makefile.am lib/Makefile.inc +VC10_SRCTMPL = projects/Windows/VC10/src/curl.tmpl +VC10_SRCVCXPROJ = projects/Windows/VC10/src/curl.vcxproj.dist +VC10_SRCVCXPROJ_DEPS = $(VC10_SRCTMPL) Makefile.am src/Makefile.inc + +VC11_LIBTMPL = projects/Windows/VC11/lib/libcurl.tmpl +VC11_LIBVCXPROJ = projects/Windows/VC11/lib/libcurl.vcxproj.dist +VC11_LIBVCXPROJ_DEPS = $(VC11_LIBTMPL) Makefile.am lib/Makefile.inc +VC11_SRCTMPL = projects/Windows/VC11/src/curl.tmpl +VC11_SRCVCXPROJ = projects/Windows/VC11/src/curl.vcxproj.dist +VC11_SRCVCXPROJ_DEPS = $(VC11_SRCTMPL) Makefile.am src/Makefile.inc + +VC12_LIBTMPL = projects/Windows/VC12/lib/libcurl.tmpl +VC12_LIBVCXPROJ = projects/Windows/VC12/lib/libcurl.vcxproj.dist +VC12_LIBVCXPROJ_DEPS = $(VC12_LIBTMPL) Makefile.am lib/Makefile.inc +VC12_SRCTMPL = projects/Windows/VC12/src/curl.tmpl +VC12_SRCVCXPROJ = projects/Windows/VC12/src/curl.vcxproj.dist +VC12_SRCVCXPROJ_DEPS = $(VC12_SRCTMPL) Makefile.am src/Makefile.inc + VC14_LIBTMPL = projects/Windows/VC14/lib/libcurl.tmpl VC14_LIBVCXPROJ = projects/Windows/VC14/lib/libcurl.vcxproj.dist VC14_LIBVCXPROJ_DEPS = $(VC14_LIBTMPL) Makefile.am lib/Makefile.inc @@ -67,13 +88,6 @@ VC14_10_SRCTMPL = projects/Windows/VC14.10/src/curl.tmpl VC14_10_SRCVCXPROJ = projects/Windows/VC14.10/src/curl.vcxproj.dist VC14_10_SRCVCXPROJ_DEPS = $(VC14_10_SRCTMPL) Makefile.am src/Makefile.inc -VC14_20_LIBTMPL = projects/Windows/VC14.20/lib/libcurl.tmpl -VC14_20_LIBVCXPROJ = projects/Windows/VC14.20/lib/libcurl.vcxproj.dist -VC14_20_LIBVCXPROJ_DEPS = $(VC14_20_LIBTMPL) Makefile.am lib/Makefile.inc -VC14_20_SRCTMPL = projects/Windows/VC14.20/src/curl.tmpl -VC14_20_SRCVCXPROJ = projects/Windows/VC14.20/src/curl.vcxproj.dist -VC14_20_SRCVCXPROJ_DEPS = $(VC14_20_SRCTMPL) Makefile.am src/Makefile.inc - VC14_30_LIBTMPL = projects/Windows/VC14.30/lib/libcurl.tmpl VC14_30_LIBVCXPROJ = projects/Windows/VC14.30/lib/libcurl.vcxproj.dist VC14_30_LIBVCXPROJ_DEPS = $(VC14_30_LIBTMPL) Makefile.am lib/Makefile.inc @@ -85,6 +99,21 @@ VC_DIST = projects/README.md \ projects/build-openssl.bat \ projects/build-wolfssl.bat \ projects/checksrc.bat \ + projects/Windows/VC10/curl-all.sln \ + projects/Windows/VC10/lib/libcurl.sln \ + projects/Windows/VC10/lib/libcurl.vcxproj.filters \ + projects/Windows/VC10/src/curl.sln \ + projects/Windows/VC10/src/curl.vcxproj.filters \ + projects/Windows/VC11/curl-all.sln \ + projects/Windows/VC11/lib/libcurl.sln \ + projects/Windows/VC11/lib/libcurl.vcxproj.filters \ + projects/Windows/VC11/src/curl.sln \ + projects/Windows/VC11/src/curl.vcxproj.filters \ + projects/Windows/VC12/curl-all.sln \ + projects/Windows/VC12/lib/libcurl.sln \ + projects/Windows/VC12/lib/libcurl.vcxproj.filters \ + projects/Windows/VC12/src/curl.sln \ + projects/Windows/VC12/src/curl.vcxproj.filters \ projects/Windows/VC14/curl-all.sln \ projects/Windows/VC14/lib/libcurl.sln \ projects/Windows/VC14/lib/libcurl.vcxproj.filters \ @@ -95,11 +124,6 @@ VC_DIST = projects/README.md \ projects/Windows/VC14.10/lib/libcurl.vcxproj.filters \ projects/Windows/VC14.10/src/curl.sln \ projects/Windows/VC14.10/src/curl.vcxproj.filters \ - projects/Windows/VC14.20/curl-all.sln \ - projects/Windows/VC14.20/lib/libcurl.sln \ - projects/Windows/VC14.20/lib/libcurl.vcxproj.filters \ - projects/Windows/VC14.20/src/curl.sln \ - projects/Windows/VC14.20/src/curl.vcxproj.filters \ projects/Windows/VC14.30/curl-all.sln \ projects/Windows/VC14.30/lib/libcurl.sln \ projects/Windows/VC14.30/lib/libcurl.vcxproj.filters \ @@ -127,7 +151,8 @@ EXTRA_DIST = CHANGES COPYING maketgz Makefile.dist curl-config.in \ $(VC_DIST) $(WINBUILD_DIST) $(PLAN9_DIST) lib/libcurl.vers.in buildconf.bat \ libcurl.def -CLEANFILES = $(VC14_LIBVCXPROJ) \ +CLEANFILES = $(VC10_LIBVCXPROJ) $(VC10_SRCVCXPROJ) $(VC11_LIBVCXPROJ) \ + $(VC11_SRCVCXPROJ) $(VC12_LIBVCXPROJ) $(VC12_SRCVCXPROJ) $(VC14_LIBVCXPROJ) \ $(VC14_SRCVCXPROJ) $(VC14_10_LIBVCXPROJ) $(VC14_10_SRCVCXPROJ) \ $(VC14_30_LIBVCXPROJ) $(VC14_30_SRCVCXPROJ) @@ -275,9 +300,10 @@ checksrc: .PHONY: vc-ide -vc-ide: $(VC14_LIBVCXPROJ_DEPS) $(VC14_SRCVCXPROJ_DEPS) \ - $(VC14_10_LIBVCXPROJ_DEPS) $(VC14_10_SRCVCXPROJ_DEPS) \ - $(VC14_20_LIBVCXPROJ_DEPS) $(VC14_20_SRCVCXPROJ_DEPS) \ +vc-ide: $(VC10_LIBVCXPROJ_DEPS) $(VC10_SRCVCXPROJ_DEPS) \ + $(VC11_LIBVCXPROJ_DEPS) $(VC11_SRCVCXPROJ_DEPS) $(VC12_LIBVCXPROJ_DEPS) \ + $(VC12_SRCVCXPROJ_DEPS) $(VC14_LIBVCXPROJ_DEPS) $(VC14_SRCVCXPROJ_DEPS) \ + $(VC14_10_LIBVCXPROJ_DEPS) $(VC14_10_SRCVCXPROJ_DEPS) \ $(VC14_30_LIBVCXPROJ_DEPS) $(VC14_30_SRCVCXPROJ_DEPS) @(win32_lib_srcs='$(LIB_CFILES)'; \ win32_lib_hdrs='$(LIB_HFILES) config-win32.h'; \ @@ -439,6 +465,78 @@ function gen_element(type, dir, file)\ printf("%s\r\n", $$0);\ }';\ \ + echo "generating '$(VC10_LIBVCXPROJ)'"; \ + awk -v proj_type=vcxproj \ + -v lib_srcs="$$sorted_lib_srcs" \ + -v lib_hdrs="$$sorted_lib_hdrs" \ + -v lib_rc="$$win32_lib_rc" \ + -v lib_vauth_srcs="$$sorted_lib_vauth_srcs" \ + -v lib_vauth_hdrs="$$sorted_lib_vauth_hdrs" \ + -v lib_vquic_srcs="$$sorted_lib_vquic_srcs" \ + -v lib_vquic_hdrs="$$sorted_lib_vquic_hdrs" \ + -v lib_vssh_srcs="$$sorted_lib_vssh_srcs" \ + -v lib_vssh_hdrs="$$sorted_lib_vssh_hdrs" \ + -v lib_vtls_srcs="$$sorted_lib_vtls_srcs" \ + -v lib_vtls_hdrs="$$sorted_lib_vtls_hdrs" \ + "$$awk_code" $(srcdir)/$(VC10_LIBTMPL) > $(VC10_LIBVCXPROJ) || { exit 1; }; \ + \ + echo "generating '$(VC10_SRCVCXPROJ)'"; \ + awk -v proj_type=vcxproj \ + -v src_srcs="$$sorted_src_srcs" \ + -v src_hdrs="$$sorted_src_hdrs" \ + -v src_rc="$$win32_src_rc" \ + -v src_x_srcs="$$sorted_src_x_srcs" \ + -v src_x_hdrs="$$sorted_src_x_hdrs" \ + "$$awk_code" $(srcdir)/$(VC10_SRCTMPL) > $(VC10_SRCVCXPROJ) || { exit 1; }; \ + \ + echo "generating '$(VC11_LIBVCXPROJ)'"; \ + awk -v proj_type=vcxproj \ + -v lib_srcs="$$sorted_lib_srcs" \ + -v lib_hdrs="$$sorted_lib_hdrs" \ + -v lib_rc="$$win32_lib_rc" \ + -v lib_vauth_srcs="$$sorted_lib_vauth_srcs" \ + -v lib_vauth_hdrs="$$sorted_lib_vauth_hdrs" \ + -v lib_vquic_srcs="$$sorted_lib_vquic_srcs" \ + -v lib_vquic_hdrs="$$sorted_lib_vquic_hdrs" \ + -v lib_vssh_srcs="$$sorted_lib_vssh_srcs" \ + -v lib_vssh_hdrs="$$sorted_lib_vssh_hdrs" \ + -v lib_vtls_srcs="$$sorted_lib_vtls_srcs" \ + -v lib_vtls_hdrs="$$sorted_lib_vtls_hdrs" \ + "$$awk_code" $(srcdir)/$(VC11_LIBTMPL) > $(VC11_LIBVCXPROJ) || { exit 1; }; \ + \ + echo "generating '$(VC11_SRCVCXPROJ)'"; \ + awk -v proj_type=vcxproj \ + -v src_srcs="$$sorted_src_srcs" \ + -v src_hdrs="$$sorted_src_hdrs" \ + -v src_rc="$$win32_src_rc" \ + -v src_x_srcs="$$sorted_src_x_srcs" \ + -v src_x_hdrs="$$sorted_src_x_hdrs" \ + "$$awk_code" $(srcdir)/$(VC11_SRCTMPL) > $(VC11_SRCVCXPROJ) || { exit 1; }; \ + \ + echo "generating '$(VC12_LIBVCXPROJ)'"; \ + awk -v proj_type=vcxproj \ + -v lib_srcs="$$sorted_lib_srcs" \ + -v lib_hdrs="$$sorted_lib_hdrs" \ + -v lib_rc="$$win32_lib_rc" \ + -v lib_vauth_srcs="$$sorted_lib_vauth_srcs" \ + -v lib_vauth_hdrs="$$sorted_lib_vauth_hdrs" \ + -v lib_vquic_srcs="$$sorted_lib_vquic_srcs" \ + -v lib_vquic_hdrs="$$sorted_lib_vquic_hdrs" \ + -v lib_vssh_srcs="$$sorted_lib_vssh_srcs" \ + -v lib_vssh_hdrs="$$sorted_lib_vssh_hdrs" \ + -v lib_vtls_srcs="$$sorted_lib_vtls_srcs" \ + -v lib_vtls_hdrs="$$sorted_lib_vtls_hdrs" \ + "$$awk_code" $(srcdir)/$(VC12_LIBTMPL) > $(VC12_LIBVCXPROJ) || { exit 1; }; \ + \ + echo "generating '$(VC12_SRCVCXPROJ)'"; \ + awk -v proj_type=vcxproj \ + -v src_srcs="$$sorted_src_srcs" \ + -v src_hdrs="$$sorted_src_hdrs" \ + -v src_rc="$$win32_src_rc" \ + -v src_x_srcs="$$sorted_src_x_srcs" \ + -v src_x_hdrs="$$sorted_src_x_hdrs" \ + "$$awk_code" $(srcdir)/$(VC12_SRCTMPL) > $(VC12_SRCVCXPROJ) || { exit 1; }; \ + \ echo "generating '$(VC14_LIBVCXPROJ)'"; \ awk -v proj_type=vcxproj \ -v lib_srcs="$$sorted_lib_srcs" \ @@ -487,29 +585,6 @@ function gen_element(type, dir, file)\ -v src_x_hdrs="$$sorted_src_x_hdrs" \ "$$awk_code" $(srcdir)/$(VC14_10_SRCTMPL) > $(VC14_10_SRCVCXPROJ) || { exit 1; }; \ \ - echo "generating '$(VC14_20_LIBVCXPROJ)'"; \ - awk -v proj_type=vcxproj \ - -v lib_srcs="$$sorted_lib_srcs" \ - -v lib_hdrs="$$sorted_lib_hdrs" \ - -v lib_rc="$$win32_lib_rc" \ - -v lib_vauth_srcs="$$sorted_lib_vauth_srcs" \ - -v lib_vauth_hdrs="$$sorted_lib_vauth_hdrs" \ - -v lib_vquic_srcs="$$sorted_lib_vquic_srcs" \ - -v lib_vquic_hdrs="$$sorted_lib_vquic_hdrs" \ - -v lib_vssh_srcs="$$sorted_lib_vssh_srcs" \ - -v lib_vssh_hdrs="$$sorted_lib_vssh_hdrs" \ - -v lib_vtls_srcs="$$sorted_lib_vtls_srcs" \ - -v lib_vtls_hdrs="$$sorted_lib_vtls_hdrs" \ - "$$awk_code" $(srcdir)/$(VC14_20_LIBTMPL) > $(VC14_20_LIBVCXPROJ) || { exit 1; }; \ - \ - echo "generating '$(VC14_20_SRCVCXPROJ)'"; \ - awk -v proj_type=vcxproj \ - -v src_srcs="$$sorted_src_srcs" \ - -v src_hdrs="$$sorted_src_hdrs" \ - -v src_rc="$$win32_src_rc" \ - -v src_x_srcs="$$sorted_src_x_srcs" \ - -v src_x_hdrs="$$sorted_src_x_hdrs" \ - "$$awk_code" $(srcdir)/$(VC14_20_SRCTMPL) > $(VC14_20_SRCVCXPROJ) || { exit 1; };) \ echo "generating '$(VC14_30_LIBVCXPROJ)'"; \ awk -v proj_type=vcxproj \ -v lib_srcs="$$sorted_lib_srcs" \ diff --git a/deps/curl/RELEASE-NOTES b/deps/curl/RELEASE-NOTES index f2712ee5..0b331a48 100644 --- a/deps/curl/RELEASE-NOTES +++ b/deps/curl/RELEASE-NOTES @@ -1,193 +1,155 @@ -curl and libcurl 8.5.0 +curl and libcurl 8.4.0 - Public curl releases: 253 + Public curl releases: 252 Command line options: 258 curl_easy_setopt() options: 303 Public functions in libcurl: 93 - Contributors: 3035 + Contributors: 2995 This release includes the following changes: - o gnutls: support CURLSSLOPT_NATIVE_CA [31] - o HTTP3: ngtcp2 builds are no longer experimental [77] + o curl: add support for the IPFS protocols via HTTP gateway [46] + o curl_multi_get_handles: get easy handles from a multi handle [20] + o mingw: delete support for legacy mingw.org toolchain [45] This release includes the following bugfixes: - o appveyor: make VS2008-built curl tool runnable [93] - o asyn-thread: use pipe instead of socketpair for IPC when available [4] - o autotools: accept linker flags via `CURL_LDFLAGS_{LIB,BIN}` [128] - o autotools: avoid passing `LDFLAGS` twice to libcurl [127] - o autotools: delete LCC compiler support bits [137] - o autotools: fix/improve gcc and Apple clang version detection [136] - o autotools: stop setting `-std=gnu89` with `--enable-warnings` [135] - o autotools: update references to deleted `crypt-auth` option [46] - o BINDINGS: add V binding [54] - o build: add `src/.checksrc` to source tarball [1] - o build: add more picky warnings and fix them [172] - o build: always revert `#pragma GCC diagnostic` after use [143] - o build: delete `HAVE_STDINT_H` and `HAVE_INTTYPES_H` [107] - o build: delete support bits for obsolete Windows compilers [106] - o build: fix 'threadsafe' feature detection for older gcc [19] - o build: fix compiler warning with auths disabled [85] - o build: fix libssh2 + `CURL_DISABLE_DIGEST_AUTH` + `CURL_DISABLE_AWS` [120] - o build: picky warning updates [125] - o build: require Windows XP or newer [86] - o cfilter: provide call to tell connection to forget a socket [65] - o CI: add autotools, out-of-tree, debug build to distro check job [14] - o CI: ignore test 286 on Appveyor gcc 9 build [6] - o cmake: add `CURL_DISABLE_BINDLOCAL` option [146] - o cmake: add test for `DISABLE` options, add `CURL_DISABLE_HEADERS_API` [138] - o cmake: dedupe Windows system libs [114] - o cmake: fix `HAVE_H_ERRNO_ASSIGNABLE` detection [2] - o cmake: fix CURL_DISABLE_GETOPTIONS [12] - o cmake: fix multiple include of CURL package [96] - o cmake: fix OpenSSL quic detection in quiche builds [56] - o cmake: option to disable install & drop `curlu` target when unused [72] - o cmake: pre-fill rest of detection values for Windows [50] - o cmake: replace `check_library_exists_concat()` [23] - o cmake: speed up threads setup for Windows [68] - o cmake: speed up zstd detection [69] - o config-win32: set `HAVE_SNPRINTF` for mingw-w64 [123] - o configure: better --disable-http [80] - o configure: check for the fseeko declaration too [55] - o conncache: use the closure handle when disconnecting surplus connections [173] - o content_encoding: make Curl_all_content_encodings allocless [101] - o cookie: lowercase the domain names before PSL checks [160] - o curl.h: delete Symbian OS references [162] - o curl.h: on FreeBSD include sys/param.h instead of osreldate.h [21] - o curl.rc: switch out the copyright symbol for plain ASCII [167] - o curl: improved IPFS and IPNS URL support [87] - o curl_easy_duphandle.3: clarify how HSTS and alt-svc are duped [99] - o Curl_http_body: cleanup properly when Curl_getformdata errors [152] - o curl_setup: disallow Windows IPv6 builds missing getaddrinfo [57] - o curl_sspi: support more revocation error names in error messages [95] - o CURLMOPT_MAX_CONCURRENT_STREAMS: make sure the set value is within range [165] - o CURLOPT_CAINFO_BLOB.3: explain what CURL_BLOB_COPY does [113] - o CURLOPT_WRITEFUNCTION.3: clarify libcurl returns for CURL_WRITEFUNC_ERROR [45] - o CURPOST_POSTFIELDS.3: add CURLOPT_COPYPOSTFIELDS in SEE ALSO - o docs/example/keepalive.c: show TCP keep-alive options [73] - o docs/example/localport.c: show off CURLOPT_LOCALPORT [83] - o docs/examples/interface.c: show CURLOPT_INTERFACE use [84] - o docs/libcurl: fix three minor man page format mistakes [26] - o docs/libcurl: SYNSOPSIS cleanup [150] - o docs: add supported version for the json write-out [92] - o docs: clarify that curl passes on input unfiltered [47] - o docs: fix function typo in curl_easy_option_next.3 [36] - o docs: KNOWN_BUGS cleanup - o docs: preserve the modification date when copying the prebuilt man page [89] - o docs: remove bold from some man page SYNOPSIS sections [90] - o docs: use SOURCE_DATE_EPOCH for generated manpages [16] - o doh: provide better return code for responses w/o addresses [133] - o doh: use PIPEWAIT when HTTP/2 is attempted [63] - o duphandle: also free 'outcurl->cookies' in error path [122] - o duphandle: make dupset() not return with pointers to old alloced data [109] - o duphandle: use strdup to clone *COPYPOSTFIELDS if size is not set [132] - o easy: in duphandle, init the cookies for the new handle [131] - o easy: remove duplicate wolfSSH init call [37] - o easy_lock: add a pthread_mutex_t fallback [13] - o fopen: create new file using old file's mode [153] - o fopen: create short(er) temporary file name [155] - o getenv: PlayStation doesn't have getenv() [41] - o GHA: move mod_h2 version in CI to v2.0.25 [43] - o hostip: show the list of IPs when resolving is done [35] - o hostip: silence compiler warning `-Wparentheses-equality` [62] - o hsts: skip single-dot hostname [67] - o HTTP/2, HTTP/3: handle detach of onoing transfers [134] - o http2: header conversion tightening [33] - o http2: provide an error callback and failf the message [53] - o http2: safer invocation of populate_binsettings [8] - o http: allow longer HTTP/2 request method names [112] - o http: avoid Expect: 100-continue if Upgrade: is used [15] - o http: consider resume with CURLOPT_FAILONERRROR and 416 to be fine [81] - o http: fix `-Wunused-parameter` with no auth and no proxy [149] - o http: fix `-Wunused-variable` compiler warning [115] - o http: fix empty-body warning [76] - o http_aws_sigv4: canonicalise valueless query params [88] - o hyper: temporarily remove HTTP/2 support [139] - o IPFS: fix IPFS_PATH and file parsing [119] - o keylog: disable if unused [145] - o lib: add and use Curl_strndup() [97] - o lib: apache style infof and trace macros/functions [71] - o lib: fix gcc warning in printf call [7] - o libcurl-errors.3: sync with current public headers [156] - o libcurl-thread.3: simplify the TLS section [79] - o Makefile.am: drop vc10, vc11 and vc12 projects from dist [103] - o Makefile.mk: fix `-rtmp` option for non-Windows - o mime: store "form escape" as a single bit [170] - o misc: fix -Walloc-size warnings [118] - o msh3: error when built with CURL_DISABLE_SOCKETPAIR set [61] - o multi: use pipe instead of socketpair to *wakeup() [18] - o ntlm_wb: use pipe instead of socketpair when possible [44] - o openldap: move the alloc of ldapconninfo to *connect() [29] - o openldap: set the callback argument in oldap_do [30] - o openssl: avoid BN_num_bits() NULL pointer derefs [9] - o openssl: enable `infof_certstack` for 1.1 and LibreSSL 3.6 [157] - o openssl: fix building with v3 `no-deprecated` + add CI test [161] - o openssl: fix infof() to avoid compiler warning for %s with null [70] - o openssl: identify the "quictls" backend correctly [82] - o openssl: include SIG and KEM algorithms in verbose [52] - o openssl: make CURLSSLOPT_NATIVE_CA import Windows intermediate CAs [58] - o openssl: two multi pointer checks should probably rather be asserts [91] - o openssl: when a session-ID is reused, skip OCSP stapling [142] - o page-footer: clarify exit code 25 [51] - o projects: add VC14.20 project files [104] - o pytest: use lower count in repeat tests [98] - o quic: make eyeballers connect retries stop at weird replies [140] - o quic: manage connection idle timeouts [5] - o quiche: use quiche_conn_peer_transport_params() [116] - o rand: fix build error with autotools + LibreSSL [111] - o resolve.d: drop a multi use-sentence [100] - o RTSP: improved RTP parser [32] - o sasl: fix `-Wunused-function` compiler warning [124] - o schannel: add CA cache support for files and memory blobs [121] - o setopt: check CURLOPT_TFTP_BLKSIZE range on set [171] - o setopt: remove outdated cookie comment [64] - o setopt: remove superfluous use of ternary expressions [169] - o socks: better buffer size checks for socks4a user and hostname [20] - o socks: make SOCKS5 use the CURLOPT_IPRESOLVE choice [38] - o test1683: remove commented-out check alternatives - o test3103: add missing quotes around a test tag attribute - o test613: stop showing an error on missing output file - o tests/README: SOCKS tests are not using OpenSSH, it has its own server [48] - o tests/server: add more SOCKS5 handshake error checking [27] - o tests: Fix Windows test helper tool search & use it for handle64 [17] - o tidy-up: casing typos, delete unused Windows version aliases [144] - o tool: fix --capath when proxy support is disabled [28] - o tool: support bold headers in Windows [117] - o tool_cb_hdr: add an additional parsing check [129] - o tool_cb_prg: make the carriage return fit for wide progress bars [159] - o tool_cb_wrt: fix write output for very old Windows versions [24] - o tool_getparam: limit --rate to be smaller than number of ms [3] - o tool_operate: do not mix memory models [108] - o tool_operate: fix links in ipfs errors [22] - o tool_parsecfg: make warning output propose double-quoting [164] - o tool_urlglob: fix build for old gcc versions [25] - o tool_urlglob: make multiply() bail out on negative values [11] - o transfer: avoid calling the read callback again after EOF [130] - o transfer: only reset the FTP wildcard engine in CLEAR state [42] - o url: don't touch the multi handle when closing internal handles [40] - o url: find scheme with a "perfect hash" [141] - o url: fix `-Wzero-length-array` with no protocols [147] - o url: fix builds with `CURL_DISABLE_HTTP` [148] - o url: protocol handler lookup tidy-up [66] - o url: proxy ssl connection reuse fix [94] - o urlapi: avoid null deref if setting blank host to url encode [75] - o urlapi: skip appending NULL pointer query [74] - o urlapi: when URL encoding the fragment, pass in the right length [59] - o urldata: make maxconnects a 32 bit value [166] - o urldata: move async resolver state from easy handle to connectdata [34] - o urldata: move cookielist from UserDefined to UrlState [126] - o urldata: move hstslist from 'set' to 'state' [105] - o urldata: move the 'internal' boolean to the state struct [39] - o vssh: remove the #ifdef for Curl_ssh_init, use empty macro - o vtls: cleanup SSL config management [78] - o vtls: late clone of connection ssl config [60] - o vtls: use ALPN "http/1.1" for HTTP/1.x, including HTTP/1.0 [102] - o VULN-DISCLOSURE-POLICY: escape sequences are not a security flaw [110] - o windows: use built-in `_WIN32` macro to detect Windows [163] - o wolfssh: remove redundant static prototypes [168] - o wolfssl: add default case for wolfssl_connect_step1 switch [49] - o wolfssl: require WOLFSSL_SYS_CA_CERTS for loading system CA [10] + o acinclude.m4: Document proper system truststore on FreeBSD [83] + o appveyor: fix yamlint issues, indent [67] + o appveyor: rewrite batch in PowerShell + CI improvements [109] + o autotools: adjust `CURL_CA_PATH` value to CMake [53] + o autotools: restore `HAVE_IOCTL_*` detections [111] + o base64: also build for curl [78] + o bufq: remove Curl_bufq_skip_and_shift (unused) [47] + o build: delete checks for C89 standard headers [65] + o build: do not publish `HAVE_BORINGSSL`, `HAVE_AWSLC` macros [114] + o cf-socket: simulate slow/blocked receives in debug [120] + o cmake, configure: also link with CoreServices [32] + o cmake: add check for suseconds_t [91] + o cmake: add feature checks for `memrchr` and `getifaddrs` [57] + o cmake: add missing checks [86] + o cmake: delete old `HAVE_LDAP_URL_PARSE` logic [105] + o cmake: detect `HAVE_CLOCK_GETTIME_MONOTONIC_RAW` [75] + o cmake: detect `HAVE_GETADDRINFO_THREADSAFE` [76] + o cmake: detect `sys/wait.h` and `netinet/udp.h` [61] + o cmake: detect TLS-SRP in OpenSSL/wolfSSL/GnuTLS [93] + o cmake: disable unity mode with Windows Unicode + TrackMemory [108] + o cmake: fix `HAVE_LDAP_SSL`, `HAVE_LDAP_URL_PARSE` on non-Windows [110] + o cmake: fix `HAVE_WRITABLE_ARGV` detection [77] + o cmake: fix duplicate symbols when linking tests [73] + o cmake: fix missing `zlib.h` when compiling `libcurltool` [72] + o cmake: fix stderr initialization in unity builds [71] + o cmake: fix the help text to the static build option in CMakeLists.txt [10] + o cmake: fix unity builds for more build combinations [96] + o cmake: fix unity symbol collisions in h2 builds [48] + o cmake: fix unity with Windows Unicode + TrackMemory [107] + o cmake: improve OpenLDAP builds [92] + o cmake: lib `CURL_STATICLIB` fixes (Windows) [74] + o cmake: move global headers to specific checks [58] + o cmake: pre-cache `HAVE_BASENAME` for mingw-w64 and MSVC [85] + o cmake: pre-cache `HAVE_POLL_FINE` on Windows [36] + o cmake: tidy-up `NOT_NEED_LBER_H` detection + o cmake: validate `CURL_DEFAULT_SSL_BACKEND` config value [50] + o configure: check for the capath by default [63] + o configure: remove unused checks [87] + o configure: replace adhoc domain with `localhost` in tests [79] + o configure: sort AC_CHECK_FUNCS + o connect: expire the timeout when trying next [54] + o connect: only start the happy eyeballs timer when needed [95] + o cookie: do not store the expire or max-age strings [16] + o cookie: remove unnecessary struct fields [17] + o cookie: set ->running in cookie_init even if data is NULL [5] + o create-dirs.d: clarify it also uses --output-dirs [66] + o curl.h: mark CURLSSLBACKEND_NSS as deprecated since 8.3.0 [18] + o curl_easy_pause.3: mention h2/h3 buffering [113] + o curl_easy_pause.3: mention it works within callbacks [112] + o curl_easy_pause: set "in callback" true on exit if true [100] + o CURLOPT_DEBUGFUNCTION.3: warn about internal handles [122] + o docs/libcurl/opts/Makefile.inc: add missing manpage files + o docs: adapt SEE ALSO sections to new requirements [52] + o docs: explain how PINNEDPUBLICKEY is independent of VERIFYPEER [68] + o docs: replace made up domains with example.com [82] + o docs: update curl man page references [89] + o docs: use CURLSSLBACKEND_NONE [19] + o doh: inherit DEBUGFUNCTION/DATA [12] + o escape: replace Curl_isunreserved with ISUNRESERVED [2] + o FAQ: How do I upgrade curl.exe in Windows? [84] + o GHA/linux: run singleuse to detect single-use global functions [35] + o GHA: add workflow to compare configure vs cmake outputs [102] + o h2-proxy: remove left-over mistake in drain_tunnel() [7] + o h2: testcase and fix for pausing h2 streams [49] + o h3: add support for ngtcp2 with AWS-LC builds [103] + o http2: refused stream handling for retry [121] + o http: fix CURL_DISABLE_BEARER_AUTH breakage [28] + o http: h1/h2 proxy unification [21] + o http: remove wrong comment for http_should_fail [55] + o http: use per-request counter to check too large headers [6] + o http_aws_sigv4: fix sorting with empty parts [13] + o idn: fix WinIDN null ptr deref on bad host [90] + o idn: if idn2_check_version returns NULL, return error [27] + o inet_ntop: add typecast to silence Coverity [51] + o lib: disambiguate Curl_client_write flag semantics [24] + o lib: enable hmac for digest as well [26] + o lib: failf/infof compiler warnings [8] + o lib: let the max filesize option stop too big transfers too [44] + o lib: move handling of `data->req.writer_stack` into Curl_client_write() [97] + o lib: provide and use Curl_hexencode [62] + o lib: remove TIME_WITH_SYS_TIME [88] + o lib: use wrapper for curl_mime_data fseek callback [30] + o libssh2: fix error message on failed pubkey-from-file [22] + o libssh: cap SFTP packet size sent [14] + o Makefile.mk: always set `CURL_STATICLIB` for lib (Windows) [42] + o MANUAL.md: change domain to example.com [11] + o misc: better random strings [15] + o MQTT: improve receive of ACKs [125] + o multi: do CURLM_CALL_MULTI_PERFORM at two more places [99] + o multi: fix small timeouts [70] + o multi: remove Curl_multi_dump [37] + o multi: round the timeout up to prevent early wakeups [98] + o multi: set CURLM_CALL_MULTI_PERFORM after switch to DOING_MORE [115] + o openssl: improve ssl shutdown handling [69] + o openssl: use X509_ALGOR_get0 instead of reaching into X509_ALGOR [104] + o pytest: exclude test_03_goaway in CI runs due to timing dependency [23] + o quic: set ciphers/curves the same way regular TLS does [43] + o quiche: fix build error with --with-ca-fallback [1] + o RELEASE-PROCEDURE.md: updated coming release dates + o runtests: display the test status if tests appear hung [81] + o runtests: eliminate a warning on old perl versions + o socks: return error if hostname too long for remote resolve [118] + o src/mkhelp: make generated code pass `checksrc` [59] + o test1056: disable on Windows + o test1474: disable test on NetBSD, OpenBSD and Solaris 10 [31] + o test1592: greatly increase the maximum test timeout + o test1903: actually verify the cookies after the test [116] + o test1906: set a lower timeout since it's hit on Windows [117] + o test2600: remove special case handling for USE_ALARM_TIMEOUT [3] + o test650: fix an end tag typo + o test661: return from test early in case of curl error + o test: add missing s + o tests: close the shell used to start sshd [41] + o tests: fix a race condition in ftp server disconnect [101] + o tests: fix compiler warnings [38] + o tests: Fix zombie processes left behind by FTP tests. [80] + o tests: improve SLOWDOWN test reliability by reducing sent data + o tests: increase lib571 timeout from 3s to 30s [106] + o tests: log the test result code after each libtest + o tests: propagate errors in libtests + o tests: set --expect100-timeout to improve test reliability + o tests: show which curl tool `runtests.pl` is using [60] + o tests: stop overriding the lock timeout + o tftpd: always use curl's own tftp.h [25] + o tool: use our own stderr variable [94] + o tool_cb_wrt: fix debug assertion [4] + o tool_getparam: accept variable expansion on file names too [123] + o tool_setopt: remove unused function tool_setopt_flags [56] + o upload-file.d: describe the file name slash/backslash handling [9] + o url: fall back to http/https proxy env-variable if ws/wss not set [119] + o url: fix netrc info message [39] + o warnless: remove unused functions [33] + o wolfssh: do cleanup in Curl_ssh_cleanup [40] + o wolfssl: allow capath with CURLOPT_CAINFO_BLOB [29] + o wolfssl: if CURLOPT_CAINFO_BLOB is set, ignore the CA files [34] + o wolfssl: ignore errors in CA path [64] This release includes the following known bugs: @@ -202,193 +164,143 @@ Planned upcoming removals include: This release would not have looked like this without help, code, reports and advice from friends like these: - 12932 on github, Alex Bozarth, Alexey Larikov, Alex Klyubin, Ammar Faizi, - Andrew Kurushin, Anubhav Rai, boilingoden, calvin2021y on github, - Carlos Henrique Lima Melara, Casey Bodley, Charlie C, Dan Fandrich, - Daniel Jeliński, Daniel Stenberg, David Suter, Emanuele Torre, Enno Boland, - enWILLYado on github, Faraz Fallahi, Gisle Vanem, Goro FUJI, Harry Mallon, - Harry Sintonen, icy17 on github, Jacob Hoffman-Andrews, - Jan Alexander Steffens, Jeroen Ooms, Jiehong on github, Jiri Hruska, - Junho Choi, Kai Pastor, Kareem, Kartatz on Github, kirbyn17 on hackerone, - lkordos on github, Loïc Yhuel, LoRd_MuldeR, lRoccoon on github, - Maksymilian Arciemowicz, Manfred Schwarb, Marcel Raad, Marcin Rataj, - Mark Gaiser, Martin Schmatz, Michael Kaufmann, Nico Rieck, Niracler Li, - ohyeaah on github, Ophir Lojkine, Paweł Wegner, Philip Heiduck, Ray Satiro, - rilysh, Robert Southee, Romain Geissler, Sam James, Samuel Henrique, - sd0 on hackerone, Smackd0wn, Sohom Datta, Stefan Eissing, Steven Allen, - Tim Hill, Torben Dury, Turiiya, Viktor Szakats, yushicheng7788 on github, - zhengqwe on github, 積丹尼 Dan Jacobson - (70 contributors) + Aleksander Mazur, black-desk on github, calvin2021y on github, + Christian Schmitz, Christian Weisgerber, claudiusaiz on github, + consulion on github, Craig Andrews, Dan Fandrich, Daniel Stenberg, + David Benjamin, Douglas R. Reno, Eduard Strehlau, Elliot Killick, + Gisle Vanem, Hakan Sunay Halil, Harry Sintonen, Jakub Jelen, John Haugabook, + Joshix-1 on github, Juliusz Sosinowicz, Junho Choi, + Karthikdasari0423 on github, Lars Francke, Loïc Yhuel, Marc Hörsken, + Mark Gaiser, Mathias Fuchs, Maxim Dzhura, Michael Osipov, Natanael Copa, + Patrick Monnerat, PBudmark on github, Peter Wang, Philip Heiduck, Ray Satiro, + Robert Simpson, Ryan Schmidt, s0urc3_ on hackerone, Samuel Henrique, + Stefan Eissing, Ted Lyngmo, Viktor Szakats, vvb2060, w0x42 on hackerone, + 南宫雪珊 + (46 contributors) References to bug reports and discussions on issues: - [1] = https://curl.se/bug/?i=12084 - [2] = https://curl.se/bug/?i=12093 - [3] = https://curl.se/bug/?i=12116 - [4] = https://curl.se/bug/?i=12146 - [5] = https://curl.se/bug/?i=12064 - [6] = https://curl.se/bug/?i=12040 - [7] = https://curl.se/bug/?i=12082 - [8] = https://curl.se/bug/?i=12101 - [9] = https://curl.se/bug/?i=12099 - [10] = https://curl.se/bug/?i=12108 - [11] = https://curl.se/bug/?i=12102 - [12] = https://curl.se/bug/?i=12091 - [13] = https://curl.se/bug/?i=12090 - [14] = https://curl.se/bug/?i=12088 - [15] = https://curl.se/bug/?i=12022 - [16] = https://curl.se/bug/?i=12092 - [17] = https://curl.se/bug/?i=12115 - [18] = https://curl.se/bug/?i=12142 - [19] = https://curl.se/bug/?i=12125 - [20] = https://curl.se/bug/?i=12139 - [21] = https://curl.se/bug/?i=12107 - [22] = https://curl.se/bug/?i=12133 - [23] = https://curl.se/bug/?i=11285 - [24] = https://curl.se/bug/?i=12131 - [25] = https://curl.se/bug/?i=12124 - [26] = https://curl.se/bug/?i=12126 - [27] = https://curl.se/bug/?i=12117 - [28] = https://curl.se/bug/?i=12089 - [29] = https://curl.se/bug/?i=12166 - [30] = https://curl.se/bug/?i=12166 - [31] = https://curl.se/bug/?i=12137 - [32] = https://curl.se/bug/?i=12052 - [33] = https://curl.se/bug/?i=12097 - [34] = https://curl.se/bug/?i=12198 - [35] = https://curl.se/bug/?i=12145 - [36] = https://curl.se/bug/?i=12170 - [37] = https://curl.se/bug/?i=12168 - [38] = https://curl.se/bug/?i=11949 - [39] = https://curl.se/bug/?i=12165 - [40] = https://curl.se/bug/?i=12165 - [41] = https://curl.se/bug/?i=12140 - [42] = https://curl.se/bug/?i=11775 - [43] = https://curl.se/bug/?i=12157 - [44] = https://curl.se/bug/?i=12149 - [45] = https://curl.se/bug/?i=12201 - [46] = https://curl.se/bug/?i=12194 - [47] = https://curl.se/bug/?i=12249 - [48] = https://curl.se/bug/?i=12195 - [49] = https://curl.se/bug/?i=12218 - [50] = https://curl.se/bug/?i=12044 - [51] = https://curl.se/bug/?i=12189 - [52] = https://curl.se/bug/?i=12030 - [53] = https://curl.se/bug/?i=12179 - [54] = https://curl.se/bug/?i=12182 - [55] = https://curl.se/bug/?i=12086 - [56] = https://curl.se/bug/?i=12160 - [57] = https://curl.se/bug/?i=12221 - [58] = https://curl.se/bug/?i=12155 - [59] = https://curl.se/bug/?i=12250 - [60] = https://curl.se/bug/?i=12237 - [61] = https://curl.se/bug/?i=12213 - [62] = https://curl.se/bug/?i=12215 - [63] = https://curl.se/bug/?i=12214 - [64] = https://curl.se/bug/?i=12206 - [65] = https://curl.se/bug/?i=12207 - [66] = https://curl.se/bug/?i=12216 - [67] = https://curl.se/bug/?i=12247 - [68] = https://curl.se/bug/?i=12202 - [69] = https://curl.se/bug/?i=12200 - [70] = https://curl.se/bug/?i=12196 - [71] = https://curl.se/bug/?i=12083 - [72] = https://curl.se/bug/?i=12287 - [73] = https://curl.se/bug/?i=12242 - [74] = https://curl.se/bug/?i=12240 - [75] = https://curl.se/bug/?i=12240 - [76] = https://curl.se/bug/?i=12262 - [77] = https://curl.se/bug/?i=12235 - [78] = https://curl.se/bug/?i=12204 - [79] = https://curl.se/bug/?i=12233 - [80] = https://curl.se/bug/?i=12223 - [81] = https://curl.se/bug/?i=10521 - [82] = https://curl.se/bug/?i=12270 - [83] = https://curl.se/bug/?i=12230 - [84] = https://curl.se/bug/?i=12229 - [85] = https://curl.se/bug/?i=12227 - [86] = https://curl.se/bug/?i=12225 - [87] = https://curl.se/bug/?i=12148 - [88] = https://curl.se/bug/?i=8107 - [89] = https://curl.se/bug/?i=12199 - [90] = https://curl.se/bug/?i=12267 - [91] = https://curl.se/bug/?i=12264 - [92] = https://curl.se/bug/?i=12266 - [93] = https://curl.se/bug/?i=12263 - [94] = https://curl.se/bug/?i=12255 - [95] = https://curl.se/bug/?i=12239 - [96] = https://curl.se/bug/?i=11913 - [97] = https://curl.se/bug/?i=12251 - [98] = https://curl.se/bug/?i=12248 - [99] = https://curl.se/bug/?i=12315 - [100] = https://curl.se/bug/?i=12294 - [101] = https://curl.se/bug/?i=12289 - [102] = https://curl.se/bug/?i=12259 - [103] = https://curl.se/bug/?i=12288 - [104] = https://curl.se/bug/?i=12282 - [105] = https://curl.se/bug/?i=12315 - [106] = https://curl.se/bug/?i=12222 - [107] = https://curl.se/bug/?i=12275 - [108] = https://curl.se/bug/?i=12280 - [109] = https://curl.se/bug/?i=12337 - [110] = https://curl.se/bug/?i=12278 - [111] = https://curl.se/bug/?i=12257 - [112] = https://curl.se/bug/?i=12311 - [113] = https://curl.se/bug/?i=12277 - [114] = https://curl.se/bug/?i=12307 - [115] = https://curl.se/bug/?i=12228 - [116] = https://curl.se/bug/?i=12180 - [117] = https://curl.se/bug/?i=12321 - [118] = https://curl.se/bug/?i=12292 - [119] = https://curl.se/bug/?i=12152 - [120] = https://curl.se/bug/?i=12273 - [121] = https://curl.se/bug/?i=12261 - [122] = https://curl.se/bug/?i=12329 - [123] = https://curl.se/bug/?i=12325 - [124] = https://curl.se/bug/?i=12326 - [125] = https://curl.se/bug/?i=12324 - [126] = https://curl.se/bug/?i=12323 - [127] = https://curl.se/bug/?i=12310 - [128] = https://curl.se/bug/?i=12312 - [129] = https://curl.se/bug/?i=12320 - [130] = https://curl.se/mail/lib-2023-11/0017.html - [131] = https://curl.se/bug/?i=12318 - [132] = https://curl.se/bug/?i=12317 - [133] = https://curl.se/bug/?i=12365 - [134] = https://curl.se/bug/?i=12356 - [135] = https://curl.se/bug/?i=12346 - [136] = https://curl.se/bug/?i=12362 - [137] = https://curl.se/bug/?i=12357 - [138] = https://curl.se/bug/?i=12353 - [139] = https://curl.se/bug/?i=12191 - [140] = https://curl.se/bug/?i=12400 - [141] = https://curl.se/bug/?i=12347 - [142] = https://curl.se/bug/?i=12399 - [143] = https://curl.se/bug/?i=12352 - [144] = https://curl.se/bug/?i=12351 - [145] = https://curl.se/bug/?i=12350 - [146] = https://curl.se/bug/?i=12345 - [147] = https://curl.se/bug/?i=12344 - [148] = https://curl.se/bug/?i=12343 - [149] = https://curl.se/bug/?i=12338 - [150] = https://curl.se/bug/?i=12402 - [152] = https://curl.se/bug/?i=12410 - [153] = https://curl.se/bug/?i=12299 - [155] = https://curl.se/bug/?i=12388 - [156] = https://curl.se/bug/?i=12424 - [157] = https://curl.se/bug/?i=12385 - [159] = https://curl.se/bug/?i=12407 - [160] = https://curl.se/bug/?i=12387 - [161] = https://curl.se/bug/?i=12384 - [162] = https://curl.se/bug/?i=12378 - [163] = https://curl.se/bug/?i=12376 - [164] = https://curl.se/bug/?i=12409 - [165] = https://curl.se/bug/?i=12382 - [166] = https://curl.se/bug/?i=12375 - [167] = https://curl.se/bug/?i=12403 - [168] = https://curl.se/bug/?i=12381 - [169] = https://curl.se/bug/?i=12374 - [170] = https://curl.se/bug/?i=12374 - [171] = https://curl.se/bug/?i=12374 - [172] = https://curl.se/bug/?i=12331 - [173] = https://curl.se/bug/?i=12367 + [1] = https://curl.se/bug/?i=11850 + [2] = https://curl.se/bug/?i=11846 + [3] = https://curl.se/bug/?i=11767 + [4] = https://github.com/curl/curl/commit/af3f4e41#r127212213 + [5] = https://curl.se/bug/?i=11875 + [6] = https://curl.se/bug/?i=11871 + [7] = https://curl.se/bug/?i=11877 + [8] = https://curl.se/bug/?i=11874 + [9] = https://curl.se/bug/?i=11911 + [10] = https://curl.se/bug/?i=11843 + [11] = https://curl.se/bug/?i=11866 + [12] = https://curl.se/bug/?i=11864 + [13] = https://curl.se/bug/?i=11855 + [14] = https://curl.se/bug/?i=11804 + [15] = https://curl.se/bug/?i=11838 + [16] = https://curl.se/bug/?i=11862 + [17] = https://curl.se/bug/?i=11862 + [18] = https://curl.se/bug/?i=11905 + [19] = https://curl.se/bug/?i=11909 + [20] = https://curl.se/bug/?i=11750 + [21] = https://curl.se/bug/?i=11808 + [22] = https://curl.se/bug/?i=11837 + [23] = https://curl.se/bug/?i=11860 + [24] = https://curl.se/bug/?i=11885 + [25] = https://curl.se/bug/?i=11897 + [26] = https://curl.se/bug/?i=11890 + [27] = https://curl.se/bug/?i=11898 + [28] = https://curl.se/bug/?i=11892 + [29] = https://curl.se/bug/?i=11886 + [30] = https://curl.se/bug/?i=11882 + [31] = https://curl.se/bug/?i=11888 + [32] = https://curl.se/bug/?i=11893 + [33] = https://curl.se/bug/?i=11932 + [34] = https://curl.se/bug/?i=11884 + [35] = https://curl.se/bug/?i=11932 + [36] = https://curl.se/bug/?i=12003 + [37] = https://curl.se/bug/?i=11931 + [38] = https://curl.se/bug/?i=11925 + [39] = https://curl.se/bug/?i=11904 + [40] = https://curl.se/bug/?i=11921 + [41] = https://curl.se/bug/?i=12032 + [42] = https://curl.se/bug/?i=11924 + [43] = https://curl.se/bug/?i=11796 + [44] = https://curl.se/bug/?i=11810 + [45] = https://curl.se/bug/?i=11625 + [46] = https://curl.se/bug/?i=8805 + [47] = https://curl.se/bug/?i=11915 + [48] = https://curl.se/bug/?i=11912 + [49] = https://curl.se/bug/?i=11982 + [50] = https://curl.se/bug/?i=11998 + [51] = https://curl.se/bug/?i=11960 + [52] = https://curl.se/bug/?i=11957 + [53] = https://curl.se/bug/?i=11997 + [54] = https://curl.se/bug/?i=11920 + [55] = https://curl.se/bug/?i=11941 + [56] = https://curl.se/bug/?i=11943 + [57] = https://curl.se/bug/?i=11954 + [58] = https://curl.se/bug/?i=11951 + [59] = https://curl.se/bug/?i=11955 + [60] = https://curl.se/bug/?i=11953 + [61] = https://curl.se/bug/?i=11996 + [62] = https://curl.se/bug/?i=11990 + [63] = https://curl.se/bug/?i=11987 + [64] = https://curl.se/bug/?i=11987 + [65] = https://curl.se/bug/?i=11940 + [66] = https://curl.se/bug/?i=11991 + [67] = https://curl.se/bug/?i=11994 + [68] = https://curl.se/bug/?i=2935 + [69] = https://curl.se/bug/?i=11858 + [70] = https://curl.se/bug/?i=11937 + [71] = https://curl.se/bug/?i=11929 + [72] = https://curl.se/bug/?i=11927 + [73] = https://curl.se/bug/?i=11926 + [74] = https://curl.se/bug/?i=11914 + [75] = https://curl.se/bug/?i=11981 + [76] = https://curl.se/bug/?i=11979 + [77] = https://curl.se/bug/?i=11978 + [78] = https://curl.se/bug/?i=12010 + [79] = https://curl.se/bug/?i=11988 + [80] = https://curl.se/bug/?i=12018 + [81] = https://curl.se/bug/?i=11980 + [82] = https://curl.se/bug/?i=11986 + [83] = https://curl.se/bug/?i=11985 + [84] = https://curl.se/bug/?i=11984 + [85] = https://curl.se/bug/?i=11974 + [86] = https://curl.se/bug/?i=11973 + [87] = https://curl.se/bug/?i=11973 + [88] = https://curl.se/bug/?i=11975 + [89] = https://curl.se/bug/?i=11963 + [90] = https://curl.se/bug/?i=11983 + [91] = https://curl.se/bug/?i=11977 + [92] = https://curl.se/bug/?i=12024 + [93] = https://curl.se/bug/?i=11967 + [94] = https://curl.se/bug/?i=11958 + [95] = https://curl.se/bug/?i=11939 + [96] = https://curl.se/bug/?i=12027 + [97] = https://curl.se/bug/?i=11908 + [98] = https://curl.se/bug/?i=11938 + [99] = https://curl.se/bug/?i=12033 + [100] = https://curl.se/bug/?i=12059 + [101] = https://curl.se/bug/?i=12002 + [102] = https://curl.se/bug/?i=11964 + [103] = https://curl.se/bug/?i=12066 + [104] = https://curl.se/bug/?i=12038 + [105] = https://curl.se/bug/?i=12015 + [106] = https://curl.se/bug/?i=12013 + [107] = https://curl.se/bug/?i=11928 + [108] = https://curl.se/bug/?i=12005 + [109] = https://curl.se/bug/?i=11999 + [110] = https://curl.se/bug/?i=12006 + [111] = https://curl.se/bug/?i=12008 + [112] = https://curl.se/mail/lib-2023-10/0010.html + [113] = https://curl.se/bug/?i=12045 + [114] = https://curl.se/bug/?i=12065 + [115] = https://curl.se/bug/?i=12042 + [116] = https://curl.se/bug/?i=12041 + [117] = https://curl.se/bug/?i=12036 + [118] = https://curl.se/docs/CVE-2023-38545.html + [119] = https://curl.se/bug/?i=12031 + [120] = https://curl.se/bug/?i=12035 + [121] = https://curl.se/bug/?i=12054 + [122] = https://curl.se/bug/?i=12034 + [123] = https://curl.se/bug/?i=12048 + [125] = https://curl.se/bug/?i=12071 diff --git a/deps/curl/acinclude.m4 b/deps/curl/acinclude.m4 index ac026e39..5fdd51e5 100644 --- a/deps/curl/acinclude.m4 +++ b/deps/curl/acinclude.m4 @@ -705,10 +705,10 @@ AC_DEFUN([TYPE_SOCKADDR_STORAGE], #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif +#include #ifdef HAVE_WINSOCK2_H #include #endif -#include #else #ifdef HAVE_SYS_TYPES_H #include @@ -743,10 +743,10 @@ AC_DEFUN([CURL_CHECK_FUNC_RECV], [ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif +#include #ifdef HAVE_WINSOCK2_H #include #endif -#include #else $curl_includes_bsdsocket #ifdef HAVE_SYS_TYPES_H @@ -794,10 +794,10 @@ AC_DEFUN([CURL_CHECK_FUNC_SEND], [ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif +#include #ifdef HAVE_WINSOCK2_H #include #endif -#include #else $curl_includes_bsdsocket #ifdef HAVE_SYS_TYPES_H @@ -841,10 +841,10 @@ AC_DEFUN([CURL_CHECK_MSG_NOSIGNAL], [ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif +#include #ifdef HAVE_WINSOCK2_H #include #endif -#include #else #ifdef HAVE_SYS_TYPES_H #include @@ -886,10 +886,10 @@ AC_DEFUN([CURL_CHECK_STRUCT_TIMEVAL], [ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif +#include #ifdef HAVE_WINSOCK2_H #include #endif -#include #endif #ifdef HAVE_SYS_TYPES_H #include @@ -941,10 +941,10 @@ AC_DEFUN([TYPE_IN_ADDR_T], [ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif +#include #ifdef HAVE_WINSOCK2_H #include #endif -#include #else #ifdef HAVE_SYS_TYPES_H #include @@ -983,10 +983,10 @@ AC_DEFUN([TYPE_IN_ADDR_T], [ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif +#include #ifdef HAVE_WINSOCK2_H #include #endif -#include #else #ifdef HAVE_SYS_TYPES_H #include @@ -1298,10 +1298,10 @@ AC_DEFUN([CURL_CHECK_FUNC_SELECT], [ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif +#include #ifdef HAVE_WINSOCK2_H #include #endif -#include #endif #ifdef HAVE_SYS_TYPES_H #include @@ -1374,6 +1374,70 @@ int main() ]) +dnl CURL_CHECK_VARIADIC_MACROS +dnl ------------------------------------------------- +dnl Check compiler support of variadic macros + +AC_DEFUN([CURL_CHECK_VARIADIC_MACROS], [ + AC_CACHE_CHECK([for compiler support of C99 variadic macro style], + [curl_cv_variadic_macros_c99], [ + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([[ +#define c99_vmacro3(first, ...) fun3(first, __VA_ARGS__) +#define c99_vmacro2(first, ...) fun2(first, __VA_ARGS__) + int fun3(int arg1, int arg2, int arg3); + int fun2(int arg1, int arg2); + int fun3(int arg1, int arg2, int arg3) + { return arg1 + arg2 + arg3; } + int fun2(int arg1, int arg2) + { return arg1 + arg2; } + ]],[[ + int res3 = c99_vmacro3(1, 2, 3); + int res2 = c99_vmacro2(1, 2); + ]]) + ],[ + curl_cv_variadic_macros_c99="yes" + ],[ + curl_cv_variadic_macros_c99="no" + ]) + ]) + case "$curl_cv_variadic_macros_c99" in + yes) + AC_DEFINE_UNQUOTED(HAVE_VARIADIC_MACROS_C99, 1, + [Define to 1 if compiler supports C99 variadic macro style.]) + ;; + esac + AC_CACHE_CHECK([for compiler support of old gcc variadic macro style], + [curl_cv_variadic_macros_gcc], [ + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([[ +#define gcc_vmacro3(first, args...) fun3(first, args) +#define gcc_vmacro2(first, args...) fun2(first, args) + int fun3(int arg1, int arg2, int arg3); + int fun2(int arg1, int arg2); + int fun3(int arg1, int arg2, int arg3) + { return arg1 + arg2 + arg3; } + int fun2(int arg1, int arg2) + { return arg1 + arg2; } + ]],[[ + int res3 = gcc_vmacro3(1, 2, 3); + int res2 = gcc_vmacro2(1, 2); + ]]) + ],[ + curl_cv_variadic_macros_gcc="yes" + ],[ + curl_cv_variadic_macros_gcc="no" + ]) + ]) + case "$curl_cv_variadic_macros_gcc" in + yes) + AC_DEFINE_UNQUOTED(HAVE_VARIADIC_MACROS_GCC, 1, + [Define to 1 if compiler supports old gcc variadic macro style.]) + ;; + esac +]) + + dnl CURL_CHECK_CA_BUNDLE dnl ------------------------------------------------- dnl Check if a default ca-bundle should be used diff --git a/deps/curl/appveyor.yml b/deps/curl/appveyor.yml index 175f298d..874bf7ce 100644 --- a/deps/curl/appveyor.yml +++ b/deps/curl/appveyor.yml @@ -21,12 +21,9 @@ # SPDX-License-Identifier: curl # ########################################################################### - # https://ci.appveyor.com/project/curlorg/curl/history -# AppVeyor configuration: -# https://www.appveyor.com/docs/appveyor-yml/ -# AppVeyor worker images: -# https://www.appveyor.com/docs/windows-images-software/ +# Appveyor configuration +# https://www.appveyor.com/docs/appveyor-yml/ version: 7.50.0.{build} @@ -37,7 +34,7 @@ environment: SHARED: 'OFF' matrix: # generated CMake-based Visual Studio Release builds - - job_name: 'CMake, VS2008, Release, x86, Schannel, Build-only' + - job_name: 'CMake, VS2008, Release x86, Schannel, Build-only' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015' BUILD_SYSTEM: CMake PRJ_GEN: 'Visual Studio 9 2008' @@ -48,7 +45,8 @@ environment: SHARED: 'ON' TESTING: 'OFF' DISABLED_TESTS: '' - - job_name: 'CMake, VS2022, Release, x64, OpenSSL 3, WebSockets, Unity, Build-only' + SKIP_RUN: 'Needs missing MSVCR90.dll' + - job_name: 'CMake, VS2022, Release x64, OpenSSL, WebSockets, Unity, Build-only' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022' BUILD_SYSTEM: CMake PRJ_GEN: 'Visual Studio 17 2022' @@ -63,7 +61,7 @@ environment: DISABLED_TESTS: '' WEBSOCKETS: 'ON' UNITY: 'ON' - - job_name: 'CMake, VS2022, Release, arm64, Schannel, Static, Build-only' + - job_name: 'CMake, VS2022, Release arm64, Schannel, Static, Build-only' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022' BUILD_SYSTEM: CMake PRJ_GEN: 'Visual Studio 17 2022' @@ -75,7 +73,7 @@ environment: TESTING: 'OFF' DISABLED_TESTS: '' # generated CMake-based Visual Studio Debug builds - - job_name: 'CMake, VS2010, Debug, x64, no SSL, Static' + - job_name: 'CMake, VS2010, Debug x64, no SSL, Static' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015' BUILD_SYSTEM: CMake PRJ_GEN: 'Visual Studio 10 2010 Win64' @@ -86,7 +84,7 @@ environment: TESTING: 'ON' DISABLED_TESTS: '!1139 !1501' ADD_PATH: 'C:\msys64\usr\bin' - - job_name: 'CMake, VS2022, Debug, x64, Schannel, Static, Unicode' + - job_name: 'CMake, VS2022, Debug x64, Schannel, Static, Unicode' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022' BUILD_SYSTEM: CMake PRJ_GEN: 'Visual Studio 17 2022' @@ -98,7 +96,7 @@ environment: TESTING: 'ON' DISABLED_TESTS: '!1139 !1501' ADD_PATH: 'C:\msys64\usr\bin' - - job_name: 'CMake, VS2022, Debug, x64, no SSL, Static' + - job_name: 'CMake, VS2022, Debug x64, no SSL, Static' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022' BUILD_SYSTEM: CMake PRJ_GEN: 'Visual Studio 17 2022' @@ -110,7 +108,7 @@ environment: TESTING: 'ON' DISABLED_TESTS: '!1139 !1501' ADD_PATH: 'C:\msys64\usr\bin' - - job_name: 'CMake, VS2022, Debug, x64, no SSL, Static, HTTP only' + - job_name: 'CMake, VS2022, Debug x64, no SSL, Static, HTTP only' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022' BUILD_SYSTEM: CMake PRJ_GEN: 'Visual Studio 17 2022' @@ -123,7 +121,7 @@ environment: DISABLED_TESTS: '!1139 !1501' ADD_PATH: 'C:\msys64\usr\bin' # generated CMake-based MSYS Makefiles builds (mingw cross-compiling) - - job_name: 'CMake, mingw-w64, gcc 13, Debug, x64, Schannel, Static, Unicode, Unity' + - job_name: 'CMake, mingw-w64, gcc 13, Debug x64, Schannel, Static, Unicode, Unity' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022' BUILD_SYSTEM: CMake PRJ_GEN: 'MSYS Makefiles' @@ -137,7 +135,7 @@ environment: MSYS2_ARG_CONV_EXCL: '/*' BUILD_OPT: -k UNITY: 'ON' - - job_name: 'CMake, mingw-w64, gcc 7, Debug, x64, Schannel, Static, Unicode' + - job_name: 'CMake, mingw-w64, gcc 7, Debug x64, Schannel, Static, Unicode' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017' BUILD_SYSTEM: CMake PRJ_GEN: 'MSYS Makefiles' @@ -150,7 +148,7 @@ environment: ADD_PATH: 'C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin;C:\msys64\usr\bin' MSYS2_ARG_CONV_EXCL: '/*' BUILD_OPT: -k - - job_name: 'CMake, mingw-w64, gcc 9, Debug, x64, Schannel, Static, Unity' + - job_name: 'CMake, mingw-w64, gcc 9, Debug x64, Schannel, Static, Unity' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017' BUILD_SYSTEM: CMake PRJ_GEN: 'MSYS Makefiles' @@ -159,13 +157,12 @@ environment: ENABLE_UNICODE: 'OFF' HTTP_ONLY: 'OFF' TESTING: 'ON' - # test 286 disabled due to https://github.com/curl/curl/issues/12040 - DISABLED_TESTS: '~286 !1086 !1139 !1451 !1501' + DISABLED_TESTS: '!1086 !1139 !1451 !1501' ADD_PATH: 'C:\msys64\mingw64\bin;C:\msys64\usr\bin' MSYS2_ARG_CONV_EXCL: '/*' BUILD_OPT: -k UNITY: 'ON' - - job_name: 'CMake, mingw-w64, gcc 6, Debug, x86, Schannel, Static' + - job_name: 'CMake, mingw-w64, gcc 6, Debug x86, Schannel, Static' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015' BUILD_SYSTEM: CMake PRJ_GEN: 'MSYS Makefiles' @@ -179,56 +176,56 @@ environment: MSYS2_ARG_CONV_EXCL: '/*' BUILD_OPT: -k # winbuild-based builds - - job_name: 'winbuild, VS2015, Debug, x64, OpenSSL 1.1.1, Build-only' + - job_name: 'winbuild, VS2015, Debug, x64, Build-only' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015' BUILD_SYSTEM: winbuild_vs2015 DEBUG: 'yes' PATHPART: debug TESTING: 'OFF' ENABLE_UNICODE: 'no' - - job_name: 'winbuild, VS2015, Release, x64, OpenSSL 1.1.1, Build-only' + - job_name: 'winbuild, VS2015, Release, x64, Build-only' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015' BUILD_SYSTEM: winbuild_vs2015 DEBUG: 'no' PATHPART: release TESTING: 'OFF' ENABLE_UNICODE: 'no' - - job_name: 'winbuild, VS2017, Debug, x64, OpenSSL 1.1.1, Build-only' + - job_name: 'winbuild, VS2017, Debug, x64, Build-only' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017' BUILD_SYSTEM: winbuild_vs2017 DEBUG: 'yes' PATHPART: debug TESTING: 'OFF' ENABLE_UNICODE: 'no' - - job_name: 'winbuild, VS2017, Release, x64, OpenSSL 1.1.1, Build-only' + - job_name: 'winbuild, VS2017, Release, x64, Build-only' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017' BUILD_SYSTEM: winbuild_vs2017 DEBUG: 'no' PATHPART: release TESTING: 'OFF' ENABLE_UNICODE: 'no' - - job_name: 'winbuild, VS2015, Debug, x64, OpenSSL 1.1.1, Unicode, Build-only' + - job_name: 'winbuild, VS2015, Debug, x64, Unicode, Build-only' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015' BUILD_SYSTEM: winbuild_vs2015 DEBUG: 'yes' PATHPART: debug TESTING: 'OFF' ENABLE_UNICODE: 'yes' - - job_name: 'winbuild, VS2015, Release, x64, OpenSSL 1.1.1, Unicode, Build-only' + - job_name: 'winbuild, VS2015, Release, x64, Unicode, Build-only' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015' BUILD_SYSTEM: winbuild_vs2015 DEBUG: 'no' PATHPART: release TESTING: 'OFF' ENABLE_UNICODE: 'yes' - - job_name: 'winbuild, VS2017, Debug, x64, OpenSSL 1.1.1, Unicode, Build-only' + - job_name: 'winbuild, VS2017, Debug, x64, Unicode, Build-only' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017' BUILD_SYSTEM: winbuild_vs2017 DEBUG: 'yes' PATHPART: debug TESTING: 'OFF' ENABLE_UNICODE: 'yes' - - job_name: 'winbuild, VS2017, Release, x64, OpenSSL 1.1.1, Unicode, Build-only' + - job_name: 'winbuild, VS2017, Release, x64, Unicode, Build-only' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017' BUILD_SYSTEM: winbuild_vs2017 DEBUG: 'no' @@ -236,7 +233,7 @@ environment: TESTING: 'OFF' ENABLE_UNICODE: 'yes' # generated VisualStudioSolution-based builds - - job_name: 'VisualStudioSolution, VS2017, Debug, x86, Schannel, Build-only' + - job_name: 'VisualStudioSolution, VS2017, Debug, x86, Build-only' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017' BUILD_SYSTEM: VisualStudioSolution PRJ_CFG: 'DLL Debug - DLL Windows SSPI - DLL WinIDN' @@ -292,12 +289,7 @@ build_script: $ErrorActionPreference = 'Stop' - if($env:APPVEYOR_BUILD_WORKER_IMAGE -eq 'Visual Studio 2022') { - $openssl_root = 'C:\OpenSSL-v30-Win64' - } - else { - $openssl_root = 'C:\OpenSSL-v111-Win64' - } + $openssl_root = 'C:\OpenSSL-v111-Win64' if($env:BUILD_SYSTEM -eq 'CMake') { @@ -332,11 +324,8 @@ build_script: if($env:PRJ_GEN.Contains('Visual Studio')) { $options += '-DCMAKE_VS_GLOBALS=TrackFileAccess=false' } - if($env:PRJ_GEN -eq 'Visual Studio 9 2008') { - # Without this it fails to run due to missing MSVCR90.dll - $options += '-DCURL_STATIC_CRT=ON' - } + cmake --version Write-Host 'CMake options:' $options cmake . $options cmake --build . --config $env:PRJ_CFG --parallel 2 --clean-first -- $env:BUILD_OPT diff --git a/deps/curl/configure.ac b/deps/curl/configure.ac index d9b39637..2d71c838 100644 --- a/deps/curl/configure.ac +++ b/deps/curl/configure.ac @@ -174,7 +174,7 @@ curl_headers_msg="enabled (--disable-headers-api)" curl_ws_msg="no (--enable-websockets)" ssl_backends= curl_h1_msg="enabled (internal)" - curl_h2_msg="no (--with-nghttp2)" + curl_h2_msg="no (--with-nghttp2, --with-hyper)" curl_h3_msg="no (--with-ngtcp2 --with-nghttp3, --with-quiche, --with-msh3)" enable_altsvc="yes" @@ -803,6 +803,7 @@ if test X"$want_hyper" != Xno; then experimental="$experimental Hyper" AC_MSG_NOTICE([Hyper support is experimental]) curl_h1_msg="enabled (Hyper)" + curl_h2_msg=$curl_h1_msg HYPER_ENABLED=1 AC_DEFINE(USE_HYPER, 1, [if hyper is in use]) AC_SUBST(USE_HYPER, [1]) @@ -1144,10 +1145,10 @@ then #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif +#include #ifdef HAVE_WINSOCK2_H #include #endif -#include #endif ]],[[ gethostbyname("localhost"); @@ -3098,6 +3099,7 @@ if test X"$want_nghttp3" != Xno; then CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$DIR_NGHTTP3" export CURL_LIBRARY_PATH AC_MSG_NOTICE([Added $DIR_NGHTTP3 to CURL_LIBRARY_PATH]) + experimental="$experimental HTTP3" ) ], dnl not found, revert back to clean variables @@ -3416,6 +3418,7 @@ dnl default includes dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST +CURL_CHECK_VARIADIC_MACROS AC_TYPE_SIZE_T CURL_CHECK_STRUCT_TIMEVAL @@ -3578,9 +3581,11 @@ AC_CHECK_DECLS([getpwuid_r], [], [AC_DEFINE(HAVE_DECL_GETPWUID_R_MISSING, 1, "Se [[#include #include ]]) + AC_CHECK_FUNCS([\ _fseeki64 \ arc4random \ + fchmod \ fnmatch \ fseeko \ geteuid \ @@ -3623,15 +3628,6 @@ AC_CHECK_FUNCS([\ fi ]) -dnl On Android, the only way to know if fseeko can be used is to see if it is -dnl declared or not (for this API level), as the symbol always exists in the -dnl lib. -AC_CHECK_DECL([fseeko], - [AC_DEFINE([HAVE_DECL_FSEEKO], [1], - [Define to 1 if you have the fseeko declaration])], - [], - [[#include ]]) - CURL_CHECK_NONBLOCKING_SOCKET dnl ************************************************************ @@ -4574,7 +4570,7 @@ if test "x$USE_TLS_SRP" = "x1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES TLS-SRP" fi -if test "x$USE_NGHTTP2" = "x1"; then +if test "x$USE_NGHTTP2" = "x1" -o "x$USE_HYPER" = "x1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP2" fi @@ -4587,31 +4583,20 @@ if test "x$CURL_WITH_MULTI_SSL" = "x1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES MultiSSL" fi -AC_MSG_CHECKING([if this build supports HTTPS-proxy]) dnl if not explicitly turned off, HTTPS-proxy comes with some TLS backends -if test "x$CURL_DISABLE_HTTP" != "x1"; then - if test "x$https_proxy" != "xno"; then - if test "x$OPENSSL_ENABLED" = "x1" \ - -o "x$GNUTLS_ENABLED" = "x1" \ - -o "x$SECURETRANSPORT_ENABLED" = "x1" \ - -o "x$RUSTLS_ENABLED" = "x1" \ - -o "x$BEARSSL_ENABLED" = "x1" \ - -o "x$SCHANNEL_ENABLED" = "x1" \ - -o "x$GNUTLS_ENABLED" = "x1" \ - -o "x$MBEDTLS_ENABLED" = "x1"; then - SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPS-proxy" - AC_MSG_RESULT([yes]) - elif test "x$WOLFSSL_ENABLED" = "x1" -a "x$WOLFSSL_FULL_BIO" = "x1"; then - SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPS-proxy" - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - fi - else - AC_MSG_RESULT([no]) +if test "x$https_proxy" != "xno"; then + if test "x$OPENSSL_ENABLED" = "x1" \ + -o "x$GNUTLS_ENABLED" = "x1" \ + -o "x$SECURETRANSPORT_ENABLED" = "x1" \ + -o "x$RUSTLS_ENABLED" = "x1" \ + -o "x$BEARSSL_ENABLED" = "x1" \ + -o "x$SCHANNEL_ENABLED" = "x1" \ + -o "x$GNUTLS_ENABLED" = "x1" \ + -o "x$MBEDTLS_ENABLED" = "x1"; then + SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPS-proxy" + elif test "x$WOLFSSL_ENABLED" = "x1" -a "x$WOLFSSL_FULL_BIO" = "x1"; then + SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPS-proxy" fi -else - AC_MSG_RESULT([no]) fi if test "x$ECH_ENABLED" = "x1"; then @@ -4627,9 +4612,6 @@ fi if test "$tst_atomic" = "yes"; then SUPPORT_FEATURES="$SUPPORT_FEATURES threadsafe" -elif test "x$USE_THREADS_POSIX" = "x1" -a \ - "x$ac_cv_header_pthread_h" = "xyes"; then - SUPPORT_FEATURES="$SUPPORT_FEATURES threadsafe" else AC_COMPILE_IFELSE([ AC_LANG_PROGRAM([[ diff --git a/deps/curl/docs/BINDINGS.md b/deps/curl/docs/BINDINGS.md index 7f5da421..57f87a5f 100644 --- a/deps/curl/docs/BINDINGS.md +++ b/deps/curl/docs/BINDINGS.md @@ -125,8 +125,6 @@ Ruby: [curb](https://github.com/taf2/curb) written by Ross Bamford, [Tcl](https://web.archive.org/web/20160826011806/mirror.yellow5.com/tclcurl/) Tclcurl by Andrés García -[Vibe](https://github.com/ttytm/vibe) HTTP requests through libcurl in V - [Visual Basic](https://sourceforge.net/projects/libcurl-vb/) libcurl-vb by Jeffrey Phillips [Visual Foxpro](https://web.archive.org/web/20130730181523/www.ctl32.com.ar/libcurl.asp) by Carlos Alloatti diff --git a/deps/curl/docs/EXPERIMENTAL.md b/deps/curl/docs/EXPERIMENTAL.md index de694013..6b7145df 100644 --- a/deps/curl/docs/EXPERIMENTAL.md +++ b/deps/curl/docs/EXPERIMENTAL.md @@ -19,6 +19,6 @@ Experimental support in curl means: ## Experimental features right now - The Hyper HTTP backend - - HTTP/3 support (using the quiche or msh3 backends) + - HTTP/3 support and options - The rustls backend - WebSocket diff --git a/deps/curl/docs/FEATURES.md b/deps/curl/docs/FEATURES.md index 05364aaf..9f763d3a 100644 --- a/deps/curl/docs/FEATURES.md +++ b/deps/curl/docs/FEATURES.md @@ -12,7 +12,7 @@ ## libcurl - - URL RFC 3986 syntax + - full URL syntax with no length limit - custom maximum download time - custom least download speed acceptable - custom output result after completion diff --git a/deps/curl/docs/HTTP3.md b/deps/curl/docs/HTTP3.md index 4f066282..41d757f0 100644 --- a/deps/curl/docs/HTTP3.md +++ b/deps/curl/docs/HTTP3.md @@ -9,19 +9,18 @@ book describing the protocols involved. ## QUIC libraries -QUIC libraries we are using: +QUIC libraries we are experimenting with: [ngtcp2](https://github.com/ngtcp2/ngtcp2) -[quiche](https://github.com/cloudflare/quiche) - **EXPERIMENTAL** +[quiche](https://github.com/cloudflare/quiche) -[msh3](https://github.com/nibanks/msh3) (with [msquic](https://github.com/microsoft/msquic)) - **EXPERIMENTAL** +[msh3](https://github.com/nibanks/msh3) (with [msquic](https://github.com/microsoft/msquic)) ## Experimental -HTTP/3 support in curl is considered **EXPERIMENTAL** until further notice -when built to use *quiche* or *msh3*. Only the *ngtcp2* backend is not -experimental. +HTTP/3 and QUIC support in curl is considered **EXPERIMENTAL** until further +notice. It needs to be enabled at build-time. Further development and tweaking of the HTTP/3 support in curl will happen in the master branch using pull-requests, just like ordinary changes. @@ -35,17 +34,16 @@ To fix before we remove the experimental label: Building curl with ngtcp2 involves 3 components: `ngtcp2` itself, `nghttp3` and a QUIC supporting TLS library. The supported TLS libraries are covered below. - * `ngtcp2`: v1.0.1 - * `nghttp3`: v1.0.0 +For now, `ngtcp2` and `nghttp3` are still *experimental* which means their evolution bring breaking changes. Therefore, the proper version of both libraries need to be used when building curl. These are -## Build with quictls + * `ngtcp2`: v0.19.1 + * `nghttp3`: v0.15.0 -OpenSSL does not offer the required APIs for building a QUIC client. You need -to use a TLS library that has such APIs and that works with *ngtcp2*. +## Build with OpenSSL -Build quictls +Build (patched) OpenSSL - % git clone --depth 1 -b openssl-3.1.4+quic https://github.com/quictls/openssl + % git clone --depth 1 -b openssl-3.0.10+quic https://github.com/quictls/openssl % cd openssl % ./config enable-tls1_3 --prefix= % make @@ -54,7 +52,7 @@ Build quictls Build nghttp3 % cd .. - % git clone -b v1.0.0 https://github.com/ngtcp2/nghttp3 + % git clone -b v0.15.0 https://github.com/ngtcp2/nghttp3 % cd nghttp3 % autoreconf -fi % ./configure --prefix= --enable-lib-only @@ -64,7 +62,7 @@ Build nghttp3 Build ngtcp2 % cd .. - % git clone -b v1.0.1 https://github.com/ngtcp2/ngtcp2 + % git clone -b v0.19.1 https://github.com/ngtcp2/ngtcp2 % cd ngtcp2 % autoreconf -fi % ./configure PKG_CONFIG_PATH=/lib/pkgconfig:/lib/pkgconfig LDFLAGS="-Wl,-rpath,/lib" --prefix= --enable-lib-only @@ -97,7 +95,7 @@ Build GnuTLS Build nghttp3 % cd .. - % git clone -b v1.0.0 https://github.com/ngtcp2/nghttp3 + % git clone -b v0.15.0 https://github.com/ngtcp2/nghttp3 % cd nghttp3 % autoreconf -fi % ./configure --prefix= --enable-lib-only @@ -107,7 +105,7 @@ Build nghttp3 Build ngtcp2 % cd .. - % git clone -b v1.0.1 https://github.com/ngtcp2/ngtcp2 + % git clone -b v0.19.1 https://github.com/ngtcp2/ngtcp2 % cd ngtcp2 % autoreconf -fi % ./configure PKG_CONFIG_PATH=/lib/pkgconfig:/lib/pkgconfig LDFLAGS="-Wl,-rpath,/lib" --prefix= --enable-lib-only --with-gnutls @@ -138,7 +136,7 @@ Build wolfSSL Build nghttp3 % cd .. - % git clone -b v1.0.0 https://github.com/ngtcp2/nghttp3 + % git clone -b v0.15.0 https://github.com/ngtcp2/nghttp3 % cd nghttp3 % autoreconf -fi % ./configure --prefix= --enable-lib-only @@ -148,7 +146,7 @@ Build nghttp3 Build ngtcp2 % cd .. - % git clone -b v1.0.1 https://github.com/ngtcp2/ngtcp2 + % git clone -b v0.19.1 https://github.com/ngtcp2/ngtcp2 % cd ngtcp2 % autoreconf -fi % ./configure PKG_CONFIG_PATH=/lib/pkgconfig:/lib/pkgconfig LDFLAGS="-Wl,-rpath,/lib" --prefix= --enable-lib-only --with-wolfssl @@ -167,8 +165,6 @@ Build curl # quiche version -quiche support is **EXPERIMENTAL** - Since the quiche build manages its dependencies, curl can be built against the latest version. You are *probably* able to build against their main branch, but in case of problems, we recommend their latest release tag. ## build @@ -199,8 +195,6 @@ Build curl: one as of September 2023. Feel free to help us test it and improve it, but there is no point in filing bugs about it just yet. -msh3 support is **EXPERIMENTAL** - ## Build Linux (with quictls fork of OpenSSL) Build msh3: diff --git a/deps/curl/docs/HYPER.md b/deps/curl/docs/HYPER.md index 9932c1bb..1c3b0dde 100644 --- a/deps/curl/docs/HYPER.md +++ b/deps/curl/docs/HYPER.md @@ -57,10 +57,6 @@ The hyper backend does not support - leading whitespace in first HTTP/1 response header - HTTP/0.9 - HTTP/2 upgrade using HTTP:// URLs. Aka 'h2c' -- HTTP/2 in general. Hyper has support for HTTP/2 but the curl side - needs changes so that a `hyper_clientconn` can last for the duration - of a connection. Probably this means turning the Hyper HTTP/2 backend - into a connection filter. ## Remaining issues diff --git a/deps/curl/docs/INSTALL.md b/deps/curl/docs/INSTALL.md index a6780b45..7e3a2698 100644 --- a/deps/curl/docs/INSTALL.md +++ b/deps/curl/docs/INSTALL.md @@ -162,8 +162,6 @@ library check. # Windows -Building for Windows XP is required as a minimum. - ## Building Windows DLLs and C runtime (CRT) linkage issues As a general rule, building a DLL with static CRT linkage is highly @@ -526,12 +524,7 @@ disabling support for some feature: - `--disable-alt-svc` (HTTP Alt-Svc) - `--disable-ares` (the C-ARES DNS library) - `--disable-cookies` (HTTP cookies) - - `--disable-basic-auth` (cryptographic authentication) - - `--disable-bearer-auth` (cryptographic authentication) - - `--disable-digest-auth` (cryptographic authentication) - - `--disable-kerberos-auth` (cryptographic authentication) - - `--disable-negotiate-auth` (cryptographic authentication) - - `--disable-aws` (cryptographic authentication) + - `--disable-crypto-auth` (cryptographic authentication) - `--disable-dateparse` (date parsing for time conditionals) - `--disable-dnsshuffle` (internal server load spreading) - `--disable-doh` (DNS-over-HTTP) @@ -596,29 +589,29 @@ that are not automatically detected: - `--disable-libcurl-option` !`--libcurl` - `--disable-verbose` !verbose\ logs -# Ports +# PORTS This is a probably incomplete list of known CPU architectures and operating systems that curl has been compiled for. If you know a system curl compiles and runs on, that is not listed, please let us know! -## 101 Operating Systems +## 92 Operating Systems - AIX, AmigaOS, Android, ArcoOS, Aros, Atari FreeMiNT, BeOS, Blackberry 10, - Blackberry Tablet OS, Cell OS, CheriBSD, Chrome OS, Cisco IOS, DG/UX, - Dragonfly BSD, DR DOS, eCOS, FreeBSD, FreeDOS, FreeRTOS, Fuchsia, Garmin OS, - Genode, Haiku, HardenedBSD, HP-UX, Hurd, Illumos, Integrity, iOS, ipadOS, IRIX, - Linux, Lua RTOS, Mac OS 9, macOS, Mbed, Meego, Micrium, MINIX, Moblin, MorphOS, - MPE/iX, MS-DOS, NCR MP-RAS, NetBSD, Netware, NextStep, Nintendo Switch, - NonStop OS, NuttX, OpenBSD, OpenStep, Orbis OS, OS/2, OS/400, OS21, Plan 9, - PlayStation Portable, QNX, Qubes OS, ReactOS, Redox, RICS OS, ROS, RTEMS, - Sailfish OS, SCO Unix, Serenity, SINIX-Z, SkyOS, Solaris, Sortix, SunOS, - Syllable OS, Symbian, Tizen, TPF, Tru64, tvOS, ucLinux, Ultrix, UNICOS, - UnixWare, VMS, vxWorks, watchOS, Wear OS, WebOS, Wii system software, Wii U, - Windows, Windows CE, Xbox System, Xenix, Zephyr, z/OS, z/TPF, z/VM, z/VSE + AIX, AmigaOS, Android, Aros, BeOS, Blackberry 10, Blackberry Tablet OS, + Cell OS, Chrome OS, Cisco IOS, Cygwin, DG/UX, Dragonfly BSD, DR DOS, eCOS, + FreeBSD, FreeDOS, FreeRTOS, Fuchsia, Garmin OS, Genode, Haiku, HardenedBSD, + HP-UX, Hurd, Illumos, Integrity, iOS, ipadOS, IRIX, Linux, Lua RTOS, + Mac OS 9, macOS, Mbed, Micrium, MINIX, MorphOS, MPE/iX, MS-DOS, NCR MP-RAS, + NetBSD, Netware, Nintendo Switch, NonStop OS, NuttX, Omni OS, OpenBSD, + OpenStep, Orbis OS, OS/2, OS/400, OS21, Plan 9, PlayStation Portable, QNX, + Qubes OS, ReactOS, Redox, RICS OS, RTEMS, Sailfish OS, SCO Unix, Serenity, + SINIX-Z, Solaris, SunOS, Syllable OS, Symbian, Tizen, TPF, Tru64, tvOS, + ucLinux, Ultrix, UNICOS, UnixWare, VMS, vxWorks, watchOS, WebOS, + Wii system software, Windows, Windows CE, Xbox System, Xenix, Zephyr, + z/OS, z/TPF, z/VM, z/VSE -## 28 CPU Architectures +## 26 CPU Architectures - Alpha, ARC, ARM, AVR32, C-SKY, CompactRISC, Elbrus, ETRAX, HP-PA, Itanium, + Alpha, ARC, ARM, AVR32, CompactRISC, Elbrus, ETRAX, HP-PA, Itanium, LoongArch, m68k, m88k, MicroBlaze, MIPS, Nios, OpenRISC, POWER, PowerPC, - RISC-V, s390, SH4, SPARC, Tilera, VAX, x86, Xtensa, z/arch + RISC-V, s390, SH4, SPARC, Tilera, VAX, x86, Xtensa diff --git a/deps/curl/docs/IPFS.md b/deps/curl/docs/IPFS.md index 24bba8b7..be8c597d 100644 --- a/deps/curl/docs/IPFS.md +++ b/deps/curl/docs/IPFS.md @@ -69,7 +69,7 @@ If you trust this behavior from your gateway of choice then passing the `-L` opt Depending on the arguments, cURL could present the user with an error. ### Gateway file and environment variable -cURL tried to look for the file: `~/.ipfs/gateway` but couldn't find it. It also tried to look for the `IPFS_GATEWAY` environment variable but couldn't find that either. This happens when no extra arguments are passed to cURL and letting it try to figure it out [automatically](#automatic-gateway-detection). +cURL tried to look for the file: `~/.ipfs/gateway` but couldn't find it. It also tried to look for the `IPFS_GATEWAY` environment variable but couldn't find that either. This happens when no extra arguments are passed to cURL and letting it try to figure it out [automatically](#Automatic-gateway-detection). Any IPFS implementation that has gateway support should expose it's URL in `~/.ipfs/gateway`. If you are already running a gateway, make sure it exposes the file where cURL expects to find it. @@ -78,5 +78,5 @@ Alternatively you could set the `IPFS_GATEWAY` environment variable or pass the ### Malformed gateway URL The command executed evaluates in an invalid URL. This could be anywhere in the URL, but a likely point is a wrong gateway URL. -Inspect the URL set via the `IPFS_GATEWAY` environment variable or passed with the `--ipfs-gateway` flag. -Alternatively opt to go for the [automatic](#automatic-gateway-detection) gateway detection. +Inspect your URL. +Alternatively opt to go for the [automatic](#Automatic-gateway-detection) gateway detection. diff --git a/deps/curl/docs/KNOWN_BUGS b/deps/curl/docs/KNOWN_BUGS index e52774a1..395426b4 100644 --- a/deps/curl/docs/KNOWN_BUGS +++ b/deps/curl/docs/KNOWN_BUGS @@ -12,6 +12,7 @@ check the changelog of the current development status, as one or more of these problems may have been fixed or changed somewhat since this was written. 1. HTTP + 1.1 hyper memory-leaks 1.2 hyper is slow 1.5 Expect-100 meets 417 @@ -101,6 +102,10 @@ problems may have been fixed or changed somewhat since this was written. 16. aws-sigv4 16.1 aws-sigv4 does not sign requests with * correctly + 16.2 aws-sigv4 does not sign requests with valueless queries correctly + 16.3 aws-sigv4 is missing the amz-content-sha256 header + 16.4 aws-sigv4 does not sort query string parameters before signing + 16.5 aws-sigv4 does not sign requests with empty URL query correctly 16.6 aws-sigv4 does not behave well with AWS VPC Lattice 17. HTTP/2 @@ -574,6 +579,22 @@ problems may have been fixed or changed somewhat since this was written. https://github.com/curl/curl/issues/7559 +16.2 aws-sigv4 does not sign requests with valueless queries correctly + + https://github.com/curl/curl/issues/8107 + +16.3 aws-sigv4 is missing the amz-content-sha256 header + + https://github.com/curl/curl/issues/8810 + +16.4 aws-sigv4 does not sort query string parameters before signing + + https://github.com/curl/curl/issues/9717 + +16.5 aws-sigv4 does not sign requests with empty URL query correctly + + https://github.com/curl/curl/issues/10129 + 16.6 aws-sigv4 does not behave well with AWS VPC Lattice https://github.com/curl/curl/issues/11007 diff --git a/deps/curl/docs/Makefile.am b/deps/curl/docs/Makefile.am index 9190b441..5454e833 100644 --- a/deps/curl/docs/Makefile.am +++ b/deps/curl/docs/Makefile.am @@ -111,8 +111,7 @@ SUFFIXES = .1 .html .pdf # have changed. $(abs_builddir)/curl.1: if test "$(top_builddir)x" != "$(top_srcdir)x" -a -e "$(srcdir)/curl.1"; then \ - $(INSTALL_DATA) "$(srcdir)/curl.1" $@ \ - && touch -r "$(srcdir)/curl.1" $@; fi + $(INSTALL_DATA) "$(srcdir)/curl.1" $@; fi cd cmdline-opts && $(MAKE) html: $(HTMLPAGES) diff --git a/deps/curl/docs/TODO b/deps/curl/docs/TODO index 06162c8b..f487f88a 100644 --- a/deps/curl/docs/TODO +++ b/deps/curl/docs/TODO @@ -122,7 +122,6 @@ 13.8 Support DANE 13.9 TLS record padding 13.10 Support Authority Information Access certificate extension (AIA) - 13.11 Some TLS options are not offered for HTTPS proxies 13.12 Reduce CA certificate bundle reparsing 13.13 Make sure we forbid TLS 1.3 post-handshake authentication 13.14 Support the clienthello extension @@ -885,14 +884,6 @@ See https://github.com/curl/curl/issues/2793 -13.11 Some TLS options are not offered for HTTPS proxies - - Some TLS related options to the command line tool and libcurl are only - provided for the server and not for HTTPS proxies. --proxy-tls-max, - --proxy-tlsv1.3, --proxy-curves and a few more.a - - https://github.com/curl/curl/issues/12286 - 13.12 Reduce CA certificate bundle reparsing When using the OpenSSL backend, curl will load and reparse the CA bundle at diff --git a/deps/curl/docs/VULN-DISCLOSURE-POLICY.md b/deps/curl/docs/VULN-DISCLOSURE-POLICY.md index 65059934..3ce22032 100644 --- a/deps/curl/docs/VULN-DISCLOSURE-POLICY.md +++ b/deps/curl/docs/VULN-DISCLOSURE-POLICY.md @@ -59,7 +59,8 @@ announcement. [SECURITY-ADVISORY](https://curl.se/dev/advisory.html) for help on creating the advisory. -- Request a CVE number from HackerOne +- Request a CVE number from + [HackerOne](https://docs.hackerone.com/programs/cve-requests.html) - Update the "security advisory" with the CVE number. @@ -282,12 +283,3 @@ and if an attacker can trick the user to run a specifically crafted curl command line, all bets are off. Such an attacker can just as well have the user run a much worse command that can do something fatal (like `sudo rm -rf /`). - -## Terminal output and escape sequences - -Content that is transferred from a server and gets displayed in a terminal by -curl may contain escape sequences or use other tricks to fool the user. This -is curl working as designed and is not a curl security problem. Escape -sequences, moving cursor, changing color etc, is also frequently used for -good. To reduce the risk of getting fooled, save files and browse them after -download using a display method that minimizes risks. diff --git a/deps/curl/docs/cmdline-opts/gen.pl b/deps/curl/docs/cmdline-opts/gen.pl index edf90622..8b9b98bb 100644 --- a/deps/curl/docs/cmdline-opts/gen.pl +++ b/deps/curl/docs/cmdline-opts/gen.pl @@ -48,14 +48,8 @@ my %protolong; my %catlong; use POSIX qw(strftime); -my @ts; -if (defined($ENV{SOURCE_DATE_EPOCH})) { - @ts = localtime($ENV{SOURCE_DATE_EPOCH}); -} else { - @ts = localtime; -} -my $date = strftime "%B %d %Y", @ts; -my $year = strftime "%Y", @ts; +my $date = strftime "%B %d %Y", localtime; +my $year = strftime "%Y", localtime; my $version = "unknown"; my $globals; diff --git a/deps/curl/docs/cmdline-opts/header.d b/deps/curl/docs/cmdline-opts/header.d index 95c1565e..f5b76855 100644 --- a/deps/curl/docs/cmdline-opts/header.d +++ b/deps/curl/docs/cmdline-opts/header.d @@ -34,8 +34,7 @@ with no-value then its header must be terminated with a semicolon, such as \-H curl makes sure that each header you add/replace is sent with the proper end-of-line marker, you should thus **not** add that as a part of the header content: do not add newlines or carriage returns, they only mess things up for -you. curl passes on the verbatim string you give it without any filter or -other safe guards. That includes white space and control characters. +you. This option can take an argument in @filename style, which then adds a header for each line in the input file. Using @- makes curl read the header file from diff --git a/deps/curl/docs/cmdline-opts/ipfs-gateway.d b/deps/curl/docs/cmdline-opts/ipfs-gateway.d index e6845b32..5d5f8b2d 100644 --- a/deps/curl/docs/cmdline-opts/ipfs-gateway.d +++ b/deps/curl/docs/cmdline-opts/ipfs-gateway.d @@ -9,24 +9,36 @@ Category: ipfs Example: --ipfs-gateway $URL ipfs:// Multi: single --- -Specify which gateway to use for IPFS and IPNS URLs. Not specifying this will -instead make curl check if the IPFS_GATEWAY environment variable is set, or if -a ~/.ipfs/gateway file holding the gateway URL exists. +Specifies which gateway to use for IPFS and IPNS URLs. +Not specifying this argument will let cURL try to automatically +check if IPFS_GATEWAY environment variable is set, +or if ~/.ipfs/gateway plain text file exists. -If you run a local IPFS node, this gateway is by default available under -http://localhost:8080. A full example URL would look like: +If you run a local IPFS node, this gateway is by default +available under http://localhost:8080. A full example URL would +look like: curl --ipfs-gateway http://localhost:8080 ipfs://bafybeigagd5nmnn2iys2f3doro7ydrevyr2mzarwidgadawmamiteydbzi -There are many public IPFS gateways. See for example: + +You can also specify publicly available gateways. One such +gateway is https://ipfs.io. A full example url would look like: + + curl --ipfs-gateway https://ipfs.io ipfs://bafybeigagd5nmnn2iys2f3doro7ydrevyr2mzarwidgadawmamiteydbzi + + +There are many public IPFS gateways. As a starting point to find +one that works for your case, consult this page: https://ipfs.github.io/public-gateway-checker/ -WARNING: If you opt to go for a remote gateway you should be aware that you -completely trust the gateway. This is fine in local gateways as you host it -yourself. With remote gateways there could potentially be a malicious actor -returning you data that does not match the request you made, inspect or even -interfere with the request. You will not notice this when using curl. A -mitigation could be to go for a "trustless" gateway. This means you locally -verify that the data. Consult the docs page on trusted vs trustless: + +A word of caution! When you opt to go for a remote gateway you should +be aware that you completely trust the gateway. This is fine in local gateways +as you host it yourself. With remote gateways there could potentially be +a malicious actor returning you data that does not match the request you made, +inspect or even interfere with the request. You won't notice this when using cURL. +A mitigation could be to go for a "trustless" gateway. This means you +locally verify that the data. Consult the docs page on trusted vs trustless: https://docs.ipfs.tech/reference/http/gateway/#trusted-vs-trustless + diff --git a/deps/curl/docs/cmdline-opts/page-footer b/deps/curl/docs/cmdline-opts/page-footer index af41c948..beae49ac 100644 --- a/deps/curl/docs/cmdline-opts/page-footer +++ b/deps/curl/docs/cmdline-opts/page-footer @@ -173,8 +173,8 @@ appears if --fail is used. .IP 23 Write error. Curl could not write data to a local filesystem or similar. .IP 25 -Failed starting the upload. For FTP, the server typically denied the STOR -command. +FTP could not STOR file. The server denied the STOR operation, used for FTP +uploading. .IP 26 Read error. Various reading problems. .IP 27 diff --git a/deps/curl/docs/cmdline-opts/request-target.d b/deps/curl/docs/cmdline-opts/request-target.d index be53c658..61ead5f2 100644 --- a/deps/curl/docs/cmdline-opts/request-target.d +++ b/deps/curl/docs/cmdline-opts/request-target.d @@ -14,6 +14,3 @@ Tells curl to use an alternative "target" (path) instead of using the path as provided in the URL. Particularly useful when wanting to issue HTTP requests without leading slash or other data that does not follow the regular URL pattern, like "OPTIONS *". - -curl passes on the verbatim string you give it its the request without any -filter or other safe guards. That includes white space and control characters. diff --git a/deps/curl/docs/cmdline-opts/request.d b/deps/curl/docs/cmdline-opts/request.d index 6afd5356..0020babf 100644 --- a/deps/curl/docs/cmdline-opts/request.d +++ b/deps/curl/docs/cmdline-opts/request.d @@ -12,9 +12,6 @@ See-also: request-target Multi: single --- Change the method to use when starting the transfer. - -curl passes on the verbatim string you give it its the request without any -filter or other safe guards. That includes white space and control characters. .RS .TP 15 **HTTP** diff --git a/deps/curl/docs/cmdline-opts/resolve.d b/deps/curl/docs/cmdline-opts/resolve.d index badb54e4..31dd099a 100644 --- a/deps/curl/docs/cmdline-opts/resolve.d +++ b/deps/curl/docs/cmdline-opts/resolve.d @@ -37,3 +37,5 @@ Support for providing multiple IP addresses per entry was added in 7.59.0. Support for resolving with wildcard was added in 7.64.0. Support for the '+' prefix was was added in 7.75.0. + +This option can be used many times to add many host names to resolve. diff --git a/deps/curl/docs/cmdline-opts/write-out.d b/deps/curl/docs/cmdline-opts/write-out.d index e069afcf..b2ac2ec0 100644 --- a/deps/curl/docs/cmdline-opts/write-out.d +++ b/deps/curl/docs/cmdline-opts/write-out.d @@ -91,7 +91,7 @@ curl CONNECT request. (Added in 7.12.4) The http version that was effectively used. (Added in 7.50.0) .TP **json** -A JSON object with all available keys. (Added in 7.70.0) +A JSON object with all available keys. .TP **local_ip** The IP address of the local end of the most recently done connection - can be diff --git a/deps/curl/docs/examples/10-at-a-time.c b/deps/curl/docs/examples/10-at-a-time.c index 60777505..b54a4410 100644 --- a/deps/curl/docs/examples/10-at-a-time.c +++ b/deps/curl/docs/examples/10-at-a-time.c @@ -29,7 +29,7 @@ #include #include #include -#ifndef _WIN32 +#ifndef WIN32 # include #endif #include diff --git a/deps/curl/docs/examples/Makefile.inc b/deps/curl/docs/examples/Makefile.inc index f0e073cf..60a006ca 100644 --- a/deps/curl/docs/examples/Makefile.inc +++ b/deps/curl/docs/examples/Makefile.inc @@ -76,10 +76,7 @@ check_PROGRAMS = \ imap-ssl \ imap-store \ imap-tls \ - interface \ ipv6 \ - keepalive \ - localport \ maxconnects \ multi-app \ multi-debugcallback \ diff --git a/deps/curl/docs/examples/anyauthput.c b/deps/curl/docs/examples/anyauthput.c index 1f4340f4..8b979515 100644 --- a/deps/curl/docs/examples/anyauthput.c +++ b/deps/curl/docs/examples/anyauthput.c @@ -33,7 +33,7 @@ #include -#ifdef _WIN32 +#ifdef WIN32 # define FILENO(fp) _fileno(fp) #else # define FILENO(fp) fileno(fp) diff --git a/deps/curl/docs/examples/cookie_interface.c b/deps/curl/docs/examples/cookie_interface.c index 12004983..557b57dc 100644 --- a/deps/curl/docs/examples/cookie_interface.c +++ b/deps/curl/docs/examples/cookie_interface.c @@ -91,7 +91,7 @@ main(void) printf("-----------------------------------------------\n" "Setting a cookie \"PREF\" via cookie interface:\n"); -#ifdef _WIN32 +#ifdef WIN32 #define snprintf _snprintf #endif /* Netscape format cookie */ diff --git a/deps/curl/docs/examples/externalsocket.c b/deps/curl/docs/examples/externalsocket.c index 270a3199..1c78c3db 100644 --- a/deps/curl/docs/examples/externalsocket.c +++ b/deps/curl/docs/examples/externalsocket.c @@ -30,7 +30,7 @@ #include #include -#ifdef _WIN32 +#ifdef WIN32 #include #include #include @@ -96,7 +96,7 @@ int main(void) struct sockaddr_in servaddr; /* socket address structure */ curl_socket_t sockfd; -#ifdef _WIN32 +#ifdef WIN32 WSADATA wsaData; int initwsa = WSAStartup(MAKEWORD(2, 2), &wsaData); if(initwsa) { @@ -168,7 +168,7 @@ int main(void) } } -#ifdef _WIN32 +#ifdef WIN32 WSACleanup(); #endif return 0; diff --git a/deps/curl/docs/examples/ftpupload.c b/deps/curl/docs/examples/ftpupload.c index 92bb0b8a..00de126e 100644 --- a/deps/curl/docs/examples/ftpupload.c +++ b/deps/curl/docs/examples/ftpupload.c @@ -29,7 +29,7 @@ #include #include #include -#ifdef _WIN32 +#ifdef WIN32 #include #else #include diff --git a/deps/curl/docs/examples/interface.c b/deps/curl/docs/examples/interface.c deleted file mode 100644 index f1a2016c..00000000 --- a/deps/curl/docs/examples/interface.c +++ /dev/null @@ -1,52 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at https://curl.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - * SPDX-License-Identifier: curl - * - ***************************************************************************/ -/* - * Use CURLOPT_INTERFACE to bind the outgoing socket to an interface - * - */ -#include -#include - -int main(void) -{ - CURL *curl; - CURLcode res = CURLE_OK; - - curl = curl_easy_init(); - if(curl) { - /* The interface needs to be a local existing interface over which you can - connect to the host in the URL. It can also specify an IP address, but - that address needs to be assigned one of the local network - interfaces. */ - curl_easy_setopt(curl, CURLOPT_INTERFACE, "enp3s0"); - curl_easy_setopt(curl, CURLOPT_URL, "https://curl.se/"); - - res = curl_easy_perform(curl); - - /* always cleanup */ - curl_easy_cleanup(curl); - } - - return (int)res; -} diff --git a/deps/curl/docs/examples/ipv6.c b/deps/curl/docs/examples/ipv6.c index dc305a07..49a44fa7 100644 --- a/deps/curl/docs/examples/ipv6.c +++ b/deps/curl/docs/examples/ipv6.c @@ -28,13 +28,13 @@ #include #include -#ifndef _WIN32 +#ifndef WIN32 #include #endif int main(void) { -#ifndef _WIN32 +#ifndef WIN32 /* Windows users need to find how to use if_nametoindex() */ CURL *curl; CURLcode res; diff --git a/deps/curl/docs/examples/keepalive.c b/deps/curl/docs/examples/keepalive.c deleted file mode 100644 index 1c876bb1..00000000 --- a/deps/curl/docs/examples/keepalive.c +++ /dev/null @@ -1,55 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at https://curl.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - * SPDX-License-Identifier: curl - * - ***************************************************************************/ -/* - * Use the TCP keep-alive options - * - */ -#include -#include - -int main(void) -{ - CURL *curl; - CURLcode res = CURLE_OK; - - curl = curl_easy_init(); - if(curl) { - /* enable TCP keep-alive for this transfer */ - curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L); - - /* keep-alive idle time to 120 seconds */ - curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L); - - /* interval time between keep-alive probes: 60 seconds */ - curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L); - - curl_easy_setopt(curl, CURLOPT_URL, "https://curl.se/"); - - res = curl_easy_perform(curl); - - curl_easy_cleanup(curl); - } - - return (int)res; -} diff --git a/deps/curl/docs/examples/localport.c b/deps/curl/docs/examples/localport.c deleted file mode 100644 index 56e0b62c..00000000 --- a/deps/curl/docs/examples/localport.c +++ /dev/null @@ -1,53 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at https://curl.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - * SPDX-License-Identifier: curl - * - ***************************************************************************/ -/* - * Use CURLOPT_LOCALPORT to control local port number - * - */ -#include -#include - -int main(void) -{ - CURL *curl; - CURLcode res = CURLE_OK; - - curl = curl_easy_init(); - if(curl) { - /* Try to use a local port number between 20000-20009 */ - curl_easy_setopt(curl, CURLOPT_LOCALPORT, 20000L); - /* 10 means number of attempts, which starts with the number set in - CURLOPT_LOCALPORT. The lowe value set, the smaller the change it will - work. */ - curl_easy_setopt(curl, CURLOPT_LOCALPORTRANGE, 10L); - curl_easy_setopt(curl, CURLOPT_URL, "https://curl.se/"); - - res = curl_easy_perform(curl); - - /* always cleanup */ - curl_easy_cleanup(curl); - } - - return (int)res; -} diff --git a/deps/curl/docs/libcurl/curl_easy_duphandle.3 b/deps/curl/docs/libcurl/curl_easy_duphandle.3 index 007efa57..f66c1dff 100644 --- a/deps/curl/docs/libcurl/curl_easy_duphandle.3 +++ b/deps/curl/docs/libcurl/curl_easy_duphandle.3 @@ -45,9 +45,6 @@ The new handle does \fBnot\fP inherit any state information, no connections, no SSL sessions and no cookies. It also does not inherit any share object states or options (created as if \fICURLOPT_SHARE(3)\fP was set to NULL). -If the source handle has HSTS or alt-svc enabled, the duplicate gets data read -data from the main file name to populate the cache. - In multi-threaded programs, this function must be called in a synchronous way, the input handle may not be in use when cloned. .SH EXAMPLE diff --git a/deps/curl/docs/libcurl/curl_easy_header.3 b/deps/curl/docs/libcurl/curl_easy_header.3 index 4898180e..3aa62649 100644 --- a/deps/curl/docs/libcurl/curl_easy_header.3 +++ b/deps/curl/docs/libcurl/curl_easy_header.3 @@ -34,7 +34,6 @@ CURLHcode curl_easy_header(CURL *easy, unsigned int origin, int request, struct curl_header **hout); -.fi .SH DESCRIPTION \fIcurl_easy_header(3)\fP returns a pointer to a "curl_header" struct in \fBhout\fP with data for the HTTP response header \fIname\fP. The case diff --git a/deps/curl/docs/libcurl/curl_easy_option_next.3 b/deps/curl/docs/libcurl/curl_easy_option_next.3 index 2f636451..8109573e 100644 --- a/deps/curl/docs/libcurl/curl_easy_option_next.3 +++ b/deps/curl/docs/libcurl/curl_easy_option_next.3 @@ -28,25 +28,6 @@ curl_easy_option_next - iterate over easy setopt options .nf #include -const struct curl_easyoption * -curl_easy_option_next(const struct curl_easyoption *prev); -.fi -.SH DESCRIPTION -This function returns a pointer to the first or the next \fIcurl_easyoption\fP -struct, providing an ability to iterate over all known options for -\fIcurl_easy_setopt(3)\fP in this instance of libcurl. - -Pass a \fBNULL\fP argument as \fBprev\fP to get the first option returned, or -pass in the current option to get the next one returned. If there is no more -option to return, \fIcurl_easy_option_next(3)\fP returns NULL. - -The options returned by this functions are the ones known to this libcurl and -information about what argument type they want. - -If the \fBCURLOT_FLAG_ALIAS\fP bit is set in the flags field, it means the -name is provided for backwards compatibility as an alias. -.SH struct -.nf typedef enum { CURLOT_LONG, /* long (a range of values) */ CURLOT_VALUES, /* (a defined set or bitmask) */ @@ -67,15 +48,32 @@ struct curl_easyoption { curl_easytype type; unsigned int flags; }; + +const struct curl_easyoption * +curl_easy_option_next(const struct curl_easyoption *prev); .fi +.SH DESCRIPTION +This function returns a pointer to the first or the next \fIcurl_easyoption\fP +struct, providing an ability to iterate over all known options for +\fIcurl_easy_setopt(3)\fP in this instance of libcurl. + +Pass a \fBNULL\fP argument as \fBprev\fP to get the first option returned, or +pass in the current option to get the next one returned. If there is no more +option to return, \fIcurl_easy_option_next(3)\fP returns NULL. + +The options returned by this functions are the ones known to this libcurl and +information about what argument type they want. + +If the \fBCURLOT_FLAG_ALIAS\fP bit is set in the flags field, it means the +name is provided for backwards compatibility as an alias. .SH EXAMPLE .nf /* iterate over all available options */ const struct curl_easyoption *opt; -opt = curl_easy_option_next(NULL); +opt = curl_easy_option_by_next(NULL); while(opt) { printf("Name: %s\\n", opt->name); - opt = curl_easy_option_next(opt); + opt = curl_easy_option_by_next(opt); } .fi .SH AVAILABILITY diff --git a/deps/curl/docs/libcurl/curl_easy_pause.3 b/deps/curl/docs/libcurl/curl_easy_pause.3 index 068d0c44..a3cf4b81 100644 --- a/deps/curl/docs/libcurl/curl_easy_pause.3 +++ b/deps/curl/docs/libcurl/curl_easy_pause.3 @@ -26,9 +26,9 @@ curl_easy_pause - pause and unpause a connection .SH SYNOPSIS .nf -#include +.B #include -CURLcode curl_easy_pause(CURL *handle, int bitmask ); +.BI "CURLcode curl_easy_pause(CURL *"handle ", int "bitmask ");" .fi .SH DESCRIPTION Using this function, you can explicitly mark a running connection to get diff --git a/deps/curl/docs/libcurl/curl_easy_recv.3 b/deps/curl/docs/libcurl/curl_easy_recv.3 index 3d724696..c215a544 100644 --- a/deps/curl/docs/libcurl/curl_easy_recv.3 +++ b/deps/curl/docs/libcurl/curl_easy_recv.3 @@ -27,7 +27,7 @@ curl_easy_recv - receives raw data on an "easy" connection .SH SYNOPSIS .nf -#include +#include CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, size_t *n); .fi diff --git a/deps/curl/docs/libcurl/curl_easy_send.3 b/deps/curl/docs/libcurl/curl_easy_send.3 index 95fdc077..4da5a238 100644 --- a/deps/curl/docs/libcurl/curl_easy_send.3 +++ b/deps/curl/docs/libcurl/curl_easy_send.3 @@ -27,7 +27,7 @@ curl_easy_send - sends raw data over an "easy" connection .SH SYNOPSIS .nf -#include +#include CURLcode curl_easy_send(CURL *curl, const void *buffer, size_t buflen, size_t *n); diff --git a/deps/curl/docs/libcurl/curl_formget.3 b/deps/curl/docs/libcurl/curl_formget.3 index cd6b7692..0ce76101 100644 --- a/deps/curl/docs/libcurl/curl_formget.3 +++ b/deps/curl/docs/libcurl/curl_formget.3 @@ -26,11 +26,10 @@ curl_formget - serialize a previously built multipart form POST chain .SH SYNOPSIS .nf -#include +.B #include int curl_formget(struct curl_httppost * form, void *userp, - curl_formget_callback append); -.fi + curl_formget_callback append ); .SH DESCRIPTION curl_formget() is used to serialize data previously built/appended with \fIcurl_formadd(3)\fP. Accepts a void pointer as second argument named diff --git a/deps/curl/docs/libcurl/curl_getdate.3 b/deps/curl/docs/libcurl/curl_getdate.3 index b4c07e8c..2f88fdb9 100644 --- a/deps/curl/docs/libcurl/curl_getdate.3 +++ b/deps/curl/docs/libcurl/curl_getdate.3 @@ -21,14 +21,14 @@ .\" * SPDX-License-Identifier: curl .\" * .\" ************************************************************************** -.TH curl_getdate 3 "12 Aug 2005" "libcurl" "libcurl" +a.TH curl_getdate 3 "12 Aug 2005" "libcurl" "libcurl" .SH NAME curl_getdate - Convert a date string to number of seconds .SH SYNOPSIS .nf #include -time_t curl_getdate(const char *datestring, const time_t *now); +time_t curl_getdate(char *datestring, time_t *now); .fi .SH DESCRIPTION \fIcurl_getdate(3)\fP returns the number of seconds since the Epoch, January diff --git a/deps/curl/docs/libcurl/curl_global_sslset.3 b/deps/curl/docs/libcurl/curl_global_sslset.3 index e9fd54b2..e1d5bdfb 100644 --- a/deps/curl/docs/libcurl/curl_global_sslset.3 +++ b/deps/curl/docs/libcurl/curl_global_sslset.3 @@ -28,9 +28,31 @@ curl_global_sslset - Select SSL backend to use with libcurl .nf #include +typedef struct { + curl_sslbackend id; + const char *name; +} curl_ssl_backend; + +typedef enum { + CURLSSLBACKEND_NONE = 0, + CURLSSLBACKEND_OPENSSL = 1, /* or one of its forks */ + CURLSSLBACKEND_GNUTLS = 2, + CURLSSLBACKEND_NSS = 3, + CURLSSLBACKEND_GSKIT = 5, /* deprecated */ + CURLSSLBACKEND_POLARSSL = 6, /* deprecated */ + CURLSSLBACKEND_WOLFSSL = 7, + CURLSSLBACKEND_SCHANNEL = 8, + CURLSSLBACKEND_SECURETRANSPORT = 9, + CURLSSLBACKEND_AXTLS = 10, /* deprecated */ + CURLSSLBACKEND_MBEDTLS = 11, + CURLSSLBACKEND_MESALINK = 12, /* deprecated */ + CURLSSLBACKEND_BEARSSL = 13, + CURLSSLBACKEND_RUSTLS = 14 +} curl_sslbackend; + CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, - const curl_ssl_backend ***avail); + curl_ssl_backend ***avail); .fi .SH DESCRIPTION This function configures at runtime which SSL backend to use with @@ -77,30 +99,6 @@ provide the same API. \fIcurl_version_info(3)\fP can return more specific info about the exact OpenSSL flavor and version number is use. -.SH struct -.nf -typedef struct { - curl_sslbackend id; - const char *name; -} curl_ssl_backend; - -typedef enum { - CURLSSLBACKEND_NONE = 0, - CURLSSLBACKEND_OPENSSL = 1, /* or one of its forks */ - CURLSSLBACKEND_GNUTLS = 2, - CURLSSLBACKEND_NSS = 3, - CURLSSLBACKEND_GSKIT = 5, /* deprecated */ - CURLSSLBACKEND_POLARSSL = 6, /* deprecated */ - CURLSSLBACKEND_WOLFSSL = 7, - CURLSSLBACKEND_SCHANNEL = 8, - CURLSSLBACKEND_SECURETRANSPORT = 9, - CURLSSLBACKEND_AXTLS = 10, /* deprecated */ - CURLSSLBACKEND_MBEDTLS = 11, - CURLSSLBACKEND_MESALINK = 12, /* deprecated */ - CURLSSLBACKEND_BEARSSL = 13, - CURLSSLBACKEND_RUSTLS = 14 -} curl_sslbackend; -.fi .SH EXAMPLE .nf /* choose a specific backend */ diff --git a/deps/curl/docs/libcurl/curl_global_trace.3 b/deps/curl/docs/libcurl/curl_global_trace.3 index 686896fd..8f16bb4a 100644 --- a/deps/curl/docs/libcurl/curl_global_trace.3 +++ b/deps/curl/docs/libcurl/curl_global_trace.3 @@ -102,10 +102,10 @@ Below is a trace sample where "http/2" was configured. The trace output of an enabled component appears at the beginning in brackets. .nf * [HTTP/2] [h2sid=1] cf_send(len=96) submit https://example.com/ -\&... +... * [HTTP/2] [h2sid=1] FRAME[HEADERS] * [HTTP/2] [h2sid=1] 249 header bytes -\&... +... .fi .SH AVAILABILITY diff --git a/deps/curl/docs/libcurl/curl_multi_fdset.3 b/deps/curl/docs/libcurl/curl_multi_fdset.3 index d569b84e..dbcb5b2b 100644 --- a/deps/curl/docs/libcurl/curl_multi_fdset.3 +++ b/deps/curl/docs/libcurl/curl_multi_fdset.3 @@ -33,7 +33,7 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle, fd_set *write_fd_set, fd_set *exc_fd_set, int *max_fd); -.fi +.ad .SH DESCRIPTION This function extracts file descriptor information from a given multi_handle. libcurl returns its \fIfd_set\fP sets. The application can use these to diff --git a/deps/curl/docs/libcurl/curl_multi_poll.3 b/deps/curl/docs/libcurl/curl_multi_poll.3 index 8ea7bd10..c7091231 100644 --- a/deps/curl/docs/libcurl/curl_multi_poll.3 +++ b/deps/curl/docs/libcurl/curl_multi_poll.3 @@ -33,7 +33,7 @@ CURLMcode curl_multi_poll(CURLM *multi_handle, unsigned int extra_nfds, int timeout_ms, int *numfds); -.fi +.ad .SH DESCRIPTION \fIcurl_multi_poll(3)\fP polls all file descriptors used by the curl easy handles contained in the given multi handle set. It blocks until activity is diff --git a/deps/curl/docs/libcurl/curl_multi_setopt.3 b/deps/curl/docs/libcurl/curl_multi_setopt.3 index 38e17065..f0976535 100644 --- a/deps/curl/docs/libcurl/curl_multi_setopt.3 +++ b/deps/curl/docs/libcurl/curl_multi_setopt.3 @@ -28,17 +28,17 @@ curl_multi_setopt \- set options for a curl multi handle .nf #include -CURLMcode curl_multi_setopt(CURLM *multi_handle, CURLMoption option, parameter); +CURLMcode curl_multi_setopt(CURLM *multi_handle, CURLMoption option, param); .fi .SH DESCRIPTION \fIcurl_multi_setopt(3)\fP is used to tell a libcurl multi handle how to behave. By using the appropriate options to \fIcurl_multi_setopt(3)\fP, you can change libcurl's behavior when using that multi handle. All options are -set with the \fIoption\fP followed by the \fIparameter\fP. That parameter can -be a \fBlong\fP, a \fBfunction pointer\fP, an \fBobject pointer\fP or a -\fBcurl_off_t\fP type, depending on what the specific option expects. Read -this manual carefully as bad input values may cause libcurl to behave -badly. You can only set one option in each function call. +set with the \fIoption\fP followed by the parameter \fIparam\fP. That +parameter can be a \fBlong\fP, a \fBfunction pointer\fP, an \fBobject +pointer\fP or a \fBcurl_off_t\fP type, depending on what the specific option +expects. Read this manual carefully as bad input values may cause libcurl to +behave badly. You can only set one option in each function call. .SH OPTIONS .IP CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE diff --git a/deps/curl/docs/libcurl/curl_multi_strerror.3 b/deps/curl/docs/libcurl/curl_multi_strerror.3 index 11538b0e..7dd7e889 100644 --- a/deps/curl/docs/libcurl/curl_multi_strerror.3 +++ b/deps/curl/docs/libcurl/curl_multi_strerror.3 @@ -26,10 +26,8 @@ curl_multi_strerror - return string describing error code .SH SYNOPSIS .nf -#include - -const char *curl_multi_strerror(CURLMcode errornum); -.fi +.B #include +.BI "const char *curl_multi_strerror(CURLMcode " errornum ");" .SH DESCRIPTION This function returns a string describing the \fICURLMcode\fP error code passed in the argument \fIerrornum\fP. diff --git a/deps/curl/docs/libcurl/curl_multi_wait.3 b/deps/curl/docs/libcurl/curl_multi_wait.3 index 0698bcad..565fdb8d 100644 --- a/deps/curl/docs/libcurl/curl_multi_wait.3 +++ b/deps/curl/docs/libcurl/curl_multi_wait.3 @@ -33,7 +33,7 @@ CURLMcode curl_multi_wait(CURLM *multi_handle, unsigned int extra_nfds, int timeout_ms, int *numfds); -.fi +.ad .SH DESCRIPTION \fIcurl_multi_wait(3)\fP polls all file descriptors used by the curl easy handles contained in the given multi handle set. It blocks until activity is diff --git a/deps/curl/docs/libcurl/curl_share_strerror.3 b/deps/curl/docs/libcurl/curl_share_strerror.3 index a8329efa..6dd857dc 100644 --- a/deps/curl/docs/libcurl/curl_share_strerror.3 +++ b/deps/curl/docs/libcurl/curl_share_strerror.3 @@ -26,10 +26,8 @@ curl_share_strerror - return string describing error code .SH SYNOPSIS .nf -#include - -const char *curl_share_strerror(CURLSHcode errornum); -.fi +.B #include +.BI "const char *curl_share_strerror(CURLSHcode " errornum ");" .SH DESCRIPTION The \fIcurl_share_strerror(3)\fP function returns a string describing the \fICURLSHcode\fP error code passed in the argument \fIerrornum\fP. diff --git a/deps/curl/docs/libcurl/curl_strequal.3 b/deps/curl/docs/libcurl/curl_strequal.3 index 881b0d70..c66c6529 100644 --- a/deps/curl/docs/libcurl/curl_strequal.3 +++ b/deps/curl/docs/libcurl/curl_strequal.3 @@ -28,8 +28,8 @@ curl_strequal, curl_strnequal - case insensitive string comparisons .nf #include -int curl_strequal(const char *str1, const char *str2); -int curl_strnequal(const char *str1, const char *str2, size_t length); +int curl_strequal(char *str1, char *str2); +int curl_strnequal(char *str1, char *str2, size_t length); .fi .SH DESCRIPTION The diff --git a/deps/curl/docs/libcurl/curl_url_dup.3 b/deps/curl/docs/libcurl/curl_url_dup.3 index 059515e1..a2e9850b 100644 --- a/deps/curl/docs/libcurl/curl_url_dup.3 +++ b/deps/curl/docs/libcurl/curl_url_dup.3 @@ -28,7 +28,7 @@ curl_url_dup - duplicate a URL handle .nf #include -CURLU *curl_url_dup(const CURLU *inhandle); +CURLU *curl_url_dup(CURLU *inhandle); .fi .SH DESCRIPTION Duplicates the URL object the input \fICURLU\fP \fIinhandle\fP identifies and diff --git a/deps/curl/docs/libcurl/curl_url_get.3 b/deps/curl/docs/libcurl/curl_url_get.3 index 34c56c3c..815e5587 100644 --- a/deps/curl/docs/libcurl/curl_url_get.3 +++ b/deps/curl/docs/libcurl/curl_url_get.3 @@ -28,7 +28,7 @@ curl_url_get - extract a part from a URL .nf #include -CURLUcode curl_url_get(const CURLU *url, +CURLUcode curl_url_get(CURLU *url, CURLUPart part, char **content, unsigned int flags); diff --git a/deps/curl/docs/libcurl/curl_url_strerror.3 b/deps/curl/docs/libcurl/curl_url_strerror.3 index 382a4049..b3fd4037 100644 --- a/deps/curl/docs/libcurl/curl_url_strerror.3 +++ b/deps/curl/docs/libcurl/curl_url_strerror.3 @@ -26,10 +26,8 @@ curl_url_strerror - return string describing error code .SH SYNOPSIS .nf -#include - -const char *curl_url_strerror(CURLUcode errornum); -.fi +.B #include +.BI "const char *curl_url_strerror(CURLUcode " errornum ");" .SH DESCRIPTION This function returns a string describing the CURLUcode error code passed in the argument \fIerrornum\fP. diff --git a/deps/curl/docs/libcurl/curl_ws_meta.3 b/deps/curl/docs/libcurl/curl_ws_meta.3 index 04b67592..d9ab43a1 100644 --- a/deps/curl/docs/libcurl/curl_ws_meta.3 +++ b/deps/curl/docs/libcurl/curl_ws_meta.3 @@ -27,7 +27,14 @@ curl_ws_meta - meta data WebSocket information .SH SYNOPSIS .nf -#include +#include + +struct curl_ws_frame { + int age; /* zero */ + int flags; /* See the CURLWS_* defines */ + curl_off_t offset; /* the offset of this data into the frame */ + curl_off_t bytesleft; /* number of pending bytes left of the payload */ +}; const struct curl_ws_frame *curl_ws_meta(CURL *curl); .fi @@ -46,15 +53,7 @@ what transfer the question is about, but as there is no such pointer provided to the callback by libcurl itself, applications that want to use \fIcurl_ws_meta(3)\fP need to pass it on to the callback on its own. -.SH "struct curl_ws_frame" -.nf -struct curl_ws_frame { - int age; - int flags; - curl_off_t offset; - curl_off_t bytesleft; -}; -.fi +.SH "struct fields" .IP age This field specify the age of this struct. It is always zero for now. .IP flags diff --git a/deps/curl/docs/libcurl/curl_ws_recv.3 b/deps/curl/docs/libcurl/curl_ws_recv.3 index dcfcbe5d..a9df029e 100644 --- a/deps/curl/docs/libcurl/curl_ws_recv.3 +++ b/deps/curl/docs/libcurl/curl_ws_recv.3 @@ -27,7 +27,7 @@ curl_ws_recv - receive WebSocket data .SH SYNOPSIS .nf -#include +#include CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen, size_t *recv, const struct curl_ws_frame **meta); diff --git a/deps/curl/docs/libcurl/curl_ws_send.3 b/deps/curl/docs/libcurl/curl_ws_send.3 index 0dd52fcf..9df2cc16 100644 --- a/deps/curl/docs/libcurl/curl_ws_send.3 +++ b/deps/curl/docs/libcurl/curl_ws_send.3 @@ -27,7 +27,7 @@ curl_ws_send - send WebSocket data .SH SYNOPSIS .nf -#include +#include CURLcode curl_ws_send(CURL *curl, const void *buffer, size_t buflen, size_t *sent, curl_off_t fragsize, diff --git a/deps/curl/docs/libcurl/libcurl-errors.3 b/deps/curl/docs/libcurl/libcurl-errors.3 index 03f18e6b..f83bf6a2 100644 --- a/deps/curl/docs/libcurl/libcurl-errors.3 +++ b/deps/curl/docs/libcurl/libcurl-errors.3 @@ -288,6 +288,9 @@ the specific problem. SSL Client Certificate required. .IP "CURLE_UNRECOVERABLE_POLL (99)" An internal call to poll() or select() returned error that is not recoverable. +.IP "CURLE_OBSOLETE*" +These error codes are never returned. They were used in an old libcurl version +and are currently unused. .SH "CURLMcode" This is the generic return code used by functions in the libcurl multi interface. Also consider \fIcurl_multi_strerror(3)\fP. @@ -297,6 +300,9 @@ This is not really an error. It means you should call between. Before version 7.20.0 (released on February 9 2010) this could be returned by \fIcurl_multi_perform(3)\fP, but in later versions this return code is never used. +.IP "CURLM_CALL_MULTI_SOCKET (-1)" +An alias for \fICURLM_CALL_MULTI_PERFORM\fP. Never returned by modern libcurl +versions. .IP "CURLM_OK (0)" Things are fine. .IP "CURLM_BAD_HANDLE (1)" @@ -408,13 +414,9 @@ The scheme part of the URL contained bad or invalid characters. The URL contained an invalid number of slashes. .IP "CURLUE_BAD_USER (29)" The user part of the URL contained bad or invalid characters. -.IP "CURLUE_LACKS_IDN (30)" -libcurl lacks IDN support. .SH "CURLHcode" The header interface returns a \fICURLHcode\fP to indicate when an error has occurred. -.IP "CURLHE_OK (0)" -All fine. Proceed as usual. .IP "CURLHE_BADINDEX (1)" There is no header with the requested index. .IP "CURLHE_MISSING (2)" diff --git a/deps/curl/docs/libcurl/libcurl-security.3 b/deps/curl/docs/libcurl/libcurl-security.3 index 0d7bce06..0bc056c5 100644 --- a/deps/curl/docs/libcurl/libcurl-security.3 +++ b/deps/curl/docs/libcurl/libcurl-security.3 @@ -68,7 +68,7 @@ plain text anywhere. Many of the protocols libcurl supports send name and password unencrypted as clear text (HTTP Basic authentication, FTP, TELNET etc). It is easy for anyone on your network or a network nearby yours to just fire up a network analyzer -tool and eavesdrop on your passwords. Do not let the fact that HTTP Basic uses +tool and eavesdrop on your passwords. do not let the fact that HTTP Basic uses base64 encoded passwords fool you. They may not look readable at a first glance, but they are easily "deciphered" by anyone within seconds. diff --git a/deps/curl/docs/libcurl/libcurl-thread.3 b/deps/curl/docs/libcurl/libcurl-thread.3 index 397eeae6..00e7d69d 100644 --- a/deps/curl/docs/libcurl/libcurl-thread.3 +++ b/deps/curl/docs/libcurl/libcurl-thread.3 @@ -42,10 +42,37 @@ interface but you must provide your own locking and set Note that some items are specifically documented as not thread-safe in the share API (the connection pool and HSTS cache for example). .SH TLS -All current TLS libraries libcurl supports are thread-safe. OpenSSL 1.1.0+ can -be safely used in multi-threaded applications provided that support for the -underlying OS threading API is built-in. For older versions of OpenSSL, the -user must set mutex callbacks. +If you are accessing HTTPS or FTPS URLs in a multi-threaded manner, you are +then of course using the underlying SSL library multi-threaded and those libs +might have their own requirements on this issue. You may need to provide one +or two functions to allow it to function properly: +.IP OpenSSL +OpenSSL 1.1.0+ "can be safely used in multi-threaded applications provided that +support for the underlying OS threading API is built-in." In that case the +engine is used by libcurl in a way that is fully thread-safe. + +https://www.openssl.org/docs/man1.1.0/man3/CRYPTO_THREAD_run_once.html#DESCRIPTION + +OpenSSL <= 1.0.2 the user must set callbacks. + +https://www.openssl.org/docs/man1.0.2/man3/CRYPTO_set_locking_callback.html#DESCRIPTION + +https://curl.se/libcurl/c/opensslthreadlock.html + +.IP GnuTLS +https://gnutls.org/manual/html_node/Thread-safety.html +.IP NSS +thread-safe already without anything required. +.IP Secure-Transport +The engine is used by libcurl in a way that is fully thread-safe. +.IP Schannel +The engine is used by libcurl in a way that is fully thread-safe. +.IP wolfSSL +The engine is used by libcurl in a way that is fully thread-safe. +.IP BoringSSL +The engine is used by libcurl in a way that is fully thread-safe. +.IP AWS-LC +The engine is used by libcurl in a way that is fully thread-safe. .SH "Signals" Signals are used for timing out name resolves (during DNS lookup) - when built without using either the c-ares or threaded resolver backends. On systems that diff --git a/deps/curl/docs/libcurl/libcurl.3 b/deps/curl/docs/libcurl/libcurl.3 index dd4163a7..1c174066 100644 --- a/deps/curl/docs/libcurl/libcurl.3 +++ b/deps/curl/docs/libcurl/libcurl.3 @@ -71,7 +71,7 @@ get information about a performed transfer. See \fIcurl_easy_getinfo(3)\fP helps building an HTTP form POST. See \fIcurl_mime_addpart(3)\fP .IP curl_slist_append() builds a linked list. See \fIcurl_slist_append(3)\fP -.IP "Sharing data between transfers" +.IP Sharing data between transfers You can have multiple easy handles share certain data, even if they are used in different threads. This magic is setup using the share interface, as described in the \fIlibcurl-share(3)\fP man page. diff --git a/deps/curl/docs/libcurl/mksymbolsmanpage.pl b/deps/curl/docs/libcurl/mksymbolsmanpage.pl index 3bc68694..a8cb10d8 100644 --- a/deps/curl/docs/libcurl/mksymbolsmanpage.pl +++ b/deps/curl/docs/libcurl/mksymbolsmanpage.pl @@ -26,14 +26,8 @@ my $version="7.41.0"; use POSIX qw(strftime); -my @ts; -if (defined($ENV{SOURCE_DATE_EPOCH})) { - @ts = localtime($ENV{SOURCE_DATE_EPOCH}); -} else { - @ts = localtime; -} -my $date = strftime "%b %e, %Y", @ts; -my $year = strftime "%Y", @ts; +my $date = strftime "%b %e, %Y", localtime; +my $year = strftime "%Y", localtime; print <
#include -#if defined(__FreeBSD__) || defined(__MidnightBSD__) +#if (defined(__FreeBSD__) && (__FreeBSD__ >= 2)) || defined(__MidnightBSD__) /* Needed for __FreeBSD_version or __MidnightBSD_version symbol definition */ -#include +#include #endif /* The include stuff here below is mainly for time_t! */ #include #include -#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__) +#if defined(CURL_WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__) #if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \ defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H)) /* The check above prevents the winsock2 inclusion if winsock.h already was @@ -79,7 +88,7 @@ libc5-based Linux systems. Only include it on systems that are known to require it! */ #if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ - defined(__minix) || defined(__INTEGRITY) || \ + defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \ defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \ defined(__CYGWIN__) || defined(AMIGA) || defined(__NuttX__) || \ (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) || \ @@ -88,11 +97,11 @@ #include #endif -#if !defined(_WIN32) && !defined(_WIN32_WCE) +#if !defined(CURL_WIN32) && !defined(_WIN32_WCE) #include #endif -#if !defined(_WIN32) +#if !defined(CURL_WIN32) #include #endif @@ -119,7 +128,7 @@ typedef void CURLSH; #ifdef CURL_STATICLIB # define CURL_EXTERN -#elif defined(_WIN32) || \ +#elif defined(CURL_WIN32) || defined(__SYMBIAN32__) || \ (__has_declspec_attribute(dllexport) && \ __has_declspec_attribute(dllimport)) # if defined(BUILDING_LIBCURL) @@ -135,7 +144,7 @@ typedef void CURLSH; #ifndef curl_socket_typedef /* socket typedef */ -#if defined(_WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H) +#if defined(CURL_WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H) typedef SOCKET curl_socket_t; #define CURL_SOCKET_BAD INVALID_SOCKET #else diff --git a/deps/curl/include/curl/curlver.h b/deps/curl/include/curl/curlver.h index 1ff5de61..89881684 100644 --- a/deps/curl/include/curl/curlver.h +++ b/deps/curl/include/curl/curlver.h @@ -32,12 +32,12 @@ /* This is the version number of the libcurl package from which this header file origins: */ -#define LIBCURL_VERSION "8.5.0-DEV" +#define LIBCURL_VERSION "8.4.0-DEV" /* The numeric version number is also available "in parts" by using these defines: */ #define LIBCURL_VERSION_MAJOR 8 -#define LIBCURL_VERSION_MINOR 5 +#define LIBCURL_VERSION_MINOR 4 #define LIBCURL_VERSION_PATCH 0 /* This is the numeric version of the libcurl version number, meant for easier @@ -59,7 +59,7 @@ CURL_VERSION_BITS() macro since curl's own configure script greps for it and needs it to contain the full number. */ -#define LIBCURL_VERSION_NUM 0x080500 +#define LIBCURL_VERSION_NUM 0x080400 /* * This is the date and time when the full source package was created. The diff --git a/deps/curl/include/curl/system.h b/deps/curl/include/curl/system.h index f2554b4a..97e0d037 100644 --- a/deps/curl/include/curl/system.h +++ b/deps/curl/include/curl/system.h @@ -141,6 +141,29 @@ # define CURL_TYPEOF_CURL_SOCKLEN_T int # endif +#elif defined(__SYMBIAN32__) +# if defined(__EABI__) /* Treat all ARM compilers equally */ +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__CW32__) +# pragma longlong on +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__VC32__) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int + #elif defined(macintosh) # include # if TYPE_LONGLONG @@ -178,10 +201,9 @@ # define CURL_TYPEOF_CURL_SOCKLEN_T int #elif defined(__MINGW32__) -# include # define CURL_TYPEOF_CURL_OFF_T long long -# define CURL_FORMAT_CURL_OFF_T PRId64 -# define CURL_FORMAT_CURL_OFF_TU PRIu64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" # define CURL_SUFFIX_CURL_OFF_T LL # define CURL_SUFFIX_CURL_OFF_TU ULL # define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t @@ -348,14 +370,7 @@ /* ===================================== */ #elif defined(_MSC_VER) -# if (_MSC_VER >= 1800) -# include -# define CURL_TYPEOF_CURL_OFF_T __int64 -# define CURL_FORMAT_CURL_OFF_T PRId64 -# define CURL_FORMAT_CURL_OFF_TU PRIu64 -# define CURL_SUFFIX_CURL_OFF_T i64 -# define CURL_SUFFIX_CURL_OFF_TU ui64 -# elif (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) # define CURL_TYPEOF_CURL_OFF_T __int64 # define CURL_FORMAT_CURL_OFF_T "I64d" # define CURL_FORMAT_CURL_OFF_TU "I64u" diff --git a/deps/curl/lib/CMakeLists.txt b/deps/curl/lib/CMakeLists.txt index 51d52578..6f849199 100644 --- a/deps/curl/lib/CMakeLists.txt +++ b/deps/curl/lib/CMakeLists.txt @@ -47,25 +47,20 @@ if(USE_ARES) include_directories(${CARES_INCLUDE_DIR}) endif() -if(BUILD_TESTING) - add_library( - curlu # special libcurlu library just for unittests - STATIC - EXCLUDE_FROM_ALL - ${HHEADERS} ${CSOURCES} - ) - target_compile_definitions(curlu PUBLIC UNITTESTS CURL_STATICLIB) -endif() +add_library( + curlu # special libcurlu library just for unittests + STATIC + EXCLUDE_FROM_ALL + ${HHEADERS} ${CSOURCES} +) +target_compile_definitions(curlu PUBLIC UNITTESTS CURL_STATICLIB) if(ENABLE_CURLDEBUG) # We must compile these sources separately to avoid memdebug.h redefinitions # applying to them. set_source_files_properties(memdebug.c curl_multibyte.c PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON) endif() - -if(BUILD_TESTING) - target_link_libraries(curlu PRIVATE ${CURL_LIBS}) -endif() +target_link_libraries(curlu PRIVATE ${CURL_LIBS}) transform_makefile_inc("Makefile.soname" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake") include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake) diff --git a/deps/curl/lib/Makefile.am b/deps/curl/lib/Makefile.am index 1237c8e9..3c0a7091 100644 --- a/deps/curl/lib/Makefile.am +++ b/deps/curl/lib/Makefile.am @@ -110,7 +110,7 @@ libcurl_la_CFLAGS_EXTRA += $(CFLAG_CURL_SYMBOL_HIDING) endif libcurl_la_CPPFLAGS = $(AM_CPPFLAGS) $(libcurl_la_CPPFLAGS_EXTRA) -libcurl_la_LDFLAGS = $(AM_LDFLAGS) $(libcurl_la_LDFLAGS_EXTRA) $(CURL_LDFLAGS_LIB) $(LIBCURL_LIBS) +libcurl_la_LDFLAGS = $(AM_LDFLAGS) $(libcurl_la_LDFLAGS_EXTRA) $(LDFLAGS) $(LIBCURL_LIBS) libcurl_la_CFLAGS = $(AM_CFLAGS) $(libcurl_la_CFLAGS_EXTRA) libcurlu_la_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB -DUNITTESTS diff --git a/deps/curl/lib/Makefile.mk b/deps/curl/lib/Makefile.mk index 1513cafe..5071600b 100644 --- a/deps/curl/lib/Makefile.mk +++ b/deps/curl/lib/Makefile.mk @@ -145,10 +145,7 @@ ifneq ($(findstring -rtmp,$(CFG)),) CPPFLAGS += -DUSE_LIBRTMP CPPFLAGS += -I"$(LIBRTMP_PATH)" _LDFLAGS += -L"$(LIBRTMP_PATH)/librtmp" - _LIBS += -lrtmp - ifdef WIN32 - _LIBS += -lwinmm - endif + _LIBS += -lrtmp -lwinmm ZLIB := 1 endif diff --git a/deps/curl/lib/altsvc.c b/deps/curl/lib/altsvc.c index 35450d6b..22b0b69c 100644 --- a/deps/curl/lib/altsvc.c +++ b/deps/curl/lib/altsvc.c @@ -97,7 +97,7 @@ static struct altsvc *altsvc_createid(const char *srchost, unsigned int srcport, unsigned int dstport) { - struct altsvc *as = calloc(1, sizeof(struct altsvc)); + struct altsvc *as = calloc(sizeof(struct altsvc), 1); size_t hlen; size_t dlen; if(!as) @@ -123,13 +123,15 @@ static struct altsvc *altsvc_createid(const char *srchost, dlen -= 2; } - as->src.host = Curl_strndup(srchost, hlen); + as->src.host = Curl_memdup(srchost, hlen + 1); if(!as->src.host) goto error; + as->src.host[hlen] = 0; - as->dst.host = Curl_strndup(dsthost, dlen); + as->dst.host = Curl_memdup(dsthost, dlen + 1); if(!as->dst.host) goto error; + as->dst.host[dlen] = 0; as->src.alpnid = srcalpnid; as->dst.alpnid = dstalpnid; @@ -299,7 +301,7 @@ static CURLcode altsvc_out(struct altsvc *as, FILE *fp) */ struct altsvcinfo *Curl_altsvc_init(void) { - struct altsvcinfo *asi = calloc(1, sizeof(struct altsvcinfo)); + struct altsvcinfo *asi = calloc(sizeof(struct altsvcinfo), 1); if(!asi) return NULL; Curl_llist_init(&asi->list, NULL); diff --git a/deps/curl/lib/arpa_telnet.h b/deps/curl/lib/arpa_telnet.h index 228b4466..de137380 100644 --- a/deps/curl/lib/arpa_telnet.h +++ b/deps/curl/lib/arpa_telnet.h @@ -56,14 +56,12 @@ static const char * const telnetoptions[]= "TERM SPEED", "LFLOW", "LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON" }; -#define CURL_TELOPT(x) telnetoptions[x] -#else -#define CURL_TELOPT(x) "" #endif #define CURL_TELOPT_MAXIMUM CURL_TELOPT_NEW_ENVIRON #define CURL_TELOPT_OK(x) ((x) <= CURL_TELOPT_MAXIMUM) +#define CURL_TELOPT(x) telnetoptions[x] #define CURL_NTELOPTS 40 @@ -105,12 +103,7 @@ static const char * const telnetcmds[]= #define CURL_TELCMD_OK(x) ( ((unsigned int)(x) >= CURL_TELCMD_MINIMUM) && \ ((unsigned int)(x) <= CURL_TELCMD_MAXIMUM) ) - -#ifndef CURL_DISABLE_VERBOSE_STRINGS #define CURL_TELCMD(x) telnetcmds[(x)-CURL_TELCMD_MINIMUM] -#else -#define CURL_TELCMD(x) "" -#endif #endif /* CURL_DISABLE_TELNET */ diff --git a/deps/curl/lib/asyn-ares.c b/deps/curl/lib/asyn-ares.c index 437c9337..e73e41da 100644 --- a/deps/curl/lib/asyn-ares.c +++ b/deps/curl/lib/asyn-ares.c @@ -60,13 +60,13 @@ #include "progress.h" #include "timediff.h" -#if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \ - defined(_WIN32) -# define CARES_STATICLIB -#endif -#include -#include /* really old c-ares didn't include this by - itself */ +# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \ + defined(WIN32) +# define CARES_STATICLIB +# endif +# include +# include /* really old c-ares didn't include this by + itself */ #if ARES_VERSION >= 0x010500 /* c-ares 1.5.0 or later, the callback proto is modified */ @@ -228,9 +228,9 @@ static void destroy_async_data(struct Curl_async *async); void Curl_resolver_cancel(struct Curl_easy *data) { DEBUGASSERT(data); - if(data->conn->resolve_async.resolver) - ares_cancel((ares_channel)data->conn->resolve_async.resolver); - destroy_async_data(&data->conn->resolve_async); + if(data->state.async.resolver) + ares_cancel((ares_channel)data->state.async.resolver); + destroy_async_data(&data->state.async); } /* @@ -278,14 +278,14 @@ int Curl_resolver_getsock(struct Curl_easy *data, struct timeval timebuf; struct timeval *timeout; long milli; - int max = ares_getsock((ares_channel)data->conn->resolve_async.resolver, + int max = ares_getsock((ares_channel)data->state.async.resolver, (ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE); maxtime.tv_sec = CURL_TIMEOUT_RESOLVE; maxtime.tv_usec = 0; - timeout = ares_timeout((ares_channel)data->conn->resolve_async.resolver, - &maxtime, &timebuf); + timeout = ares_timeout((ares_channel)data->state.async.resolver, &maxtime, + &timebuf); milli = (long)curlx_tvtoms(timeout); if(milli == 0) milli += 10; @@ -313,8 +313,8 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms) int i; int num = 0; - bitmask = ares_getsock((ares_channel)data->conn->resolve_async.resolver, - socks, ARES_GETSOCK_MAXNUM); + bitmask = ares_getsock((ares_channel)data->state.async.resolver, socks, + ARES_GETSOCK_MAXNUM); for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) { pfd[i].events = 0; @@ -344,12 +344,12 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms) if(!nfds) /* Call ares_process() unconditionally here, even if we simply timed out above, as otherwise the ares name resolve won't timeout! */ - ares_process_fd((ares_channel)data->conn->resolve_async.resolver, - ARES_SOCKET_BAD, ARES_SOCKET_BAD); + ares_process_fd((ares_channel)data->state.async.resolver, ARES_SOCKET_BAD, + ARES_SOCKET_BAD); else { /* move through the descriptors and ask for processing on them */ for(i = 0; i < num; i++) - ares_process_fd((ares_channel)data->conn->resolve_async.resolver, + ares_process_fd((ares_channel)data->state.async.resolver, (pfd[i].revents & (POLLRDNORM|POLLIN))? pfd[i].fd:ARES_SOCKET_BAD, (pfd[i].revents & (POLLWRNORM|POLLOUT))? @@ -368,7 +368,7 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms) CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, struct Curl_dns_entry **dns) { - struct thread_data *res = data->conn->resolve_async.tdata; + struct thread_data *res = data->state.async.tdata; CURLcode result = CURLE_OK; DEBUGASSERT(dns); @@ -397,7 +397,7 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, ARES_ECANCELLED synchronously for all pending responses. This will leave us with res->num_pending == 0, which is perfect for the next block. */ - ares_cancel((ares_channel)data->conn->resolve_async.resolver); + ares_cancel((ares_channel)data->state.async.resolver); DEBUGASSERT(res->num_pending == 0); } #endif @@ -408,12 +408,12 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, them */ res->temp_ai = NULL; - if(!data->conn->resolve_async.dns) + if(!data->state.async.dns) result = Curl_resolver_error(data); else - *dns = data->conn->resolve_async.dns; + *dns = data->state.async.dns; - destroy_async_data(&data->conn->resolve_async); + destroy_async_data(&data->state.async); } return result; @@ -464,8 +464,7 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data, store.tv_sec = itimeout/1000; store.tv_usec = (itimeout%1000)*1000; - tvp = ares_timeout((ares_channel)data->conn->resolve_async.resolver, - &store, &tv); + tvp = ares_timeout((ares_channel)data->state.async.resolver, &store, &tv); /* use the timeout period ares returned to us above if less than one second is left, otherwise just use 1000ms to make sure the progress @@ -479,7 +478,7 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data, return CURLE_UNRECOVERABLE_POLL; result = Curl_resolver_is_resolved(data, entry); - if(result || data->conn->resolve_async.done) + if(result || data->state.async.done) break; if(Curl_pgrsUpdate(data)) @@ -500,12 +499,12 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data, } if(result) /* failure, so we cancel the ares operation */ - ares_cancel((ares_channel)data->conn->resolve_async.resolver); + ares_cancel((ares_channel)data->state.async.resolver); /* Operation complete, if the lookup was successful we now have the entry in the cache. */ if(entry) - *entry = data->conn->resolve_async.dns; + *entry = data->state.async.dns; if(result) /* close the connection, since we can't return failure here without @@ -572,13 +571,12 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */ be valid so only defer it when we know the 'status' says its fine! */ return; - res = data->conn->resolve_async.tdata; + res = data->state.async.tdata; if(res) { res->num_pending--; if(CURL_ASYNC_SUCCESS == status) { - struct Curl_addrinfo *ai = Curl_he2ai(hostent, - data->conn->resolve_async.port); + struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->state.async.port); if(ai) { compound_results(res, ai); } @@ -729,16 +727,14 @@ static void addrinfo_cb(void *arg, int status, int timeouts, struct ares_addrinfo *result) { struct Curl_easy *data = (struct Curl_easy *)arg; - if(data->conn) { - struct thread_data *res = data->conn->resolve_async.tdata; - (void)timeouts; - if(ARES_SUCCESS == status) { - res->temp_ai = ares2addr(result->nodes); - res->last_status = CURL_ASYNC_SUCCESS; - ares_freeaddrinfo(result); - } - res->num_pending--; + struct thread_data *res = data->state.async.tdata; + (void)timeouts; + if(ARES_SUCCESS == status) { + res->temp_ai = ares2addr(result->nodes); + res->last_status = CURL_ASYNC_SUCCESS; + ares_freeaddrinfo(result); } + res->num_pending--; } #endif @@ -759,15 +755,15 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, size_t namelen = strlen(hostname); *waitp = 0; /* default to synchronous response */ - res = calloc(1, sizeof(struct thread_data) + namelen); + res = calloc(sizeof(struct thread_data) + namelen, 1); if(res) { strcpy(res->hostname, hostname); - data->conn->resolve_async.hostname = res->hostname; - data->conn->resolve_async.port = port; - data->conn->resolve_async.done = FALSE; /* not done */ - data->conn->resolve_async.status = 0; /* clear */ - data->conn->resolve_async.dns = NULL; /* clear */ - data->conn->resolve_async.tdata = res; + data->state.async.hostname = res->hostname; + data->state.async.port = port; + data->state.async.done = FALSE; /* not done */ + data->state.async.status = 0; /* clear */ + data->state.async.dns = NULL; /* clear */ + data->state.async.tdata = res; /* initial status - failed */ res->last_status = ARES_ENOTFOUND; @@ -797,8 +793,8 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, hints.ai_flags = ARES_AI_NUMERICSERV; msnprintf(service, sizeof(service), "%d", port); res->num_pending = 1; - ares_getaddrinfo((ares_channel)data->conn->resolve_async.resolver, - hostname, service, &hints, addrinfo_cb, data); + ares_getaddrinfo((ares_channel)data->state.async.resolver, hostname, + service, &hints, addrinfo_cb, data); } #else @@ -808,10 +804,10 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, res->num_pending = 2; /* areschannel is already setup in the Curl_open() function */ - ares_gethostbyname((ares_channel)data->conn->resolve_async.resolver, - hostname, PF_INET, query_completed_cb, data); - ares_gethostbyname((ares_channel)data->conn->resolve_async.resolver, - hostname, PF_INET6, query_completed_cb, data); + ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, + PF_INET, query_completed_cb, data); + ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, + PF_INET6, query_completed_cb, data); } else #endif @@ -819,7 +815,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, res->num_pending = 1; /* areschannel is already setup in the Curl_open() function */ - ares_gethostbyname((ares_channel)data->conn->resolve_async.resolver, + ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, PF_INET, query_completed_cb, data); } @@ -833,7 +829,6 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data, char *servers) { CURLcode result = CURLE_NOT_BUILT_IN; - ares_channel channel, lchannel = NULL; int ares_result; /* If server is NULL or empty, this would purge all DNS servers @@ -846,23 +841,11 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data, return CURLE_OK; #ifdef HAVE_CARES_SERVERS_CSV - if(data->conn) - channel = data->conn->resolve_async.resolver; - else { - /* we are called by setopt on a data without a connection (yet). In that - * case we set the value on a local instance for checking. - * The configured data options are set when the connection for this - * transfer is created. */ - result = Curl_resolver_init(data, (void **)&lchannel); - if(result) - goto out; - channel = lchannel; - } - #ifdef HAVE_CARES_PORTS_CSV - ares_result = ares_set_servers_ports_csv(channel, servers); + ares_result = ares_set_servers_ports_csv(data->state.async.resolver, + servers); #else - ares_result = ares_set_servers_csv(channel, servers); + ares_result = ares_set_servers_csv(data->state.async.resolver, servers); #endif switch(ares_result) { case ARES_SUCCESS: @@ -878,9 +861,6 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data, result = CURLE_BAD_FUNCTION_ARGUMENT; break; } -out: - if(lchannel) - Curl_resolver_cleanup(lchannel); #else /* too old c-ares version! */ (void)data; (void)(ares_result); @@ -892,14 +872,11 @@ CURLcode Curl_set_dns_interface(struct Curl_easy *data, const char *interf) { #ifdef HAVE_CARES_LOCAL_DEV - if(data->conn) { - /* not a setopt test run, set the value */ - if(!interf) - interf = ""; + if(!interf) + interf = ""; + + ares_set_local_dev((ares_channel)data->state.async.resolver, interf); - ares_set_local_dev((ares_channel)data->conn->resolve_async.resolver, - interf); - } return CURLE_OK; #else /* c-ares version too old! */ (void)data; @@ -923,11 +900,8 @@ CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data, } } - if(data->conn) { - /* not a setopt test run, set the value */ - ares_set_local_ip4((ares_channel)data->conn->resolve_async.resolver, - ntohl(a4.s_addr)); - } + ares_set_local_ip4((ares_channel)data->state.async.resolver, + ntohl(a4.s_addr)); return CURLE_OK; #else /* c-ares version too old! */ @@ -953,10 +927,7 @@ CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data, } } - if(data->conn) { - /* not a setopt test run, set the value */ - ares_set_local_ip6((ares_channel)data->conn->resolve_async.resolver, a6); - } + ares_set_local_ip6((ares_channel)data->state.async.resolver, a6); return CURLE_OK; #else /* c-ares version too old! */ diff --git a/deps/curl/lib/asyn-thread.c b/deps/curl/lib/asyn-thread.c index 63414b61..a2e294f8 100644 --- a/deps/curl/lib/asyn-thread.c +++ b/deps/curl/lib/asyn-thread.c @@ -136,7 +136,7 @@ static void destroy_async_data(struct Curl_async *); */ void Curl_resolver_cancel(struct Curl_easy *data) { - destroy_async_data(&data->conn->resolve_async); + destroy_async_data(&data->state.async); } /* This function is used to init a threaded resolve */ @@ -173,7 +173,7 @@ struct thread_data { static struct thread_sync_data *conn_thread_sync_data(struct Curl_easy *data) { - return &(data->conn->resolve_async.tdata->tsd); + return &(data->state.async.tdata->tsd); } /* Destroy resolver thread synchronization data */ @@ -196,7 +196,7 @@ void destroy_thread_sync_data(struct thread_sync_data *tsd) * the other end (for reading) is always closed in the parent thread. */ if(tsd->sock_pair[1] != CURL_SOCKET_BAD) { - wakeup_close(tsd->sock_pair[1]); + sclose(tsd->sock_pair[1]); } #endif memset(tsd, 0, sizeof(*tsd)); @@ -233,8 +233,8 @@ int init_thread_sync_data(struct thread_data *td, Curl_mutex_init(tsd->mtx); #ifndef CURL_DISABLE_SOCKETPAIR - /* create socket pair or pipe */ - if(wakeup_create(&tsd->sock_pair[0]) < 0) { + /* create socket pair, avoid AF_LOCAL since it doesn't build on Solaris */ + if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, &tsd->sock_pair[0]) < 0) { tsd->sock_pair[0] = CURL_SOCKET_BAD; tsd->sock_pair[1] = CURL_SOCKET_BAD; goto err_exit; @@ -254,7 +254,7 @@ int init_thread_sync_data(struct thread_data *td, err_exit: #ifndef CURL_DISABLE_SOCKETPAIR if(tsd->sock_pair[0] != CURL_SOCKET_BAD) { - wakeup_close(tsd->sock_pair[0]); + sclose(tsd->sock_pair[0]); tsd->sock_pair[0] = CURL_SOCKET_BAD; } #endif @@ -320,7 +320,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg) if(tsd->sock_pair[1] != CURL_SOCKET_BAD) { /* DNS has been resolved, signal client task */ buf[0] = 1; - if(wakeup_write(tsd->sock_pair[1], buf, sizeof(buf)) < 0) { + if(swrite(tsd->sock_pair[1], buf, sizeof(buf)) < 0) { /* update sock_erro to errno */ tsd->sock_error = SOCKERRNO; } @@ -428,9 +428,9 @@ static bool init_resolve_thread(struct Curl_easy *data, { struct thread_data *td = calloc(1, sizeof(struct thread_data)); int err = ENOMEM; - struct Curl_async *asp = &data->conn->resolve_async; + struct Curl_async *asp = &data->state.async; - data->conn->resolve_async.tdata = td; + data->state.async.tdata = td; if(!td) goto errno_exit; @@ -488,7 +488,7 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data, CURLcode result = CURLE_OK; DEBUGASSERT(data); - td = data->conn->resolve_async.tdata; + td = data->state.async.tdata; DEBUGASSERT(td); DEBUGASSERT(td->thread_hnd != curl_thread_t_null); @@ -500,18 +500,18 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data, else DEBUGASSERT(0); - data->conn->resolve_async.done = TRUE; + data->state.async.done = TRUE; if(entry) - *entry = data->conn->resolve_async.dns; + *entry = data->state.async.dns; - if(!data->conn->resolve_async.dns && report) + if(!data->state.async.dns && report) /* a name was not resolved, report error */ result = Curl_resolver_error(data); - destroy_async_data(&data->conn->resolve_async); + destroy_async_data(&data->state.async); - if(!data->conn->resolve_async.dns && report) + if(!data->state.async.dns && report) connclose(data->conn, "asynch resolve failed"); return result; @@ -524,7 +524,7 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data, */ void Curl_resolver_kill(struct Curl_easy *data) { - struct thread_data *td = data->conn->resolve_async.tdata; + struct thread_data *td = data->state.async.tdata; /* If we're still resolving, we must wait for the threads to fully clean up, unfortunately. Otherwise, we can simply cancel to clean up any resolver @@ -563,7 +563,7 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data, CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, struct Curl_dns_entry **entry) { - struct thread_data *td = data->conn->resolve_async.tdata; + struct thread_data *td = data->state.async.tdata; int done = 0; DEBUGASSERT(entry); @@ -581,13 +581,13 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, if(done) { getaddrinfo_complete(data); - if(!data->conn->resolve_async.dns) { + if(!data->state.async.dns) { CURLcode result = Curl_resolver_error(data); - destroy_async_data(&data->conn->resolve_async); + destroy_async_data(&data->state.async); return result; } - destroy_async_data(&data->conn->resolve_async); - *entry = data->conn->resolve_async.dns; + destroy_async_data(&data->state.async); + *entry = data->state.async.dns; } else { /* poll for name lookup done with exponential backoff up to 250ms */ @@ -619,9 +619,9 @@ int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks) int ret_val = 0; timediff_t milli; timediff_t ms; - struct resdata *reslv = (struct resdata *)data->conn->resolve_async.resolver; + struct resdata *reslv = (struct resdata *)data->state.async.resolver; #ifndef CURL_DISABLE_SOCKETPAIR - struct thread_data *td = data->conn->resolve_async.tdata; + struct thread_data *td = data->state.async.tdata; #else (void)socks; #endif @@ -662,7 +662,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, int port, int *waitp) { - struct resdata *reslv = (struct resdata *)data->conn->resolve_async.resolver; + struct resdata *reslv = (struct resdata *)data->state.async.resolver; *waitp = 0; /* default to synchronous response */ @@ -691,7 +691,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, { struct addrinfo hints; int pf = PF_INET; - struct resdata *reslv = (struct resdata *)data->conn->resolve_async.resolver; + struct resdata *reslv = (struct resdata *)data->state.async.resolver; *waitp = 0; /* default to synchronous response */ diff --git a/deps/curl/lib/base64.c b/deps/curl/lib/base64.c index 919eb623..2a49b5ac 100644 --- a/deps/curl/lib/base64.c +++ b/deps/curl/lib/base64.c @@ -31,7 +31,6 @@ !defined(CURL_DISABLE_SMTP) || \ !defined(CURL_DISABLE_POP3) || \ !defined(CURL_DISABLE_IMAP) || \ - !defined(CURL_DISABLE_DIGEST_AUTH) || \ !defined(CURL_DISABLE_DOH) || defined(USE_SSL) || defined(BUILDING_CURL) #include "curl/curl.h" #include "warnless.h" diff --git a/deps/curl/lib/c-hyper.c b/deps/curl/lib/c-hyper.c index 787d6bbd..5726ff1c 100644 --- a/deps/curl/lib/c-hyper.c +++ b/deps/curl/lib/c-hyper.c @@ -22,10 +22,6 @@ * ***************************************************************************/ -/* Curl's integration with Hyper. This replaces certain functions in http.c, - * based on configuration #defines. This implementation supports HTTP/1.1 but - * not HTTP/2. - */ #include "curl_setup.h" #if !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) @@ -176,15 +172,17 @@ static int hyper_each_header(void *userdata, Curl_debug(data, CURLINFO_HEADER_IN, headp, len); - writetype = CLIENTWRITE_HEADER; - if(data->state.hconnect) - writetype |= CLIENTWRITE_CONNECT; - if(data->req.httpcode/100 == 1) - writetype |= CLIENTWRITE_1XX; - result = Curl_client_write(data, writetype, headp, len); - if(result) { - data->state.hresult = CURLE_ABORTED_BY_CALLBACK; - return HYPER_ITER_BREAK; + if(!data->state.hconnect || !data->set.suppress_connect_headers) { + writetype = CLIENTWRITE_HEADER; + if(data->state.hconnect) + writetype |= CLIENTWRITE_CONNECT; + if(data->req.httpcode/100 == 1) + writetype |= CLIENTWRITE_1XX; + result = Curl_client_write(data, writetype, headp, len); + if(result) { + data->state.hresult = CURLE_ABORTED_BY_CALLBACK; + return HYPER_ITER_BREAK; + } } result = Curl_bump_headersize(data, len, FALSE); @@ -203,7 +201,7 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk) struct SingleRequest *k = &data->req; CURLcode result = CURLE_OK; - if(0 == k->bodywrites) { + if(0 == k->bodywrites++) { bool done = FALSE; #if defined(USE_NTLM) struct connectdata *conn = data->conn; @@ -243,6 +241,11 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk) return HYPER_ITER_BREAK; } } + if(k->ignorebody) + return HYPER_ITER_CONTINUE; + if(0 == len) + return HYPER_ITER_CONTINUE; + Curl_debug(data, CURLINFO_DATA_IN, buf, len); result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len); if(result) { @@ -250,6 +253,12 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk) return HYPER_ITER_BREAK; } + data->req.bytecount += len; + result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount); + if(result) { + data->state.hresult = result; + return HYPER_ITER_BREAK; + } return HYPER_ITER_CONTINUE; } @@ -301,14 +310,13 @@ static CURLcode status_line(struct Curl_easy *data, Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb), len); - writetype = CLIENTWRITE_HEADER|CLIENTWRITE_STATUS; - if(data->state.hconnect) - writetype |= CLIENTWRITE_CONNECT; - result = Curl_client_write(data, writetype, - Curl_dyn_ptr(&data->state.headerb), len); - if(result) - return result; - + if(!data->state.hconnect || !data->set.suppress_connect_headers) { + writetype = CLIENTWRITE_HEADER|CLIENTWRITE_STATUS; + result = Curl_client_write(data, writetype, + Curl_dyn_ptr(&data->state.headerb), len); + if(result) + return result; + } result = Curl_bump_headersize(data, len, FALSE); return result; } @@ -543,9 +551,11 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data, static CURLcode debug_request(struct Curl_easy *data, const char *method, - const char *path) + const char *path, + bool h2) { - char *req = aprintf("%s %s HTTP/1.1\r\n", method, path); + char *req = aprintf("%s %s HTTP/%s\r\n", method, path, + h2?"2":"1.1"); if(!req) return CURLE_OUT_OF_MEMORY; Curl_debug(data, CURLINFO_HEADER_OUT, req, strlen(req)); @@ -627,6 +637,7 @@ CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers, static CURLcode request_target(struct Curl_easy *data, struct connectdata *conn, const char *method, + bool h2, hyper_request *req) { CURLcode result; @@ -638,13 +649,26 @@ static CURLcode request_target(struct Curl_easy *data, if(result) return result; - if(hyper_request_set_uri(req, (uint8_t *)Curl_dyn_uptr(&r), + if(h2 && hyper_request_set_uri_parts(req, + /* scheme */ + (uint8_t *)data->state.up.scheme, + strlen(data->state.up.scheme), + /* authority */ + (uint8_t *)conn->host.name, + strlen(conn->host.name), + /* path_and_query */ + (uint8_t *)Curl_dyn_uptr(&r), + Curl_dyn_len(&r))) { + failf(data, "error setting uri parts to hyper"); + result = CURLE_OUT_OF_MEMORY; + } + else if(!h2 && hyper_request_set_uri(req, (uint8_t *)Curl_dyn_uptr(&r), Curl_dyn_len(&r))) { failf(data, "error setting uri to hyper"); result = CURLE_OUT_OF_MEMORY; } else - result = debug_request(data, method, Curl_dyn_ptr(&r)); + result = debug_request(data, method, Curl_dyn_ptr(&r), h2); Curl_dyn_free(&r); @@ -875,6 +899,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) const char *p_accept; /* Accept: string */ const char *method; Curl_HttpReq httpreq; + bool h2 = FALSE; const char *te = NULL; /* transfer-encoding */ hyper_code rc; @@ -882,7 +907,6 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) may be parts of the request that is not yet sent, since we can deal with the rest of the request in the PERFORM phase. */ *done = TRUE; - Curl_client_cleanup(data); infof(data, "Time for the Hyper dance"); memset(h, 0, sizeof(struct hyptransfer)); @@ -893,8 +917,6 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) Curl_http_method(data, conn, &method, &httpreq); - DEBUGASSERT(data->req.bytecount == 0); - /* setup the authentication headers */ { char *pq = NULL; @@ -950,9 +972,8 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) goto error; } if(conn->alpn == CURL_HTTP_VERSION_2) { - failf(data, "ALPN protocol h2 not supported with Hyper"); - result = CURLE_UNSUPPORTED_PROTOCOL; - goto error; + hyper_clientconn_options_http2(options, 1); + h2 = TRUE; } hyper_clientconn_options_set_preserve_header_case(options, 1); hyper_clientconn_options_set_preserve_header_order(options, 1); @@ -1003,7 +1024,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) } } else { - if(!data->state.disableexpect) { + if(!h2 && !data->state.disableexpect) { data->state.expect100header = TRUE; } } @@ -1014,7 +1035,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) goto error; } - result = request_target(data, conn, method, req); + result = request_target(data, conn, method, h2, req); if(result) goto error; @@ -1035,10 +1056,19 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) if(result) goto error; - if(data->state.aptr.host) { - result = Curl_hyper_header(data, headers, data->state.aptr.host); - if(result) - goto error; + if(!h2) { + if(data->state.aptr.host) { + result = Curl_hyper_header(data, headers, data->state.aptr.host); + if(result) + goto error; + } + } + else { + /* For HTTP/2, we show the Host: header as if we sent it, to make it look + like for HTTP/1 but it isn't actually sent since :authority is then + used. */ + Curl_debug(data, CURLINFO_HEADER_OUT, data->state.aptr.host, + strlen(data->state.aptr.host)); } if(data->state.aptr.proxyuserpwd) { diff --git a/deps/curl/lib/cf-h1-proxy.c b/deps/curl/lib/cf-h1-proxy.c index 2e23b0b9..67480211 100644 --- a/deps/curl/lib/cf-h1-proxy.c +++ b/deps/curl/lib/cf-h1-proxy.c @@ -374,7 +374,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf, curl_socket_t tunnelsocket = Curl_conn_cf_get_socket(cf, data); char *linep; size_t perline; - int error, writetype; + int error; #define SELECT_OK 0 #define SELECT_ERROR 1 @@ -386,12 +386,12 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf, return CURLE_OK; while(ts->keepon) { - ssize_t nread; + ssize_t gotbytes; char byte; /* Read one byte at a time to avoid a race condition. Wait at most one second before looping to ensure continuous pgrsUpdates. */ - result = Curl_read(data, tunnelsocket, &byte, 1, &nread); + result = Curl_read(data, tunnelsocket, &byte, 1, &gotbytes); if(result == CURLE_AGAIN) /* socket buffer drained, return */ return CURLE_OK; @@ -404,7 +404,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf, break; } - if(nread <= 0) { + if(gotbytes <= 0) { if(data->set.proxyauth && data->state.authproxy.avail && data->state.aptr.proxyuserpwd) { /* proxy auth was requested and there was proxy auth available, @@ -437,11 +437,11 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf, properly to know when the end of the body is reached */ CHUNKcode r; CURLcode extra; - size_t consumed = 0; + ssize_t tookcareof = 0; /* now parse the chunked piece of data so that we can properly tell when the stream ends */ - r = Curl_httpchunk_read(data, &byte, 1, &consumed, &extra); + r = Curl_httpchunk_read(data, &byte, 1, &tookcareof, &extra); if(r == CHUNKE_STOP) { /* we're done reading chunks! */ infof(data, "chunk reading DONE"); @@ -467,12 +467,15 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf, /* output debug if that is requested */ Curl_debug(data, CURLINFO_HEADER_IN, linep, perline); - /* send the header to the callback */ - writetype = CLIENTWRITE_HEADER | CLIENTWRITE_CONNECT | - (ts->headerlines == 1 ? CLIENTWRITE_STATUS : 0); - result = Curl_client_write(data, writetype, linep, perline); - if(result) - return result; + if(!data->set.suppress_connect_headers) { + /* send the header to the callback */ + int writetype = CLIENTWRITE_HEADER | CLIENTWRITE_CONNECT | + (ts->headerlines == 1 ? CLIENTWRITE_STATUS : 0); + + result = Curl_client_write(data, writetype, linep, perline); + if(result) + return result; + } result = Curl_bump_headersize(data, perline, TRUE); if(result) @@ -499,7 +502,6 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf, else if(ts->chunked_encoding) { CHUNKcode r; CURLcode extra; - size_t consumed = 0; infof(data, "Ignore chunked response-body"); @@ -514,7 +516,8 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf, /* now parse the chunked piece of data so that we can properly tell when the stream ends */ - r = Curl_httpchunk_read(data, linep + 1, 1, &consumed, &extra); + r = Curl_httpchunk_read(data, linep + 1, 1, &gotbytes, + &extra); if(r == CHUNKE_STOP) { /* we're done reading chunks! */ infof(data, "chunk reading DONE"); @@ -1035,29 +1038,31 @@ out: return result; } -static void cf_h1_proxy_adjust_pollset(struct Curl_cfilter *cf, +static int cf_h1_proxy_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data, - struct easy_pollset *ps) + curl_socket_t *socks) { struct h1_tunnel_state *ts = cf->ctx; + int fds; - if(!cf->connected) { + fds = cf->next->cft->get_select_socks(cf->next, data, socks); + if(!fds && cf->next->connected && !cf->connected) { /* If we are not connected, but the filter "below" is * and not waiting on something, we are tunneling. */ - curl_socket_t sock = Curl_conn_cf_get_socket(cf, data); + socks[0] = Curl_conn_cf_get_socket(cf, data); if(ts) { /* when we've sent a CONNECT to a proxy, we should rather either wait for the socket to become readable to be able to get the response headers or if we're still sending the request, wait for write. */ - if(ts->CONNECT.sending == HTTPSEND_REQUEST) - Curl_pollset_set_out_only(data, ps, sock); - else - Curl_pollset_set_in_only(data, ps, sock); + if(ts->CONNECT.sending == HTTPSEND_REQUEST) { + return GETSOCK_WRITESOCK(0); + } + return GETSOCK_READSOCK(0); } - else - Curl_pollset_set_out_only(data, ps, sock); + return GETSOCK_WRITESOCK(0); } + return fds; } static void cf_h1_proxy_destroy(struct Curl_cfilter *cf, @@ -1088,7 +1093,7 @@ struct Curl_cftype Curl_cft_h1_proxy = { cf_h1_proxy_connect, cf_h1_proxy_close, Curl_cf_http_proxy_get_host, - cf_h1_proxy_adjust_pollset, + cf_h1_proxy_get_select_socks, Curl_cf_def_data_pending, Curl_cf_def_send, Curl_cf_def_recv, diff --git a/deps/curl/lib/cf-h2-proxy.c b/deps/curl/lib/cf-h2-proxy.c index 147acdc8..dbc895d2 100644 --- a/deps/curl/lib/cf-h2-proxy.c +++ b/deps/curl/lib/cf-h2-proxy.c @@ -688,8 +688,12 @@ static int proxy_h2_on_frame_recv(nghttp2_session *session, * window and *assume* that we treat this like a WINDOW_UPDATE. Some * servers send an explicit WINDOW_UPDATE, but not all seem to do that. * To be safe, we UNHOLD a stream in order not to stall. */ - if(CURL_WANT_SEND(data)) { + if((data->req.keepon & KEEP_SEND_HOLD) && + (data->req.keepon & KEEP_SEND)) { + data->req.keepon &= ~KEEP_SEND_HOLD; drain_tunnel(cf, data, &ctx->tunnel); + CURL_TRC_CF(data, cf, "[%d] un-holding after SETTINGS", + stream_id); } break; case NGHTTP2_GOAWAY: @@ -723,8 +727,12 @@ static int proxy_h2_on_frame_recv(nghttp2_session *session, } break; case NGHTTP2_WINDOW_UPDATE: - if(CURL_WANT_SEND(data)) { - drain_tunnel(cf, data, &ctx->tunnel); + if((data->req.keepon & KEEP_SEND_HOLD) && + (data->req.keepon & KEEP_SEND)) { + data->req.keepon &= ~KEEP_SEND_HOLD; + Curl_expire(data, 0, EXPIRE_RUN_NOW); + CURL_TRC_CF(data, cf, "[%d] unpausing after win update", + stream_id); } break; default: @@ -901,6 +909,7 @@ static CURLcode proxy_h2_submit(int32_t *pstream_id, { struct dynhds h2_headers; nghttp2_nv *nva = NULL; + unsigned int i; int32_t stream_id = -1; size_t nheader; CURLcode result; @@ -911,12 +920,22 @@ static CURLcode proxy_h2_submit(int32_t *pstream_id, if(result) goto out; - nva = Curl_dynhds_to_nva(&h2_headers, &nheader); + nheader = Curl_dynhds_count(&h2_headers); + nva = malloc(sizeof(nghttp2_nv) * nheader); if(!nva) { result = CURLE_OUT_OF_MEMORY; goto out; } + for(i = 0; i < nheader; ++i) { + struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i); + nva[i].name = (unsigned char *)e->name; + nva[i].namelen = e->namelen; + nva[i].value = (unsigned char *)e->value; + nva[i].valuelen = e->valuelen; + nva[i].flags = NGHTTP2_NV_FLAG_NONE; + } + if(read_callback) { nghttp2_data_provider data_prd; @@ -1168,31 +1187,25 @@ static bool cf_h2_proxy_data_pending(struct Curl_cfilter *cf, return cf->next? cf->next->cft->has_data_pending(cf->next, data) : FALSE; } -static void cf_h2_proxy_adjust_pollset(struct Curl_cfilter *cf, - struct Curl_easy *data, - struct easy_pollset *ps) +static int cf_h2_proxy_get_select_socks(struct Curl_cfilter *cf, + struct Curl_easy *data, + curl_socket_t *sock) { struct cf_h2_proxy_ctx *ctx = cf->ctx; - curl_socket_t sock = Curl_conn_cf_get_socket(cf, data); - bool want_recv, want_send; + int bitmap = GETSOCK_BLANK; + struct cf_call_data save; - Curl_pollset_check(data, ps, sock, &want_recv, &want_send); - if(ctx->h2 && (want_recv || want_send)) { - struct cf_call_data save; - bool c_exhaust, s_exhaust; + CF_DATA_SAVE(save, cf, data); + sock[0] = Curl_conn_cf_get_socket(cf, data); + bitmap |= GETSOCK_READSOCK(0); - CF_DATA_SAVE(save, cf, data); - c_exhaust = !nghttp2_session_get_remote_window_size(ctx->h2); - s_exhaust = ctx->tunnel.stream_id >= 0 && - !nghttp2_session_get_stream_remote_window_size( - ctx->h2, ctx->tunnel.stream_id); - want_recv = (want_recv || c_exhaust || s_exhaust); - want_send = (!s_exhaust && want_send) || - (!c_exhaust && nghttp2_session_want_write(ctx->h2)); + /* HTTP/2 layer wants to send data) AND there's a window to send data in */ + if(nghttp2_session_want_write(ctx->h2) && + nghttp2_session_get_remote_window_size(ctx->h2)) + bitmap |= GETSOCK_WRITESOCK(0); - Curl_pollset_set(data, ps, sock, want_recv, want_send); - CF_DATA_RESTORE(cf, save); - } + CF_DATA_RESTORE(cf, save); + return bitmap; } static ssize_t h2_handle_tunnel_close(struct Curl_cfilter *cf, @@ -1529,7 +1542,7 @@ struct Curl_cftype Curl_cft_h2_proxy = { cf_h2_proxy_connect, cf_h2_proxy_close, Curl_cf_http_proxy_get_host, - cf_h2_proxy_adjust_pollset, + cf_h2_proxy_get_select_socks, cf_h2_proxy_data_pending, cf_h2_proxy_send, cf_h2_proxy_recv, @@ -1547,7 +1560,7 @@ CURLcode Curl_cf_h2_proxy_insert_after(struct Curl_cfilter *cf, CURLcode result = CURLE_OUT_OF_MEMORY; (void)data; - ctx = calloc(1, sizeof(*ctx)); + ctx = calloc(sizeof(*ctx), 1); if(!ctx) goto out; diff --git a/deps/curl/lib/cf-haproxy.c b/deps/curl/lib/cf-haproxy.c index 1ca43937..39ac4157 100644 --- a/deps/curl/lib/cf-haproxy.c +++ b/deps/curl/lib/cf-haproxy.c @@ -171,17 +171,23 @@ static void cf_haproxy_close(struct Curl_cfilter *cf, cf->next->cft->do_close(cf->next, data); } -static void cf_haproxy_adjust_pollset(struct Curl_cfilter *cf, - struct Curl_easy *data, - struct easy_pollset *ps) +static int cf_haproxy_get_select_socks(struct Curl_cfilter *cf, + struct Curl_easy *data, + curl_socket_t *socks) { - if(cf->next->connected && !cf->connected) { + int fds; + + fds = cf->next->cft->get_select_socks(cf->next, data, socks); + if(!fds && cf->next->connected && !cf->connected) { /* If we are not connected, but the filter "below" is * and not waiting on something, we are sending. */ - Curl_pollset_set_out_only(data, ps, Curl_conn_cf_get_socket(cf, data)); + socks[0] = Curl_conn_cf_get_socket(cf, data); + return GETSOCK_WRITESOCK(0); } + return fds; } + struct Curl_cftype Curl_cft_haproxy = { "HAPROXY", 0, @@ -190,7 +196,7 @@ struct Curl_cftype Curl_cft_haproxy = { cf_haproxy_connect, cf_haproxy_close, Curl_cf_def_get_host, - cf_haproxy_adjust_pollset, + cf_haproxy_get_select_socks, Curl_cf_def_data_pending, Curl_cf_def_send, Curl_cf_def_recv, @@ -208,7 +214,7 @@ static CURLcode cf_haproxy_create(struct Curl_cfilter **pcf, CURLcode result; (void)data; - ctx = calloc(1, sizeof(*ctx)); + ctx = calloc(sizeof(*ctx), 1); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; diff --git a/deps/curl/lib/cf-https-connect.c b/deps/curl/lib/cf-https-connect.c index b4f33c8e..be54aec7 100644 --- a/deps/curl/lib/cf-https-connect.c +++ b/deps/curl/lib/cf-https-connect.c @@ -188,6 +188,9 @@ static CURLcode baller_connected(struct Curl_cfilter *cf, #endif infof(data, "using HTTP/2"); break; + case CURL_HTTP_VERSION_1_1: + infof(data, "using HTTP/1.1"); + break; default: infof(data, "using HTTP/1.x"); break; @@ -322,25 +325,42 @@ out: return result; } -static void cf_hc_adjust_pollset(struct Curl_cfilter *cf, +static int cf_hc_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data, - struct easy_pollset *ps) + curl_socket_t *socks) { - if(!cf->connected) { - struct cf_hc_ctx *ctx = cf->ctx; - struct cf_hc_baller *ballers[2]; - size_t i; + struct cf_hc_ctx *ctx = cf->ctx; + size_t i, j, s; + int brc, rc = GETSOCK_BLANK; + curl_socket_t bsocks[MAX_SOCKSPEREASYHANDLE]; + struct cf_hc_baller *ballers[2]; - ballers[0] = &ctx->h3_baller; - ballers[1] = &ctx->h21_baller; - for(i = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) { - struct cf_hc_baller *b = ballers[i]; - if(!cf_hc_baller_is_active(b)) - continue; - Curl_conn_cf_adjust_pollset(b->cf, data, ps); + if(cf->connected) + return cf->next->cft->get_select_socks(cf->next, data, socks); + + ballers[0] = &ctx->h3_baller; + ballers[1] = &ctx->h21_baller; + for(i = s = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) { + struct cf_hc_baller *b = ballers[i]; + if(!cf_hc_baller_is_active(b)) + continue; + brc = Curl_conn_cf_get_select_socks(b->cf, data, bsocks); + CURL_TRC_CF(data, cf, "get_selected_socks(%s) -> %x", b->name, brc); + if(!brc) + continue; + for(j = 0; j < MAX_SOCKSPEREASYHANDLE && s < MAX_SOCKSPEREASYHANDLE; ++j) { + if((brc & GETSOCK_WRITESOCK(j)) || (brc & GETSOCK_READSOCK(j))) { + socks[s] = bsocks[j]; + if(brc & GETSOCK_WRITESOCK(j)) + rc |= GETSOCK_WRITESOCK(s); + if(brc & GETSOCK_READSOCK(j)) + rc |= GETSOCK_READSOCK(s); + s++; + } } - CURL_TRC_CF(data, cf, "adjust_pollset -> %d socks", ps->num); } + CURL_TRC_CF(data, cf, "get_selected_socks -> %x", rc); + return rc; } static bool cf_hc_data_pending(struct Curl_cfilter *cf, @@ -435,7 +455,7 @@ struct Curl_cftype Curl_cft_http_connect = { cf_hc_connect, cf_hc_close, Curl_cf_def_get_host, - cf_hc_adjust_pollset, + cf_hc_get_select_socks, cf_hc_data_pending, Curl_cf_def_send, Curl_cf_def_recv, @@ -455,7 +475,7 @@ static CURLcode cf_hc_create(struct Curl_cfilter **pcf, CURLcode result = CURLE_OK; (void)data; - ctx = calloc(1, sizeof(*ctx)); + ctx = calloc(sizeof(*ctx), 1); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; diff --git a/deps/curl/lib/cf-socket.c b/deps/curl/lib/cf-socket.c index e42b4a87..ce3f9e94 100644 --- a/deps/curl/lib/cf-socket.c +++ b/deps/curl/lib/cf-socket.c @@ -81,7 +81,7 @@ #include "memdebug.h" -#if defined(ENABLE_IPV6) && defined(IPV6_V6ONLY) && defined(_WIN32) +#if defined(ENABLE_IPV6) && defined(IPV6_V6ONLY) && defined(WIN32) /* It makes support for IPv4-mapped IPv6 addresses. * Linux kernel, NetBSD, FreeBSD and Darwin: default is off; * Windows Vista and later: default is on; @@ -102,7 +102,11 @@ static void tcpnodelay(struct Curl_easy *data, curl_socket_t sockfd) #if defined(TCP_NODELAY) curl_socklen_t onoff = (curl_socklen_t) 1; int level = IPPROTO_TCP; +#if !defined(CURL_DISABLE_VERBOSE_STRINGS) char buffer[STRERROR_LEN]; +#else + (void) data; +#endif if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff, sizeof(onoff)) < 0) @@ -123,7 +127,6 @@ static void nosigpipe(struct Curl_easy *data, curl_socket_t sockfd) { int onoff = 1; - (void)data; if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff, sizeof(onoff)) < 0) { #if !defined(CURL_DISABLE_VERBOSE_STRINGS) @@ -659,7 +662,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error) int err = 0; curl_socklen_t errSize = sizeof(err); -#ifdef _WIN32 +#ifdef WIN32 /* * In October 2003 we effectively nullified this function on Windows due to * problems with it using all CPU in multi-threaded cases. @@ -880,14 +883,34 @@ static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data) struct cf_socket_ctx *ctx = cf->ctx; if(ctx && CURL_SOCKET_BAD != ctx->sock) { - CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T - ")", ctx->sock); - if(ctx->sock == cf->conn->sock[cf->sockindex]) - cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD; - socket_close(data, cf->conn, !ctx->accepted, ctx->sock); - ctx->sock = CURL_SOCKET_BAD; - if(ctx->active && cf->sockindex == FIRSTSOCKET) - cf->conn->remote_addr = NULL; + if(ctx->active) { + /* We share our socket at cf->conn->sock[cf->sockindex] when active. + * If it is no longer there, someone has stolen (and hopefully + * closed it) and we just forget about it. + */ + if(ctx->sock == cf->conn->sock[cf->sockindex]) { + CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T + ", active)", ctx->sock); + socket_close(data, cf->conn, !ctx->accepted, ctx->sock); + cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD; + } + else { + CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T + ") no longer at conn->sock[], discarding", ctx->sock); + /* TODO: we do not want this to happen. Need to check which + * code is messing with conn->sock[cf->sockindex] */ + } + ctx->sock = CURL_SOCKET_BAD; + if(cf->sockindex == FIRSTSOCKET) + cf->conn->remote_addr = NULL; + } + else { + /* this is our local socket, we did never publish it */ + CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T + ", not active)", ctx->sock); + socket_close(data, cf->conn, !ctx->accepted, ctx->sock); + ctx->sock = CURL_SOCKET_BAD; + } Curl_bufq_reset(&ctx->recvbuf); ctx->active = FALSE; ctx->buffer_recv = FALSE; @@ -1146,7 +1169,6 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf, *done = FALSE; /* a very negative world view is best */ if(ctx->sock == CURL_SOCKET_BAD) { - int error; result = cf_socket_open(cf, data); if(result) @@ -1159,12 +1181,8 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf, /* Connect TCP socket */ rc = do_connect(cf, data, cf->conn->bits.tcp_fastopen); - error = SOCKERRNO; - set_local_ip(cf, data); - CURL_TRC_CF(data, cf, "local address %s port %d...", - ctx->l_ip, ctx->l_port); if(-1 == rc) { - result = socket_connect_result(data, ctx->r_ip, error); + result = socket_connect_result(data, ctx->r_ip, SOCKERRNO); goto out; } } @@ -1202,14 +1220,13 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf, out: if(result) { if(ctx->error) { - set_local_ip(cf, data); data->state.os_errno = ctx->error; SET_SOCKERRNO(ctx->error); #ifndef CURL_DISABLE_VERBOSE_STRINGS { char buffer[STRERROR_LEN]; - infof(data, "connect to %s port %u from %s port %d failed: %s", - ctx->r_ip, ctx->r_port, ctx->l_ip, ctx->l_port, + infof(data, "connect to %s port %u failed: %s", + ctx->r_ip, ctx->r_port, Curl_strerror(ctx->error, buffer, sizeof(buffer))); } #endif @@ -1235,19 +1252,20 @@ static void cf_socket_get_host(struct Curl_cfilter *cf, *pport = cf->conn->port; } -static void cf_socket_adjust_pollset(struct Curl_cfilter *cf, +static int cf_socket_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data, - struct easy_pollset *ps) + curl_socket_t *socks) { struct cf_socket_ctx *ctx = cf->ctx; + int rc = GETSOCK_BLANK; - if(ctx->sock != CURL_SOCKET_BAD) { - if(!cf->connected) - Curl_pollset_set_out_only(data, ps, ctx->sock); - else - Curl_pollset_add_in(data, ps, ctx->sock); - CURL_TRC_CF(data, cf, "adjust_pollset -> %d socks", ps->num); + (void)data; + if(!cf->connected && ctx->sock != CURL_SOCKET_BAD) { + socks[0] = ctx->sock; + rc |= GETSOCK_WRITESOCK(0); } + + return rc; } static bool cf_socket_data_pending(struct Curl_cfilter *cf, @@ -1500,9 +1518,6 @@ static CURLcode cf_socket_cntrl(struct Curl_cfilter *cf, case CF_CTRL_DATA_SETUP: Curl_persistconninfo(data, cf->conn, ctx->l_ip, ctx->l_port); break; - case CF_CTRL_FORGET_SOCKET: - ctx->sock = CURL_SOCKET_BAD; - break; } return CURLE_OK; } @@ -1597,7 +1612,7 @@ struct Curl_cftype Curl_cft_tcp = { cf_tcp_connect, cf_socket_close, cf_socket_get_host, - cf_socket_adjust_pollset, + cf_socket_get_select_socks, cf_socket_data_pending, cf_socket_send, cf_socket_recv, @@ -1620,7 +1635,7 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf, (void)data; (void)conn; DEBUGASSERT(transport == TRNSPRT_TCP); - ctx = calloc(1, sizeof(*ctx)); + ctx = calloc(sizeof(*ctx), 1); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -1727,7 +1742,7 @@ struct Curl_cftype Curl_cft_udp = { cf_udp_connect, cf_socket_close, cf_socket_get_host, - cf_socket_adjust_pollset, + cf_socket_get_select_socks, cf_socket_data_pending, cf_socket_send, cf_socket_recv, @@ -1750,7 +1765,7 @@ CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf, (void)data; (void)conn; DEBUGASSERT(transport == TRNSPRT_UDP || transport == TRNSPRT_QUIC); - ctx = calloc(1, sizeof(*ctx)); + ctx = calloc(sizeof(*ctx), 1); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -1778,7 +1793,7 @@ struct Curl_cftype Curl_cft_unix = { cf_tcp_connect, cf_socket_close, cf_socket_get_host, - cf_socket_adjust_pollset, + cf_socket_get_select_socks, cf_socket_data_pending, cf_socket_send, cf_socket_recv, @@ -1801,7 +1816,7 @@ CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf, (void)data; (void)conn; DEBUGASSERT(transport == TRNSPRT_UNIX); - ctx = calloc(1, sizeof(*ctx)); + ctx = calloc(sizeof(*ctx), 1); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -1842,7 +1857,7 @@ struct Curl_cftype Curl_cft_tcp_accept = { cf_tcp_accept_connect, cf_socket_close, cf_socket_get_host, /* TODO: not accurate */ - cf_socket_adjust_pollset, + cf_socket_get_select_socks, cf_socket_data_pending, cf_socket_send, cf_socket_recv, @@ -1864,7 +1879,7 @@ CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data, Curl_conn_cf_discard_all(data, conn, sockindex); DEBUGASSERT(conn->sock[sockindex] == CURL_SOCKET_BAD); - ctx = calloc(1, sizeof(*ctx)); + ctx = calloc(sizeof(*ctx), 1); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; diff --git a/deps/curl/lib/cfilters.c b/deps/curl/lib/cfilters.c index e78ecd71..f74eb400 100644 --- a/deps/curl/lib/cfilters.c +++ b/deps/curl/lib/cfilters.c @@ -33,7 +33,6 @@ #include "sockaddr.h" /* required for Curl_sockaddr_storage */ #include "multiif.h" #include "progress.h" -#include "select.h" #include "warnless.h" /* The last 3 #include files should be in this order */ @@ -71,14 +70,12 @@ void Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data, } } -void Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf, +int Curl_cf_def_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data, - struct easy_pollset *ps) + curl_socket_t *socks) { - /* NOP */ - (void)cf; - (void)data; - (void)ps; + return cf->next? + cf->next->cft->get_select_socks(cf->next, data, socks) : 0; } bool Curl_cf_def_data_pending(struct Curl_cfilter *cf, @@ -215,7 +212,7 @@ CURLcode Curl_cf_create(struct Curl_cfilter **pcf, CURLcode result = CURLE_OUT_OF_MEMORY; DEBUGASSERT(cft); - cf = calloc(1, sizeof(*cf)); + cf = calloc(sizeof(*cf), 1); if(!cf) goto out; @@ -306,6 +303,15 @@ void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data) cf->cft->do_close(cf, data); } +int Curl_conn_cf_get_select_socks(struct Curl_cfilter *cf, + struct Curl_easy *data, + curl_socket_t *socks) +{ + if(cf) + return cf->cft->get_select_socks(cf, data, socks); + return 0; +} + ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data, const void *buf, size_t len, CURLcode *err) { @@ -427,31 +433,22 @@ bool Curl_conn_data_pending(struct Curl_easy *data, int sockindex) return FALSE; } -void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf, - struct Curl_easy *data, - struct easy_pollset *ps) +int Curl_conn_get_select_socks(struct Curl_easy *data, int sockindex, + curl_socket_t *socks) { - /* Get the lowest not-connected filter, if there are any */ - while(cf && !cf->connected && cf->next && !cf->next->connected) - cf = cf->next; - /* From there on, give all filters a chance to adjust the pollset. - * Lower filters are called later, so they may override */ - while(cf) { - cf->cft->adjust_pollset(cf, data, ps); - cf = cf->next; - } -} - -void Curl_conn_adjust_pollset(struct Curl_easy *data, - struct easy_pollset *ps) -{ - int i; + struct Curl_cfilter *cf; DEBUGASSERT(data); DEBUGASSERT(data->conn); - for(i = 0; i < 2; ++i) { - Curl_conn_cf_adjust_pollset(data->conn->cfilter[i], data, ps); + cf = data->conn->cfilter[sockindex]; + + /* if the next one is not yet connected, that's the one we want */ + while(cf && cf->next && !cf->next->connected) + cf = cf->next; + if(cf) { + return cf->cft->get_select_socks(cf, data, socks); } + return GETSOCK_BLANK; } void Curl_conn_get_host(struct Curl_easy *data, int sockindex, @@ -527,18 +524,6 @@ curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex) return data->conn? data->conn->sock[sockindex] : CURL_SOCKET_BAD; } -void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex) -{ - if(data->conn) { - struct Curl_cfilter *cf = data->conn->cfilter[sockindex]; - if(cf) - (void)Curl_conn_cf_cntrl(cf, data, TRUE, - CF_CTRL_FORGET_SOCKET, 0, NULL); - fake_sclose(data->conn->sock[sockindex]); - data->conn->sock[sockindex] = CURL_SOCKET_BAD; - } -} - static CURLcode cf_cntrl_all(struct connectdata *conn, struct Curl_easy *data, bool ignore_result, @@ -661,142 +646,3 @@ size_t Curl_conn_get_max_concurrent(struct Curl_easy *data, &n, NULL) : CURLE_UNKNOWN_OPTION; return (result || n <= 0)? 1 : (size_t)n; } - - -void Curl_pollset_reset(struct Curl_easy *data, - struct easy_pollset *ps) -{ - size_t i; - (void)data; - memset(ps, 0, sizeof(*ps)); - for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) - ps->sockets[i] = CURL_SOCKET_BAD; -} - -/** - * - */ -void Curl_pollset_change(struct Curl_easy *data, - struct easy_pollset *ps, curl_socket_t sock, - int add_flags, int remove_flags) -{ - unsigned int i; - - (void)data; - DEBUGASSERT(VALID_SOCK(sock)); - if(!VALID_SOCK(sock)) - return; - - DEBUGASSERT(add_flags <= (CURL_POLL_IN|CURL_POLL_OUT)); - DEBUGASSERT(remove_flags <= (CURL_POLL_IN|CURL_POLL_OUT)); - DEBUGASSERT((add_flags&remove_flags) == 0); /* no overlap */ - for(i = 0; i < ps->num; ++i) { - if(ps->sockets[i] == sock) { - ps->actions[i] &= (unsigned char)(~remove_flags); - ps->actions[i] |= (unsigned char)add_flags; - /* all gone? remove socket */ - if(!ps->actions[i]) { - if((i + 1) < ps->num) { - memmove(&ps->sockets[i], &ps->sockets[i + 1], - (ps->num - (i + 1)) * sizeof(ps->sockets[0])); - memmove(&ps->actions[i], &ps->actions[i + 1], - (ps->num - (i + 1)) * sizeof(ps->actions[0])); - } - --ps->num; - } - return; - } - } - /* not present */ - if(add_flags) { - /* Having more SOCKETS per easy handle than what is defined - * is a programming error. This indicates that we need - * to raise this limit, making easy_pollset larger. - * Since we use this in tight loops, we do not want to make - * the pollset dynamic unnecessarily. - * The current maximum in practise is HTTP/3 eyeballing where - * we have up to 4 sockets involved in connection setup. - */ - DEBUGASSERT(i < MAX_SOCKSPEREASYHANDLE); - if(i < MAX_SOCKSPEREASYHANDLE) { - ps->sockets[i] = sock; - ps->actions[i] = (unsigned char)add_flags; - ps->num = i + 1; - } - } -} - -void Curl_pollset_set(struct Curl_easy *data, - struct easy_pollset *ps, curl_socket_t sock, - bool do_in, bool do_out) -{ - Curl_pollset_change(data, ps, sock, - (do_in?CURL_POLL_IN:0)|(do_out?CURL_POLL_OUT:0), - (!do_in?CURL_POLL_IN:0)|(!do_out?CURL_POLL_OUT:0)); -} - -static void ps_add(struct Curl_easy *data, struct easy_pollset *ps, - int bitmap, curl_socket_t *socks) -{ - if(bitmap) { - int i; - for(i = 0; i < MAX_SOCKSPEREASYHANDLE; ++i) { - if(!(bitmap & GETSOCK_MASK_RW(i)) || !VALID_SOCK((socks[i]))) { - break; - } - if(bitmap & GETSOCK_READSOCK(i)) { - if(bitmap & GETSOCK_WRITESOCK(i)) - Curl_pollset_add_inout(data, ps, socks[i]); - else - /* is READ, since we checked MASK_RW above */ - Curl_pollset_add_in(data, ps, socks[i]); - } - else - Curl_pollset_add_out(data, ps, socks[i]); - } - } -} - -void Curl_pollset_add_socks(struct Curl_easy *data, - struct easy_pollset *ps, - int (*get_socks_cb)(struct Curl_easy *data, - struct connectdata *conn, - curl_socket_t *socks)) -{ - curl_socket_t socks[MAX_SOCKSPEREASYHANDLE]; - int bitmap; - - DEBUGASSERT(data->conn); - bitmap = get_socks_cb(data, data->conn, socks); - ps_add(data, ps, bitmap, socks); -} - -void Curl_pollset_add_socks2(struct Curl_easy *data, - struct easy_pollset *ps, - int (*get_socks_cb)(struct Curl_easy *data, - curl_socket_t *socks)) -{ - curl_socket_t socks[MAX_SOCKSPEREASYHANDLE]; - int bitmap; - - bitmap = get_socks_cb(data, socks); - ps_add(data, ps, bitmap, socks); -} - -void Curl_pollset_check(struct Curl_easy *data, - struct easy_pollset *ps, curl_socket_t sock, - bool *pwant_read, bool *pwant_write) -{ - unsigned int i; - - (void)data; - DEBUGASSERT(VALID_SOCK(sock)); - for(i = 0; i < ps->num; ++i) { - if(ps->sockets[i] == sock) { - *pwant_read = !!(ps->actions[i] & CURL_POLL_IN); - *pwant_write = !!(ps->actions[i] & CURL_POLL_OUT); - return; - } - } - *pwant_read = *pwant_write = FALSE; -} diff --git a/deps/curl/lib/cfilters.h b/deps/curl/lib/cfilters.h index 09a3f162..2c65264d 100644 --- a/deps/curl/lib/cfilters.h +++ b/deps/curl/lib/cfilters.h @@ -60,34 +60,14 @@ typedef void Curl_cft_get_host(struct Curl_cfilter *cf, const char **pdisplay_host, int *pport); -struct easy_pollset; - -/* Passing in an easy_pollset for monitoring of sockets, let - * filters add or remove sockets actions (CURL_POLL_OUT, CURL_POLL_IN). - * This may add a socket or, in case no actions remain, remove - * a socket from the set. - * - * Filter implementations need to call filters "below" *after* they have - * made their adjustments. This allows lower filters to override "upper" - * actions. If a "lower" filter is unable to write, it needs to be able - * to disallow POLL_OUT. - * - * A filter without own restrictions/preferences should not modify - * the pollset. Filters, whose filter "below" is not connected, should - * also do no adjustments. - * - * Examples: a TLS handshake, while ongoing, might remove POLL_IN - * when it needs to write, or vice versa. A HTTP/2 filter might remove - * POLL_OUT when a stream window is exhausted and a WINDOW_UPDATE needs - * to be received first and add instead POLL_IN. - * - * @param cf the filter to ask - * @param data the easy handle the pollset is about - * @param ps the pollset (inout) for the easy handle +/* Filters may return sockets and fdset flags they are waiting for. + * The passes array has room for up to MAX_SOCKSPEREASYHANDLE sockets. + * @return read/write fdset for index in socks + * or GETSOCK_BLANK when nothing to wait on */ -typedef void Curl_cft_adjust_pollset(struct Curl_cfilter *cf, - struct Curl_easy *data, - struct easy_pollset *ps); +typedef int Curl_cft_get_select_socks(struct Curl_cfilter *cf, + struct Curl_easy *data, + curl_socket_t *socks); typedef bool Curl_cft_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data); @@ -130,7 +110,6 @@ typedef CURLcode Curl_cft_conn_keep_alive(struct Curl_cfilter *cf, #define CF_CTRL_DATA_DONE_SEND 8 /* 0 NULL ignored */ /* update conn info at connection and data */ #define CF_CTRL_CONN_INFO_UPDATE (256+0) /* 0 NULL ignored */ -#define CF_CTRL_FORGET_SOCKET (256+1) /* 0 NULL ignored */ /** * Handle event/control for the filter. @@ -192,7 +171,7 @@ struct Curl_cftype { Curl_cft_connect *do_connect; /* establish connection */ Curl_cft_close *do_close; /* close conn */ Curl_cft_get_host *get_host; /* host filter talks to */ - Curl_cft_adjust_pollset *adjust_pollset; /* adjust transfer poll set */ + Curl_cft_get_select_socks *get_select_socks;/* sockets to select on */ Curl_cft_data_pending *has_data_pending;/* conn has data pending */ Curl_cft_send *do_send; /* send data */ Curl_cft_recv *do_recv; /* receive data */ @@ -221,9 +200,9 @@ void Curl_cf_def_destroy_this(struct Curl_cfilter *cf, void Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data, const char **phost, const char **pdisplay_host, int *pport); -void Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf, - struct Curl_easy *data, - struct easy_pollset *ps); +int Curl_cf_def_get_select_socks(struct Curl_cfilter *cf, + struct Curl_easy *data, + curl_socket_t *socks); bool Curl_cf_def_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data); ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data, @@ -300,6 +279,9 @@ CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf, struct Curl_easy *data, bool blocking, bool *done); void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data); +int Curl_conn_cf_get_select_socks(struct Curl_cfilter *cf, + struct Curl_easy *data, + curl_socket_t *socks); ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data, const void *buf, size_t len, CURLcode *err); ssize_t Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data, @@ -382,22 +364,11 @@ bool Curl_conn_data_pending(struct Curl_easy *data, curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex); /** - * Tell filters to forget about the socket at sockindex. + * Get any select fd flags and the socket filters at chain `sockindex` + * at connection `conn` might be waiting for. */ -void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex); - -/** - * Adjust the pollset for the filter chain startgin at `cf`. - */ -void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf, - struct Curl_easy *data, - struct easy_pollset *ps); - -/** - * Adjust pollset from filters installed at transfer's connection. - */ -void Curl_conn_adjust_pollset(struct Curl_easy *data, - struct easy_pollset *ps); +int Curl_conn_get_select_socks(struct Curl_easy *data, int sockindex, + curl_socket_t *socks); /** * Receive data through the filter chain at `sockindex` for connection @@ -497,54 +468,6 @@ size_t Curl_conn_get_max_concurrent(struct Curl_easy *data, int sockindex); -void Curl_pollset_reset(struct Curl_easy *data, - struct easy_pollset *ps); - -/* Change the poll flags (CURL_POLL_IN/CURL_POLL_OUT) to the poll set for - * socket `sock`. If the socket is not already part of the poll set, it - * will be added. - * If the socket is present and all poll flags are cleared, it will be removed. - */ -void Curl_pollset_change(struct Curl_easy *data, - struct easy_pollset *ps, curl_socket_t sock, - int add_flags, int remove_flags); - -void Curl_pollset_set(struct Curl_easy *data, - struct easy_pollset *ps, curl_socket_t sock, - bool do_in, bool do_out); - -#define Curl_pollset_add_in(data, ps, sock) \ - Curl_pollset_change((data), (ps), (sock), CURL_POLL_IN, 0) -#define Curl_pollset_add_out(data, ps, sock) \ - Curl_pollset_change((data), (ps), (sock), CURL_POLL_OUT, 0) -#define Curl_pollset_add_inout(data, ps, sock) \ - Curl_pollset_change((data), (ps), (sock), \ - CURL_POLL_IN|CURL_POLL_OUT, 0) -#define Curl_pollset_set_in_only(data, ps, sock) \ - Curl_pollset_change((data), (ps), (sock), \ - CURL_POLL_IN, CURL_POLL_OUT) -#define Curl_pollset_set_out_only(data, ps, sock) \ - Curl_pollset_change((data), (ps), (sock), \ - CURL_POLL_OUT, CURL_POLL_IN) - -void Curl_pollset_add_socks(struct Curl_easy *data, - struct easy_pollset *ps, - int (*get_socks_cb)(struct Curl_easy *data, - struct connectdata *conn, - curl_socket_t *socks)); -void Curl_pollset_add_socks2(struct Curl_easy *data, - struct easy_pollset *ps, - int (*get_socks_cb)(struct Curl_easy *data, - curl_socket_t *socks)); - -/** - * Check if the pollset, as is, wants to read and/or write regarding - * the given socket. - */ -void Curl_pollset_check(struct Curl_easy *data, - struct easy_pollset *ps, curl_socket_t sock, - bool *pwant_read, bool *pwant_write); - /** * Types and macros used to keep the current easy handle in filter calls, * allowing for nested invocations. See #10336. diff --git a/deps/curl/lib/config-amigaos.h b/deps/curl/lib/config-amigaos.h index d168b446..8f4d3e6c 100644 --- a/deps/curl/lib/config-amigaos.h +++ b/deps/curl/lib/config-amigaos.h @@ -32,6 +32,7 @@ #define HAVE_ARPA_INET_H 1 #define HAVE_CLOSESOCKET_CAMEL 1 +#define HAVE_INTTYPES_H 1 #define HAVE_IOCTLSOCKET_CAMEL 1 #define HAVE_IOCTLSOCKET_CAMEL_FIONBIO 1 #define HAVE_LONGLONG 1 diff --git a/deps/curl/lib/config-dos.h b/deps/curl/lib/config-dos.h index c6fbba79..550c410a 100644 --- a/deps/curl/lib/config-dos.h +++ b/deps/curl/lib/config-dos.h @@ -122,6 +122,7 @@ #define HAVE_SIGSETJMP 1 #define HAVE_SYS_TIME_H 1 #define HAVE_TERMIOS_H 1 + #define HAVE_VARIADIC_MACROS_GCC 1 #elif defined(__HIGHC__) #define HAVE_SYS_TIME_H 1 diff --git a/deps/curl/lib/config-os400.h b/deps/curl/lib/config-os400.h index 357a3645..e9a62886 100644 --- a/deps/curl/lib/config-os400.h +++ b/deps/curl/lib/config-os400.h @@ -104,6 +104,9 @@ /* Define if you have the `timeval' struct. */ #define HAVE_STRUCT_TIMEVAL +/* Define if you have the header file. */ +#define HAVE_INTTYPES_H + /* Define if you have the header file. */ #undef HAVE_IO_H @@ -149,6 +152,9 @@ /* Define if you have the `socket' function. */ #define HAVE_SOCKET +/* Define if you have the header file. */ +#undef HAVE_STDINT_H + /* The following define is needed on OS400 to enable strcmpi(), stricmp() and strdup(). */ diff --git a/deps/curl/lib/config-plan9.h b/deps/curl/lib/config-plan9.h index aa9623f9..fa4be8e6 100644 --- a/deps/curl/lib/config-plan9.h +++ b/deps/curl/lib/config-plan9.h @@ -91,6 +91,7 @@ #define HAVE_GMTIME_R 1 #define HAVE_INET_NTOP 1 #define HAVE_INET_PTON 1 +#define HAVE_INTTYPES_H 1 #define HAVE_LIBGEN_H 1 #define HAVE_LIBZ 1 #define HAVE_LOCALE_H 1 @@ -116,6 +117,7 @@ #define HAVE_SOCKET 1 #define HAVE_SSL_GET_SHUTDOWN 1 #define HAVE_STDBOOL_H 1 +#define HAVE_STDINT_H 1 #define HAVE_STRCASECMP 1 #define HAVE_STRDUP 1 #define HAVE_STRTOK_R 1 diff --git a/deps/curl/lib/config-riscos.h b/deps/curl/lib/config-riscos.h index f3a8e683..52c279f5 100644 --- a/deps/curl/lib/config-riscos.h +++ b/deps/curl/lib/config-riscos.h @@ -108,6 +108,9 @@ /* Define if you have the `timeval' struct. */ #define HAVE_STRUCT_TIMEVAL +/* Define if you have the header file. */ +#define HAVE_INTTYPES_H + /* Define if you have the header file. */ #undef HAVE_IO_H @@ -141,6 +144,9 @@ /* Define if you have the `socket' function. */ #define HAVE_SOCKET +/* Define if you have the header file. */ +#undef HAVE_STDINT_H + /* Define if you have the `strcasecmp' function. */ #undef HAVE_STRCASECMP diff --git a/deps/curl/lib/config-win32.h b/deps/curl/lib/config-win32.h index 7b8a289b..e55ef2fd 100644 --- a/deps/curl/lib/config-win32.h +++ b/deps/curl/lib/config-win32.h @@ -38,6 +38,17 @@ /* Define if you have the header file. */ #define HAVE_FCNTL_H 1 +/* Define to 1 if you have the header file. */ +#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || defined(__MINGW32__) +#define HAVE_INTTYPES_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#if (defined(_MSC_VER) && (_MSC_VER >= 1600)) || defined(__MINGW32__) || \ + (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0582)) || defined(__POCC__) +#define HAVE_STDINT_H 1 +#endif + /* Define if you have the header file. */ #define HAVE_IO_H 1 @@ -45,7 +56,9 @@ #define HAVE_LOCALE_H 1 /* Define if you need header even with header file. */ +#if !defined(__SALFORDC__) && !defined(__POCC__) #define NEED_MALLOC_H 1 +#endif /* Define if you have the header file. */ /* #define HAVE_NETDB_H 1 */ @@ -59,9 +72,7 @@ #endif /* Define if you have the header file. */ -#if defined(__MINGW32__) -#define HAVE_SYS_PARAM_H 1 -#endif +/* #define HAVE_SYS_PARAM_H 1 */ /* Define if you have the header file. */ /* #define HAVE_SYS_SELECT_H 1 */ @@ -76,15 +87,15 @@ #define HAVE_SYS_STAT_H 1 /* Define if you have the header file. */ -#if defined(__MINGW32__) -#define HAVE_SYS_TIME_H 1 -#endif +/* #define HAVE_SYS_TIME_H 1 */ /* Define if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define if you have the header file. */ +#ifndef __BORLANDC__ #define HAVE_SYS_UTIME_H 1 +#endif /* Define if you have the header file. */ /* #define HAVE_TERMIO_H 1 */ @@ -93,7 +104,7 @@ /* #define HAVE_TERMIOS_H 1 */ /* Define if you have the header file. */ -#if defined(__MINGW32__) +#if defined(__MINGW32__) || defined(__LCC__) || defined(__POCC__) #define HAVE_UNISTD_H 1 #endif @@ -101,10 +112,14 @@ #define HAVE_WINDOWS_H 1 /* Define if you have the header file. */ +#ifndef __SALFORDC__ #define HAVE_WINSOCK2_H 1 +#endif /* Define if you have the header file. */ +#ifndef __SALFORDC__ #define HAVE_WS2TCPIP_H 1 +#endif /* Define to 1 if you have the header file. */ #if defined(__MINGW32__) @@ -145,9 +160,7 @@ #define HAVE_GETHOSTNAME 1 /* Define if you have the gettimeofday function. */ -#if defined(__MINGW32__) -#define HAVE_GETTIMEOFDAY 1 -#endif +/* #define HAVE_GETTIMEOFDAY 1 */ /* Define if you have the ioctlsocket function. */ #define HAVE_IOCTLSOCKET 1 @@ -179,12 +192,15 @@ #define HAVE_STRICMP 1 /* Define if you have the strtoll function. */ -#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || defined(__MINGW32__) +#if defined(__MINGW32__) || defined(__POCC__) || \ + (defined(_MSC_VER) && (_MSC_VER >= 1800)) #define HAVE_STRTOLL 1 #endif /* Define if you have the utime function. */ +#ifndef __BORLANDC__ #define HAVE_UTIME 1 +#endif /* Define if you have the recv function. */ #define HAVE_RECV 1 @@ -226,7 +242,7 @@ #define SEND_TYPE_RETV int /* Define to 1 if you have the snprintf function. */ -#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || defined(__MINGW32__) +#if defined(_MSC_VER) && (_MSC_VER >= 1900) #define HAVE_SNPRINTF 1 #endif @@ -259,7 +275,7 @@ /* Define if ssize_t is not an available 'typedefed' type. */ #ifndef _SSIZE_T_DEFINED -# if defined(__MINGW32__) +# if defined(__POCC__) || defined(__MINGW32__) # elif defined(_WIN64) # define _SSIZE_T_DEFINED # define ssize_t __int64 @@ -309,6 +325,8 @@ # undef RECV_TYPE_ARG3 # undef SEND_TYPE_ARG1 # undef SEND_TYPE_ARG3 +# define HAVE_FREEADDRINFO +# define HAVE_GETADDRINFO # define HAVE_GETHOSTBYNAME_R # define HAVE_GETHOSTBYNAME_R_6 # define LWIP_POSIX_SOCKETS_IO_NAMES 0 @@ -329,11 +347,13 @@ #undef USE_WINSOCK #undef HAVE_WINSOCK2_H #undef HAVE_WS2TCPIP_H + #define HAVE_GETADDRINFO #define HAVE_SYS_IOCTL_H #define HAVE_SYS_SOCKET_H #define HAVE_NETINET_IN_H #define HAVE_NETDB_H #define HAVE_ARPA_INET_H + #define HAVE_FREEADDRINFO #define SOCKET int #endif @@ -351,8 +371,15 @@ /* Windows should not have HAVE_GMTIME_R defined */ /* #undef HAVE_GMTIME_R */ +/* Define if the compiler supports C99 variadic macro style. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#define HAVE_VARIADIC_MACROS_C99 1 +#endif + /* Define if the compiler supports the 'long long' data type. */ -#if (defined(_MSC_VER) && (_MSC_VER >= 1310)) || defined(__MINGW32__) +#if defined(__MINGW32__) || \ + (defined(_MSC_VER) && (_MSC_VER >= 1310)) || \ + (defined(__BORLANDC__) && (__BORLANDC__ >= 0x561)) #define HAVE_LONGLONG 1 #endif @@ -434,17 +461,53 @@ Vista # endif #endif -/* Windows XP is required for freeaddrinfo, getaddrinfo */ -#define HAVE_FREEADDRINFO 1 -#define HAVE_GETADDRINFO 1 -#define HAVE_GETADDRINFO_THREADSAFE 1 +/* When no build target is specified Pelles C 5.00 and later default build + target is Windows Vista. We override default target to be Windows 2000. */ +#if defined(__POCC__) && (__POCC__ >= 500) +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0500 +# endif +# ifndef WINVER +# define WINVER 0x0500 +# endif +#endif + +/* Availability of freeaddrinfo, getaddrinfo, and if_nametoindex + functions is quite convoluted, compiler dependent and even build target + dependent. */ +#if defined(HAVE_WS2TCPIP_H) +# if defined(__POCC__) +# define HAVE_FREEADDRINFO 1 +# define HAVE_GETADDRINFO 1 +# define HAVE_GETADDRINFO_THREADSAFE 1 +# elif defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) +# define HAVE_FREEADDRINFO 1 +# define HAVE_GETADDRINFO 1 +# define HAVE_GETADDRINFO_THREADSAFE 1 +# elif defined(_MSC_VER) && (_MSC_VER >= 1200) +# define HAVE_FREEADDRINFO 1 +# define HAVE_GETADDRINFO 1 +# define HAVE_GETADDRINFO_THREADSAFE 1 +# endif +#endif + +#if defined(__POCC__) +# ifndef _MSC_VER +# error Microsoft extensions /Ze compiler option is required +# endif +# ifndef __POCC__OLDNAMES +# error Compatibility names /Go compiler option is required +# endif +#endif /* ---------------------------------------------------------------- */ /* STRUCT RELATED */ /* ---------------------------------------------------------------- */ /* Define if you have struct sockaddr_storage. */ +#if !defined(__SALFORDC__) && !defined(__BORLANDC__) #define HAVE_STRUCT_SOCKADDR_STORAGE 1 +#endif /* Define if you have struct timeval. */ #define HAVE_STRUCT_TIMEVAL 1 @@ -468,6 +531,10 @@ Vista # define USE_WIN32_LARGE_FILES #endif +#if defined(__POCC__) +# undef USE_WIN32_LARGE_FILES +#endif + #if !defined(USE_WIN32_LARGE_FILES) && !defined(USE_WIN32_SMALL_FILES) # define USE_WIN32_SMALL_FILES #endif @@ -529,6 +596,10 @@ Vista #define USE_WIN32_LDAP 1 #endif +#if defined(__POCC__) && defined(USE_WIN32_LDAP) +# define CURL_DISABLE_LDAP 1 +#endif + /* Define to use the Windows crypto library. */ #if !defined(CURL_WINDOWS_APP) #define USE_WIN32_CRYPTO @@ -564,7 +635,7 @@ Vista /* If you want to build curl with the built-in manual */ #define USE_MANUAL 1 -#if defined(USE_IPV6) +#if defined(__POCC__) || defined(USE_IPV6) # define ENABLE_IPV6 1 #endif diff --git a/deps/curl/lib/config-win32ce.h b/deps/curl/lib/config-win32ce.h index e0db57fd..cc3833d0 100644 --- a/deps/curl/lib/config-win32ce.h +++ b/deps/curl/lib/config-win32ce.h @@ -81,7 +81,7 @@ /* #define HAVE_TERMIOS_H 1 */ /* Define if you have the header file. */ -#if defined(__MINGW32__) +#if defined(__MINGW32__) || defined(__LCC__) #define HAVE_UNISTD_H 1 #endif @@ -190,7 +190,8 @@ #define in_addr_t unsigned long /* Define ssize_t if it is not an available 'typedefed' type */ -#if defined(_WIN64) +#if defined(__POCC__) +#elif defined(_WIN64) #define ssize_t __int64 #else #define ssize_t int diff --git a/deps/curl/lib/conncache.c b/deps/curl/lib/conncache.c index 66f18ecb..93d87686 100644 --- a/deps/curl/lib/conncache.c +++ b/deps/curl/lib/conncache.c @@ -107,7 +107,7 @@ int Curl_conncache_init(struct conncache *connc, int size) connc->closure_handle = curl_easy_init(); if(!connc->closure_handle) return 1; /* bad */ - connc->closure_handle->state.internal = true; + connc->closure_handle->internal = true; Curl_hash_init(&connc->hash, size, Curl_hash_str, Curl_str_key_compare, free_bundle_hash_entry); @@ -243,7 +243,7 @@ CURLcode Curl_conncache_add_conn(struct Curl_easy *data) conn->connection_id = connc->next_connection_id++; connc->num_conn++; - DEBUGF(infof(data, "Added connection %" CURL_FORMAT_CURL_OFF_T ". " + DEBUGF(infof(data, "Added connection %ld. " "The cache now contains %zu members", conn->connection_id, connc->num_conn)); @@ -379,26 +379,21 @@ conncache_find_first_connection(struct conncache *connc) bool Curl_conncache_return_conn(struct Curl_easy *data, struct connectdata *conn) { - unsigned int maxconnects = !data->multi->maxconnects ? - data->multi->num_easy * 4: data->multi->maxconnects; + /* data->multi->maxconnects can be negative, deal with it. */ + size_t maxconnects = + (data->multi->maxconnects < 0) ? data->multi->num_easy * 4: + data->multi->maxconnects; struct connectdata *conn_candidate = NULL; conn->lastused = Curl_now(); /* it was used up until now */ - if(maxconnects && Curl_conncache_size(data) > maxconnects) { + if(maxconnects > 0 && + Curl_conncache_size(data) > maxconnects) { infof(data, "Connection cache is full, closing the oldest one"); conn_candidate = Curl_conncache_extract_oldest(data); if(conn_candidate) { - /* Use the closure handle for this disconnect so that anything that - happens during the disconnect is not stored and associated with the - 'data' handle which already just finished a transfer and it is - important that details from this (unrelated) disconnect does not - taint meta-data in the data handle. */ - struct conncache *connc = data->state.conn_cache; - connc->closure_handle->state.buffer = data->state.buffer; - connc->closure_handle->set.buffer_size = data->set.buffer_size; - Curl_disconnect(connc->closure_handle, conn_candidate, - /* dead_connection */ FALSE); + /* the winner gets the honour of being disconnected */ + Curl_disconnect(data, conn_candidate, /* dead_connection */ FALSE); } } diff --git a/deps/curl/lib/connect.c b/deps/curl/lib/connect.c index ec5ab71d..c7ba3e20 100644 --- a/deps/curl/lib/connect.c +++ b/deps/curl/lib/connect.c @@ -84,9 +84,6 @@ #include "curl_memory.h" #include "memdebug.h" -#ifndef ARRAYSIZE -#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) -#endif /* * Curl_timeleft() returns the amount of milliseconds left allowed for the @@ -351,7 +348,6 @@ void Curl_conncontrol(struct connectdata *conn, */ struct eyeballer { const char *name; - const struct Curl_addrinfo *first; /* complete address list, not owned */ const struct Curl_addrinfo *addr; /* List of addresses to try, not owned */ int ai_family; /* matching address family only */ cf_ip_connect_create *cf_create; /* for creating cf */ @@ -363,12 +359,9 @@ struct eyeballer { expire_id timeout_id; /* ID for Curl_expire() */ CURLcode result; int error; - BIT(rewinded); /* if we rewinded the addr list */ BIT(has_started); /* attempts have started */ BIT(is_done); /* out of addresses/time */ BIT(connected); /* cf has connected */ - BIT(inconclusive); /* connect was not a hard failure, we - * might talk to a restarting server */ }; @@ -415,7 +408,7 @@ static CURLcode eyeballer_new(struct eyeballer **pballer, #endif "ip")); baller->cf_create = cf_create; - baller->first = baller->addr = addr; + baller->addr = addr; baller->ai_family = ai_family; baller->primary = primary; baller->delay_ms = delay_ms; @@ -445,13 +438,6 @@ static void baller_free(struct eyeballer *baller, } } -static void baller_rewind(struct eyeballer *baller) -{ - baller->rewinded = TRUE; - baller->addr = baller->first; - baller->inconclusive = FALSE; -} - static void baller_next_addr(struct eyeballer *baller) { baller->addr = addr_next_match(baller->addr, baller->ai_family); @@ -542,10 +528,6 @@ static CURLcode baller_start_next(struct Curl_cfilter *cf, { if(cf->sockindex == FIRSTSOCKET) { baller_next_addr(baller); - /* If we get inconclusive answers from the server(s), we make - * a second iteration over the address list */ - if(!baller->addr && baller->inconclusive && !baller->rewinded) - baller_rewind(baller); baller_start(cf, data, baller, timeoutms); } else { @@ -584,8 +566,6 @@ static CURLcode baller_connect(struct Curl_cfilter *cf, baller->result = CURLE_OPERATION_TIMEDOUT; } } - else if(baller->result == CURLE_WEIRD_SERVER_REPLY) - baller->inconclusive = TRUE; } return baller->result; } @@ -615,7 +595,7 @@ evaluate: *connected = FALSE; /* a very negative world view is best */ now = Curl_now(); ongoing = not_started = 0; - for(i = 0; i < ARRAYSIZE(ctx->baller); i++) { + for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) { struct eyeballer *baller = ctx->baller[i]; if(!baller || baller->is_done) @@ -676,7 +656,7 @@ evaluate: if(not_started > 0) { int added = 0; - for(i = 0; i < ARRAYSIZE(ctx->baller); i++) { + for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) { struct eyeballer *baller = ctx->baller[i]; if(!baller || baller->has_started) @@ -711,13 +691,13 @@ evaluate: /* all ballers have failed to connect. */ CURL_TRC_CF(data, cf, "all eyeballers failed"); result = CURLE_COULDNT_CONNECT; - for(i = 0; i < ARRAYSIZE(ctx->baller); i++) { + for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) { struct eyeballer *baller = ctx->baller[i]; - if(!baller) - continue; CURL_TRC_CF(data, cf, "%s assess started=%d, result=%d", - baller->name, baller->has_started, baller->result); - if(baller->has_started && baller->result) { + baller?baller->name:NULL, + baller?baller->has_started:0, + baller?baller->result:0); + if(baller && baller->has_started && baller->result) { result = baller->result; break; } @@ -858,7 +838,7 @@ static void cf_he_ctx_clear(struct Curl_cfilter *cf, struct Curl_easy *data) DEBUGASSERT(ctx); DEBUGASSERT(data); - for(i = 0; i < ARRAYSIZE(ctx->baller); i++) { + for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) { baller_free(ctx->baller[i], data); ctx->baller[i] = NULL; } @@ -866,22 +846,35 @@ static void cf_he_ctx_clear(struct Curl_cfilter *cf, struct Curl_easy *data) ctx->winner = NULL; } -static void cf_he_adjust_pollset(struct Curl_cfilter *cf, +static int cf_he_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data, - struct easy_pollset *ps) + curl_socket_t *socks) { struct cf_he_ctx *ctx = cf->ctx; - size_t i; + size_t i, s; + int wrc, rc = GETSOCK_BLANK; + curl_socket_t wsocks[MAX_SOCKSPEREASYHANDLE]; - if(!cf->connected) { - for(i = 0; i < ARRAYSIZE(ctx->baller); i++) { - struct eyeballer *baller = ctx->baller[i]; - if(!baller || !baller->cf) - continue; - Curl_conn_cf_adjust_pollset(baller->cf, data, ps); + if(cf->connected) + return cf->next->cft->get_select_socks(cf->next, data, socks); + + for(i = s = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) { + struct eyeballer *baller = ctx->baller[i]; + if(!baller || !baller->cf) + continue; + + wrc = Curl_conn_cf_get_select_socks(baller->cf, data, wsocks); + if(wrc) { + /* TODO: we assume we get at most one socket back */ + socks[s] = wsocks[0]; + if(wrc & GETSOCK_WRITESOCK(0)) + rc |= GETSOCK_WRITESOCK(s); + if(wrc & GETSOCK_READSOCK(0)) + rc |= GETSOCK_READSOCK(s); + s++; } - CURL_TRC_CF(data, cf, "adjust_pollset -> %d socks", ps->num); } + return rc; } static CURLcode cf_he_connect(struct Curl_cfilter *cf, @@ -963,7 +956,7 @@ static bool cf_he_data_pending(struct Curl_cfilter *cf, if(cf->connected) return cf->next->cft->has_data_pending(cf->next, data); - for(i = 0; i < ARRAYSIZE(ctx->baller); i++) { + for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) { struct eyeballer *baller = ctx->baller[i]; if(!baller || !baller->cf) continue; @@ -982,7 +975,7 @@ static struct curltime get_max_baller_time(struct Curl_cfilter *cf, size_t i; memset(&tmax, 0, sizeof(tmax)); - for(i = 0; i < ARRAYSIZE(ctx->baller); i++) { + for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) { struct eyeballer *baller = ctx->baller[i]; memset(&t, 0, sizeof(t)); @@ -1007,7 +1000,7 @@ static CURLcode cf_he_query(struct Curl_cfilter *cf, int reply_ms = -1; size_t i; - for(i = 0; i < ARRAYSIZE(ctx->baller); i++) { + for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) { struct eyeballer *baller = ctx->baller[i]; int breply_ms; @@ -1062,7 +1055,7 @@ struct Curl_cftype Curl_cft_happy_eyeballs = { cf_he_connect, cf_he_close, Curl_cf_def_get_host, - cf_he_adjust_pollset, + cf_he_get_select_socks, cf_he_data_pending, Curl_cf_def_send, Curl_cf_def_recv, @@ -1096,7 +1089,7 @@ cf_happy_eyeballs_create(struct Curl_cfilter **pcf, (void)data; (void)conn; *pcf = NULL; - ctx = calloc(1, sizeof(*ctx)); + ctx = calloc(sizeof(*ctx), 1); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -1129,14 +1122,14 @@ struct transport_provider transport_providers[] = { #ifdef ENABLE_QUIC { TRNSPRT_QUIC, Curl_cf_quic_create }, #endif -#ifndef CURL_DISABLE_TFTP { TRNSPRT_UDP, Curl_cf_udp_create }, -#endif -#ifdef USE_UNIX_SOCKETS { TRNSPRT_UNIX, Curl_cf_unix_create }, -#endif }; +#ifndef ARRAYSIZE +#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) +#endif + static cf_ip_connect_create *get_cf_create(int transport) { size_t i; @@ -1326,7 +1319,7 @@ struct Curl_cftype Curl_cft_setup = { cf_setup_connect, cf_setup_close, Curl_cf_def_get_host, - Curl_cf_def_adjust_pollset, + Curl_cf_def_get_select_socks, Curl_cf_def_data_pending, Curl_cf_def_send, Curl_cf_def_recv, @@ -1347,7 +1340,7 @@ static CURLcode cf_setup_create(struct Curl_cfilter **pcf, CURLcode result = CURLE_OK; (void)data; - ctx = calloc(1, sizeof(*ctx)); + ctx = calloc(sizeof(*ctx), 1); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; diff --git a/deps/curl/lib/content_encoding.c b/deps/curl/lib/content_encoding.c index 4167d4d6..be7c075e 100644 --- a/deps/curl/lib/content_encoding.c +++ b/deps/curl/lib/content_encoding.c @@ -63,9 +63,6 @@ #ifndef CURL_DISABLE_HTTP -/* allow no more than 5 "chained" compression steps */ -#define MAX_ENCODE_STACK 5 - #define DSIZ CURL_MAX_WRITE_SIZE /* buffer size for decompressed data */ @@ -98,7 +95,7 @@ typedef enum { /* Deflate and gzip writer. */ struct zlib_writer { - struct Curl_cwriter super; + struct contenc_writer super; zlibInitState zlib_init; /* zlib init state */ uInt trailerlen; /* Remaining trailer byte count. */ z_stream z; /* State structure for zlib. */ @@ -174,7 +171,7 @@ static CURLcode process_trailer(struct Curl_easy *data, } static CURLcode inflate_stream(struct Curl_easy *data, - struct Curl_cwriter *writer, int type, + struct contenc_writer *writer, zlibInitState started) { struct zlib_writer *zp = (struct zlib_writer *) writer; @@ -199,7 +196,7 @@ static CURLcode inflate_stream(struct Curl_easy *data, return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); /* because the buffer size is fixed, iteratively decompress and transfer to - the client via next_write function. */ + the client via downstream_write function. */ while(!done) { int status; /* zlib status */ done = TRUE; @@ -220,7 +217,7 @@ static CURLcode inflate_stream(struct Curl_easy *data, if(z->avail_out != DSIZ) { if(status == Z_OK || status == Z_STREAM_END) { zp->zlib_init = started; /* Data started. */ - result = Curl_cwriter_write(data, writer->next, type, decomp, + result = Curl_unencode_write(data, writer->downstream, decomp, DSIZ - z->avail_out); if(result) { exit_zlib(data, z, &zp->zlib_init, result); @@ -277,8 +274,8 @@ static CURLcode inflate_stream(struct Curl_easy *data, /* Deflate handler. */ -static CURLcode deflate_do_init(struct Curl_easy *data, - struct Curl_cwriter *writer) +static CURLcode deflate_init_writer(struct Curl_easy *data, + struct contenc_writer *writer) { struct zlib_writer *zp = (struct zlib_writer *) writer; z_stream *z = &zp->z; /* zlib state structure */ @@ -293,16 +290,13 @@ static CURLcode deflate_do_init(struct Curl_easy *data, return CURLE_OK; } -static CURLcode deflate_do_write(struct Curl_easy *data, - struct Curl_cwriter *writer, int type, +static CURLcode deflate_unencode_write(struct Curl_easy *data, + struct contenc_writer *writer, const char *buf, size_t nbytes) { struct zlib_writer *zp = (struct zlib_writer *) writer; z_stream *z = &zp->z; /* zlib state structure */ - if(!(type & CLIENTWRITE_BODY)) - return Curl_cwriter_write(data, writer->next, type, buf, nbytes); - /* Set the compressed input when this function is called */ z->next_in = (Bytef *) buf; z->avail_in = (uInt) nbytes; @@ -311,11 +305,11 @@ static CURLcode deflate_do_write(struct Curl_easy *data, return process_trailer(data, zp); /* Now uncompress the data */ - return inflate_stream(data, writer, type, ZLIB_INFLATING); + return inflate_stream(data, writer, ZLIB_INFLATING); } -static void deflate_do_close(struct Curl_easy *data, - struct Curl_cwriter *writer) +static void deflate_close_writer(struct Curl_easy *data, + struct contenc_writer *writer) { struct zlib_writer *zp = (struct zlib_writer *) writer; z_stream *z = &zp->z; /* zlib state structure */ @@ -323,19 +317,19 @@ static void deflate_do_close(struct Curl_easy *data, exit_zlib(data, z, &zp->zlib_init, CURLE_OK); } -static const struct Curl_cwtype deflate_encoding = { +static const struct content_encoding deflate_encoding = { "deflate", NULL, - deflate_do_init, - deflate_do_write, - deflate_do_close, + deflate_init_writer, + deflate_unencode_write, + deflate_close_writer, sizeof(struct zlib_writer) }; /* Gzip handler. */ -static CURLcode gzip_do_init(struct Curl_easy *data, - struct Curl_cwriter *writer) +static CURLcode gzip_init_writer(struct Curl_easy *data, + struct contenc_writer *writer) { struct zlib_writer *zp = (struct zlib_writer *) writer; z_stream *z = &zp->z; /* zlib state structure */ @@ -447,22 +441,19 @@ static enum { } #endif -static CURLcode gzip_do_write(struct Curl_easy *data, - struct Curl_cwriter *writer, int type, +static CURLcode gzip_unencode_write(struct Curl_easy *data, + struct contenc_writer *writer, const char *buf, size_t nbytes) { struct zlib_writer *zp = (struct zlib_writer *) writer; z_stream *z = &zp->z; /* zlib state structure */ - if(!(type & CLIENTWRITE_BODY)) - return Curl_cwriter_write(data, writer->next, type, buf, nbytes); - if(zp->zlib_init == ZLIB_INIT_GZIP) { /* Let zlib handle the gzip decompression entirely */ z->next_in = (Bytef *) buf; z->avail_in = (uInt) nbytes; /* Now uncompress the data */ - return inflate_stream(data, writer, type, ZLIB_INIT_GZIP); + return inflate_stream(data, writer, ZLIB_INIT_GZIP); } #ifndef OLD_ZLIB_SUPPORT @@ -574,12 +565,12 @@ static CURLcode gzip_do_write(struct Curl_easy *data, } /* We've parsed the header, now uncompress the data */ - return inflate_stream(data, writer, type, ZLIB_GZIP_INFLATING); + return inflate_stream(data, writer, ZLIB_GZIP_INFLATING); #endif } -static void gzip_do_close(struct Curl_easy *data, - struct Curl_cwriter *writer) +static void gzip_close_writer(struct Curl_easy *data, + struct contenc_writer *writer) { struct zlib_writer *zp = (struct zlib_writer *) writer; z_stream *z = &zp->z; /* zlib state structure */ @@ -587,12 +578,12 @@ static void gzip_do_close(struct Curl_easy *data, exit_zlib(data, z, &zp->zlib_init, CURLE_OK); } -static const struct Curl_cwtype gzip_encoding = { +static const struct content_encoding gzip_encoding = { "gzip", "x-gzip", - gzip_do_init, - gzip_do_write, - gzip_do_close, + gzip_init_writer, + gzip_unencode_write, + gzip_close_writer, sizeof(struct zlib_writer) }; @@ -602,7 +593,7 @@ static const struct Curl_cwtype gzip_encoding = { #ifdef HAVE_BROTLI /* Brotli writer. */ struct brotli_writer { - struct Curl_cwriter super; + struct contenc_writer super; BrotliDecoderState *br; /* State structure for brotli. */ }; @@ -644,8 +635,8 @@ static CURLcode brotli_map_error(BrotliDecoderErrorCode be) return CURLE_WRITE_ERROR; } -static CURLcode brotli_do_init(struct Curl_easy *data, - struct Curl_cwriter *writer) +static CURLcode brotli_init_writer(struct Curl_easy *data, + struct contenc_writer *writer) { struct brotli_writer *bp = (struct brotli_writer *) writer; (void) data; @@ -654,8 +645,8 @@ static CURLcode brotli_do_init(struct Curl_easy *data, return bp->br? CURLE_OK: CURLE_OUT_OF_MEMORY; } -static CURLcode brotli_do_write(struct Curl_easy *data, - struct Curl_cwriter *writer, int type, +static CURLcode brotli_unencode_write(struct Curl_easy *data, + struct contenc_writer *writer, const char *buf, size_t nbytes) { struct brotli_writer *bp = (struct brotli_writer *) writer; @@ -666,9 +657,6 @@ static CURLcode brotli_do_write(struct Curl_easy *data, CURLcode result = CURLE_OK; BrotliDecoderResult r = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT; - if(!(type & CLIENTWRITE_BODY)) - return Curl_cwriter_write(data, writer->next, type, buf, nbytes); - if(!bp->br) return CURLE_WRITE_ERROR; /* Stream already ended. */ @@ -682,7 +670,7 @@ static CURLcode brotli_do_write(struct Curl_easy *data, dstleft = DSIZ; r = BrotliDecoderDecompressStream(bp->br, &nbytes, &src, &dstleft, &dst, NULL); - result = Curl_cwriter_write(data, writer->next, type, + result = Curl_unencode_write(data, writer->downstream, decomp, DSIZ - dstleft); if(result) break; @@ -705,8 +693,8 @@ static CURLcode brotli_do_write(struct Curl_easy *data, return result; } -static void brotli_do_close(struct Curl_easy *data, - struct Curl_cwriter *writer) +static void brotli_close_writer(struct Curl_easy *data, + struct contenc_writer *writer) { struct brotli_writer *bp = (struct brotli_writer *) writer; @@ -718,12 +706,12 @@ static void brotli_do_close(struct Curl_easy *data, } } -static const struct Curl_cwtype brotli_encoding = { +static const struct content_encoding brotli_encoding = { "br", NULL, - brotli_do_init, - brotli_do_write, - brotli_do_close, + brotli_init_writer, + brotli_unencode_write, + brotli_close_writer, sizeof(struct brotli_writer) }; #endif @@ -732,13 +720,13 @@ static const struct Curl_cwtype brotli_encoding = { #ifdef HAVE_ZSTD /* Zstd writer. */ struct zstd_writer { - struct Curl_cwriter super; + struct contenc_writer super; ZSTD_DStream *zds; /* State structure for zstd. */ void *decomp; }; -static CURLcode zstd_do_init(struct Curl_easy *data, - struct Curl_cwriter *writer) +static CURLcode zstd_init_writer(struct Curl_easy *data, + struct contenc_writer *writer) { struct zstd_writer *zp = (struct zstd_writer *) writer; @@ -749,8 +737,8 @@ static CURLcode zstd_do_init(struct Curl_easy *data, return zp->zds ? CURLE_OK : CURLE_OUT_OF_MEMORY; } -static CURLcode zstd_do_write(struct Curl_easy *data, - struct Curl_cwriter *writer, int type, +static CURLcode zstd_unencode_write(struct Curl_easy *data, + struct contenc_writer *writer, const char *buf, size_t nbytes) { CURLcode result = CURLE_OK; @@ -759,9 +747,6 @@ static CURLcode zstd_do_write(struct Curl_easy *data, ZSTD_outBuffer out; size_t errorCode; - if(!(type & CLIENTWRITE_BODY)) - return Curl_cwriter_write(data, writer->next, type, buf, nbytes); - if(!zp->decomp) { zp->decomp = malloc(DSIZ); if(!zp->decomp) @@ -781,7 +766,7 @@ static CURLcode zstd_do_write(struct Curl_easy *data, return CURLE_BAD_CONTENT_ENCODING; } if(out.pos > 0) { - result = Curl_cwriter_write(data, writer->next, type, + result = Curl_unencode_write(data, writer->downstream, zp->decomp, out.pos); if(result) break; @@ -793,8 +778,8 @@ static CURLcode zstd_do_write(struct Curl_easy *data, return result; } -static void zstd_do_close(struct Curl_easy *data, - struct Curl_cwriter *writer) +static void zstd_close_writer(struct Curl_easy *data, + struct contenc_writer *writer) { struct zstd_writer *zp = (struct zstd_writer *) writer; @@ -810,30 +795,52 @@ static void zstd_do_close(struct Curl_easy *data, } } -static const struct Curl_cwtype zstd_encoding = { +static const struct content_encoding zstd_encoding = { "zstd", NULL, - zstd_do_init, - zstd_do_write, - zstd_do_close, + zstd_init_writer, + zstd_unencode_write, + zstd_close_writer, sizeof(struct zstd_writer) }; #endif /* Identity handler. */ -static const struct Curl_cwtype identity_encoding = { +static CURLcode identity_init_writer(struct Curl_easy *data, + struct contenc_writer *writer) +{ + (void)data; + (void)writer; + return CURLE_OK; +} + +static CURLcode identity_unencode_write(struct Curl_easy *data, + struct contenc_writer *writer, + const char *buf, size_t nbytes) +{ + return Curl_unencode_write(data, writer->downstream, buf, nbytes); +} + +static void identity_close_writer(struct Curl_easy *data, + struct contenc_writer *writer) +{ + (void) data; + (void) writer; +} + +static const struct content_encoding identity_encoding = { "identity", "none", - Curl_cwriter_def_init, - Curl_cwriter_def_write, - Curl_cwriter_def_close, - sizeof(struct Curl_cwriter) + identity_init_writer, + identity_unencode_write, + identity_close_writer, + sizeof(struct contenc_writer) }; /* supported content encodings table. */ -static const struct Curl_cwtype * const encodings[] = { +static const struct content_encoding * const encodings[] = { &identity_encoding, #ifdef HAVE_LIBZ &deflate_encoding, @@ -849,17 +856,13 @@ static const struct Curl_cwtype * const encodings[] = { }; -/* Provide a list of comma-separated names of supported encodings. -*/ -void Curl_all_content_encodings(char *buf, size_t blen) +/* Return a list of comma-separated names of supported encodings. */ +char *Curl_all_content_encodings(void) { size_t len = 0; - const struct Curl_cwtype * const *cep; - const struct Curl_cwtype *ce; - - DEBUGASSERT(buf); - DEBUGASSERT(blen); - buf[0] = 0; + const struct content_encoding * const *cep; + const struct content_encoding *ce; + char *ace; for(cep = encodings; *cep; cep++) { ce = *cep; @@ -867,12 +870,12 @@ void Curl_all_content_encodings(char *buf, size_t blen) len += strlen(ce->name) + 2; } - if(!len) { - if(blen >= sizeof(CONTENT_ENCODING_DEFAULT)) - strcpy(buf, CONTENT_ENCODING_DEFAULT); - } - else if(blen > len) { - char *p = buf; + if(!len) + return strdup(CONTENT_ENCODING_DEFAULT); + + ace = malloc(len); + if(ace) { + char *p = ace; for(cep = encodings; *cep; cep++) { ce = *cep; if(!strcasecompare(ce->name, CONTENT_ENCODING_DEFAULT)) { @@ -884,60 +887,75 @@ void Curl_all_content_encodings(char *buf, size_t blen) } p[-2] = '\0'; } + + return ace; } + /* Deferred error dummy writer. */ -static CURLcode error_do_init(struct Curl_easy *data, - struct Curl_cwriter *writer) +static CURLcode error_init_writer(struct Curl_easy *data, + struct contenc_writer *writer) { (void)data; (void)writer; return CURLE_OK; } -static CURLcode error_do_write(struct Curl_easy *data, - struct Curl_cwriter *writer, int type, +static CURLcode error_unencode_write(struct Curl_easy *data, + struct contenc_writer *writer, const char *buf, size_t nbytes) { - char all[256]; - (void)Curl_all_content_encodings(all, sizeof(all)); + char *all = Curl_all_content_encodings(); (void) writer; (void) buf; (void) nbytes; - if(!(type & CLIENTWRITE_BODY)) - return Curl_cwriter_write(data, writer->next, type, buf, nbytes); - + if(!all) + return CURLE_OUT_OF_MEMORY; failf(data, "Unrecognized content encoding type. " "libcurl understands %s content encodings.", all); + free(all); return CURLE_BAD_CONTENT_ENCODING; } -static void error_do_close(struct Curl_easy *data, - struct Curl_cwriter *writer) +static void error_close_writer(struct Curl_easy *data, + struct contenc_writer *writer) { (void) data; (void) writer; } -static const struct Curl_cwtype error_writer = { - "ce-error", +static const struct content_encoding error_encoding = { NULL, - error_do_init, - error_do_write, - error_do_close, - sizeof(struct Curl_cwriter) + NULL, + error_init_writer, + error_unencode_write, + error_close_writer, + sizeof(struct contenc_writer) }; +/* Write data using an unencoding writer stack. "nbytes" is not + allowed to be 0. */ +CURLcode Curl_unencode_write(struct Curl_easy *data, + struct contenc_writer *writer, + const char *buf, size_t nbytes) +{ + if(!nbytes) + return CURLE_OK; + if(!writer) + return CURLE_WRITE_ERROR; + return writer->handler->unencode_write(data, writer, buf, nbytes); +} + /* Find the content encoding by name. */ -static const struct Curl_cwtype *find_encoding(const char *name, +static const struct content_encoding *find_encoding(const char *name, size_t len) { - const struct Curl_cwtype * const *cep; + const struct content_encoding * const *cep; for(cep = encodings; *cep; cep++) { - const struct Curl_cwtype *ce = *cep; + const struct content_encoding *ce = *cep; if((strncasecompare(name, ce->name, len) && !ce->name[len]) || (ce->alias && strncasecompare(name, ce->alias, len) && !ce->alias[len])) return ce; @@ -951,8 +969,7 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, const char *enclist, int is_transfer) { struct SingleRequest *k = &data->req; - Curl_cwriter_phase phase = is_transfer? - CURL_CW_TRANSFER_DECODE:CURL_CW_CONTENT_DECODE; + unsigned int order = is_transfer? 2: 1; CURLcode result; do { @@ -975,32 +992,23 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, Curl_httpchunk_init(data); /* init our chunky engine. */ } else if(namelen) { - const struct Curl_cwtype *cwt; - struct Curl_cwriter *writer; - - if((is_transfer && !data->set.http_transfer_encoding) || - (!is_transfer && data->set.http_ce_skip)) { + const struct content_encoding *encoding; + struct contenc_writer *writer; + if(is_transfer && !data->set.http_transfer_encoding) /* not requested, ignore */ return CURLE_OK; - } - if(Curl_cwriter_count(data, phase) + 1 >= MAX_ENCODE_STACK) { - failf(data, "Reject response due to more than %u content encodings", - MAX_ENCODE_STACK); - return CURLE_BAD_CONTENT_ENCODING; - } + encoding = find_encoding(name, namelen); + if(!encoding) + encoding = &error_encoding; /* Defer error at stack use. */ - cwt = find_encoding(name, namelen); - if(!cwt) - cwt = &error_writer; /* Defer error at use. */ - - result = Curl_cwriter_create(&writer, data, cwt, phase); + result = Curl_client_create_writer(&writer, data, encoding, order); if(result) return result; - result = Curl_cwriter_add(data, writer); + result = Curl_client_add_writer(data, writer); if(result) { - Curl_cwriter_free(data, writer); + Curl_client_free_writer(data, writer); return result; } } @@ -1020,15 +1028,20 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, return CURLE_NOT_BUILT_IN; } -void Curl_all_content_encodings(char *buf, size_t blen) +CURLcode Curl_unencode_write(struct Curl_easy *data, + struct contenc_writer *writer, + const char *buf, size_t nbytes) { - DEBUGASSERT(buf); - DEBUGASSERT(blen); - if(blen < sizeof(CONTENT_ENCODING_DEFAULT)) - buf[0] = 0; - else - strcpy(buf, CONTENT_ENCODING_DEFAULT); + (void) data; + (void) writer; + (void) buf; + (void) nbytes; + return CURLE_NOT_BUILT_IN; } +char *Curl_all_content_encodings(void) +{ + return strdup(CONTENT_ENCODING_DEFAULT); /* Satisfy caller. */ +} #endif /* CURL_DISABLE_HTTP */ diff --git a/deps/curl/lib/content_encoding.h b/deps/curl/lib/content_encoding.h index 1addf230..ef7930cb 100644 --- a/deps/curl/lib/content_encoding.h +++ b/deps/curl/lib/content_encoding.h @@ -25,10 +25,15 @@ ***************************************************************************/ #include "curl_setup.h" -struct Curl_cwriter; +struct contenc_writer; -void Curl_all_content_encodings(char *buf, size_t blen); +char *Curl_all_content_encodings(void); CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, const char *enclist, int is_transfer); +CURLcode Curl_unencode_write(struct Curl_easy *data, + struct contenc_writer *writer, + const char *buf, size_t nbytes); +void Curl_unencode_cleanup(struct Curl_easy *data); + #endif /* HEADER_CURL_CONTENT_ENCODING_H */ diff --git a/deps/curl/lib/cookie.c b/deps/curl/lib/cookie.c index 9095cea3..af01203a 100644 --- a/deps/curl/lib/cookie.c +++ b/deps/curl/lib/cookie.c @@ -330,7 +330,7 @@ static char *sanitize_cookie_path(const char *cookie_path) */ void Curl_cookie_loadfiles(struct Curl_easy *data) { - struct curl_slist *list = data->state.cookielist; + struct curl_slist *list = data->set.cookielist; if(list) { Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); while(list) { @@ -365,7 +365,9 @@ static void strstore(char **str, const char *newstr, size_t len) DEBUGASSERT(newstr); DEBUGASSERT(str); free(*str); - *str = Curl_strndup(newstr, len); + *str = Curl_memdup(newstr, len + 1); + if(*str) + (*str)[len] = 0; } /* @@ -1027,23 +1029,15 @@ Curl_cookie_add(struct Curl_easy *data, * dereference it. */ if(data && (domain && co->domain && !Curl_host_is_ipnum(co->domain))) { - bool acceptable = FALSE; - char lcase[256]; - char lcookie[256]; - size_t dlen = strlen(domain); - size_t clen = strlen(co->domain); - if((dlen < sizeof(lcase)) && (clen < sizeof(lcookie))) { - const psl_ctx_t *psl = Curl_psl_use(data); - if(psl) { - /* the PSL check requires lowercase domain name and pattern */ - Curl_strntolower(lcase, domain, dlen + 1); - Curl_strntolower(lcookie, co->domain, clen + 1); - acceptable = psl_is_cookie_domain_acceptable(psl, lcase, lcookie); - Curl_psl_release(data); - } - else - acceptable = !bad_domain(domain, strlen(domain)); + const psl_ctx_t *psl = Curl_psl_use(data); + int acceptable; + + if(psl) { + acceptable = psl_is_cookie_domain_acceptable(psl, domain, co->domain); + Curl_psl_release(data); } + else + acceptable = !bad_domain(domain, strlen(domain)); if(!acceptable) { infof(data, "cookie '%s' dropped, domain '%s' must not " @@ -1353,7 +1347,7 @@ static int cookie_sort_ct(const void *p1, const void *p2) static struct Cookie *dup_cookie(struct Cookie *src) { - struct Cookie *d = calloc(1, sizeof(struct Cookie)); + struct Cookie *d = calloc(sizeof(struct Cookie), 1); if(d) { CLONE(domain); CLONE(path); diff --git a/deps/curl/lib/curl_config.h.cmake b/deps/curl/lib/curl_config.h.cmake index 339358ea..0bfb4579 100644 --- a/deps/curl/lib/curl_config.h.cmake +++ b/deps/curl/lib/curl_config.h.cmake @@ -74,15 +74,9 @@ /* disables FTP */ #cmakedefine CURL_DISABLE_FTP 1 -/* disables curl_easy_options API for existing options to curl_easy_setopt */ -#cmakedefine CURL_DISABLE_GETOPTIONS 1 - /* disables GOPHER */ #cmakedefine CURL_DISABLE_GOPHER 1 -/* disables headers-api support */ -#cmakedefine CURL_DISABLE_HEADERS_API 1 - /* disables HSTS support */ #cmakedefine CURL_DISABLE_HSTS 1 @@ -104,9 +98,6 @@ /* disables MIME support */ #cmakedefine CURL_DISABLE_MIME 1 -/* disables local binding support */ -#cmakedefine CURL_DISABLE_BINDLOCAL 1 - /* disables MQTT */ #cmakedefine CURL_DISABLE_MQTT 1 @@ -177,6 +168,9 @@ /* Define to 1 if you have _Atomic support. */ #cmakedefine HAVE_ATOMIC 1 +/* Define to 1 if you have the `fchmod' function. */ +#cmakedefine HAVE_FCHMOD 1 + /* Define to 1 if you have the `fnmatch' function. */ #cmakedefine HAVE_FNMATCH 1 @@ -214,9 +208,6 @@ /* Define to 1 if you have the fseeko function. */ #cmakedefine HAVE_FSEEKO 1 -/* Define to 1 if you have the fseeko declaration. */ -#cmakedefine HAVE_DECL_FSEEKO 1 - /* Define to 1 if you have the _fseeki64 function. */ #cmakedefine HAVE__FSEEKI64 1 @@ -322,6 +313,9 @@ /* Define to 1 if symbol `ADDRESS_FAMILY' exists */ #cmakedefine HAVE_ADDRESS_FAMILY 1 +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H 1 + /* Define to 1 if you have the ioctlsocket function. */ #cmakedefine HAVE_IOCTLSOCKET 1 @@ -503,6 +497,9 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STDBOOL_H 1 +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H 1 + /* Define to 1 if you have the strcasecmp function. */ #cmakedefine HAVE_STRCASECMP 1 @@ -599,6 +596,12 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_UTIME_H 1 +/* Define to 1 if compiler supports C99 variadic macro style. */ +#cmakedefine HAVE_VARIADIC_MACROS_C99 1 + +/* Define to 1 if compiler supports old gcc variadic macro style. */ +#cmakedefine HAVE_VARIADIC_MACROS_GCC 1 + /* Define to 1 if you have the windows.h header file. */ #cmakedefine HAVE_WINDOWS_H 1 diff --git a/deps/curl/lib/curl_hmac.h b/deps/curl/lib/curl_hmac.h index 7a5387a9..2ea03dd2 100644 --- a/deps/curl/lib/curl_hmac.h +++ b/deps/curl/lib/curl_hmac.h @@ -25,8 +25,7 @@ ***************************************************************************/ #if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \ - || !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) \ - || defined(USE_LIBSSH2) + || !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) #include diff --git a/deps/curl/lib/curl_memory.h b/deps/curl/lib/curl_memory.h index 714ad71c..b8c46d79 100644 --- a/deps/curl/lib/curl_memory.h +++ b/deps/curl/lib/curl_memory.h @@ -68,7 +68,7 @@ #undef send #undef recv -#ifdef _WIN32 +#ifdef WIN32 # ifdef UNICODE # undef wcsdup # undef _wcsdup @@ -134,7 +134,7 @@ extern curl_free_callback Curl_cfree; extern curl_realloc_callback Curl_crealloc; extern curl_strdup_callback Curl_cstrdup; extern curl_calloc_callback Curl_ccalloc; -#if defined(_WIN32) && defined(UNICODE) +#if defined(WIN32) && defined(UNICODE) extern curl_wcsdup_callback Curl_cwcsdup; #endif @@ -160,7 +160,7 @@ extern curl_wcsdup_callback Curl_cwcsdup; #undef free #define free(ptr) Curl_cfree(ptr) -#ifdef _WIN32 +#ifdef WIN32 # ifdef UNICODE # undef wcsdup # define wcsdup(ptr) Curl_cwcsdup(ptr) diff --git a/deps/curl/lib/curl_multibyte.c b/deps/curl/lib/curl_multibyte.c index ff210985..522ea34e 100644 --- a/deps/curl/lib/curl_multibyte.c +++ b/deps/curl/lib/curl_multibyte.c @@ -32,7 +32,7 @@ #include "curl_setup.h" -#if defined(_WIN32) +#if defined(WIN32) #include "curl_multibyte.h" @@ -84,7 +84,7 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w) return str_utf8; } -#endif /* _WIN32 */ +#endif /* WIN32 */ #if defined(USE_WIN32_LARGE_FILES) || defined(USE_WIN32_SMALL_FILES) diff --git a/deps/curl/lib/curl_multibyte.h b/deps/curl/lib/curl_multibyte.h index 8b9ac719..ddac1f63 100644 --- a/deps/curl/lib/curl_multibyte.h +++ b/deps/curl/lib/curl_multibyte.h @@ -25,7 +25,7 @@ ***************************************************************************/ #include "curl_setup.h" -#if defined(_WIN32) +#if defined(WIN32) /* * MultiByte conversions using Windows kernel32 library. @@ -33,7 +33,7 @@ wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8); char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w); -#endif /* _WIN32 */ +#endif /* WIN32 */ /* * Macros curlx_convert_UTF8_to_tchar(), curlx_convert_tchar_to_UTF8() @@ -54,7 +54,7 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w); * ensure that the curl memdebug override macros do not replace them. */ -#if defined(UNICODE) && defined(_WIN32) +#if defined(UNICODE) && defined(WIN32) #define curlx_convert_UTF8_to_tchar(ptr) curlx_convert_UTF8_to_wchar((ptr)) #define curlx_convert_tchar_to_UTF8(ptr) curlx_convert_wchar_to_UTF8((ptr)) @@ -78,7 +78,7 @@ typedef union { const unsigned char *const_tbyte_ptr; } xcharp_u; -#endif /* UNICODE && _WIN32 */ +#endif /* UNICODE && WIN32 */ #define curlx_unicodefree(ptr) \ do { \ diff --git a/deps/curl/lib/curl_ntlm_core.c b/deps/curl/lib/curl_ntlm_core.c index 6f6d75c0..cc0ed916 100644 --- a/deps/curl/lib/curl_ntlm_core.c +++ b/deps/curl/lib/curl_ntlm_core.c @@ -111,7 +111,6 @@ # include #else # error "Can't compile NTLM support without a crypto library with DES." -# define CURL_NTLM_NOT_SUPPORTED #endif #include "urldata.h" @@ -131,7 +130,6 @@ #define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00" #define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4) -#if !defined(CURL_NTLM_NOT_SUPPORTED) /* * Turns a 56-bit key into being 64-bit wide. */ @@ -146,7 +144,6 @@ static void extend_key_56_to_64(const unsigned char *key_56, char *key) key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6)); key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF); } -#endif #if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL) /* @@ -340,10 +337,6 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys, encrypt_des(plaintext, results, keys); encrypt_des(plaintext, results + 8, keys + 7); encrypt_des(plaintext, results + 16, keys + 14); -#else - (void)keys; - (void)plaintext; - (void)results; #endif } @@ -354,11 +347,9 @@ CURLcode Curl_ntlm_core_mk_lm_hash(const char *password, unsigned char *lmbuffer /* 21 bytes */) { unsigned char pw[14]; -#if !defined(CURL_NTLM_NOT_SUPPORTED) static const unsigned char magic[] = { 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */ }; -#endif size_t len = CURLMIN(strlen(password), 14); Curl_strntoupper((char *)pw, password, len); diff --git a/deps/curl/lib/curl_ntlm_wb.c b/deps/curl/lib/curl_ntlm_wb.c index b087a37a..aa7bea75 100644 --- a/deps/curl/lib/curl_ntlm_wb.c +++ b/deps/curl/lib/curl_ntlm_wb.c @@ -68,9 +68,7 @@ /* Portable 'sclose_nolog' used only in child process instead of 'sclose' to avoid fooling the socket leak detector */ -#ifdef HAVE_PIPE -# define sclose_nolog(x) close((x)) -#elif defined(HAVE_CLOSESOCKET) +#if defined(HAVE_CLOSESOCKET) # define sclose_nolog(x) closesocket((x)) #elif defined(HAVE_CLOSESOCKET_CAMEL) # define sclose_nolog(x) CloseSocket((x)) @@ -191,7 +189,7 @@ static CURLcode ntlm_wb_init(struct Curl_easy *data, struct ntlmdata *ntlm, goto done; } - if(wakeup_create(sockfds)) { + if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) { failf(data, "Could not open socket pair. errno %d: %s", errno, Curl_strerror(errno, buffer, sizeof(buffer))); goto done; @@ -199,8 +197,8 @@ static CURLcode ntlm_wb_init(struct Curl_easy *data, struct ntlmdata *ntlm, child_pid = fork(); if(child_pid == -1) { - wakeup_close(sockfds[0]); - wakeup_close(sockfds[1]); + sclose(sockfds[0]); + sclose(sockfds[1]); failf(data, "Could not fork. errno %d: %s", errno, Curl_strerror(errno, buffer, sizeof(buffer))); goto done; @@ -270,7 +268,7 @@ static CURLcode ntlm_wb_response(struct Curl_easy *data, struct ntlmdata *ntlm, Curl_dyn_init(&b, MAX_NTLM_WB_RESPONSE); while(len_in > 0) { - ssize_t written = wakeup_write(ntlm->ntlm_auth_hlpr_socket, input, len_in); + ssize_t written = swrite(ntlm->ntlm_auth_hlpr_socket, input, len_in); if(written == -1) { /* Interrupted by a signal, retry it */ if(errno == EINTR) @@ -284,7 +282,7 @@ static CURLcode ntlm_wb_response(struct Curl_easy *data, struct ntlmdata *ntlm, /* Read one line */ while(1) { ssize_t size = - wakeup_read(ntlm->ntlm_auth_hlpr_socket, buf, data->set.buffer_size); + sread(ntlm->ntlm_auth_hlpr_socket, buf, data->set.buffer_size); if(size == -1) { if(errno == EINTR) continue; diff --git a/deps/curl/lib/curl_path.h b/deps/curl/lib/curl_path.h index cbe51c22..9ed09dea 100644 --- a/deps/curl/lib/curl_path.h +++ b/deps/curl/lib/curl_path.h @@ -28,7 +28,7 @@ #include #include "urldata.h" -#ifdef _WIN32 +#ifdef WIN32 # undef PATH_MAX # define PATH_MAX MAX_PATH # ifndef R_OK diff --git a/deps/curl/lib/curl_rtmp.c b/deps/curl/lib/curl_rtmp.c index f7cf54e8..406fb42a 100644 --- a/deps/curl/lib/curl_rtmp.c +++ b/deps/curl/lib/curl_rtmp.c @@ -39,7 +39,7 @@ /* The last #include file should be: */ #include "memdebug.h" -#if defined(_WIN32) && !defined(USE_LWIPSOCK) +#if defined(WIN32) && !defined(USE_LWIPSOCK) #define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e) #define SET_RCVTIMEO(tv,s) int tv = s*1000 #elif defined(LWIP_SO_SNDRCVTIMEO_NONSTANDARD) diff --git a/deps/curl/lib/curl_sasl.c b/deps/curl/lib/curl_sasl.c index 78ad298f..91ddf106 100644 --- a/deps/curl/lib/curl_sasl.c +++ b/deps/curl/lib/curl_sasl.c @@ -262,8 +262,6 @@ static void sasl_state(struct SASL *sasl, struct Curl_easy *data, sasl->state = newstate; } -#if defined(USE_NTLM) || defined(USE_GSASL) || defined(USE_KERBEROS5) || \ - !defined(CURL_DISABLE_DIGEST_AUTH) /* Get the SASL server message and convert it to binary. */ static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data, struct bufref *out) @@ -286,7 +284,6 @@ static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data, } return result; } -#endif /* Encode the outgoing SASL message. */ static CURLcode build_message(struct SASL *sasl, struct bufref *msg) diff --git a/deps/curl/lib/curl_setup.h b/deps/curl/lib/curl_setup.h index a0878414..ba14972e 100644 --- a/deps/curl/lib/curl_setup.h +++ b/deps/curl/lib/curl_setup.h @@ -28,11 +28,6 @@ #define CURL_NO_OLDIES #endif -/* Set default _WIN32_WINNT */ -#ifdef __MINGW32__ -#include <_mingw.h> -#endif - /* * Disable Visual Studio warnings: * 4127 "conditional expression is constant" @@ -41,7 +36,15 @@ #pragma warning(disable:4127) #endif -#ifdef _WIN32 +/* + * Define WIN32 when build target is Win32 API + */ + +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +#define WIN32 +#endif + +#ifdef WIN32 /* * Don't include unneeded stuff in Windows headers to avoid compiler * warnings and macro clashes. @@ -79,7 +82,7 @@ #ifdef _WIN32_WCE # include "config-win32ce.h" #else -# ifdef _WIN32 +# ifdef WIN32 # include "config-win32.h" # endif #endif @@ -211,23 +214,6 @@ # define CURL_DISABLE_RTSP #endif -/* - * When HTTP is disabled, disable HTTP-only features - */ - -#if defined(CURL_DISABLE_HTTP) -# define CURL_DISABLE_ALTSVC 1 -# define CURL_DISABLE_COOKIES 1 -# define CURL_DISABLE_BASIC_AUTH 1 -# define CURL_DISABLE_BEARER_AUTH 1 -# define CURL_DISABLE_AWS 1 -# define CURL_DISABLE_DOH 1 -# define CURL_DISABLE_FORM_API 1 -# define CURL_DISABLE_HEADERS_API 1 -# define CURL_DISABLE_HSTS 1 -# define CURL_DISABLE_HTTP_AUTH 1 -#endif - /* ================================================================ */ /* No system header file shall be included in this file before this */ /* point. */ @@ -345,6 +331,23 @@ #include #endif +#ifdef __POCC__ +# include +# include +# define sys_nerr EILSEQ +#endif + +/* + * Salford-C kludge section (mostly borrowed from wxWidgets). + */ +#ifdef __SALFORDC__ + #pragma suppress 353 /* Possible nested comments */ + #pragma suppress 593 /* Define not used */ + #pragma suppress 61 /* enum has no name */ + #pragma suppress 106 /* unnamed, unused parameter */ + #include +#endif + /* * Large file (>2Gb) support using WIN32 functions. */ @@ -497,11 +500,11 @@ 5. set dir/file naming defines */ -#ifdef _WIN32 +#ifdef WIN32 # define DIR_CHAR "\\" -#else /* _WIN32 */ +#else /* WIN32 */ # ifdef MSDOS /* Watt-32 */ @@ -526,19 +529,48 @@ # define DIR_CHAR "/" -#endif /* _WIN32 */ +# ifndef fileno /* sunos 4 have this as a macro! */ + int fileno(FILE *stream); +# endif + +#endif /* WIN32 */ + +/* + * msvc 6.0 requires PSDK in order to have INET6_ADDRSTRLEN + * defined in ws2tcpip.h as well as to provide IPv6 support. + * Does not apply if lwIP is used. + */ + +#if defined(_MSC_VER) && !defined(__POCC__) && !defined(USE_LWIPSOCK) +# if !defined(HAVE_WS2TCPIP_H) || \ + ((_MSC_VER < 1300) && !defined(INET6_ADDRSTRLEN)) +# undef HAVE_GETADDRINFO_THREADSAFE +# undef HAVE_FREEADDRINFO +# undef HAVE_GETADDRINFO +# undef ENABLE_IPV6 +# endif +#endif /* ---------------------------------------------------------------- */ /* resolver specialty compile-time defines */ /* CURLRES_* defines to use in the host*.c sources */ /* ---------------------------------------------------------------- */ +/* + * lcc-win32 doesn't have _beginthreadex(), lacks threads support. + */ + +#if defined(__LCC__) && defined(WIN32) +# undef USE_THREADS_POSIX +# undef USE_THREADS_WIN32 +#endif + /* * MSVC threads support requires a multi-threaded runtime library. * _beginthreadex() is not available in single-threaded ones. */ -#if defined(_MSC_VER) && !defined(_MT) +#if defined(_MSC_VER) && !defined(__POCC__) && !defined(_MT) # undef USE_THREADS_POSIX # undef USE_THREADS_WIN32 #endif @@ -549,9 +581,6 @@ #if defined(ENABLE_IPV6) && defined(HAVE_GETADDRINFO) # define CURLRES_IPV6 -#elif defined(ENABLE_IPV6) && (defined(_WIN32) || defined(__CYGWIN__)) -/* assume on Windows that IPv6 without getaddrinfo is a broken build */ -# error "Unexpected build: IPv6 is enabled but getaddrinfo was not found." #else # define CURLRES_IPV4 #endif @@ -571,6 +600,35 @@ /* ---------------------------------------------------------------- */ +/* + * msvc 6.0 does not have struct sockaddr_storage and + * does not define IPPROTO_ESP in winsock2.h. But both + * are available if PSDK is properly installed. + */ + +#if defined(_MSC_VER) && !defined(__POCC__) +# if !defined(HAVE_WINSOCK2_H) || ((_MSC_VER < 1300) && !defined(IPPROTO_ESP)) +# undef HAVE_STRUCT_SOCKADDR_STORAGE +# endif +#endif + +/* + * Intentionally fail to build when using msvc 6.0 without PSDK installed. + * The brave of heart can circumvent this, defining ALLOW_MSVC6_WITHOUT_PSDK + * in lib/config-win32.h although absolutely discouraged and unsupported. + */ + +#if defined(_MSC_VER) && !defined(__POCC__) +# if !defined(HAVE_WINDOWS_H) || ((_MSC_VER < 1300) && !defined(_FILETIME_)) +# if !defined(ALLOW_MSVC6_WITHOUT_PSDK) +# error MSVC 6.0 requires "February 2003 Platform SDK" a.k.a. \ + "Windows Server 2003 PSDK" +# else +# define CURL_DISABLE_LDAP 1 +# endif +# endif +#endif + #if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H) && !defined(USE_WIN32_IDN) /* The lib and header are present */ #define USE_LIBIDN2 @@ -636,18 +694,6 @@ # define WARN_UNUSED_RESULT #endif -/* noreturn attribute */ - -#if !defined(CURL_NORETURN) -#if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__clang__) -# define CURL_NORETURN __attribute__((__noreturn__)) -#elif defined(_MSC_VER) && (_MSC_VER >= 1200) -# define CURL_NORETURN __declspec(noreturn) -#else -# define CURL_NORETURN -#endif -#endif - /* * Include macros and defines that should only be processed once. */ @@ -706,7 +752,7 @@ /* In Windows the default file mode is text but an application can override it. Therefore we specify it explicitly. https://github.com/curl/curl/pull/258 */ -#if defined(_WIN32) || defined(MSDOS) +#if defined(WIN32) || defined(MSDOS) #define FOPEN_READTEXT "rt" #define FOPEN_WRITETEXT "wt" #define FOPEN_APPENDTEXT "at" @@ -761,8 +807,7 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, #define UNITTEST static #endif -/* Hyper supports HTTP2 also, but Curl's integration with Hyper does not */ -#if defined(USE_NGHTTP2) +#if defined(USE_NGHTTP2) || defined(USE_HYPER) #define USE_HTTP2 #endif @@ -775,11 +820,11 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, /* Certain Windows implementations are not aligned with what curl expects, so always use the local one on this platform. E.g. the mingw-w64 implementation can return wrong results for non-ASCII inputs. */ -#if defined(HAVE_BASENAME) && defined(_WIN32) +#if defined(HAVE_BASENAME) && defined(WIN32) #undef HAVE_BASENAME #endif -#if defined(USE_UNIX_SOCKETS) && defined(_WIN32) +#if defined(USE_UNIX_SOCKETS) && defined(WIN32) # if !defined(UNIX_PATH_MAX) /* Replicating logic present in afunix.h (distributed with newer Windows 10 SDK versions only) */ diff --git a/deps/curl/lib/curl_setup_once.h b/deps/curl/lib/curl_setup_once.h index bf0ee663..c1ed0590 100644 --- a/deps/curl/lib/curl_setup_once.h +++ b/deps/curl/lib/curl_setup_once.h @@ -56,7 +56,7 @@ #include #endif -#ifdef _WIN32 +#ifdef WIN32 #include #include #endif @@ -70,7 +70,11 @@ #endif #ifdef USE_WOLFSSL -#include +# if defined(HAVE_STDINT_H) +# include +# elif defined(HAVE_INTTYPES_H) +# include +# endif #endif #ifdef USE_SCHANNEL diff --git a/deps/curl/lib/curl_sspi.h b/deps/curl/lib/curl_sspi.h index b26c3915..5af7c248 100644 --- a/deps/curl/lib/curl_sspi.h +++ b/deps/curl/lib/curl_sspi.h @@ -88,22 +88,6 @@ extern PSecurityFunctionTable s_pSecFn; # define CRYPT_E_REVOKED ((HRESULT)0x80092010L) #endif -#ifndef CRYPT_E_NO_REVOCATION_DLL -# define CRYPT_E_NO_REVOCATION_DLL ((HRESULT)0x80092011L) -#endif - -#ifndef CRYPT_E_NO_REVOCATION_CHECK -# define CRYPT_E_NO_REVOCATION_CHECK ((HRESULT)0x80092012L) -#endif - -#ifndef CRYPT_E_REVOCATION_OFFLINE -# define CRYPT_E_REVOCATION_OFFLINE ((HRESULT)0x80092013L) -#endif - -#ifndef CRYPT_E_NOT_IN_REVOCATION_DATABASE -# define CRYPT_E_NOT_IN_REVOCATION_DATABASE ((HRESULT)0x80092014L) -#endif - #ifdef UNICODE # define SECFLAG_WINNT_AUTH_IDENTITY \ (unsigned long)SEC_WINNT_AUTH_IDENTITY_UNICODE diff --git a/deps/curl/lib/curl_trc.c b/deps/curl/lib/curl_trc.c index 0ebe40b8..e53b3057 100644 --- a/deps/curl/lib/curl_trc.c +++ b/deps/curl/lib/curl_trc.c @@ -61,6 +61,10 @@ void Curl_debug(struct Curl_easy *data, curl_infotype type, "* ", "< ", "> ", "{ ", "} ", "{ ", "} " }; if(data->set.fdebug) { bool inCallback = Curl_is_in_callback(data); + /* CURLOPT_DEBUGFUNCTION doc says the user may set CURLOPT_PRIVATE to + distinguish their handle from internal handles. */ + if(data->internal) + DEBUGASSERT(!data->set.private_data); Curl_set_in_callback(data, true); (void)(*data->set.fdebug)(data, type, ptr, size, data->set.debugdata); Curl_set_in_callback(data, inCallback); @@ -105,8 +109,6 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...) } } -#if !defined(CURL_DISABLE_VERBOSE_STRINGS) - /* Curl_infof() is for info message along the way */ #define MAXINFO 2048 @@ -126,11 +128,13 @@ void Curl_infof(struct Curl_easy *data, const char *fmt, ...) } } +#if !defined(CURL_DISABLE_VERBOSE_STRINGS) + void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf, const char *fmt, ...) { DEBUGASSERT(cf); - if(Curl_trc_cf_is_verbose(cf, data)) { + if(data && Curl_trc_cf_is_verbose(cf, data)) { va_list ap; int len; char buffer[MAXINFO + 2]; @@ -228,14 +232,24 @@ CURLcode Curl_trc_init(void) if(config) { return Curl_trc_opt(config); } -#endif /* DEBUGBUILD */ +#endif return CURLE_OK; } -#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */ +#else /* !CURL_DISABLE_VERBOSE_STRINGS) */ CURLcode Curl_trc_init(void) { return CURLE_OK; } -#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */ +#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) +void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf, + const char *fmt, ...) +{ + (void)data; + (void)cf; + (void)fmt; +} +#endif + +#endif /* !DEBUGBUILD */ diff --git a/deps/curl/lib/curl_trc.h b/deps/curl/lib/curl_trc.h index ade9108a..84b5471d 100644 --- a/deps/curl/lib/curl_trc.h +++ b/deps/curl/lib/curl_trc.h @@ -54,6 +54,19 @@ CURLcode Curl_trc_opt(const char *config); void Curl_debug(struct Curl_easy *data, curl_infotype type, char *ptr, size_t size); +/** + * Output an informational message when transfer's verbose logging is enabled. + */ +void Curl_infof(struct Curl_easy *data, +#if defined(__GNUC__) && !defined(printf) && \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__MINGW32__) + const char *fmt, ...) + __attribute__((format(printf, 2, 3))); +#else + const char *fmt, ...); +#endif + /** * Output a failure message on registered callbacks for transfer. */ @@ -69,28 +82,25 @@ void Curl_failf(struct Curl_easy *data, #define failf Curl_failf +/** + * Output an informational message when both transfer's verbose logging + * and connection filters verbose logging are enabled. + */ +void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf, +#if defined(__GNUC__) && !defined(printf) && \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__MINGW32__) + const char *fmt, ...) + __attribute__((format(printf, 3, 4))); +#else + const char *fmt, ...); +#endif + #define CURL_LOG_LVL_NONE 0 #define CURL_LOG_LVL_INFO 1 -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -#define CURL_HAVE_C99 -#endif - -#ifdef CURL_HAVE_C99 -#define infof(data, ...) \ - do { if(Curl_trc_is_verbose(data)) \ - Curl_infof(data, __VA_ARGS__); } while(0) -#define CURL_TRC_CF(data, cf, ...) \ - do { if(Curl_trc_cf_is_verbose(cf, data)) \ - Curl_trc_cf_infof(data, cf, __VA_ARGS__); } while(0) - -#else -#define infof Curl_infof -#define CURL_TRC_CF Curl_trc_cf_infof -#endif - -#ifndef CURL_DISABLE_VERBOSE_STRINGS +#if !defined(CURL_DISABLE_VERBOSE_STRINGS) /* informational messages enabled */ #define Curl_trc_is_verbose(data) ((data) && (data)->set.verbose) @@ -98,49 +108,43 @@ void Curl_failf(struct Curl_easy *data, ((data) && (data)->set.verbose && \ (cf) && (cf)->cft->log_level >= CURL_LOG_LVL_INFO) -/** - * Output an informational message when transfer's verbose logging is enabled. +/* explainer: we have some mix configuration and werror settings + * that define HAVE_VARIADIC_MACROS_C99 even though C89 is enforced + * on gnuc and some other compiler. Need to treat carefully. */ -void Curl_infof(struct Curl_easy *data, -#if defined(__GNUC__) && !defined(printf) && defined(CURL_HAVE_C99) && \ - !defined(__MINGW32__) - const char *fmt, ...) - __attribute__((format(printf, 2, 3))); -#else - const char *fmt, ...); -#endif +#if defined(HAVE_VARIADIC_MACROS_C99) && \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -/** - * Output an informational message when both transfer's verbose logging - * and connection filters verbose logging are enabled. - */ -void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf, -#if defined(__GNUC__) && !defined(printf) && defined(CURL_HAVE_C99) && \ - !defined(__MINGW32__) - const char *fmt, ...) - __attribute__((format(printf, 3, 4))); -#else - const char *fmt, ...); -#endif +#define infof(data, ...) \ + do { if(Curl_trc_is_verbose(data)) \ + Curl_infof(data, __VA_ARGS__); } while(0) +#define CURL_TRC_CF(data, cf, ...) \ + do { if(Curl_trc_cf_is_verbose(cf, data)) \ + Curl_trc_cf_infof(data, cf, __VA_ARGS__); } while(0) -#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */ +#else /* no variadic macro args */ +#define infof Curl_infof +#define CURL_TRC_CF Curl_trc_cf_infof +#endif /* variadic macro args */ + +#else /* !CURL_DISABLE_VERBOSE_STRINGS */ /* All informational messages are not compiled in for size savings */ #define Curl_trc_is_verbose(d) ((void)(d), FALSE) #define Curl_trc_cf_is_verbose(x,y) ((void)(x), (void)(y), FALSE) -static void Curl_infof(struct Curl_easy *data, const char *fmt, ...) -{ - (void)data; (void)fmt; -} +#if defined(HAVE_VARIADIC_MACROS_C99) +#define infof(...) Curl_nop_stmt +#define CURL_TRC_CF(...) Curl_nop_stmt +#define Curl_trc_cf_infof(...) Curl_nop_stmt +#elif defined(HAVE_VARIADIC_MACROS_GCC) +#define infof(x...) Curl_nop_stmt +#define CURL_TRC_CF(x...) Curl_nop_stmt +#define Curl_trc_cf_infof(x...) Curl_nop_stmt +#else +#error "missing VARIADIC macro define, fix and rebuild!" +#endif -static void Curl_trc_cf_infof(struct Curl_easy *data, - struct Curl_cfilter *cf, - const char *fmt, ...) -{ - (void)data; (void)cf; (void)fmt; -} - -#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */ +#endif /* CURL_DISABLE_VERBOSE_STRINGS */ #endif /* HEADER_CURL_TRC_H */ diff --git a/deps/curl/lib/doh.c b/deps/curl/lib/doh.c index 1d928e92..bb0c89ec 100644 --- a/deps/curl/lib/doh.c +++ b/deps/curl/lib/doh.c @@ -242,7 +242,7 @@ static CURLcode dohprobe(struct Curl_easy *data, /* pass in the struct pointer via a local variable to please coverity and the gcc typecheck helpers */ struct dynbuf *resp = &p->serverdoh; - doh->state.internal = true; + doh->internal = true; ERROR_CHECK_SETOPT(CURLOPT_URL, url); ERROR_CHECK_SETOPT(CURLOPT_DEFAULT_PROTOCOL, "https"); ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb); @@ -252,7 +252,6 @@ static CURLcode dohprobe(struct Curl_easy *data, ERROR_CHECK_SETOPT(CURLOPT_HTTPHEADER, headers); #ifdef USE_HTTP2 ERROR_CHECK_SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS); - ERROR_CHECK_SETOPT(CURLOPT_PIPEWAIT, 1L); #endif #ifndef CURLDEBUG /* enforce HTTPS if not debug */ @@ -340,10 +339,9 @@ static CURLcode dohprobe(struct Curl_easy *data, doh->set.dohfor = data; /* identify for which transfer this is done */ p->easy = doh; - /* DoH handles must not inherit private_data. The handles may be passed to - the user via callbacks and the user will be able to identify them as - internal handles because private data is not set. The user can then set - private_data via CURLOPT_PRIVATE if they so choose. */ + /* DoH private_data must be null because the user must have a way to + distinguish their transfer's handle from DoH handles in user + callbacks (ie SSL CTX callback). */ DEBUGASSERT(!doh->set.private_data); if(curl_multi_add_handle(multi, doh)) @@ -374,7 +372,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data, int slot; struct dohdata *dohp; struct connectdata *conn = data->conn; - *waitp = FALSE; + *waitp = TRUE; /* this never returns synchronously */ (void)hostname; (void)port; @@ -382,7 +380,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data, DEBUGASSERT(conn); /* start clean, consider allocating this struct on demand */ - dohp = data->req.doh = calloc(1, sizeof(struct dohdata)); + dohp = data->req.doh = calloc(sizeof(struct dohdata), 1); if(!dohp) return NULL; @@ -414,14 +412,12 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data, dohp->pending++; } #endif - *waitp = TRUE; /* this never returns synchronously */ return NULL; error: curl_slist_free_all(dohp->headers); data->req.doh->headers = NULL; for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) { - (void)curl_multi_remove_handle(data->multi, dohp->probe[slot].easy); Curl_close(&dohp->probe[slot].easy); } Curl_safefree(data->req.doh); @@ -791,8 +787,8 @@ static void showdoh(struct Curl_easy *data, * must be an associated call later to Curl_freeaddrinfo(). */ -static CURLcode doh2ai(const struct dohentry *de, const char *hostname, - int port, struct Curl_addrinfo **aip) +static struct Curl_addrinfo * +doh2ai(const struct dohentry *de, const char *hostname, int port) { struct Curl_addrinfo *ai; struct Curl_addrinfo *prevai = NULL; @@ -805,10 +801,9 @@ static CURLcode doh2ai(const struct dohentry *de, const char *hostname, int i; size_t hostlen = strlen(hostname) + 1; /* include null-terminator */ - DEBUGASSERT(de); - - if(!de->numaddr) - return CURLE_COULDNT_RESOLVE_HOST; + if(!de) + /* no input == no output! */ + return NULL; for(i = 0; i < de->numaddr; i++) { size_t ss_size; @@ -881,9 +876,8 @@ static CURLcode doh2ai(const struct dohentry *de, const char *hostname, Curl_freeaddrinfo(firstai); firstai = NULL; } - *aip = firstai; - return result; + return firstai; } #ifndef CURL_DISABLE_VERBOSE_STRINGS @@ -904,7 +898,6 @@ UNITTEST void de_cleanup(struct dohentry *d) CURLcode Curl_doh_is_resolved(struct Curl_easy *data, struct Curl_dns_entry **dnsp) { - struct connectdata *conn = data->conn; CURLcode result; struct dohdata *dohp = data->req.doh; *dnsp = NULL; /* defaults to no response */ @@ -913,7 +906,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data, if(!dohp->probe[DOH_PROBE_SLOT_IPADDR_V4].easy && !dohp->probe[DOH_PROBE_SLOT_IPADDR_V6].easy) { - failf(data, "Could not DoH-resolve: %s", conn->resolve_async.hostname); + failf(data, "Could not DoH-resolve: %s", data->state.async.hostname); return CONN_IS_PROXIED(data->conn)?CURLE_COULDNT_RESOLVE_PROXY: CURLE_COULDNT_RESOLVE_HOST; } @@ -939,12 +932,10 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data, p->dnstype, &de); Curl_dyn_free(&p->serverdoh); -#ifndef CURL_DISABLE_VERBOSE_STRINGS if(rc[slot]) { infof(data, "DoH: %s type %s for %s", doh_strerror(rc[slot]), type2name(p->dnstype), dohp->host); } -#endif } /* next slot */ result = CURLE_COULDNT_RESOLVE_HOST; /* until we know better */ @@ -956,10 +947,10 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data, infof(data, "DoH Host name: %s", dohp->host); showdoh(data, &de); - result = doh2ai(&de, dohp->host, dohp->port, &ai); - if(result) { + ai = doh2ai(&de, dohp->host, dohp->port); + if(!ai) { de_cleanup(&de); - return result; + return CURLE_OUT_OF_MEMORY; } if(data->share) @@ -976,7 +967,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data, Curl_freeaddrinfo(ai); } else { - conn->resolve_async.dns = dns; + data->state.async.dns = dns; *dnsp = dns; result = CURLE_OK; /* address resolution OK */ } diff --git a/deps/curl/lib/dynbuf.c b/deps/curl/lib/dynbuf.c index 2973d8da..0c9c491a 100644 --- a/deps/curl/lib/dynbuf.c +++ b/deps/curl/lib/dynbuf.c @@ -77,7 +77,6 @@ static CURLcode dyn_nappend(struct dynbuf *s, DEBUGASSERT(indx < s->toobig); DEBUGASSERT(!s->leng || s->bufr); DEBUGASSERT(a <= s->toobig); - DEBUGASSERT(!len || mem); if(fit > s->toobig) { Curl_dyn_free(s); @@ -175,12 +174,10 @@ CURLcode Curl_dyn_addn(struct dynbuf *s, const void *mem, size_t len) */ CURLcode Curl_dyn_add(struct dynbuf *s, const char *str) { - size_t n; - DEBUGASSERT(str); + size_t n = strlen(str); DEBUGASSERT(s); DEBUGASSERT(s->init == DYNINIT); DEBUGASSERT(!s->leng || s->bufr); - n = strlen(str); return dyn_nappend(s, (unsigned char *)str, n); } @@ -194,7 +191,6 @@ CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap) DEBUGASSERT(s); DEBUGASSERT(s->init == DYNINIT); DEBUGASSERT(!s->leng || s->bufr); - DEBUGASSERT(fmt); rc = Curl_dyn_vprintf(s, fmt, ap); if(!rc) diff --git a/deps/curl/lib/dynhds.c b/deps/curl/lib/dynhds.c index d7548959..979b3e82 100644 --- a/deps/curl/lib/dynhds.c +++ b/deps/curl/lib/dynhds.c @@ -27,10 +27,6 @@ #include "strcase.h" /* The last 3 #include files should be in this order */ -#ifdef USE_NGHTTP2 -#include -#include -#endif /* USE_NGHTTP2 */ #include "curl_printf.h" #include "curl_memory.h" #include "memdebug.h" @@ -369,28 +365,3 @@ CURLcode Curl_dynhds_h1_dprint(struct dynhds *dynhds, struct dynbuf *dbuf) return result; } -#ifdef USE_NGHTTP2 - -nghttp2_nv *Curl_dynhds_to_nva(struct dynhds *dynhds, size_t *pcount) -{ - nghttp2_nv *nva = calloc(1, sizeof(nghttp2_nv) * dynhds->hds_len); - size_t i; - - *pcount = 0; - if(!nva) - return NULL; - - for(i = 0; i < dynhds->hds_len; ++i) { - struct dynhds_entry *e = dynhds->hds[i]; - DEBUGASSERT(e); - nva[i].name = (unsigned char *)e->name; - nva[i].namelen = e->namelen; - nva[i].value = (unsigned char *)e->value; - nva[i].valuelen = e->valuelen; - nva[i].flags = NGHTTP2_NV_FLAG_NONE; - } - *pcount = dynhds->hds_len; - return nva; -} - -#endif /* USE_NGHTTP2 */ diff --git a/deps/curl/lib/dynhds.h b/deps/curl/lib/dynhds.h index 3b536000..8a053480 100644 --- a/deps/curl/lib/dynhds.h +++ b/deps/curl/lib/dynhds.h @@ -171,13 +171,4 @@ CURLcode Curl_dynhds_h1_add_line(struct dynhds *dynhds, */ CURLcode Curl_dynhds_h1_dprint(struct dynhds *dynhds, struct dynbuf *dbuf); -#ifdef USE_NGHTTP2 - -#include -#include - -nghttp2_nv *Curl_dynhds_to_nva(struct dynhds *dynhds, size_t *pcount); - -#endif /* USE_NGHTTP2 */ - #endif /* HEADER_CURL_DYNHDS_H */ diff --git a/deps/curl/lib/easy.c b/deps/curl/lib/easy.c index 322d1a41..6b4fb8ef 100644 --- a/deps/curl/lib/easy.c +++ b/deps/curl/lib/easy.c @@ -112,7 +112,7 @@ static curl_simple_lock s_lock = CURL_SIMPLE_LOCK_INIT; #define system_strdup strdup #endif -#if defined(_MSC_VER) && defined(_DLL) +#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) # pragma warning(disable:4232) /* MSVC extension, dllimport identity */ #endif @@ -125,11 +125,11 @@ curl_free_callback Curl_cfree = (curl_free_callback)free; curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc; curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup; curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc; -#if defined(_WIN32) && defined(UNICODE) +#if defined(WIN32) && defined(UNICODE) curl_wcsdup_callback Curl_cwcsdup = Curl_wcsdup; #endif -#if defined(_MSC_VER) && defined(_DLL) +#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) # pragma warning(default:4232) /* MSVC extension, dllimport identity */ #endif @@ -153,7 +153,7 @@ static CURLcode global_init(long flags, bool memoryfuncs) Curl_crealloc = (curl_realloc_callback)realloc; Curl_cstrdup = (curl_strdup_callback)system_strdup; Curl_ccalloc = (curl_calloc_callback)calloc; -#if defined(_WIN32) && defined(UNICODE) +#if defined(WIN32) && defined(UNICODE) Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; #endif } @@ -188,10 +188,18 @@ static CURLcode global_init(long flags, bool memoryfuncs) goto fail; } +#if defined(USE_SSH) if(Curl_ssh_init()) { - DEBUGF(fprintf(stderr, "Error: Curl_ssh_init failed\n")); goto fail; } +#endif + +#ifdef USE_WOLFSSH + if(WS_SUCCESS != wolfSSH_Init()) { + DEBUGF(fprintf(stderr, "Error: wolfSSH_Init failed\n")); + return CURLE_FAILED_INIT; + } +#endif easy_init_flags = flags; @@ -287,7 +295,7 @@ void curl_global_cleanup(void) Curl_ssl_cleanup(); Curl_resolver_global_cleanup(); -#ifdef _WIN32 +#ifdef WIN32 Curl_win32_cleanup(easy_init_flags); #endif @@ -744,7 +752,7 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events) return CURLE_RECURSIVE_API_CALL; /* Copy the MAXCONNECTS option to the multi handle */ - curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, (long)data->set.maxconnects); + curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects); mcode = curl_multi_add_handle(multi, data); if(mcode) { @@ -837,10 +845,8 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src) dst->set = src->set; Curl_mime_initpart(&dst->set.mimepost); - /* clear all dest string and blob pointers first, in case we error out - mid-function */ + /* clear all string pointers first */ memset(dst->set.str, 0, STRING_LAST * sizeof(char *)); - memset(dst->set.blobs, 0, BLOB_LAST * sizeof(struct curl_blob *)); /* duplicate all strings */ for(i = (enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) { @@ -849,6 +855,8 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src) return result; } + /* clear all blob pointers first */ + memset(dst->set.blobs, 0, BLOB_LAST * sizeof(struct curl_blob *)); /* duplicate all blobs */ for(j = (enum dupblob)0; j < BLOB_LAST; j++) { result = Curl_setblobopt(&dst->set.blobs[j], src->set.blobs[j]); @@ -858,13 +866,10 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src) /* duplicate memory areas pointed to */ i = STRING_COPYPOSTFIELDS; - if(src->set.str[i]) { - if(src->set.postfieldsize == -1) - dst->set.str[i] = strdup(src->set.str[i]); - else - /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */ - dst->set.str[i] = Curl_memdup(src->set.str[i], - curlx_sotouz(src->set.postfieldsize)); + if(src->set.postfieldsize && src->set.str[i]) { + /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */ + dst->set.str[i] = Curl_memdup(src->set.str[i], + curlx_sotouz(src->set.postfieldsize)); if(!dst->set.str[i]) return CURLE_OUT_OF_MEMORY; /* point to the new copy */ @@ -914,19 +919,18 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) outcurl->progress.callback = data->progress.callback; #ifndef CURL_DISABLE_COOKIES - outcurl->state.cookielist = NULL; - if(data->cookies && data->state.cookie_engine) { + if(data->cookies) { /* If cookies are enabled in the parent handle, we enable them in the clone as well! */ - outcurl->cookies = Curl_cookie_init(outcurl, NULL, outcurl->cookies, + outcurl->cookies = Curl_cookie_init(data, NULL, outcurl->cookies, data->set.cookiesession); if(!outcurl->cookies) goto fail; } - if(data->state.cookielist) { - outcurl->state.cookielist = Curl_slist_duplicate(data->state.cookielist); - if(!outcurl->state.cookielist) + if(data->set.cookielist) { + outcurl->set.cookielist = Curl_slist_duplicate(data->set.cookielist); + if(!outcurl->set.cookielist) goto fail; } #endif @@ -972,6 +976,33 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) (void)Curl_hsts_loadcb(outcurl, outcurl->hsts); } #endif + /* Clone the resolver handle, if present, for the new handle */ + if(Curl_resolver_duphandle(outcurl, + &outcurl->state.async.resolver, + data->state.async.resolver)) + goto fail; + +#ifdef USE_ARES + { + CURLcode rc; + + rc = Curl_set_dns_servers(outcurl, data->set.str[STRING_DNS_SERVERS]); + if(rc && rc != CURLE_NOT_BUILT_IN) + goto fail; + + rc = Curl_set_dns_interface(outcurl, data->set.str[STRING_DNS_INTERFACE]); + if(rc && rc != CURLE_NOT_BUILT_IN) + goto fail; + + rc = Curl_set_dns_local_ip4(outcurl, data->set.str[STRING_DNS_LOCAL_IP4]); + if(rc && rc != CURLE_NOT_BUILT_IN) + goto fail; + + rc = Curl_set_dns_local_ip6(outcurl, data->set.str[STRING_DNS_LOCAL_IP6]); + if(rc && rc != CURLE_NOT_BUILT_IN) + goto fail; + } +#endif /* USE_ARES */ Curl_initinfo(outcurl); @@ -985,10 +1016,13 @@ fail: if(outcurl) { #ifndef CURL_DISABLE_COOKIES - free(outcurl->cookies); + curl_slist_free_all(outcurl->set.cookielist); + outcurl->set.cookielist = NULL; #endif - free(outcurl->state.buffer); + Curl_safefree(outcurl->state.buffer); Curl_dyn_free(&outcurl->state.headerb); + Curl_safefree(outcurl->state.url); + Curl_safefree(outcurl->state.referer); Curl_altsvc_cleanup(&outcurl->asi); Curl_hsts_cleanup(&outcurl->hsts); Curl_freeset(outcurl); diff --git a/deps/curl/lib/easy_lock.h b/deps/curl/lib/easy_lock.h index 4f6764d4..d3fffd0d 100644 --- a/deps/curl/lib/easy_lock.h +++ b/deps/curl/lib/easy_lock.h @@ -93,15 +93,6 @@ static inline void curl_simple_lock_unlock(curl_simple_lock *lock) atomic_store_explicit(lock, false, memory_order_release); } -#elif defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) - -#include - -#define curl_simple_lock pthread_mutex_t -#define CURL_SIMPLE_LOCK_INIT PTHREAD_MUTEX_INITIALIZER -#define curl_simple_lock_lock(m) pthread_mutex_lock(m) -#define curl_simple_lock_unlock(m) pthread_mutex_unlock(m) - #else #undef GLOBAL_INIT_IS_THREADSAFE diff --git a/deps/curl/lib/file.c b/deps/curl/lib/file.c index c9850713..ffa9fb76 100644 --- a/deps/curl/lib/file.c +++ b/deps/curl/lib/file.c @@ -69,7 +69,7 @@ #include "curl_memory.h" #include "memdebug.h" -#if defined(_WIN32) || defined(MSDOS) || defined(__EMX__) +#if defined(WIN32) || defined(MSDOS) || defined(__EMX__) #define DOS_FILESYSTEM 1 #elif defined(__amigaos4__) #define AMIGA_FILESYSTEM 1 @@ -414,6 +414,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) bool size_known; bool fstated = FALSE; char *buf = data->state.buffer; + curl_off_t bytecount = 0; int fd; struct FILEPROTO *file; @@ -562,6 +563,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) if(nread <= 0 || (size_known && (expected_size == 0))) break; + bytecount += nread; if(size_known) expected_size -= nread; @@ -569,6 +571,10 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) if(result) return result; + result = Curl_pgrsSetDownloadCounter(data, bytecount); + if(result) + return result; + if(Curl_pgrsUpdate(data)) result = CURLE_ABORTED_BY_CALLBACK; else diff --git a/deps/curl/lib/fopen.c b/deps/curl/lib/fopen.c index 851279fe..75b8a7aa 100644 --- a/deps/curl/lib/fopen.c +++ b/deps/curl/lib/fopen.c @@ -39,51 +39,6 @@ #include "curl_memory.h" #include "memdebug.h" -/* - The dirslash() function breaks a null-terminated pathname string into - directory and filename components then returns the directory component up - to, *AND INCLUDING*, a final '/'. If there is no directory in the path, - this instead returns a "" string. - - This function returns a pointer to malloc'ed memory. - - The input path to this function is expected to have a file name part. -*/ - -#ifdef _WIN32 -#define PATHSEP "\\" -#define IS_SEP(x) (((x) == '/') || ((x) == '\\')) -#elif defined(MSDOS) || defined(__EMX__) || defined(OS2) -#define PATHSEP "\\" -#define IS_SEP(x) ((x) == '\\') -#else -#define PATHSEP "/" -#define IS_SEP(x) ((x) == '/') -#endif - -static char *dirslash(const char *path) -{ - size_t n; - struct dynbuf out; - DEBUGASSERT(path); - Curl_dyn_init(&out, CURL_MAX_INPUT_LENGTH); - n = strlen(path); - if(n) { - /* find the rightmost path separator, if any */ - while(n && !IS_SEP(path[n-1])) - --n; - /* skip over all the path separators, if any */ - while(n && IS_SEP(path[n-1])) - --n; - } - if(Curl_dyn_addn(&out, path, n)) - return NULL; - /* if there was a directory, append a single trailing slash */ - if(n && Curl_dyn_addn(&out, PATHSEP, 1)) - return NULL; - return Curl_dyn_ptr(&out); -} - /* * Curl_fopen() opens a file for writing with a temp name, to be renamed * to the final name when completed. If there is an existing file using this @@ -95,44 +50,47 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, FILE **fh, char **tempname) { CURLcode result = CURLE_WRITE_ERROR; - unsigned char randbuf[41]; + unsigned char randsuffix[9]; char *tempstore = NULL; struct_stat sb; int fd = -1; - char *dir = NULL; *tempname = NULL; *fh = fopen(filename, FOPEN_WRITETEXT); if(!*fh) goto fail; - if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode)) { + if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode)) return CURLE_OK; - } fclose(*fh); *fh = NULL; - result = Curl_rand_alnum(data, randbuf, sizeof(randbuf)); + result = Curl_rand_alnum(data, randsuffix, sizeof(randsuffix)); if(result) goto fail; - dir = dirslash(filename); - if(dir) { - /* The temp file name should not end up too long for the target file - system */ - tempstore = aprintf("%s%s.tmp", dir, randbuf); - free(dir); - } - + tempstore = aprintf("%s.%s.tmp", filename, randsuffix); if(!tempstore) { result = CURLE_OUT_OF_MEMORY; goto fail; } result = CURLE_WRITE_ERROR; - fd = open(tempstore, O_WRONLY | O_CREAT | O_EXCL, 0600|sb.st_mode); + fd = open(tempstore, O_WRONLY | O_CREAT | O_EXCL, 0600); if(fd == -1) goto fail; +#ifdef HAVE_FCHMOD + { + struct_stat nsb; + if((fstat(fd, &nsb) != -1) && + (nsb.st_uid == sb.st_uid) && (nsb.st_gid == sb.st_gid)) { + /* if the user and group are the same, clone the original mode */ + if(fchmod(fd, (mode_t)sb.st_mode) == -1) + goto fail; + } + } +#endif + *fh = fdopen(fd, FOPEN_WRITETEXT); if(!*fh) goto fail; @@ -147,6 +105,7 @@ fail: } free(tempstore); + return result; } diff --git a/deps/curl/lib/formdata.c b/deps/curl/lib/formdata.c index 05dc9b53..e40c4bcb 100644 --- a/deps/curl/lib/formdata.c +++ b/deps/curl/lib/formdata.c @@ -603,9 +603,9 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, app passed in a bad combo, so we better check for that first. */ if(form->name) { /* copy name (without strdup; possibly not null-terminated) */ - form->name = Curl_strndup(form->name, form->namelength? - form->namelength: - strlen(form->name)); + form->name = Curl_memdup(form->name, form->namelength? + form->namelength: + strlen(form->name) + 1); } if(!form->name) { return_value = CURL_FORMADD_MEMORY; @@ -792,7 +792,7 @@ static CURLcode setname(curl_mimepart *part, const char *name, size_t len) /* wrap call to fseeko so it matches the calling convention of callback */ static int fseeko_wrapper(void *stream, curl_off_t offset, int whence) { -#if defined(HAVE_FSEEKO) && defined(HAVE_DECL_FSEEKO) +#if defined(HAVE_FSEEKO) return fseeko(stream, (off_t)offset, whence); #elif defined(HAVE__FSEEKI64) return _fseeki64(stream, (__int64)offset, whence); diff --git a/deps/curl/lib/ftp.c b/deps/curl/lib/ftp.c index a8dcedf5..518c9233 100644 --- a/deps/curl/lib/ftp.c +++ b/deps/curl/lib/ftp.c @@ -819,7 +819,7 @@ static int ftp_domore_getsock(struct Curl_easy *data, DEBUGF(infof(data, "ftp_domore_getsock()")); if(conn->cfilter[SECONDARYSOCKET] && !Curl_conn_is_connected(conn, SECONDARYSOCKET)) - return 0; + return Curl_conn_get_select_socks(data, SECONDARYSOCKET, socks); if(FTP_STOP == ftpc->state) { int bits = GETSOCK_READSOCK(0); @@ -947,7 +947,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data, char *port_start = NULL; char *port_sep = NULL; - addr = calloc(1, addrlen + 1); + addr = calloc(addrlen + 1, 1); if(!addr) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -4379,7 +4379,7 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data, CURLcode result = CURLE_OK; struct ftp_conn *ftpc = &conn->proto.ftpc; - ftp = calloc(1, sizeof(struct FTP)); + ftp = calloc(sizeof(struct FTP), 1); if(!ftp) return CURLE_OUT_OF_MEMORY; diff --git a/deps/curl/lib/ftplistparser.c b/deps/curl/lib/ftplistparser.c index 82f1ea00..2a7ca5ba 100644 --- a/deps/curl/lib/ftplistparser.c +++ b/deps/curl/lib/ftplistparser.c @@ -55,6 +55,9 @@ /* The last #include file should be: */ #include "memdebug.h" +/* allocs buffer which will contain one line of LIST command response */ +#define FTP_BUFFER_ALLOCSIZE 160 + typedef enum { PL_UNIX_TOTALSIZE = 0, PL_UNIX_FILETYPE, diff --git a/deps/curl/lib/functypes.h b/deps/curl/lib/functypes.h index ea66d328..075c02e5 100644 --- a/deps/curl/lib/functypes.h +++ b/deps/curl/lib/functypes.h @@ -38,7 +38,7 @@ 2. For systems with config-*.h files, define them there. */ -#ifdef _WIN32 +#ifdef WIN32 /* int recv(SOCKET, char *, int, int) */ #define RECV_TYPE_ARG1 SOCKET #define RECV_TYPE_ARG2 char * diff --git a/deps/curl/lib/getenv.c b/deps/curl/lib/getenv.c index 48ee9722..80697847 100644 --- a/deps/curl/lib/getenv.c +++ b/deps/curl/lib/getenv.c @@ -31,11 +31,10 @@ static char *GetEnv(const char *variable) { -#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP) || \ - defined(__ORBIS__) || defined(__PROSPERO__) /* PlayStation 4 and 5 */ +#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP) (void)variable; return NULL; -#elif defined(_WIN32) +#elif defined(WIN32) /* This uses Windows API instead of C runtime getenv() to get the environment variable since some changes aren't always visible to the latter. #4774 */ char *buf = NULL; diff --git a/deps/curl/lib/hostasyn.c b/deps/curl/lib/hostasyn.c index faf01c5f..2f6762ca 100644 --- a/deps/curl/lib/hostasyn.c +++ b/deps/curl/lib/hostasyn.c @@ -67,11 +67,10 @@ CURLcode Curl_addrinfo_callback(struct Curl_easy *data, int status, struct Curl_addrinfo *ai) { - struct connectdata *conn = data->conn; struct Curl_dns_entry *dns = NULL; CURLcode result = CURLE_OK; - conn->resolve_async.status = status; + data->state.async.status = status; if(CURL_ASYNC_SUCCESS == status) { if(ai) { @@ -79,8 +78,8 @@ CURLcode Curl_addrinfo_callback(struct Curl_easy *data, Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); dns = Curl_cache_addr(data, ai, - conn->resolve_async.hostname, 0, - conn->resolve_async.port); + data->state.async.hostname, 0, + data->state.async.port); if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); @@ -95,12 +94,12 @@ CURLcode Curl_addrinfo_callback(struct Curl_easy *data, } } - conn->resolve_async.dns = dns; + data->state.async.dns = dns; /* Set async.done TRUE last in this function since it may be used multi- threaded and once this is TRUE the other thread may read fields from the async struct */ - conn->resolve_async.done = TRUE; + data->state.async.done = TRUE; /* IPv4: The input hostent struct will be freed by ares when we return from this function */ diff --git a/deps/curl/lib/hostip.c b/deps/curl/lib/hostip.c index e7c318af..3cd9a65c 100644 --- a/deps/curl/lib/hostip.c +++ b/deps/curl/lib/hostip.c @@ -117,13 +117,6 @@ static void freednsentry(void *freethis); -#ifndef CURL_DISABLE_VERBOSE_STRINGS -static void show_resolve_info(struct Curl_easy *data, - struct Curl_dns_entry *dns); -#else -#define show_resolve_info(x,y) Curl_nop_stmt -#endif - /* * Curl_printable_address() stores a printable version of the 1st address * given in the 'ai' argument. The result will be stored in the buf that is @@ -488,11 +481,9 @@ Curl_cache_addr(struct Curl_easy *data, return NULL; } #endif - if(!hostlen) - hostlen = strlen(hostname); /* Create a new cache entry */ - dns = calloc(1, sizeof(struct Curl_dns_entry) + hostlen); + dns = calloc(1, sizeof(struct Curl_dns_entry)); if(!dns) { return NULL; } @@ -506,9 +497,6 @@ Curl_cache_addr(struct Curl_easy *data, time(&dns->timestamp); if(dns->timestamp == 0) dns->timestamp = 1; /* zero indicates permanent CURLOPT_RESOLVE entry */ - dns->hostport = port; - if(hostlen) - memcpy(dns->hostname, hostname, hostlen); /* Store the resolved data in our DNS cache. */ dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len + 1, @@ -533,7 +521,7 @@ static struct Curl_addrinfo *get_localhost6(int port, const char *name) struct sockaddr_in6 sa6; unsigned char ipv6[16]; unsigned short port16 = (unsigned short)(port & 0xffff); - ca = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1); + ca = calloc(sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1, 1); if(!ca) return NULL; @@ -580,7 +568,7 @@ static struct Curl_addrinfo *get_localhost(int port, const char *name) return NULL; memcpy(&sa.sin_addr, &ipv4, sizeof(ipv4)); - ca = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1); + ca = calloc(sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1, 1); if(!ca) return NULL; ca->ai_flags = 0; @@ -741,7 +729,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data, Curl_set_in_callback(data, true); st = data->set.resolver_start( #ifdef USE_CURL_ASYNC - conn->resolve_async.resolver, + data->state.async.resolver, #else NULL, #endif @@ -835,10 +823,8 @@ enum resolve_t Curl_resolv(struct Curl_easy *data, if(!dns) /* returned failure, bail out nicely */ Curl_freeaddrinfo(addr); - else { + else rc = CURLRESOLV_RESOLVED; - show_resolve_info(data, dns); - } } } @@ -853,7 +839,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data, * execution. This effectively causes the remainder of the application to run * within a signal handler which is nonportable and could lead to problems. */ -CURL_NORETURN static +static void alarmfunc(int sig) { (void)sig; @@ -1283,11 +1269,9 @@ err: Curl_freeaddrinfo(head); return CURLE_OUT_OF_MEMORY; } -#ifndef CURL_DISABLE_VERBOSE_STRINGS infof(data, "Added %.*s:%d:%s to DNS cache%s", (int)hlen, host_begin, port, addresses, permanent ? "" : " (non-permanent)"); -#endif /* Wildcard hostname */ if((hlen == 1) && (host_begin[0] == '*')) { @@ -1301,89 +1285,18 @@ err: return CURLE_OK; } -#ifndef CURL_DISABLE_VERBOSE_STRINGS -static void show_resolve_info(struct Curl_easy *data, - struct Curl_dns_entry *dns) -{ - struct Curl_addrinfo *a; - CURLcode result = CURLE_OK; -#ifdef CURLRES_IPV6 - struct dynbuf out[2]; -#else - struct dynbuf out[1]; -#endif - DEBUGASSERT(data); - DEBUGASSERT(dns); - - if(!data->set.verbose || - /* ignore no name or numerical IP addresses */ - !dns->hostname[0] || Curl_host_is_ipnum(dns->hostname)) - return; - - a = dns->addr; - - infof(data, "Host %s:%d was resolved.", - (dns->hostname[0] ? dns->hostname : "(none)"), dns->hostport); - - Curl_dyn_init(&out[0], 1024); -#ifdef CURLRES_IPV6 - Curl_dyn_init(&out[1], 1024); -#endif - - while(a) { - if( -#ifdef CURLRES_IPV6 - a->ai_family == PF_INET6 || -#endif - a->ai_family == PF_INET) { - char buf[MAX_IPADR_LEN]; - struct dynbuf *d = &out[(a->ai_family != PF_INET)]; - Curl_printable_address(a, buf, sizeof(buf)); - if(Curl_dyn_len(d)) - result = Curl_dyn_addn(d, ", ", 2); - if(!result) - result = Curl_dyn_add(d, buf); - if(result) { - infof(data, "too many IP, can't show"); - goto fail; - } - } - a = a->ai_next; - } - -#ifdef CURLRES_IPV6 - infof(data, "IPv6: %s", - (Curl_dyn_len(&out[1]) ? Curl_dyn_ptr(&out[1]) : "(none)")); -#endif - infof(data, "IPv4: %s", - (Curl_dyn_len(&out[0]) ? Curl_dyn_ptr(&out[0]) : "(none)")); - -fail: - Curl_dyn_free(&out[0]); -#ifdef CURLRES_IPV6 - Curl_dyn_free(&out[1]); -#endif -} -#endif - CURLcode Curl_resolv_check(struct Curl_easy *data, struct Curl_dns_entry **dns) { - CURLcode result; #if defined(CURL_DISABLE_DOH) && !defined(CURLRES_ASYNCH) (void)data; (void)dns; #endif #ifndef CURL_DISABLE_DOH - if(data->conn->bits.doh) { - result = Curl_doh_is_resolved(data, dns); - } - else + if(data->conn->bits.doh) + return Curl_doh_is_resolved(data, dns); #endif - result = Curl_resolver_is_resolved(data, dns); - if(*dns) - show_resolve_info(data, *dns); - return result; + return Curl_resolver_is_resolved(data, dns); } int Curl_resolv_getsock(struct Curl_easy *data, @@ -1415,9 +1328,9 @@ CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done) struct connectdata *conn = data->conn; #ifdef USE_CURL_ASYNC - if(conn->resolve_async.dns) { - conn->dns_entry = conn->resolve_async.dns; - conn->resolve_async.dns = NULL; + if(data->state.async.dns) { + conn->dns_entry = data->state.async.dns; + data->state.async.dns = NULL; } #endif @@ -1439,11 +1352,11 @@ CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done) #ifdef USE_CURL_ASYNC CURLcode Curl_resolver_error(struct Curl_easy *data) { - struct connectdata *conn = data->conn; const char *host_or_proxy; CURLcode result; #ifndef CURL_DISABLE_PROXY + struct connectdata *conn = data->conn; if(conn->bits.httpproxy) { host_or_proxy = "proxy"; result = CURLE_COULDNT_RESOLVE_PROXY; @@ -1456,7 +1369,7 @@ CURLcode Curl_resolver_error(struct Curl_easy *data) } failf(data, "Could not resolve %s: %s", host_or_proxy, - conn->resolve_async.hostname); + data->state.async.hostname); return result; } diff --git a/deps/curl/lib/hostip.h b/deps/curl/lib/hostip.h index fb53a577..b68f539b 100644 --- a/deps/curl/lib/hostip.h +++ b/deps/curl/lib/hostip.h @@ -64,10 +64,6 @@ struct Curl_dns_entry { time_t timestamp; /* use-counter, use Curl_resolv_unlock to release reference */ long inuse; - /* hostname port number that resolved to addr. */ - int hostport; - /* hostname that resolved to addr. may be NULL (unix domain sockets). */ - char hostname[1]; }; bool Curl_host_is_ipnum(const char *hostname); diff --git a/deps/curl/lib/hostip6.c b/deps/curl/lib/hostip6.c index 18969a7a..6b0ba55e 100644 --- a/deps/curl/lib/hostip6.c +++ b/deps/curl/lib/hostip6.c @@ -71,7 +71,8 @@ bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn) #if defined(CURLRES_SYNCH) #ifdef DEBUG_ADDRINFO -static void dump_addrinfo(const struct Curl_addrinfo *ai) +static void dump_addrinfo(struct connectdata *conn, + const struct Curl_addrinfo *ai) { printf("dump_addrinfo:\n"); for(; ai; ai = ai->ai_next) { @@ -83,7 +84,7 @@ static void dump_addrinfo(const struct Curl_addrinfo *ai) } } #else -#define dump_addrinfo(x) Curl_nop_stmt +#define dump_addrinfo(x,y) Curl_nop_stmt #endif /* @@ -148,7 +149,7 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data, Curl_addrinfo_set_port(res, port); } - dump_addrinfo(res); + dump_addrinfo(conn, res); return res; } diff --git a/deps/curl/lib/hsts.c b/deps/curl/lib/hsts.c index 9314be29..7ecf0042 100644 --- a/deps/curl/lib/hsts.c +++ b/deps/curl/lib/hsts.c @@ -40,7 +40,6 @@ #include "fopen.h" #include "rename.h" #include "share.h" -#include "strdup.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -77,7 +76,7 @@ static time_t hsts_debugtime(void *unused) struct hsts *Curl_hsts_init(void) { - struct hsts *h = calloc(1, sizeof(struct hsts)); + struct hsts *h = calloc(sizeof(struct hsts), 1); if(h) { Curl_llist_init(&h->list, NULL); } @@ -109,7 +108,7 @@ void Curl_hsts_cleanup(struct hsts **hp) static struct stsentry *hsts_entry(void) { - return calloc(1, sizeof(struct stsentry)); + return calloc(sizeof(struct stsentry), 1); } static CURLcode hsts_create(struct hsts *h, @@ -117,30 +116,23 @@ static CURLcode hsts_create(struct hsts *h, bool subdomains, curl_off_t expires) { - struct stsentry *sts; + struct stsentry *sts = hsts_entry(); char *duphost; size_t hlen; - DEBUGASSERT(h); - DEBUGASSERT(hostname); - - hlen = strlen(hostname); - if(hlen && (hostname[hlen - 1] == '.')) - /* strip off any trailing dot */ - --hlen; - if(!hlen) - /* no host name left */ - return CURLE_BAD_FUNCTION_ARGUMENT; - - sts = hsts_entry(); if(!sts) return CURLE_OUT_OF_MEMORY; - duphost = Curl_strndup(hostname, hlen); + duphost = strdup(hostname); if(!duphost) { free(sts); return CURLE_OUT_OF_MEMORY; } + hlen = strlen(duphost); + if(duphost[hlen - 1] == '.') + /* strip off trailing any dot */ + duphost[--hlen] = 0; + sts->host = duphost; sts->expires = expires; sts->includeSubDomains = subdomains; @@ -572,7 +564,7 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h) void Curl_hsts_loadfiles(struct Curl_easy *data) { - struct curl_slist *l = data->state.hstslist; + struct curl_slist *l = data->set.hstslist; if(l) { Curl_share_lock(data, CURL_LOCK_DATA_HSTS, CURL_LOCK_ACCESS_SINGLE); diff --git a/deps/curl/lib/http.c b/deps/curl/lib/http.c index be6d442e..40ef70df 100644 --- a/deps/curl/lib/http.c +++ b/deps/curl/lib/http.c @@ -836,7 +836,6 @@ output_auth_headers(struct Curl_easy *data, (data->state.aptr.user ? data->state.aptr.user : "")); #else - (void)proxy; infof(data, "Server auth using %s with user '%s'", auth, data->state.aptr.user ? data->state.aptr.user : ""); @@ -846,7 +845,7 @@ output_auth_headers(struct Curl_easy *data, else authstatus->multipass = FALSE; - return result; + return CURLE_OK; } /** @@ -971,21 +970,17 @@ Curl_http_output_auth(struct Curl_easy *data, } #endif -#if defined(USE_SPNEGO) || defined(USE_NTLM) || \ - !defined(CURL_DISABLE_DIGEST_AUTH) || \ - !defined(CURL_DISABLE_BASIC_AUTH) || \ - !defined(CURL_DISABLE_BEARER_AUTH) -static int is_valid_auth_separator(char ch) -{ - return ch == '\0' || ch == ',' || ISSPACE(ch); -} -#endif - /* * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate: * headers. They are dealt with both in the transfer.c main loop and in the * proxy CONNECT loop. */ + +static int is_valid_auth_separator(char ch) +{ + return ch == '\0' || ch == ',' || ISSPACE(ch); +} + CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, const char *auth) /* the first non-space */ { @@ -997,15 +992,11 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state : &conn->http_negotiate_state; #endif -#if defined(USE_SPNEGO) || \ - defined(USE_NTLM) || \ - !defined(CURL_DISABLE_DIGEST_AUTH) || \ - !defined(CURL_DISABLE_BASIC_AUTH) || \ - !defined(CURL_DISABLE_BEARER_AUTH) - unsigned long *availp; struct auth *authp; + (void) conn; /* In case conditionals make it unused. */ + if(proxy) { availp = &data->info.proxyauthavail; authp = &data->state.authproxy; @@ -1014,11 +1005,6 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, availp = &data->info.httpauthavail; authp = &data->state.authhost; } -#else - (void) proxy; -#endif - - (void) conn; /* In case conditionals make it unused. */ /* * Here we check if we want the specific single authentication (using ==) and @@ -1154,14 +1140,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, } } #else - { - /* - * Empty block to terminate the if-else chain correctly. - * - * A semicolon would yield the same result here, but can cause a - * compiler warning when -Wextra is enabled. - */ - } + ; #endif /* there may be multiple methods on one line, so keep reading */ @@ -1424,7 +1403,7 @@ CURLcode Curl_buffer_send(struct dynbuf *in, * and install our own `data->state.fread_func` that * on subsequent calls reads `in` empty. * - when the whisked away `in` is empty, the `fread_func` - * is restored to its original state. + * is restored ot its original state. * The problem is that `fread_func` can only return * `upload_buffer_size` lengths. If the send we do here * is larger and blocks, we do re-sending with smaller @@ -1699,6 +1678,8 @@ static CURLcode expect100(struct Curl_easy *data, struct dynbuf *req) { CURLcode result = CURLE_OK; + data->state.expect100header = FALSE; /* default to false unless it is set + to TRUE below */ if(!data->state.disableexpect && Curl_use_http_1_1plus(data, conn) && (conn->httpversion < 20)) { /* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an @@ -2433,16 +2414,14 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn, /* Convert the form structure into a mime structure, then keep the conversion */ if(!data->state.formp) { - data->state.formp = calloc(1, sizeof(curl_mimepart)); + data->state.formp = calloc(sizeof(curl_mimepart), 1); if(!data->state.formp) return CURLE_OUT_OF_MEMORY; Curl_mime_cleanpart(data->state.formp); result = Curl_getformdata(data, data->state.formp, data->set.httppost, data->state.fread_func); - if(result) { - Curl_safefree(data->state.formp); + if(result) return result; - } data->state.mimepost = data->state.formp; } break; @@ -2515,29 +2494,6 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn, return result; } -static CURLcode addexpect(struct Curl_easy *data, struct connectdata *conn, - struct dynbuf *r) -{ - data->state.expect100header = FALSE; - /* Avoid Expect: 100-continue if Upgrade: is used */ - if(data->req.upgr101 == UPGR101_INIT) { - struct HTTP *http = data->req.p.http; - /* For really small puts we don't use Expect: headers at all, and for - the somewhat bigger ones we allow the app to disable it. Just make - sure that the expect100header is always set to the preferred value - here. */ - char *ptr = Curl_checkheaders(data, STRCONST("Expect")); - if(ptr) { - data->state.expect100header = - Curl_compareheader(ptr, STRCONST("Expect:"), - STRCONST("100-continue")); - } - else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) - return expect100(data, conn, r); - } - return CURLE_OK; -} - CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, struct dynbuf *r, Curl_HttpReq httpreq) { @@ -2550,8 +2506,14 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, #endif CURLcode result = CURLE_OK; struct HTTP *http = data->req.p.http; + const char *ptr; + + /* If 'authdone' is FALSE, we must not set the write socket index to the + Curl_transfer() call below, as we're not ready to actually upload any + data yet. */ switch(httpreq) { + case HTTPREQ_PUT: /* Let's PUT the data to the server! */ if(conn->bits.authneg) @@ -2569,9 +2531,20 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, return result; } - result = addexpect(data, conn, r); - if(result) - return result; + /* For really small puts we don't use Expect: headers at all, and for + the somewhat bigger ones we allow the app to disable it. Just make + sure that the expect100header is always set to the preferred value + here. */ + ptr = Curl_checkheaders(data, STRCONST("Expect")); + if(ptr) { + data->state.expect100header = + Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue")); + } + else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) { + result = expect100(data, conn, r); + if(result) + return result; + } /* end of headers */ result = Curl_dyn_addn(r, STRCONST("\r\n")); @@ -2644,9 +2617,22 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, } #endif - result = addexpect(data, conn, r); - if(result) - return result; + /* For really small posts we don't use Expect: headers at all, and for + the somewhat bigger ones we allow the app to disable it. Just make + sure that the expect100header is always set to the preferred value + here. */ + ptr = Curl_checkheaders(data, STRCONST("Expect")); + if(ptr) { + data->state.expect100header = + Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue")); + } + else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) { + result = expect100(data, conn, r); + if(result) + return result; + } + else + data->state.expect100header = FALSE; /* make the request end in a true CRLF */ result = Curl_dyn_addn(r, STRCONST("\r\n")); @@ -2706,9 +2692,22 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, return result; } - result = addexpect(data, conn, r); - if(result) - return result; + /* For really small posts we don't use Expect: headers at all, and for + the somewhat bigger ones we allow the app to disable it. Just make + sure that the expect100header is always set to the preferred value + here. */ + ptr = Curl_checkheaders(data, STRCONST("Expect")); + if(ptr) { + data->state.expect100header = + Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue")); + } + else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) { + result = expect100(data, conn, r); + if(result) + return result; + } + else + data->state.expect100header = FALSE; #ifndef USE_HYPER /* With Hyper the body is always passed on separately */ @@ -3194,7 +3193,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) DEBUGASSERT(Curl_conn_is_http2(data, conn, FIRSTSOCKET)); break; case CURL_HTTP_VERSION_1_1: - /* continue with HTTP/1.x when explicitly requested */ + /* continue with HTTP/1.1 when explicitly requested */ break; default: /* Check if user wants to use HTTP/2 with clear TCP */ @@ -3686,7 +3685,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, k->content_range = TRUE; } } - else if(k->httpcode < 300) + else data->state.resume_from = 0; /* get everything */ } #if !defined(CURL_DISABLE_COOKIES) @@ -3997,30 +3996,35 @@ CURLcode Curl_bump_headersize(struct Curl_easy *data, */ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, struct connectdata *conn, - const char *buf, size_t blen, - size_t *pconsumed) + ssize_t *nread, + bool *stop_reading) { CURLcode result; struct SingleRequest *k = &data->req; + ssize_t onread = *nread; + char *ostr = k->str; char *headp; + char *str_start; char *end_ptr; /* header line within buffer loop */ - *pconsumed = 0; do { - size_t line_length; + size_t rest_length; + size_t full_length; int writetype; + /* str_start is start of line within buf */ + str_start = k->str; + /* data is in network encoding so use 0x0a instead of '\n' */ - end_ptr = memchr(buf, 0x0a, blen); + end_ptr = memchr(str_start, 0x0a, *nread); if(!end_ptr) { /* Not a complete header line within buffer, append the data to the end of the headerbuff. */ - result = Curl_dyn_addn(&data->state.headerb, buf, blen); + result = Curl_dyn_addn(&data->state.headerb, str_start, *nread); if(result) return result; - *pconsumed += blen; if(!k->headerline) { /* check if this looks like a protocol header */ @@ -4032,28 +4036,31 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, if(st == STATUS_BAD) { /* this is not the beginning of a protocol first header line */ k->header = FALSE; - k->badheader = TRUE; + k->badheader = HEADER_ALLBAD; streamclose(conn, "bad HTTP: No end-of-message indicator"); if(!data->set.http09_allowed) { failf(data, "Received HTTP/0.9 when not allowed"); return CURLE_UNSUPPORTED_PROTOCOL; } - goto out; + break; } } - goto out; /* read more and try again */ + + break; /* read more and try again */ } /* decrease the size of the remaining (supposed) header line */ - line_length = (end_ptr - buf) + 1; - result = Curl_dyn_addn(&data->state.headerb, buf, line_length); + rest_length = (end_ptr - k->str) + 1; + *nread -= (ssize_t)rest_length; + + k->str = end_ptr + 1; /* move past new line */ + + full_length = k->str - str_start; + + result = Curl_dyn_addn(&data->state.headerb, str_start, full_length); if(result) return result; - blen -= line_length; - buf += line_length; - *pconsumed += line_length; - /**** * We now have a FULL header line in 'headerb'. *****/ @@ -4071,12 +4078,14 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, return CURLE_UNSUPPORTED_PROTOCOL; } k->header = FALSE; - if(blen) + if(*nread) /* since there's more, this is a partial bad header */ - k->badheader = TRUE; + k->badheader = HEADER_PARTHEADER; else { /* this was all we read so it's all a bad header */ - k->badheader = TRUE; + k->badheader = HEADER_ALLBAD; + *nread = onread; + k->str = ostr; return CURLE_OK; } break; @@ -4130,23 +4139,22 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, /* switch to http2 now. The bytes after response headers are also processed here, otherwise they are lost. */ - result = Curl_http2_upgrade(data, conn, FIRSTSOCKET, buf, blen); + result = Curl_http2_upgrade(data, conn, FIRSTSOCKET, + k->str, *nread); if(result) return result; - *pconsumed += blen; - blen = 0; + *nread = 0; } #ifdef USE_WEBSOCKETS else if(k->upgr101 == UPGR101_WS) { /* verify the response */ - result = Curl_ws_accept(data, buf, blen); + result = Curl_ws_accept(data, k->str, *nread); if(result) return result; k->header = FALSE; /* no more header to parse! */ if(data->set.connect_only) { k->keepon &= ~KEEP_RECV; /* read no more content */ - *pconsumed += blen; - blen = 0; + *nread = 0; } } #endif @@ -4358,7 +4366,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, * out and return home. */ if(data->req.no_body) - k->download_done = TRUE; + *stop_reading = TRUE; #ifndef CURL_DISABLE_RTSP else if((conn->handler->protocol & CURLPROTO_RTSP) && (data->set.rtspreq == RTSPREQ_DESCRIBE) && @@ -4367,7 +4375,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, absent, a length 0 must be assumed. It will prevent libcurl from hanging on DESCRIBE request that got refused for whatever reason */ - k->download_done = TRUE; + *stop_reading = TRUE; #endif /* If max download size is *zero* (nothing) we already have @@ -4378,12 +4386,15 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, if(0 == k->maxdownload && !Curl_conn_is_http2(data, conn, FIRSTSOCKET) && !Curl_conn_is_http3(data, conn, FIRSTSOCKET)) - k->download_done = TRUE; + *stop_reading = TRUE; - Curl_debug(data, CURLINFO_HEADER_IN, - Curl_dyn_ptr(&data->state.headerb), - Curl_dyn_len(&data->state.headerb)); - goto out; /* exit header line loop */ + if(*stop_reading) { + /* we make sure that this socket isn't read more now */ + k->keepon &= ~KEEP_RECV; + } + + Curl_debug(data, CURLINFO_HEADER_IN, str_start, headerlen); + break; /* exit header line loop */ } /* We continue reading headers, reset the line-based header */ @@ -4572,12 +4583,12 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, Curl_dyn_reset(&data->state.headerb); } - while(blen); + while(*k->str); /* header line within buffer */ /* We might have reached the end of the header part here, but there might be a non-header part left in the end of the read buffer. */ -out: + return CURLE_OK; } @@ -4607,6 +4618,17 @@ out: return result; } +/* simple implementation of strndup(), which isn't portable */ +static char *my_strndup(const char *ptr, size_t len) +{ + char *copy = malloc(len + 1); + if(!copy) + return NULL; + memcpy(copy, ptr, len); + copy[len] = '\0'; + return copy; +} + CURLcode Curl_http_req_make(struct httpreq **preq, const char *method, size_t m_len, const char *scheme, size_t s_len, @@ -4625,17 +4647,17 @@ CURLcode Curl_http_req_make(struct httpreq **preq, goto out; memcpy(req->method, method, m_len); if(scheme) { - req->scheme = Curl_strndup(scheme, s_len); + req->scheme = my_strndup(scheme, s_len); if(!req->scheme) goto out; } if(authority) { - req->authority = Curl_strndup(authority, a_len); + req->authority = my_strndup(authority, a_len); if(!req->authority) goto out; } if(path) { - req->path = Curl_strndup(path, p_len); + req->path = my_strndup(path, p_len); if(!req->path) goto out; } diff --git a/deps/curl/lib/http.h b/deps/curl/lib/http.h index 56b09130..9ee3c653 100644 --- a/deps/curl/lib/http.h +++ b/deps/curl/lib/http.h @@ -227,8 +227,8 @@ CURLcode Curl_http_size(struct Curl_easy *data); CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, struct connectdata *conn, - const char *buf, size_t blen, - size_t *pconsumed); + ssize_t *nread, + bool *stop_reading); /** * Curl_http_output_auth() setups the authentication headers for the @@ -263,7 +263,7 @@ CURLcode Curl_http_decode_status(int *pstatus, const char *s, size_t len); * All about a core HTTP request, excluding body and trailers */ struct httpreq { - char method[24]; + char method[12]; char *scheme; char *authority; char *path; diff --git a/deps/curl/lib/http2.c b/deps/curl/lib/http2.c index 97384848..c8b05949 100644 --- a/deps/curl/lib/http2.c +++ b/deps/curl/lib/http2.c @@ -107,14 +107,14 @@ static int populate_settings(nghttp2_settings_entry *iv, return 3; } -static ssize_t populate_binsettings(uint8_t *binsettings, - struct Curl_easy *data) +static size_t populate_binsettings(uint8_t *binsettings, + struct Curl_easy *data) { nghttp2_settings_entry iv[H2_SETTINGS_IV_LEN]; int ivlen; ivlen = populate_settings(iv, data); - /* this returns number of bytes it wrote or a negative number on error. */ + /* this returns number of bytes it wrote */ return nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN, iv, ivlen); } @@ -369,15 +369,12 @@ static ssize_t nw_out_writer(void *writer_ctx, { struct Curl_cfilter *cf = writer_ctx; struct Curl_easy *data = CF_DATA_CURRENT(cf); + ssize_t nwritten; - if(data) { - ssize_t nwritten = Curl_conn_cf_send(cf->next, data, - (const char *)buf, buflen, err); - if(nwritten > 0) - CURL_TRC_CF(data, cf, "[0] egress: wrote %zd bytes", nwritten); - return nwritten; - } - return 0; + nwritten = Curl_conn_cf_send(cf->next, data, (const char *)buf, buflen, err); + if(nwritten > 0) + CURL_TRC_CF(data, cf, "[0] egress: wrote %zd bytes", nwritten); + return nwritten; } static ssize_t send_callback(nghttp2_session *h2, @@ -455,14 +452,9 @@ static CURLcode cf_h2_ctx_init(struct Curl_cfilter *cf, * in the H1 request and we upgrade from there. This stream * is opened implicitly as #1. */ uint8_t binsettings[H2_BINSETTINGS_LEN]; - ssize_t binlen; /* length of the binsettings data */ + size_t binlen; /* length of the binsettings data */ binlen = populate_binsettings(binsettings, data); - if(binlen <= 0) { - failf(data, "nghttp2 unexpectedly failed on pack_settings_payload"); - result = CURLE_FAILED_INIT; - goto out; - } result = http2_data_setup(cf, data, &stream); if(result) @@ -1084,11 +1076,16 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf, stream->reset = TRUE; } stream->send_closed = TRUE; + data->req.keepon &= ~KEEP_SEND_HOLD; drain_stream(cf, data, stream); break; case NGHTTP2_WINDOW_UPDATE: - if(CURL_WANT_SEND(data)) { + if((data->req.keepon & KEEP_SEND_HOLD) && + (data->req.keepon & KEEP_SEND)) { + data->req.keepon &= ~KEEP_SEND_HOLD; drain_stream(cf, data, stream); + CURL_TRC_CF(data, cf, "[%d] un-holding after win update", + stream_id); } break; default: @@ -1233,10 +1230,15 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, * window and *assume* that we treat this like a WINDOW_UPDATE. Some * servers send an explicit WINDOW_UPDATE, but not all seem to do that. * To be safe, we UNHOLD a stream in order not to stall. */ - if(CURL_WANT_SEND(data)) { + if((data->req.keepon & KEEP_SEND_HOLD) && + (data->req.keepon & KEEP_SEND)) { struct stream_ctx *stream = H2_STREAM_CTX(data); - if(stream) + data->req.keepon &= ~KEEP_SEND_HOLD; + if(stream) { drain_stream(cf, data, stream); + CURL_TRC_CF(data, cf, "[%d] un-holding after SETTINGS", + stream_id); + } } } break; @@ -1336,6 +1338,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id, stream->error = error_code; if(stream->error) stream->reset = TRUE; + data_s->req.keepon &= ~KEEP_SEND_HOLD; if(stream->error) CURL_TRC_CF(data_s, cf, "[%d] RESET: %s (err %d)", @@ -1599,10 +1602,10 @@ static int error_callback(nghttp2_session *session, size_t len, void *userp) { - struct Curl_cfilter *cf = userp; - struct Curl_easy *data = CF_DATA_CURRENT(cf); (void)session; - failf(data, "%.*s", (int)len, msg); + (void)msg; + (void)len; + (void)userp; return 0; } #endif @@ -1618,7 +1621,7 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req, size_t blen; struct SingleRequest *k = &data->req; uint8_t binsettings[H2_BINSETTINGS_LEN]; - ssize_t binlen; /* length of the binsettings data */ + size_t binlen; /* length of the binsettings data */ binlen = populate_binsettings(binsettings, data); if(binlen <= 0) { @@ -2049,13 +2052,23 @@ static ssize_t h2_submit(struct stream_ctx **pstream, /* no longer needed */ Curl_h1_req_parse_free(&stream->h1); - nva = Curl_dynhds_to_nva(&h2_headers, &nheader); + nheader = Curl_dynhds_count(&h2_headers); + nva = malloc(sizeof(nghttp2_nv) * nheader); if(!nva) { *err = CURLE_OUT_OF_MEMORY; nwritten = -1; goto out; } + for(i = 0; i < nheader; ++i) { + struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i); + nva[i].name = (unsigned char *)e->name; + nva[i].namelen = e->namelen; + nva[i].value = (unsigned char *)e->value; + nva[i].valuelen = e->valuelen; + nva[i].flags = NGHTTP2_NV_FLAG_NONE; + } + h2_pri_spec(data, &pri_spec); if(!nghttp2_session_check_request_allowed(ctx->h2)) CURL_TRC_CF(data, cf, "send request NOT allowed (via nghttp2)"); @@ -2259,6 +2272,14 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data, * frame buffer or our network out buffer. */ size_t rwin = nghttp2_session_get_stream_remote_window_size(ctx->h2, stream->id); + if(rwin == 0) { + /* H2 flow window exhaustion. We need to HOLD upload until we get + * a WINDOW_UPDATE from the server. */ + data->req.keepon |= KEEP_SEND_HOLD; + CURL_TRC_CF(data, cf, "[%d] holding send as remote flow " + "window is exhausted", stream->id); + } + /* Whatever the cause, we need to return CURL_EAGAIN for this call. * We have unwritten state that needs us being invoked again and EAGAIN * is the only way to ensure that. */ @@ -2310,34 +2331,38 @@ out: return nwritten; } -static void cf_h2_adjust_pollset(struct Curl_cfilter *cf, - struct Curl_easy *data, - struct easy_pollset *ps) +static int cf_h2_get_select_socks(struct Curl_cfilter *cf, + struct Curl_easy *data, + curl_socket_t *sock) { struct cf_h2_ctx *ctx = cf->ctx; - bool want_recv = CURL_WANT_RECV(data); - bool want_send = CURL_WANT_SEND(data); + struct SingleRequest *k = &data->req; + struct stream_ctx *stream = H2_STREAM_CTX(data); + int bitmap = GETSOCK_BLANK; + struct cf_call_data save; - if(ctx->h2 && (want_recv || want_send)) { - struct stream_ctx *stream = H2_STREAM_CTX(data); - curl_socket_t sock = Curl_conn_cf_get_socket(cf, data); - struct cf_call_data save; - bool c_exhaust, s_exhaust; + CF_DATA_SAVE(save, cf, data); + sock[0] = Curl_conn_cf_get_socket(cf, data); - CF_DATA_SAVE(save, cf, data); - c_exhaust = !nghttp2_session_get_remote_window_size(ctx->h2); - s_exhaust = stream && stream->id >= 0 && - !nghttp2_session_get_stream_remote_window_size(ctx->h2, - stream->id); - want_recv = (want_recv || c_exhaust || s_exhaust); - want_send = (!s_exhaust && want_send) || - (!c_exhaust && nghttp2_session_want_write(ctx->h2)); + if(!(k->keepon & (KEEP_RECV_PAUSE|KEEP_RECV_HOLD))) + /* Unless paused - in an HTTP/2 connection we can basically always get a + frame so we should always be ready for one */ + bitmap |= GETSOCK_READSOCK(0); - Curl_pollset_set(data, ps, sock, want_recv, want_send); - CF_DATA_RESTORE(cf, save); - } + /* we're (still uploading OR the HTTP/2 layer wants to send data) AND + there's a window to send data in */ + if((((k->keepon & KEEP_SENDBITS) == KEEP_SEND) || + nghttp2_session_want_write(ctx->h2)) && + (nghttp2_session_get_remote_window_size(ctx->h2) && + nghttp2_session_get_stream_remote_window_size(ctx->h2, + stream->id))) + bitmap |= GETSOCK_WRITESOCK(0); + + CF_DATA_RESTORE(cf, save); + return bitmap; } + static CURLcode cf_h2_connect(struct Curl_cfilter *cf, struct Curl_easy *data, bool blocking, bool *done) @@ -2486,15 +2511,14 @@ static CURLcode cf_h2_cntrl(struct Curl_cfilter *cf, case CF_CTRL_DATA_PAUSE: result = http2_data_pause(cf, data, (arg1 != 0)); break; - case CF_CTRL_DATA_DONE_SEND: + case CF_CTRL_DATA_DONE_SEND: { result = http2_data_done_send(cf, data); break; - case CF_CTRL_DATA_DETACH: - http2_data_done(cf, data, TRUE); - break; - case CF_CTRL_DATA_DONE: + } + case CF_CTRL_DATA_DONE: { http2_data_done(cf, data, arg1 != 0); break; + } default: break; } @@ -2582,7 +2606,7 @@ struct Curl_cftype Curl_cft_nghttp2 = { cf_h2_connect, cf_h2_close, Curl_cf_def_get_host, - cf_h2_adjust_pollset, + cf_h2_get_select_socks, cf_h2_data_pending, cf_h2_send, cf_h2_recv, @@ -2602,7 +2626,7 @@ static CURLcode http2_cfilter_add(struct Curl_cfilter **pcf, CURLcode result = CURLE_OUT_OF_MEMORY; DEBUGASSERT(data->conn); - ctx = calloc(1, sizeof(*ctx)); + ctx = calloc(sizeof(*ctx), 1); if(!ctx) goto out; @@ -2628,7 +2652,7 @@ static CURLcode http2_cfilter_insert_after(struct Curl_cfilter *cf, CURLcode result = CURLE_OUT_OF_MEMORY; (void)data; - ctx = calloc(1, sizeof(*ctx)); + ctx = calloc(sizeof(*ctx), 1); if(!ctx) goto out; diff --git a/deps/curl/lib/http_aws_sigv4.c b/deps/curl/lib/http_aws_sigv4.c index b673055f..901c22fb 100644 --- a/deps/curl/lib/http_aws_sigv4.c +++ b/deps/curl/lib/http_aws_sigv4.c @@ -456,7 +456,6 @@ static CURLcode canon_query(struct Curl_easy *data, for(i = 0; !result && (i < entry); i++, ap++) { size_t len; const char *q = ap->p; - bool found_equals = false; if(!ap->len) continue; for(len = ap->len; len && !result; q++, len--) { @@ -468,13 +467,9 @@ static CURLcode canon_query(struct Curl_easy *data, case '.': case '_': case '~': - /* allowed as-is */ - result = Curl_dyn_addn(dq, q, 1); - break; case '=': /* allowed as-is */ result = Curl_dyn_addn(dq, q, 1); - found_equals = true; break; case '%': /* uppercase the following if hexadecimal */ @@ -502,11 +497,7 @@ static CURLcode canon_query(struct Curl_easy *data, } } } - if(!result && !found_equals) { - /* queries without value still need an equals */ - result = Curl_dyn_addn(dq, "=", 1); - } - if(!result && i < entry - 1) { + if(i < entry - 1) { /* insert ampersands between query pairs */ result = Curl_dyn_addn(dq, "&", 1); } diff --git a/deps/curl/lib/http_chunks.c b/deps/curl/lib/http_chunks.c index acdb1086..2a401d14 100644 --- a/deps/curl/lib/http_chunks.c +++ b/deps/curl/lib/http_chunks.c @@ -75,6 +75,8 @@ */ +#define isxdigit_ascii(x) Curl_isxdigit(x) + void Curl_httpchunk_init(struct Curl_easy *data) { struct connectdata *conn = data->conn; @@ -96,9 +98,9 @@ void Curl_httpchunk_init(struct Curl_easy *data) * For example, 0x0d and 0x0a are used instead of '\r' and '\n'. */ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, - char *buf, - size_t blen, - size_t *pconsumed, + char *datap, + ssize_t datalen, + ssize_t *wrote, CURLcode *extrap) { CURLcode result = CURLE_OK; @@ -106,27 +108,28 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, struct Curl_chunker *ch = &conn->chunk; struct SingleRequest *k = &data->req; size_t piece; + curl_off_t length = (curl_off_t)datalen; - *pconsumed = 0; /* nothing's written yet */ + *wrote = 0; /* nothing's written yet */ /* the original data is written to the client, but we go on with the chunk read process, to properly calculate the content length */ if(data->set.http_te_skip && !k->ignorebody) { - result = Curl_client_write(data, CLIENTWRITE_BODY, buf, blen); + result = Curl_client_write(data, CLIENTWRITE_BODY, datap, datalen); if(result) { *extrap = result; return CHUNKE_PASSTHRU_ERROR; } } - while(blen) { + while(length) { switch(ch->state) { case CHUNK_HEX: - if(ISXDIGIT(*buf)) { + if(ISXDIGIT(*datap)) { if(ch->hexindex < CHUNK_MAXNUM_LEN) { - ch->hexbuffer[ch->hexindex] = *buf; - buf++; - blen--; + ch->hexbuffer[ch->hexindex] = *datap; + datap++; + length--; ch->hexindex++; } else { @@ -140,7 +143,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, a hexadecimal digit. */ return CHUNKE_ILLEGAL_HEX; - /* blen and buf are unmodified */ + /* length and datap are unmodified */ ch->hexbuffer[ch->hexindex] = 0; if(curlx_strtoofft(ch->hexbuffer, &endptr, 16, &ch->datasize)) @@ -151,7 +154,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, case CHUNK_LF: /* waiting for the LF after a chunk size */ - if(*buf == 0x0a) { + if(*datap == 0x0a) { /* we're now expecting data to come, unless size was zero! */ if(0 == ch->datasize) { ch->state = CHUNK_TRAILER; /* now check for trailers */ @@ -160,21 +163,19 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, ch->state = CHUNK_DATA; } - buf++; - blen--; + datap++; + length--; break; case CHUNK_DATA: - /* We expect 'datasize' of data. We have 'blen' right now, it can be + /* We expect 'datasize' of data. We have 'length' right now, it can be more or less than 'datasize'. Get the smallest piece. */ - piece = blen; - if(ch->datasize < (curl_off_t)blen) - piece = curlx_sotouz(ch->datasize); + piece = curlx_sotouz((ch->datasize >= length)?length:ch->datasize); /* Write the data portion available */ if(!data->set.http_te_skip && !k->ignorebody) { - result = Curl_client_write(data, CLIENTWRITE_BODY, buf, piece); + result = Curl_client_write(data, CLIENTWRITE_BODY, datap, piece); if(result) { *extrap = result; @@ -182,10 +183,10 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, } } - *pconsumed += piece; + *wrote += piece; ch->datasize -= piece; /* decrease amount left to expect */ - buf += piece; /* move read pointer forward */ - blen -= piece; /* decrease space left in this round */ + datap += piece; /* move read pointer forward */ + length -= piece; /* decrease space left in this round */ if(0 == ch->datasize) /* end of data this round, we now expect a trailing CRLF */ @@ -193,18 +194,18 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, break; case CHUNK_POSTLF: - if(*buf == 0x0a) { + if(*datap == 0x0a) { /* The last one before we go back to hex state and start all over. */ Curl_httpchunk_init(data); /* sets state back to CHUNK_HEX */ } - else if(*buf != 0x0d) + else if(*datap != 0x0d) return CHUNKE_BAD_CHUNK; - buf++; - blen--; + datap++; + length--; break; case CHUNK_TRAILER: - if((*buf == 0x0d) || (*buf == 0x0a)) { + if((*datap == 0x0d) || (*datap == 0x0a)) { char *tr = Curl_dyn_ptr(&conn->trailer); /* this is the end of a trailer, but if the trailer was zero bytes there was no trailer and we move on */ @@ -228,7 +229,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, } Curl_dyn_reset(&conn->trailer); ch->state = CHUNK_TRAILER_CR; - if(*buf == 0x0a) + if(*datap == 0x0a) /* already on the LF */ break; } @@ -239,19 +240,19 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, } } else { - result = Curl_dyn_addn(&conn->trailer, buf, 1); + result = Curl_dyn_addn(&conn->trailer, datap, 1); if(result) return CHUNKE_OUT_OF_MEMORY; } - buf++; - blen--; + datap++; + length--; break; case CHUNK_TRAILER_CR: - if(*buf == 0x0a) { + if(*datap == 0x0a) { ch->state = CHUNK_TRAILER_POSTCR; - buf++; - blen--; + datap++; + length--; } else return CHUNKE_BAD_CHUNK; @@ -260,27 +261,27 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, case CHUNK_TRAILER_POSTCR: /* We enter this state when a CR should arrive so we expect to have to first pass a CR before we wait for LF */ - if((*buf != 0x0d) && (*buf != 0x0a)) { + if((*datap != 0x0d) && (*datap != 0x0a)) { /* not a CR then it must be another header in the trailer */ ch->state = CHUNK_TRAILER; break; } - if(*buf == 0x0d) { + if(*datap == 0x0d) { /* skip if CR */ - buf++; - blen--; + datap++; + length--; } /* now wait for the final LF */ ch->state = CHUNK_STOP; break; case CHUNK_STOP: - if(*buf == 0x0a) { - blen--; + if(*datap == 0x0a) { + length--; /* Record the length of any data left in the end of the buffer even if there's no more chunks to read */ - ch->datasize = blen; + ch->datasize = curlx_sotouz(length); return CHUNKE_STOP; /* return stop */ } diff --git a/deps/curl/lib/http_chunks.h b/deps/curl/lib/http_chunks.h index 0a36f379..ed507131 100644 --- a/deps/curl/lib/http_chunks.h +++ b/deps/curl/lib/http_chunks.h @@ -93,8 +93,8 @@ struct Curl_chunker { /* The following functions are defined in http_chunks.c */ void Curl_httpchunk_init(struct Curl_easy *data); -CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, char *buf, - size_t blen, size_t *pconsumed, +CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, char *datap, + ssize_t length, ssize_t *wrote, CURLcode *passthru); #endif /* HEADER_CURL_HTTP_CHUNKS_H */ diff --git a/deps/curl/lib/http_proxy.c b/deps/curl/lib/http_proxy.c index 8e183258..a1d6da95 100644 --- a/deps/curl/lib/http_proxy.c +++ b/deps/curl/lib/http_proxy.c @@ -299,7 +299,7 @@ struct Curl_cftype Curl_cft_http_proxy = { http_proxy_cf_connect, http_proxy_cf_close, Curl_cf_http_proxy_get_host, - Curl_cf_def_adjust_pollset, + Curl_cf_def_get_select_socks, Curl_cf_def_data_pending, Curl_cf_def_send, Curl_cf_def_recv, diff --git a/deps/curl/lib/idn.c b/deps/curl/lib/idn.c index 81a177f8..a024691d 100644 --- a/deps/curl/lib/idn.c +++ b/deps/curl/lib/idn.c @@ -36,7 +36,7 @@ #ifdef USE_LIBIDN2 #include -#if defined(_WIN32) && defined(UNICODE) +#if defined(WIN32) && defined(UNICODE) #define IDN2_LOOKUP(name, host, flags) \ idn2_lookup_u8((const uint8_t *)name, (uint8_t **)host, flags) #else diff --git a/deps/curl/lib/imap.c b/deps/curl/lib/imap.c index 47cff489..de64c2a7 100644 --- a/deps/curl/lib/imap.c +++ b/deps/curl/lib/imap.c @@ -1194,6 +1194,8 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data, if(result) return result; + data->req.bytecount += chunk; + infof(data, "Written %zu bytes, %" CURL_FORMAT_CURL_OFF_TU " bytes are left for transfer", chunk, size - chunk); @@ -1428,7 +1430,7 @@ static CURLcode imap_init(struct Curl_easy *data) CURLcode result = CURLE_OK; struct IMAP *imap; - imap = data->req.p.imap = calloc(1, sizeof(struct IMAP)); + imap = data->req.p.imap = calloc(sizeof(struct IMAP), 1); if(!imap) result = CURLE_OUT_OF_MEMORY; diff --git a/deps/curl/lib/ldap.c b/deps/curl/lib/ldap.c index eb5fe795..239d3fbf 100644 --- a/deps/curl/lib/ldap.c +++ b/deps/curl/lib/ldap.c @@ -313,6 +313,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) int ldap_ssl = 0; char *val_b64 = NULL; size_t val_b64_sz = 0; + curl_off_t dlsize = 0; #ifdef LDAP_OPT_NETWORK_TIMEOUT struct timeval ldap_timeout = {10, 0}; /* 10 sec connection/search timeout */ #endif @@ -326,7 +327,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) *done = TRUE; /* unconditionally */ infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d", - LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION); + LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION); infof(data, "LDAP local: %s", data->state.url); #ifdef HAVE_LDAP_URL_PARSE @@ -344,7 +345,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) if(conn->given->flags & PROTOPT_SSL) ldap_ssl = 1; infof(data, "LDAP local: trying to establish %s connection", - ldap_ssl ? "encrypted" : "cleartext"); + ldap_ssl ? "encrypted" : "cleartext"); #if defined(USE_WIN32_LDAP) host = curlx_convert_UTF8_to_tchar(conn->host.name); @@ -534,7 +535,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) goto quit; } - Curl_pgrsSetDownloadCounter(data, 0); rc = ldap_search_s(server, ludp->lud_dn, ludp->lud_scope, ludp->lud_filter, ludp->lud_attrs, 0, &ldapmsg); @@ -596,6 +596,8 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) goto quit; } + dlsize += name_len + 5; + FREE_ON_WINLDAP(name); ldap_memfree(dn); } @@ -657,6 +659,8 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) goto quit; } + dlsize += attr_len + 3; + if((attr_len > 7) && (strcmp(";binary", attr + (attr_len - 7)) == 0)) { /* Binary attribute, encode to base64. */ @@ -685,6 +689,8 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) goto quit; } + + dlsize += val_b64_sz; } } else { @@ -699,6 +705,8 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) goto quit; } + + dlsize += vals[i]->bv_len; } result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1); @@ -711,6 +719,8 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) goto quit; } + + dlsize++; } /* Free memory used to store values */ @@ -724,6 +734,10 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1); if(result) goto quit; + dlsize++; + result = Curl_pgrsSetDownloadCounter(data, dlsize); + if(result) + goto quit; } if(ber) diff --git a/deps/curl/lib/md4.c b/deps/curl/lib/md4.c index 486e5fa6..30ab62e6 100644 --- a/deps/curl/lib/md4.c +++ b/deps/curl/lib/md4.c @@ -32,8 +32,9 @@ #include "warnless.h" #ifdef USE_OPENSSL -#include -#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) && !defined(USE_AMISSL) +#include +#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) && \ + !defined(USE_AMISSL) /* OpenSSL 3.0.0 marks the MD4 functions as deprecated */ #define OPENSSL_NO_MD4 #endif diff --git a/deps/curl/lib/memdebug.c b/deps/curl/lib/memdebug.c index f6ced85c..d6952a07 100644 --- a/deps/curl/lib/memdebug.c +++ b/deps/curl/lib/memdebug.c @@ -208,7 +208,7 @@ ALLOC_FUNC char *curl_dbg_strdup(const char *str, return mem; } -#if defined(_WIN32) && defined(UNICODE) +#if defined(WIN32) && defined(UNICODE) ALLOC_FUNC wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line, const char *source) { diff --git a/deps/curl/lib/memdebug.h b/deps/curl/lib/memdebug.h index 78a01258..c9eb5dc3 100644 --- a/deps/curl/lib/memdebug.h +++ b/deps/curl/lib/memdebug.h @@ -64,7 +64,7 @@ CURL_EXTERN ALLOC_SIZE(2) void *curl_dbg_realloc(void *ptr, CURL_EXTERN void curl_dbg_free(void *ptr, int line, const char *source); CURL_EXTERN ALLOC_FUNC char *curl_dbg_strdup(const char *str, int line, const char *src); -#if defined(_WIN32) && defined(UNICODE) +#if defined(WIN32) && defined(UNICODE) CURL_EXTERN ALLOC_FUNC wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line, const char *source); @@ -121,7 +121,7 @@ CURL_EXTERN int curl_dbg_fclose(FILE *file, int line, const char *source); #define send(a,b,c,d) curl_dbg_send(a,b,c,d, __LINE__, __FILE__) #define recv(a,b,c,d) curl_dbg_recv(a,b,c,d, __LINE__, __FILE__) -#ifdef _WIN32 +#ifdef WIN32 # ifdef UNICODE # undef wcsdup # define wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__) diff --git a/deps/curl/lib/mime.c b/deps/curl/lib/mime.c index bb66130a..3b27e59e 100644 --- a/deps/curl/lib/mime.c +++ b/deps/curl/lib/mime.c @@ -48,7 +48,7 @@ #include "curl_memory.h" #include "memdebug.h" -#ifdef _WIN32 +#ifdef WIN32 # ifndef R_OK # define R_OK 4 # endif @@ -311,7 +311,8 @@ static char *escape_string(struct Curl_easy *data, table = formtable; /* data can be NULL when this function is called indirectly from curl_formget(). */ - if(strategy == MIMESTRATEGY_MAIL || (data && (data->set.mime_formescape))) + if(strategy == MIMESTRATEGY_MAIL || + (data && (data->set.mime_options & CURLMIMEOPT_FORMESCAPE))) table = mimetable; Curl_dyn_init(&db, CURL_MAX_INPUT_LENGTH); diff --git a/deps/curl/lib/mprintf.c b/deps/curl/lib/mprintf.c index 6b5df5bd..af5d753d 100644 --- a/deps/curl/lib/mprintf.c +++ b/deps/curl/lib/mprintf.c @@ -66,7 +66,9 @@ * Non-ANSI integer extensions */ -#if (defined(_WIN32_WCE)) || \ +#if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x520)) || \ + (defined(__POCC__) && defined(_MSC_VER)) || \ + (defined(_WIN32_WCE)) || \ (defined(__MINGW32__)) || \ (defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)) # define MP_HAVE_INT_EXTENSIONS @@ -1069,6 +1071,9 @@ static int alloc_addbyter(int output, FILE *data) return outc; /* fputc() returns like this on success */ } +extern int Curl_dyn_vprintf(struct dynbuf *dyn, + const char *format, va_list ap_save); + /* appends the formatted string, returns 0 on success, 1 on error */ int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save) { diff --git a/deps/curl/lib/mqtt.c b/deps/curl/lib/mqtt.c index 366235c5..54f88822 100644 --- a/deps/curl/lib/mqtt.c +++ b/deps/curl/lib/mqtt.c @@ -616,6 +616,9 @@ static void mqstate(struct Curl_easy *data, } +/* for the publish packet */ +#define MQTT_HEADER_LEN 5 /* max 5 bytes */ + static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; @@ -674,6 +677,7 @@ MQTT_SUBACK_COMING: /* FALLTHROUGH */ case MQTT_PUB_REMAIN: { /* read rest of packet, but no more. Cap to buffer size */ + struct SingleRequest *k = &data->req; size_t rest = mq->npacket; if(rest > (size_t)data->set.buffer_size) rest = (size_t)data->set.buffer_size; @@ -689,8 +693,13 @@ MQTT_SUBACK_COMING: result = CURLE_PARTIAL_FILE; goto end; } + Curl_debug(data, CURLINFO_DATA_IN, (char *)pkt, (size_t)nread); mq->npacket -= nread; + k->bytecount += nread; + result = Curl_pgrsSetDownloadCounter(data, k->bytecount); + if(result) + goto end; /* if QoS is set, message contains packet id */ diff --git a/deps/curl/lib/multi.c b/deps/curl/lib/multi.c index 5456113b..ff753ac8 100644 --- a/deps/curl/lib/multi.c +++ b/deps/curl/lib/multi.c @@ -55,6 +55,22 @@ #include "curl_memory.h" #include "memdebug.h" +#ifdef __APPLE__ + +#define wakeup_write write +#define wakeup_read read +#define wakeup_close close +#define wakeup_create pipe + +#else /* __APPLE__ */ + +#define wakeup_write swrite +#define wakeup_read sread +#define wakeup_close sclose +#define wakeup_create(p) Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, p) + +#endif /* __APPLE__ */ + /* CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97 to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every @@ -215,6 +231,10 @@ struct Curl_sh_entry { unsigned int readers; /* this many transfers want to read */ unsigned int writers; /* this many transfers want to write */ }; +/* bits for 'action' having no bits means this socket is not expecting any + action */ +#define SH_READ 1 +#define SH_WRITE 2 /* look up a given socket in the socket hash, skip invalid sockets */ static struct Curl_sh_entry *sh_getentry(struct Curl_hash *sh, @@ -396,6 +416,9 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ Curl_llist_init(&multi->msgsent, NULL); multi->multiplexing = TRUE; + + /* -1 means it not set by user, use the default value */ + multi->maxconnects = -1; multi->max_concurrent_streams = 100; #ifdef USE_WINSOCK @@ -1017,61 +1040,49 @@ static int protocol_getsock(struct Curl_easy *data, { if(conn->handler->proto_getsock) return conn->handler->proto_getsock(data, conn, socks); - return GETSOCK_BLANK; + return Curl_conn_get_select_socks(data, FIRSTSOCKET, socks); } -/* Initializes `poll_set` with the current socket poll actions needed - * for transfer `data`. */ -static void multi_getsock(struct Curl_easy *data, - struct easy_pollset *ps) +/* returns bitmapped flags for this handle and its sockets. The 'socks[]' + array contains MAX_SOCKSPEREASYHANDLE entries. */ +static int multi_getsock(struct Curl_easy *data, + curl_socket_t *socks) { + struct connectdata *conn = data->conn; /* The no connection case can happen when this is called from curl_multi_remove_handle() => singlesocket() => multi_getsock(). */ - Curl_pollset_reset(data, ps); - if(!data->conn) - return; + if(!conn) + return 0; switch(data->mstate) { default: - break; + return 0; case MSTATE_RESOLVING: - Curl_pollset_add_socks2(data, ps, Curl_resolv_getsock); - /* connection filters are not involved in this phase */ - return; + return Curl_resolv_getsock(data, socks); case MSTATE_PROTOCONNECTING: case MSTATE_PROTOCONNECT: - Curl_pollset_add_socks(data, ps, protocol_getsock); - break; + return protocol_getsock(data, conn, socks); case MSTATE_DO: case MSTATE_DOING: - Curl_pollset_add_socks(data, ps, doing_getsock); - break; + return doing_getsock(data, conn, socks); case MSTATE_TUNNELING: case MSTATE_CONNECTING: - break; + return Curl_conn_get_select_socks(data, FIRSTSOCKET, socks); case MSTATE_DOING_MORE: - Curl_pollset_add_socks(data, ps, domore_getsock); - break; + return domore_getsock(data, conn, socks); case MSTATE_DID: /* since is set after DO is completed, we switch to waiting for the same as the PERFORMING state */ case MSTATE_PERFORMING: - Curl_pollset_add_socks(data, ps, Curl_single_getsock); - break; - - case MSTATE_RATELIMITING: - /* nothing to wait for */ - return; + return Curl_single_getsock(data, conn, socks); } - /* Let connection filters add/remove as needed */ - Curl_conn_adjust_pollset(data, ps); } CURLMcode curl_multi_fdset(struct Curl_multi *multi, @@ -1083,8 +1094,8 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi, and then we must make sure that is done. */ struct Curl_easy *data; int this_max_fd = -1; - struct easy_pollset ps; - unsigned int i; + curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE]; + int i; (void)exc_fd_set; /* not used */ if(!GOOD_MULTI_HANDLE(multi)) @@ -1093,20 +1104,29 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi, if(multi->in_callback) return CURLM_RECURSIVE_API_CALL; - memset(&ps, 0, sizeof(ps)); for(data = multi->easyp; data; data = data->next) { - multi_getsock(data, &ps); + int bitmap; +#ifdef __clang_analyzer_ + /* to prevent "The left operand of '>=' is a garbage value" warnings */ + memset(sockbunch, 0, sizeof(sockbunch)); +#endif + bitmap = multi_getsock(data, sockbunch); - for(i = 0; i < ps.num; i++) { - if(!FDSET_SOCK(ps.sockets[i])) - /* pretend it doesn't exist */ - continue; - if(ps.actions[i] & CURL_POLL_IN) - FD_SET(ps.sockets[i], read_fd_set); - if(ps.actions[i] & CURL_POLL_OUT) - FD_SET(ps.sockets[i], write_fd_set); - if((int)ps.sockets[i] > this_max_fd) - this_max_fd = (int)ps.sockets[i]; + for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) { + if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) { + if(!FDSET_SOCK(sockbunch[i])) + /* pretend it doesn't exist */ + continue; + if(bitmap & GETSOCK_READSOCK(i)) + FD_SET(sockbunch[i], read_fd_set); + if(bitmap & GETSOCK_WRITESOCK(i)) + FD_SET(sockbunch[i], write_fd_set); + if((int)sockbunch[i] > this_max_fd) + this_max_fd = (int)sockbunch[i]; + } + else { + break; + } } } @@ -1142,8 +1162,9 @@ static CURLMcode multi_wait(struct Curl_multi *multi, bool use_wakeup) { struct Curl_easy *data; - struct easy_pollset ps; - size_t i; + curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE]; + int bitmap; + unsigned int i; unsigned int nfds = 0; unsigned int curlfds; long timeout_internal; @@ -1169,10 +1190,17 @@ static CURLMcode multi_wait(struct Curl_multi *multi, return CURLM_BAD_FUNCTION_ARGUMENT; /* Count up how many fds we have from the multi handle */ - memset(&ps, 0, sizeof(ps)); for(data = multi->easyp; data; data = data->next) { - multi_getsock(data, &ps); - nfds += ps.num; + bitmap = multi_getsock(data, sockbunch); + + for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) { + if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) { + ++nfds; + } + else { + break; + } + } } /* If the internally desired timeout is actually shorter than requested from @@ -1213,35 +1241,40 @@ static CURLMcode multi_wait(struct Curl_multi *multi, if(curlfds) { /* Add the curl handles to our pollfds first */ for(data = multi->easyp; data; data = data->next) { - multi_getsock(data, &ps); + bitmap = multi_getsock(data, sockbunch); - for(i = 0; i < ps.num; i++) { - struct pollfd *ufd = &ufds[nfds++]; + for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) { + if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) { + struct pollfd *ufd = &ufds[nfds++]; #ifdef USE_WINSOCK - long mask = 0; + long mask = 0; #endif - ufd->fd = ps.sockets[i]; - ufd->events = 0; - if(ps.actions[i] & CURL_POLL_IN) { + ufd->fd = sockbunch[i]; + ufd->events = 0; + if(bitmap & GETSOCK_READSOCK(i)) { #ifdef USE_WINSOCK - mask |= FD_READ|FD_ACCEPT|FD_CLOSE; + mask |= FD_READ|FD_ACCEPT|FD_CLOSE; +#endif + ufd->events |= POLLIN; + } + if(bitmap & GETSOCK_WRITESOCK(i)) { +#ifdef USE_WINSOCK + mask |= FD_WRITE|FD_CONNECT|FD_CLOSE; + reset_socket_fdwrite(sockbunch[i]); +#endif + ufd->events |= POLLOUT; + } +#ifdef USE_WINSOCK + if(WSAEventSelect(sockbunch[i], multi->wsa_event, mask) != 0) { + if(ufds_malloc) + free(ufds); + return CURLM_INTERNAL_ERROR; + } #endif - ufd->events |= POLLIN; } - if(ps.actions[i] & CURL_POLL_OUT) { -#ifdef USE_WINSOCK - mask |= FD_WRITE|FD_CONNECT|FD_CLOSE; - reset_socket_fdwrite(ps.sockets[i]); -#endif - ufd->events |= POLLOUT; + else { + break; } -#ifdef USE_WINSOCK - if(WSAEventSelect(ps.sockets[i], multi->wsa_event, mask) != 0) { - if(ufds_malloc) - free(ufds); - return CURLM_INTERNAL_ERROR; - } -#endif } } } @@ -1353,16 +1386,21 @@ static CURLMcode multi_wait(struct Curl_multi *multi, if(curlfds) { for(data = multi->easyp; data; data = data->next) { - multi_getsock(data, &ps); + bitmap = multi_getsock(data, sockbunch); - for(i = 0; i < ps.num; i++) { - wsa_events.lNetworkEvents = 0; - if(WSAEnumNetworkEvents(ps.sockets[i], NULL, - &wsa_events) == 0) { - if(ret && !pollrc && wsa_events.lNetworkEvents) - retcode++; + for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) { + if(bitmap & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))) { + wsa_events.lNetworkEvents = 0; + if(WSAEnumNetworkEvents(sockbunch[i], NULL, &wsa_events) == 0) { + if(ret && !pollrc && wsa_events.lNetworkEvents) + retcode++; + } + WSAEventSelect(sockbunch[i], multi->wsa_event, 0); + } + else { + /* break on entry not checked for being readable or writable */ + break; } - WSAEventSelect(ps.sockets[i], multi->wsa_event, 0); } } } @@ -1983,8 +2021,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, if(dns) { #ifdef CURLRES_ASYNCH - conn->resolve_async.dns = dns; - conn->resolve_async.done = TRUE; + data->state.async.dns = dns; + data->state.async.done = TRUE; #endif result = CURLE_OK; infof(data, "Hostname '%s' was found in DNS cache", hostname); @@ -2857,36 +2895,53 @@ CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue) static CURLMcode singlesocket(struct Curl_multi *multi, struct Curl_easy *data) { - struct easy_pollset cur_poll; - unsigned int i; + curl_socket_t socks[MAX_SOCKSPEREASYHANDLE]; + int i; struct Curl_sh_entry *entry; curl_socket_t s; + int num; + unsigned int curraction; + unsigned char actions[MAX_SOCKSPEREASYHANDLE]; int rc; + for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) + socks[i] = CURL_SOCKET_BAD; + /* Fill in the 'current' struct with the state as it is now: what sockets to supervise and for what actions */ - multi_getsock(data, &cur_poll); + curraction = multi_getsock(data, socks); /* We have 0 .. N sockets already and we get to know about the 0 .. M sockets we should have from now on. Detect the differences, remove no longer supervised ones and add new ones */ /* walk over the sockets we got right now */ - for(i = 0; i < cur_poll.num; i++) { - unsigned char cur_action = cur_poll.actions[i]; - unsigned char last_action = 0; + for(i = 0; (i< MAX_SOCKSPEREASYHANDLE) && + (curraction & GETSOCK_MASK_RW(i)); + i++) { + unsigned char action = CURL_POLL_NONE; + unsigned char prevaction = 0; int comboaction; + bool sincebefore = FALSE; - s = cur_poll.sockets[i]; + s = socks[i]; /* get it from the hash */ entry = sh_getentry(&multi->sockhash, s); + + if(curraction & GETSOCK_READSOCK(i)) + action |= CURL_POLL_IN; + if(curraction & GETSOCK_WRITESOCK(i)) + action |= CURL_POLL_OUT; + + actions[i] = action; if(entry) { /* check if new for this transfer */ - unsigned int j; - for(j = 0; j< data->last_poll.num; j++) { - if(s == data->last_poll.sockets[j]) { - last_action = data->last_poll.actions[j]; + int j; + for(j = 0; j< data->numsocks; j++) { + if(s == data->sockets[j]) { + prevaction = data->actions[j]; + sincebefore = TRUE; break; } } @@ -2898,23 +2953,23 @@ static CURLMcode singlesocket(struct Curl_multi *multi, /* fatal */ return CURLM_OUT_OF_MEMORY; } - if(last_action && (last_action != cur_action)) { + if(sincebefore && (prevaction != action)) { /* Socket was used already, but different action now */ - if(last_action & CURL_POLL_IN) + if(prevaction & CURL_POLL_IN) entry->readers--; - if(last_action & CURL_POLL_OUT) + if(prevaction & CURL_POLL_OUT) entry->writers--; - if(cur_action & CURL_POLL_IN) + if(action & CURL_POLL_IN) entry->readers++; - if(cur_action & CURL_POLL_OUT) + if(action & CURL_POLL_OUT) entry->writers++; } - else if(!last_action) { - /* a new transfer using this socket */ + else if(!sincebefore) { + /* a new user */ entry->users++; - if(cur_action & CURL_POLL_IN) + if(action & CURL_POLL_IN) entry->readers++; - if(cur_action & CURL_POLL_OUT) + if(action & CURL_POLL_OUT) entry->writers++; /* add 'data' to the transfer hash on this socket! */ @@ -2925,11 +2980,11 @@ static CURLMcode singlesocket(struct Curl_multi *multi, } } - comboaction = (entry->writers ? CURL_POLL_OUT : 0) | + comboaction = (entry->writers? CURL_POLL_OUT : 0) | (entry->readers ? CURL_POLL_IN : 0); /* socket existed before and has the same action set as before */ - if(last_action && ((int)entry->action == comboaction)) + if(sincebefore && ((int)entry->action == comboaction)) /* same, continue */ continue; @@ -2937,7 +2992,6 @@ static CURLMcode singlesocket(struct Curl_multi *multi, set_in_callback(multi, TRUE); rc = multi->socket_cb(data, s, comboaction, multi->socket_userp, entry->socketp); - set_in_callback(multi, FALSE); if(rc == -1) { multi->dead = TRUE; @@ -2948,15 +3002,16 @@ static CURLMcode singlesocket(struct Curl_multi *multi, entry->action = comboaction; /* store the current action state */ } - /* Check for last_poll.sockets that no longer appear in cur_poll.sockets. - * Need to remove the easy handle from the multi->sockhash->transfers and - * remove multi->sockhash entry when this was the last transfer */ - for(i = 0; i< data->last_poll.num; i++) { - unsigned int j; + num = i; /* number of sockets */ + + /* when we've walked over all the sockets we should have right now, we must + make sure to detect sockets that are removed */ + for(i = 0; i< data->numsocks; i++) { + int j; bool stillused = FALSE; - s = data->last_poll.sockets[i]; - for(j = 0; j < cur_poll.num; j++) { - if(s == cur_poll.sockets[j]) { + s = data->sockets[i]; + for(j = 0; j < num; j++) { + if(s == socks[j]) { /* this is still supervised */ stillused = TRUE; break; @@ -2969,7 +3024,7 @@ static CURLMcode singlesocket(struct Curl_multi *multi, /* if this is NULL here, the socket has been closed and notified so already by Curl_multi_closed() */ if(entry) { - unsigned char oldactions = data->last_poll.actions[i]; + unsigned char oldactions = data->actions[i]; /* this socket has been removed. Decrease user count */ entry->users--; if(oldactions & CURL_POLL_OUT) @@ -2997,10 +3052,11 @@ static CURLMcode singlesocket(struct Curl_multi *multi, } } } - } /* for loop over num */ + } /* for loop over numsocks */ - /* Remember for next time */ - memcpy(&data->last_poll, &cur_poll, sizeof(data->last_poll)); + memcpy(data->sockets, socks, num*sizeof(curl_socket_t)); + memcpy(data->actions, actions, num*sizeof(char)); + data->numsocks = num; return CURLM_OK; } @@ -3240,7 +3296,6 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi, { CURLMcode res = CURLM_OK; va_list param; - unsigned long uarg; if(!GOOD_MULTI_HANDLE(multi)) return CURLM_BAD_HANDLE; @@ -3273,9 +3328,7 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi, multi->timer_userp = va_arg(param, void *); break; case CURLMOPT_MAXCONNECTS: - uarg = va_arg(param, unsigned long); - if(uarg <= UINT_MAX) - multi->maxconnects = (unsigned int)uarg; + multi->maxconnects = va_arg(param, long); break; case CURLMOPT_MAX_HOST_CONNECTIONS: multi->max_host_connections = va_arg(param, long); @@ -3297,9 +3350,9 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi, case CURLMOPT_MAX_CONCURRENT_STREAMS: { long streams = va_arg(param, long); - if((streams < 1) || (streams > INT_MAX)) + if(streams < 1) streams = 100; - multi->max_concurrent_streams = (unsigned int)streams; + multi->max_concurrent_streams = curlx_sltoui(streams); } break; default: @@ -3729,11 +3782,11 @@ struct Curl_easy **curl_multi_get_handles(struct Curl_multi *multi) struct Curl_easy **a = malloc(sizeof(struct Curl_easy *) * (multi->num_easy + 1)); if(a) { - unsigned int i = 0; + int i = 0; struct Curl_easy *e = multi->easyp; while(e) { DEBUGASSERT(i < multi->num_easy); - if(!e->state.internal) + if(!e->internal) a[i++] = e; e = e->next; } diff --git a/deps/curl/lib/multihandle.h b/deps/curl/lib/multihandle.h index e03e382e..5b16bb60 100644 --- a/deps/curl/lib/multihandle.h +++ b/deps/curl/lib/multihandle.h @@ -93,9 +93,9 @@ struct Curl_multi { struct Curl_easy *easyp; struct Curl_easy *easylp; /* last node */ - unsigned int num_easy; /* amount of entries in the linked list above. */ - unsigned int num_alive; /* amount of easy handles that are added but have - not yet reached COMPLETE state */ + int num_easy; /* amount of entries in the linked list above. */ + int num_alive; /* amount of easy handles that are added but have not yet + reached COMPLETE state */ struct Curl_llist msglist; /* a list of messages from completed transfers */ @@ -136,6 +136,9 @@ struct Curl_multi { /* Shared connection cache (bundles)*/ struct conncache conn_cache; + long maxconnects; /* if >0, a fixed limit of the maximum number of entries + we're allowed to grow the connection cache to */ + long max_host_connections; /* if >0, a fixed limit of the maximum number of connections per host */ @@ -147,6 +150,8 @@ struct Curl_multi { void *timer_userp; struct curltime timer_lastcall; /* the fixed time for the timeout for the previous callback */ + unsigned int max_concurrent_streams; + #ifdef USE_WINSOCK WSAEVENT wsa_event; /* winsock event used for waits */ #else @@ -155,10 +160,6 @@ struct Curl_multi { 0 is used for read, 1 is used for write */ #endif #endif - unsigned int max_concurrent_streams; - unsigned int maxconnects; /* if >0, a fixed limit of the maximum number of - entries we're allowed to grow the connection - cache to */ #define IPV6_UNKNOWN 0 #define IPV6_DEAD 1 #define IPV6_WORKS 2 diff --git a/deps/curl/lib/netrc.c b/deps/curl/lib/netrc.c index 038c6dca..e6a09b18 100644 --- a/deps/curl/lib/netrc.c +++ b/deps/curl/lib/netrc.c @@ -327,7 +327,7 @@ int Curl_parsenetrc(const char *host, char **loginp, char **passwordp, } retcode = parsenetrc(host, loginp, passwordp, filealloc); free(filealloc); -#ifdef _WIN32 +#ifdef WIN32 if(retcode == NETRC_FILE_MISSING) { /* fallback to the old-style "_netrc" file */ filealloc = curl_maprintf("%s%s_netrc", home, DIR_CHAR); diff --git a/deps/curl/lib/openldap.c b/deps/curl/lib/openldap.c index 131f4741..3aff3060 100644 --- a/deps/curl/lib/openldap.c +++ b/deps/curl/lib/openldap.c @@ -319,12 +319,31 @@ static CURLcode oldap_setup_connection(struct Curl_easy *data, { CURLcode result; LDAPURLDesc *lud; - (void)conn; + struct ldapconninfo *li; /* Early URL syntax check. */ result = oldap_url_parse(data, &lud); ldap_free_urldesc(lud); + if(!result) { + li = calloc(1, sizeof(struct ldapconninfo)); + if(!li) + result = CURLE_OUT_OF_MEMORY; + else { + li->proto = ldap_pvt_url_scheme2proto(data->state.up.scheme); + conn->proto.ldapc = li; + connkeep(conn, "OpenLDAP default"); + + /* Initialize the SASL storage */ + Curl_sasl_init(&li->sasl, data, &saslldap); + + /* Clear the TLS upgraded flag */ + conn->bits.tls_upgraded = FALSE; + + result = oldap_parse_login_options(conn); + } + } + return result; } @@ -518,7 +537,7 @@ static CURLcode oldap_perform_starttls(struct Curl_easy *data) static CURLcode oldap_connect(struct Curl_easy *data, bool *done) { struct connectdata *conn = data->conn; - struct ldapconninfo *li; + struct ldapconninfo *li = conn->proto.ldapc; static const int version = LDAP_VERSION3; int rc; char *hosturl; @@ -528,26 +547,6 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done) (void)done; - DEBUGASSERT(!conn->proto.ldapc); - li = calloc(1, sizeof(struct ldapconninfo)); - if(!li) - return CURLE_OUT_OF_MEMORY; - else { - CURLcode result; - li->proto = ldap_pvt_url_scheme2proto(data->state.up.scheme); - conn->proto.ldapc = li; - - /* Initialize the SASL storage */ - Curl_sasl_init(&li->sasl, data, &saslldap); - - /* Clear the TLS upgraded flag */ - conn->bits.tls_upgraded = FALSE; - - result = oldap_parse_login_options(conn); - if(result) - return result; - } - hosturl = aprintf("ldap%s://%s:%d", conn->handler->flags & PROTOPT_SSL? "s": "", conn->host.name, conn->remote_port); @@ -887,11 +886,6 @@ static CURLcode oldap_do(struct Curl_easy *data, bool *done) result = oldap_url_parse(data, &lud); if(!result) { - Sockbuf *sb; - /* re-install the libcurl SSL handlers into the sockbuf. */ - ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb); - ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, data); - rc = ldap_search_ext(li->ld, lud->lud_dn, lud->lud_scope, lud->lud_filter, lud->lud_attrs, 0, NULL, NULL, NULL, 0, &msgid); @@ -953,12 +947,18 @@ static CURLcode client_write(struct Curl_easy *data, if(!len && plen && prefix[plen - 1] == ' ') plen--; result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) prefix, plen); + if(!result) + data->req.bytecount += plen; } if(!result && value) { result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) value, len); + if(!result) + data->req.bytecount += len; } if(!result && suffix) { result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) suffix, slen); + if(!result) + data->req.bytecount += slen; } return result; } diff --git a/deps/curl/lib/pop3.c b/deps/curl/lib/pop3.c index 3e0f20a6..a9d5fdd6 100644 --- a/deps/curl/lib/pop3.c +++ b/deps/curl/lib/pop3.c @@ -1088,7 +1088,7 @@ static CURLcode pop3_init(struct Curl_easy *data) CURLcode result = CURLE_OK; struct POP3 *pop3; - pop3 = data->req.p.pop3 = calloc(1, sizeof(struct POP3)); + pop3 = data->req.p.pop3 = calloc(sizeof(struct POP3), 1); if(!pop3) result = CURLE_OUT_OF_MEMORY; diff --git a/deps/curl/lib/progress.c b/deps/curl/lib/progress.c index e96cbf7a..e783a9c8 100644 --- a/deps/curl/lib/progress.c +++ b/deps/curl/lib/progress.c @@ -304,7 +304,7 @@ timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize, * 'actual' is the time in milliseconds it took to actually download the * last 'size' bytes. */ - actual = Curl_timediff_ceil(now, start); + actual = Curl_timediff(now, start); if(actual < minimum) { /* if it downloaded the data faster than the limit, make it wait the difference */ @@ -319,6 +319,12 @@ timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize, */ CURLcode Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size) { + if(data->set.max_filesize && (size > data->set.max_filesize)) { + failf(data, "Exceeded the maximum allowed file size " + "(%" CURL_FORMAT_CURL_OFF_T ")", + data->set.max_filesize); + return CURLE_FILESIZE_EXCEEDED; + } data->progress.downloaded = size; return CURLE_OK; } diff --git a/deps/curl/lib/rand.c b/deps/curl/lib/rand.c index 3383c490..6bd96136 100644 --- a/deps/curl/lib/rand.c +++ b/deps/curl/lib/rand.c @@ -32,6 +32,10 @@ #ifdef HAVE_ARPA_INET_H #include #endif +#ifdef HAVE_ARC4RANDOM +/* Some platforms might have the prototype missing (ubuntu + libressl) */ +uint32_t arc4random(void); +#endif #include #include "urldata.h" @@ -46,7 +50,7 @@ #include "curl_memory.h" #include "memdebug.h" -#ifdef _WIN32 +#ifdef WIN32 #if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600 # define HAVE_WIN_BCRYPTGENRANDOM @@ -101,6 +105,7 @@ CURLcode Curl_win32_random(unsigned char *entropy, size_t length) static CURLcode randit(struct Curl_easy *data, unsigned int *rnd) { + unsigned int r; CURLcode result = CURLE_OK; static unsigned int randseed; static bool seeded = FALSE; @@ -133,7 +138,7 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd) /* ---- non-cryptographic version following ---- */ -#ifdef _WIN32 +#ifdef WIN32 if(!seeded) { result = Curl_win32_random((unsigned char *)rnd, sizeof(*rnd)); if(result != CURLE_NOT_BUILT_IN) @@ -141,14 +146,12 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd) } #endif -#if defined(HAVE_ARC4RANDOM) && !defined(USE_OPENSSL) - if(!seeded) { - *rnd = (unsigned int)arc4random(); - return CURLE_OK; - } +#ifdef HAVE_ARC4RANDOM + *rnd = (unsigned int)arc4random(); + return CURLE_OK; #endif -#if defined(RANDOM_FILE) && !defined(_WIN32) +#if defined(RANDOM_FILE) && !defined(WIN32) if(!seeded) { /* if there's a random file to read a seed from, use it */ int fd = open(RANDOM_FILE, O_RDONLY); @@ -172,12 +175,9 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd) seeded = TRUE; } - { - unsigned int r; - /* Return an unsigned 32-bit pseudo-random number. */ - r = randseed = randseed * 1103515245 + 12345; - *rnd = (r << 16) | ((r >> 16) & 0xFFFF); - } + /* Return an unsigned 32-bit pseudo-random number. */ + r = randseed = randseed * 1103515245 + 12345; + *rnd = (r << 16) | ((r >> 16) & 0xFFFF); return CURLE_OK; } diff --git a/deps/curl/lib/rand.h b/deps/curl/lib/rand.h index bc05239e..1d009f52 100644 --- a/deps/curl/lib/rand.h +++ b/deps/curl/lib/rand.h @@ -41,7 +41,7 @@ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd, CURLcode Curl_rand_alnum(struct Curl_easy *data, unsigned char *rnd, size_t num); -#ifdef _WIN32 +#ifdef WIN32 /* Random generator shared between the Schannel vtls and Curl_rand*() functions */ CURLcode Curl_win32_random(unsigned char *entropy, size_t length); diff --git a/deps/curl/lib/rename.c b/deps/curl/lib/rename.c index 4c886980..97a66e94 100644 --- a/deps/curl/lib/rename.c +++ b/deps/curl/lib/rename.c @@ -40,7 +40,7 @@ /* return 0 on success, 1 on error */ int Curl_rename(const char *oldpath, const char *newpath) { -#ifdef _WIN32 +#ifdef WIN32 /* rename() on Windows doesn't overwrite, so we can't use it here. MoveFileEx() will overwrite and is usually atomic, however it fails when there are open handles to the file. */ diff --git a/deps/curl/lib/rtsp.c b/deps/curl/lib/rtsp.c index e673bb8d..ccd7264b 100644 --- a/deps/curl/lib/rtsp.c +++ b/deps/curl/lib/rtsp.c @@ -45,8 +45,8 @@ #include "curl_memory.h" #include "memdebug.h" -#define RTP_PKT_LENGTH(p) ((((unsigned int)((unsigned char)((p)[2]))) << 8) | \ - ((unsigned int)((unsigned char)((p)[3])))) +#define RTP_PKT_LENGTH(p) ((((int)((unsigned char)((p)[2]))) << 8) | \ + ((int)((unsigned char)((p)[3])))) /* protocol-specific functions set up to be called by the main engine */ static CURLcode rtsp_do(struct Curl_easy *data, bool *done); @@ -59,19 +59,14 @@ static int rtsp_getsock_do(struct Curl_easy *data, /* * Parse and write out any available RTP data. - * @param data the transfer - * @param conn the connection - * @param buf data read from connection - * @param blen amount of data in buf - * @param consumed out, number of blen consumed - * @param readmore out, TRUE iff complete buf was consumed and more data - * is needed + * + * nread: amount of data left after k->str. will be modified if RTP + * data is parsed and k->str is moved up + * readmore: whether or not the RTP parser needs more data right away */ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, struct connectdata *conn, - const char *buf, - size_t blen, - size_t *pconsumed, + ssize_t *nread, bool *readmore); static CURLcode rtsp_setup_connection(struct Curl_easy *data, @@ -93,7 +88,7 @@ static int rtsp_getsock_do(struct Curl_easy *data, struct connectdata *conn, } static -CURLcode rtp_client_write(struct Curl_easy *data, const char *ptr, size_t len); +CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len); static CURLcode rtsp_parse_transport(struct Curl_easy *data, char *transport); @@ -590,249 +585,153 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) return result; } -static CURLcode rtsp_filter_rtp(struct Curl_easy *data, - struct connectdata *conn, - const char *buf, - size_t blen, - bool in_body, - size_t *pconsumed) -{ - struct rtsp_conn *rtspc = &(conn->proto.rtspc); - CURLcode result = CURLE_OK; - - *pconsumed = 0; - while(blen) { - switch(rtspc->state) { - - case RTP_PARSE_SKIP: { - DEBUGASSERT(Curl_dyn_len(&rtspc->buf) == 0); - if(in_body && buf[0] != '$') { - /* in BODY and no valid start, do not consume and return */ - goto out; - } - while(blen && buf[0] != '$') { - if(!in_body && buf[0] == 'R' && - data->set.rtspreq != RTSPREQ_RECEIVE) { - if(strncmp(buf, "RTSP/", (blen < 5) ? blen : 5) == 0) { - /* This could be the next response, no consume and return */ - if(*pconsumed) { - DEBUGF(infof(data, "RTP rtsp_filter_rtp[SKIP] RTSP/ prefix, " - "skipping %zd bytes of junk", *pconsumed)); - } - rtspc->state = RTP_PARSE_SKIP; - rtspc->in_header = TRUE; - goto out; - } - } - /* junk, consume without buffering */ - *pconsumed += 1; - ++buf; - --blen; - } - if(blen && buf[0] == '$') { - /* possible start of an RTP message, buffer */ - if(Curl_dyn_addn(&rtspc->buf, buf, 1)) { - result = CURLE_OUT_OF_MEMORY; - goto out; - } - *pconsumed += 1; - ++buf; - --blen; - rtspc->state = RTP_PARSE_CHANNEL; - } - break; - } - - case RTP_PARSE_CHANNEL: { - int idx = ((unsigned char)buf[0]) / 8; - int off = ((unsigned char)buf[0]) % 8; - DEBUGASSERT(Curl_dyn_len(&rtspc->buf) == 1); - if(!(data->state.rtp_channel_mask[idx] & (1 << off))) { - /* invalid channel number, junk or BODY data */ - rtspc->state = RTP_PARSE_SKIP; - if(in_body) { - /* we do not consume this byte, it is BODY data */ - DEBUGF(infof(data, "RTSP: invalid RTP channel %d in BODY, " - "treating as BODY data", idx)); - if(*pconsumed == 0) { - /* We did not consume the initial '$' in our buffer, but had - * it from an earlier call. We cannot un-consume it and have - * to write it directly as BODY data */ - result = Curl_client_write(data, CLIENTWRITE_BODY, - Curl_dyn_ptr(&rtspc->buf), 1); - Curl_dyn_free(&rtspc->buf); - if(result) - goto out; - } - else { - /* un-consume the '$' and leave */ - Curl_dyn_free(&rtspc->buf); - *pconsumed -= 1; - --buf; - ++blen; - goto out; - } - } - else { - /* not BODY, forget the junk '$'. Do not consume this byte, - * it might be a start */ - infof(data, "RTSP: invalid RTP channel %d, skipping", idx); - Curl_dyn_free(&rtspc->buf); - } - break; - } - /* a valid channel, so we expect this to be a real RTP message */ - rtspc->rtp_channel = (unsigned char)buf[0]; - if(Curl_dyn_addn(&rtspc->buf, buf, 1)) { - result = CURLE_OUT_OF_MEMORY; - goto out; - } - *pconsumed += 1; - ++buf; - --blen; - rtspc->state = RTP_PARSE_LEN; - break; - } - - case RTP_PARSE_LEN: { - size_t rtp_len = Curl_dyn_len(&rtspc->buf); - const char *rtp_buf; - DEBUGASSERT(rtp_len >= 2 && rtp_len < 4); - if(Curl_dyn_addn(&rtspc->buf, buf, 1)) { - result = CURLE_OUT_OF_MEMORY; - goto out; - } - *pconsumed += 1; - ++buf; - --blen; - if(rtp_len == 2) - break; - rtp_buf = Curl_dyn_ptr(&rtspc->buf); - rtspc->rtp_len = RTP_PKT_LENGTH(rtp_buf) + 4; - rtspc->state = RTP_PARSE_DATA; - break; - } - - case RTP_PARSE_DATA: { - size_t rtp_len = Curl_dyn_len(&rtspc->buf); - size_t needed; - DEBUGASSERT(rtp_len < rtspc->rtp_len); - needed = rtspc->rtp_len - rtp_len; - if(needed <= blen) { - if(Curl_dyn_addn(&rtspc->buf, buf, needed)) { - result = CURLE_OUT_OF_MEMORY; - goto out; - } - *pconsumed += needed; - buf += needed; - blen -= needed; - /* complete RTP message in buffer */ - DEBUGF(infof(data, "RTP write channel %d rtp_len %zu", - rtspc->rtp_channel, rtspc->rtp_len)); - result = rtp_client_write(data, Curl_dyn_ptr(&rtspc->buf), - rtspc->rtp_len); - Curl_dyn_free(&rtspc->buf); - rtspc->state = RTP_PARSE_SKIP; - if(result) - goto out; - } - else { - if(Curl_dyn_addn(&rtspc->buf, buf, blen)) { - result = CURLE_OUT_OF_MEMORY; - goto out; - } - *pconsumed += blen; - buf += blen; - blen = 0; - } - break; - } - - default: - DEBUGASSERT(0); - return CURLE_RECV_ERROR; - } - } -out: - return result; -} static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, struct connectdata *conn, - const char *buf, - size_t blen, - size_t *pconsumed, - bool *readmore) -{ + ssize_t *nread, + bool *readmore) { + struct SingleRequest *k = &data->req; struct rtsp_conn *rtspc = &(conn->proto.rtspc); - CURLcode result = CURLE_OK; - size_t consumed = 0; - bool in_body; + unsigned char *rtp_channel_mask = data->state.rtp_channel_mask; - if(!data->req.header) - rtspc->in_header = FALSE; - in_body = (data->req.headerline && !rtspc->in_header) && - (data->req.size >= 0) && - (data->req.bytecount < data->req.size); + char *rtp; /* moving pointer to rtp data */ + ssize_t rtp_dataleft; /* how much data left to parse in this round */ + CURLcode result; + bool interleaved = false; + size_t skip_size = 0; - *readmore = FALSE; - *pconsumed = 0; - if(!blen) { - goto out; + if(Curl_dyn_len(&rtspc->buf)) { + /* There was some leftover data the last time. Append new buffers */ + if(Curl_dyn_addn(&rtspc->buf, k->str, *nread)) + return CURLE_OUT_OF_MEMORY; + rtp = Curl_dyn_ptr(&rtspc->buf); + rtp_dataleft = Curl_dyn_len(&rtspc->buf); + } + else { + /* Just parse the request buffer directly */ + rtp = k->str; + rtp_dataleft = *nread; } - /* If header parsing is not onging, extract RTP messages */ - if(!rtspc->in_header) { - result = rtsp_filter_rtp(data, conn, buf, blen, in_body, &consumed); - if(result) - goto out; - *pconsumed += consumed; - buf += consumed; - blen -= consumed; - } + while(rtp_dataleft > 0) { + if(rtp[0] == '$') { + if(rtp_dataleft > 4) { + unsigned char rtp_channel; + int rtp_length; + int idx; + int off; - /* we want to parse headers, do so */ - if(data->req.header && blen) { - rtspc->in_header = TRUE; - result = Curl_http_readwrite_headers(data, conn, buf, blen, - &consumed); - if(result) - goto out; + /* Parse the header */ + /* The channel identifier immediately follows and is 1 byte */ + rtp_channel = (unsigned char)rtp[1]; + idx = rtp_channel / 8; + off = rtp_channel % 8; + if(!(rtp_channel_mask[idx] & (1 << off))) { + /* invalid channel number, maybe not an RTP packet */ + rtp++; + rtp_dataleft--; + skip_size++; + continue; + } + if(skip_size > 0) { + DEBUGF(infof(data, "Skip the malformed interleaved data %lu " + "bytes", skip_size)); + } + skip_size = 0; + rtspc->rtp_channel = rtp_channel; - *pconsumed += consumed; - buf += consumed; - blen -= consumed; + /* The length is two bytes */ + rtp_length = RTP_PKT_LENGTH(rtp); - if(!data->req.header) - rtspc->in_header = FALSE; + if(rtp_dataleft < rtp_length + 4) { + /* Need more - incomplete payload */ + *readmore = TRUE; + break; + } + interleaved = true; + /* We have the full RTP interleaved packet + * Write out the header including the leading '$' */ + DEBUGF(infof(data, "RTP write channel %d rtp_length %d", + rtspc->rtp_channel, rtp_length)); + result = rtp_client_write(data, &rtp[0], rtp_length + 4); + if(result) { + *readmore = FALSE; + return result; + } - if(!rtspc->in_header) { - /* If header parsing is done and data left, extract RTP messages */ - in_body = (data->req.headerline && !rtspc->in_header) && - (data->req.size >= 0) && - (data->req.bytecount < data->req.size); - result = rtsp_filter_rtp(data, conn, buf, blen, in_body, &consumed); - if(result) - goto out; - *pconsumed += consumed; + /* Move forward in the buffer */ + rtp_dataleft -= rtp_length + 4; + rtp += rtp_length + 4; + + if(data->set.rtspreq == RTSPREQ_RECEIVE) { + /* If we are in a passive receive, give control back + * to the app as often as we can. + */ + k->keepon &= ~KEEP_RECV; + } + } + else { + /* Need more - incomplete header */ + *readmore = TRUE; + break; + } + } + else { + /* If the following data begins with 'RTSP/', which might be an RTSP + message, we should stop skipping the data. */ + /* If `k-> headerline> 0 && !interleaved` is true, we are maybe in the + middle of an RTSP message. It is difficult to determine this, so we + stop skipping. */ + size_t prefix_len = (rtp_dataleft < 5) ? rtp_dataleft : 5; + if((k->headerline > 0 && !interleaved) || + strncmp(rtp, "RTSP/", prefix_len) == 0) { + if(skip_size > 0) { + DEBUGF(infof(data, "Skip the malformed interleaved data %lu " + "bytes", skip_size)); + } + break; /* maybe is an RTSP message */ + } + /* Skip incorrect data util the next RTP packet or RTSP message */ + do { + rtp++; + rtp_dataleft--; + skip_size++; + } while(rtp_dataleft > 0 && rtp[0] != '$' && rtp[0] != 'R'); } } - if(rtspc->state != RTP_PARSE_SKIP) - *readmore = TRUE; + if(rtp_dataleft && rtp[0] == '$') { + DEBUGF(infof(data, "RTP Rewinding %zd %s", rtp_dataleft, + *readmore ? "(READMORE)" : "")); -out: - if(!*readmore && data->set.rtspreq == RTSPREQ_RECEIVE) { - /* In special mode RECEIVE, we just process one chunk of network - * data, so we stop the transfer here, if we have no incomplete - * RTP message pending. */ - data->req.keepon &= ~KEEP_RECV; + /* Store the incomplete RTP packet for a "rewind" */ + if(!Curl_dyn_len(&rtspc->buf)) { + /* nothing was stored, add this data */ + if(Curl_dyn_addn(&rtspc->buf, rtp, rtp_dataleft)) + return CURLE_OUT_OF_MEMORY; + } + else { + /* keep the remainder */ + Curl_dyn_tail(&rtspc->buf, rtp_dataleft); + } + + /* As far as the transfer is concerned, this data is consumed */ + *nread = 0; + return CURLE_OK; } - return result; + /* Fix up k->str to point just after the last RTP packet */ + k->str += *nread - rtp_dataleft; + + *nread = rtp_dataleft; + + /* If we get here, we have finished with the leftover/merge buffer */ + Curl_dyn_free(&rtspc->buf); + + return CURLE_OK; } static -CURLcode rtp_client_write(struct Curl_easy *data, const char *ptr, size_t len) +CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len) { size_t wrote; curl_write_callback writeit; @@ -857,7 +756,7 @@ CURLcode rtp_client_write(struct Curl_easy *data, const char *ptr, size_t len) } Curl_set_in_callback(data, true); - wrote = writeit((char *)ptr, 1, len, user_ptr); + wrote = writeit(ptr, 1, len, user_ptr); Curl_set_in_callback(data, false); if(CURL_WRITEFUNC_PAUSE == wrote) { diff --git a/deps/curl/lib/rtsp.h b/deps/curl/lib/rtsp.h index 237b80f8..111bac2a 100644 --- a/deps/curl/lib/rtsp.h +++ b/deps/curl/lib/rtsp.h @@ -39,12 +39,6 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header); #endif /* CURL_DISABLE_RTSP */ -typedef enum { - RTP_PARSE_SKIP, - RTP_PARSE_CHANNEL, - RTP_PARSE_LEN, - RTP_PARSE_DATA -} rtp_parse_st; /* * RTSP Connection data * @@ -53,9 +47,6 @@ typedef enum { struct rtsp_conn { struct dynbuf buf; int rtp_channel; - size_t rtp_len; - rtp_parse_st state; - BIT(in_header); }; /**************************************************************************** diff --git a/deps/curl/lib/select.c b/deps/curl/lib/select.c index d92e745a..cae9beb6 100644 --- a/deps/curl/lib/select.c +++ b/deps/curl/lib/select.c @@ -76,7 +76,7 @@ int Curl_wait_ms(timediff_t timeout_ms) } #if defined(MSDOS) delay(timeout_ms); -#elif defined(_WIN32) +#elif defined(WIN32) /* prevent overflow, timeout_ms is typecast to ULONG/DWORD. */ #if TIMEDIFF_T_MAX >= ULONG_MAX if(timeout_ms >= ULONG_MAX) diff --git a/deps/curl/lib/sendf.c b/deps/curl/lib/sendf.c index a2fac0c4..0482c5da 100644 --- a/deps/curl/lib/sendf.c +++ b/deps/curl/lib/sendf.c @@ -50,7 +50,6 @@ #include "strdup.h" #include "http2.h" #include "headers.h" -#include "progress.h" #include "ws.h" /* The last 3 #include files should be in this order */ @@ -58,9 +57,6 @@ #include "curl_memory.h" #include "memdebug.h" - -static CURLcode do_init_stack(struct Curl_easy *data); - #if defined(CURL_DO_LINEEND_CONV) && !defined(CURL_DISABLE_FTP) /* * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF @@ -389,17 +385,17 @@ static CURLcode chop_write(struct Curl_easy *data, the future to leave the original data alone. */ CURLcode Curl_client_write(struct Curl_easy *data, - int type, char *buf, size_t blen) + int type, + char *ptr, + size_t len) { - CURLcode result; - #if !defined(CURL_DISABLE_FTP) && defined(CURL_DO_LINEEND_CONV) /* FTP data may need conversion. */ if((type & CLIENTWRITE_BODY) && (data->conn->handler->protocol & PROTO_FAMILY_FTP) && data->conn->proto.ftpc.transfertype == 'A') { /* convert end-of-line markers */ - blen = convert_lineends(data, buf, blen); + len = convert_lineends(data, ptr, len); } #endif /* it is one of those, at least */ @@ -409,14 +405,14 @@ CURLcode Curl_client_write(struct Curl_easy *data, /* INFO is only INFO */ DEBUGASSERT(!(type & CLIENTWRITE_INFO) || (type == CLIENTWRITE_INFO)); - if(!data->req.writer_stack) { - result = do_init_stack(data); - if(result) - return result; - DEBUGASSERT(data->req.writer_stack); - } + if(type == CLIENTWRITE_BODY) { + if(data->req.ignorebody) + return CURLE_OK; - return Curl_cwriter_write(data, data->req.writer_stack, type, buf, blen); + if(data->req.writer_stack && !data->set.http_ce_skip) + return Curl_unencode_write(data, data->req.writer_stack, ptr, len); + } + return chop_write(data, type, FALSE, ptr, len); } CURLcode Curl_client_unpause(struct Curl_easy *data) @@ -453,12 +449,12 @@ CURLcode Curl_client_unpause(struct Curl_easy *data) void Curl_client_cleanup(struct Curl_easy *data) { - struct Curl_cwriter *writer = data->req.writer_stack; + struct contenc_writer *writer = data->req.writer_stack; size_t i; while(writer) { - data->req.writer_stack = writer->next; - writer->cwt->do_close(data, writer); + data->req.writer_stack = writer->downstream; + writer->handler->close_writer(data, writer); free(writer); writer = data->req.writer_stack; } @@ -467,222 +463,61 @@ void Curl_client_cleanup(struct Curl_easy *data) Curl_dyn_free(&data->state.tempwrite[i].b); } data->state.tempcount = 0; - data->req.bytecount = 0; - data->req.headerline = 0; + } -/* Write data using an unencoding writer stack. "nbytes" is not - allowed to be 0. */ -CURLcode Curl_cwriter_write(struct Curl_easy *data, - struct Curl_cwriter *writer, int type, - const char *buf, size_t nbytes) +/* Real client writer: no downstream. */ +static CURLcode client_cew_init(struct Curl_easy *data, + struct contenc_writer *writer) { - if(!nbytes) - return CURLE_OK; - if(!writer) - return CURLE_WRITE_ERROR; - return writer->cwt->do_write(data, writer, type, buf, nbytes); -} - -CURLcode Curl_cwriter_def_init(struct Curl_easy *data, - struct Curl_cwriter *writer) -{ - (void)data; + (void) data; (void)writer; return CURLE_OK; } -CURLcode Curl_cwriter_def_write(struct Curl_easy *data, - struct Curl_cwriter *writer, int type, - const char *buf, size_t nbytes) +static CURLcode client_cew_write(struct Curl_easy *data, + struct contenc_writer *writer, + const char *buf, size_t nbytes) { - return Curl_cwriter_write(data, writer->next, type, buf, nbytes); + (void)writer; + if(!nbytes || data->req.ignorebody) + return CURLE_OK; + return chop_write(data, CLIENTWRITE_BODY, FALSE, (char *)buf, nbytes); } -void Curl_cwriter_def_close(struct Curl_easy *data, - struct Curl_cwriter *writer) +static void client_cew_close(struct Curl_easy *data, + struct contenc_writer *writer) { (void) data; (void) writer; } -/* Real client writer to installed callbacks. */ -static CURLcode cw_client_write(struct Curl_easy *data, - struct Curl_cwriter *writer, int type, - const char *buf, size_t nbytes) -{ - (void)writer; - if(!nbytes) - return CURLE_OK; - return chop_write(data, type, FALSE, (char *)buf, nbytes); -} - -static const struct Curl_cwtype cw_client = { - "client", +static const struct content_encoding client_cew = { NULL, - Curl_cwriter_def_init, - cw_client_write, - Curl_cwriter_def_close, - sizeof(struct Curl_cwriter) -}; - -static size_t get_max_body_write_len(struct Curl_easy *data, curl_off_t limit) -{ - if(limit != -1) { - /* How much more are we allowed to write? */ - curl_off_t remain_diff; - remain_diff = limit - data->req.bytecount; - if(remain_diff < 0) { - /* already written too much! */ - return 0; - } -#if SIZEOF_CURL_OFF_T > SIZEOF_SIZE_T - else if(remain_diff > SSIZE_T_MAX) { - return SIZE_T_MAX; - } -#endif - else { - return (size_t)remain_diff; - } - } - return SIZE_T_MAX; -} - -/* Download client writer in phase CURL_CW_PROTOCOL that - * sees the "real" download body data. */ -static CURLcode cw_download_write(struct Curl_easy *data, - struct Curl_cwriter *writer, int type, - const char *buf, size_t nbytes) -{ - CURLcode result; - size_t nwrite, excess_len = 0; - const char *excess_data = NULL; - - if(!(type & CLIENTWRITE_BODY)) { - if((type & CLIENTWRITE_CONNECT) && data->set.suppress_connect_headers) - return CURLE_OK; - return Curl_cwriter_write(data, writer->next, type, buf, nbytes); - } - - nwrite = nbytes; - if(-1 != data->req.maxdownload) { - size_t wmax = get_max_body_write_len(data, data->req.maxdownload); - if(nwrite > wmax) { - excess_len = nbytes - wmax; - nwrite = wmax; - excess_data = buf + nwrite; - } - - if(nwrite == wmax) { - data->req.download_done = TRUE; - } - } - - if(data->set.max_filesize) { - size_t wmax = get_max_body_write_len(data, data->set.max_filesize); - if(nwrite > wmax) { - nwrite = wmax; - } - } - - data->req.bytecount += nwrite; - ++data->req.bodywrites; - if(!data->req.ignorebody && nwrite) { - result = Curl_cwriter_write(data, writer->next, type, buf, nwrite); - if(result) - return result; - } - result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount); - if(result) - return result; - - if(excess_len) { - if(data->conn->handler->readwrite) { - /* RTSP hack moved from transfer loop to here */ - bool readmore = FALSE; /* indicates data is incomplete, need more */ - size_t consumed = 0; - result = data->conn->handler->readwrite(data, data->conn, - excess_data, excess_len, - &consumed, &readmore); - if(result) - return result; - DEBUGASSERT(consumed <= excess_len); - excess_len -= consumed; - if(readmore) { - data->req.download_done = FALSE; - data->req.keepon |= KEEP_RECV; /* we're not done reading */ - } - } - if(excess_len && !data->req.ignorebody) { - infof(data, - "Excess found writing body:" - " excess = %zu" - ", size = %" CURL_FORMAT_CURL_OFF_T - ", maxdownload = %" CURL_FORMAT_CURL_OFF_T - ", bytecount = %" CURL_FORMAT_CURL_OFF_T, - excess_len, data->req.size, data->req.maxdownload, - data->req.bytecount); - connclose(data->conn, "excess found in a read"); - } - } - else if(nwrite < nbytes) { - failf(data, "Exceeded the maximum allowed file size " - "(%" CURL_FORMAT_CURL_OFF_T ") with %" - CURL_FORMAT_CURL_OFF_T " bytes", - data->set.max_filesize, data->req.bytecount); - return CURLE_FILESIZE_EXCEEDED; - } - - return CURLE_OK; -} - -static const struct Curl_cwtype cw_download = { - "download", NULL, - Curl_cwriter_def_init, - cw_download_write, - Curl_cwriter_def_close, - sizeof(struct Curl_cwriter) -}; - -/* RAW client writer in phase CURL_CW_RAW that - * enabled tracing of raw data. */ -static CURLcode cw_raw_write(struct Curl_easy *data, - struct Curl_cwriter *writer, int type, - const char *buf, size_t nbytes) -{ - if(type & CLIENTWRITE_BODY && data->set.verbose && !data->req.ignorebody) { - Curl_debug(data, CURLINFO_DATA_IN, (char *)buf, nbytes); - } - return Curl_cwriter_write(data, writer->next, type, buf, nbytes); -} - -static const struct Curl_cwtype cw_raw = { - "raw", - NULL, - Curl_cwriter_def_init, - cw_raw_write, - Curl_cwriter_def_close, - sizeof(struct Curl_cwriter) + client_cew_init, + client_cew_write, + client_cew_close, + sizeof(struct contenc_writer) }; /* Create an unencoding writer stage using the given handler. */ -CURLcode Curl_cwriter_create(struct Curl_cwriter **pwriter, +CURLcode Curl_client_create_writer(struct contenc_writer **pwriter, struct Curl_easy *data, - const struct Curl_cwtype *cwt, - Curl_cwriter_phase phase) + const struct content_encoding *ce_handler, + int order) { - struct Curl_cwriter *writer; + struct contenc_writer *writer; CURLcode result = CURLE_OUT_OF_MEMORY; - DEBUGASSERT(cwt->cwriter_size >= sizeof(struct Curl_cwriter)); - writer = (struct Curl_cwriter *) calloc(1, cwt->cwriter_size); + DEBUGASSERT(ce_handler->writersize >= sizeof(struct contenc_writer)); + writer = (struct contenc_writer *) calloc(1, ce_handler->writersize); if(!writer) goto out; - writer->cwt = cwt; - writer->phase = phase; - result = cwt->do_init(data, writer); + writer->handler = ce_handler; + writer->order = order; + result = ce_handler->init_writer(data, writer); out: *pwriter = result? NULL : writer; @@ -691,74 +526,55 @@ out: return result; } -void Curl_cwriter_free(struct Curl_easy *data, - struct Curl_cwriter *writer) +void Curl_client_free_writer(struct Curl_easy *data, + struct contenc_writer *writer) { if(writer) { - writer->cwt->do_close(data, writer); + writer->handler->close_writer(data, writer); free(writer); } } -size_t Curl_cwriter_count(struct Curl_easy *data, Curl_cwriter_phase phase) +/* allow no more than 5 "chained" compression steps */ +#define MAX_ENCODE_STACK 5 + + +static CURLcode init_writer_stack(struct Curl_easy *data) { - struct Curl_cwriter *w; - size_t n = 0; - - for(w = data->req.writer_stack; w; w = w->next) { - if(w->phase == phase) - ++n; - } - return n; -} - -static CURLcode do_init_stack(struct Curl_easy *data) -{ - struct Curl_cwriter *writer; - CURLcode result; - DEBUGASSERT(!data->req.writer_stack); - result = Curl_cwriter_create(&data->req.writer_stack, - data, &cw_client, CURL_CW_CLIENT); - if(result) - return result; - - result = Curl_cwriter_create(&writer, data, &cw_download, CURL_CW_PROTOCOL); - if(result) - return result; - result = Curl_cwriter_add(data, writer); - if(result) { - Curl_cwriter_free(data, writer); - } - - result = Curl_cwriter_create(&writer, data, &cw_raw, CURL_CW_RAW); - if(result) - return result; - result = Curl_cwriter_add(data, writer); - if(result) { - Curl_cwriter_free(data, writer); - } - return result; + return Curl_client_create_writer(&data->req.writer_stack, + data, &client_cew, 0); } -CURLcode Curl_cwriter_add(struct Curl_easy *data, - struct Curl_cwriter *writer) +CURLcode Curl_client_add_writer(struct Curl_easy *data, + struct contenc_writer *writer) { CURLcode result; - struct Curl_cwriter **anchor = &data->req.writer_stack; - if(!*anchor) { - result = do_init_stack(data); + if(!data->req.writer_stack) { + result = init_writer_stack(data); if(result) return result; } - /* Insert the writer as first in its phase. - * Skip existing writers of lower phases. */ - while(*anchor && (*anchor)->phase < writer->phase) - anchor = &((*anchor)->next); - writer->next = *anchor; - *anchor = writer; + if(data->req.writer_stack_depth++ >= MAX_ENCODE_STACK) { + failf(data, "Reject response due to more than %u content encodings", + MAX_ENCODE_STACK); + return CURLE_BAD_CONTENT_ENCODING; + } + + /* Stack the unencoding stage. */ + if(writer->order >= data->req.writer_stack->order) { + writer->downstream = data->req.writer_stack; + data->req.writer_stack = writer; + } + else { + struct contenc_writer *w = data->req.writer_stack; + while(w->downstream && writer->order < w->downstream->order) + w = w->downstream; + writer->downstream = w->downstream; + w->downstream = writer; + } return CURLE_OK; } diff --git a/deps/curl/lib/sendf.h b/deps/curl/lib/sendf.h index a70189f2..9ee00bb0 100644 --- a/deps/curl/lib/sendf.h +++ b/deps/curl/lib/sendf.h @@ -50,122 +50,43 @@ #define CLIENTWRITE_1XX (1<<5) /* a 1xx response related HEADER */ #define CLIENTWRITE_TRAILER (1<<6) /* a trailer HEADER */ -/** - * Write `len` bytes at `prt` to the client. `type` indicates what - * kind of data is being written. - */ CURLcode Curl_client_write(struct Curl_easy *data, int type, char *ptr, size_t len) WARN_UNUSED_RESULT; -/** - * For a paused transfer, there might be buffered data held back. - * Attempt to flush this data to the client. This *may* trigger - * another pause of the transfer. - */ CURLcode Curl_client_unpause(struct Curl_easy *data); - -/** - * Free all resources related to client writing. - */ void Curl_client_cleanup(struct Curl_easy *data); -/** - * Client Writers - a chain passing transfer BODY data to the client. - * Main application: HTTP and related protocols - * Other uses: monitoring of download progress - * - * Writers in the chain are order by their `phase`. First come all - * writers in CURL_CW_RAW, followed by any in CURL_CW_TRANSFER_DECODE, - * followed by any in CURL_CW_PROTOCOL, etc. - * - * When adding a writer, it is inserted as first in its phase. This means - * the order of adding writers of the same phase matters, but writers for - * different phases may be added in any order. - * - * Writers which do modify the BODY data written are expected to be of - * phases TRANSFER_DECODE or CONTENT_DECODE. The other phases are intended - * for monitoring writers. Which do *not* modify the data but gather - * statistics or update progress reporting. - */ - -/* Phase a writer operates at. */ -typedef enum { - CURL_CW_RAW, /* raw data written, before any decoding */ - CURL_CW_TRANSFER_DECODE, /* remove transfer-encodings */ - CURL_CW_PROTOCOL, /* after transfer, but before content decoding */ - CURL_CW_CONTENT_DECODE, /* remove content-encodings */ - CURL_CW_CLIENT /* data written to client */ -} Curl_cwriter_phase; - -/* Client Writer Type, provides the implementation */ -struct Curl_cwtype { - const char *name; /* writer name. */ - const char *alias; /* writer name alias, maybe NULL. */ - CURLcode (*do_init)(struct Curl_easy *data, - struct Curl_cwriter *writer); - CURLcode (*do_write)(struct Curl_easy *data, - struct Curl_cwriter *writer, int type, - const char *buf, size_t nbytes); - void (*do_close)(struct Curl_easy *data, - struct Curl_cwriter *writer); - size_t cwriter_size; /* sizeof() allocated struct Curl_cwriter */ +struct contenc_writer { + const struct content_encoding *handler; /* Encoding handler. */ + struct contenc_writer *downstream; /* Downstream writer. */ + unsigned int order; /* Ordering within writer stack. */ }; -/* Client writer instance */ -struct Curl_cwriter { - const struct Curl_cwtype *cwt; /* type implementation */ - struct Curl_cwriter *next; /* Downstream writer. */ - Curl_cwriter_phase phase; /* phase at which it operates */ +/* Content encoding writer. */ +struct content_encoding { + const char *name; /* Encoding name. */ + const char *alias; /* Encoding name alias. */ + CURLcode (*init_writer)(struct Curl_easy *data, + struct contenc_writer *writer); + CURLcode (*unencode_write)(struct Curl_easy *data, + struct contenc_writer *writer, + const char *buf, size_t nbytes); + void (*close_writer)(struct Curl_easy *data, + struct contenc_writer *writer); + size_t writersize; }; -/** - * Create a new cwriter instance with given type and phase. Is not - * inserted into the writer chain by this call. - * Invokes `writer->do_init()`. - */ -CURLcode Curl_cwriter_create(struct Curl_cwriter **pwriter, - struct Curl_easy *data, - const struct Curl_cwtype *ce_handler, - Curl_cwriter_phase phase); -/** - * Free a cwriter instance. - * Invokes `writer->do_close()`. - */ -void Curl_cwriter_free(struct Curl_easy *data, - struct Curl_cwriter *writer); +CURLcode Curl_client_create_writer(struct contenc_writer **pwriter, + struct Curl_easy *data, + const struct content_encoding *ce_handler, + int order); -/** - * Count the number of writers installed of the given phase. - */ -size_t Curl_cwriter_count(struct Curl_easy *data, Curl_cwriter_phase phase); +void Curl_client_free_writer(struct Curl_easy *data, + struct contenc_writer *writer); -/** - * Adds a writer to the transfer's writer chain. - * The writers `phase` determines where in the chain it is inserted. - */ -CURLcode Curl_cwriter_add(struct Curl_easy *data, - struct Curl_cwriter *writer); - -/** - * Convenience method for calling `writer->do_write()` that - * checks for NULL writer. - */ -CURLcode Curl_cwriter_write(struct Curl_easy *data, - struct Curl_cwriter *writer, int type, - const char *buf, size_t nbytes); - -/** - * Default implementations for do_init, do_write, do_close that - * do nothing and pass the data through. - */ -CURLcode Curl_cwriter_def_init(struct Curl_easy *data, - struct Curl_cwriter *writer); -CURLcode Curl_cwriter_def_write(struct Curl_easy *data, - struct Curl_cwriter *writer, int type, - const char *buf, size_t nbytes); -void Curl_cwriter_def_close(struct Curl_easy *data, - struct Curl_cwriter *writer); +CURLcode Curl_client_add_writer(struct Curl_easy *data, + struct contenc_writer *writer); /* internal read-function, does plain socket, SSL and krb4 */ diff --git a/deps/curl/lib/setopt.c b/deps/curl/lib/setopt.c index a08140cc..0d399adf 100644 --- a/deps/curl/lib/setopt.c +++ b/deps/curl/lib/setopt.c @@ -50,7 +50,6 @@ #include "multiif.h" #include "altsvc.h" #include "hsts.h" -#include "tftp.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -172,7 +171,7 @@ static CURLcode protocol2num(const char *str, curl_prot_t *val) str = strchr(str, ','); tlen = str? (size_t) (str - token): strlen(token); if(tlen) { - const struct Curl_handler *h = Curl_getn_scheme_handler(token, tlen); + const struct Curl_handler *h = Curl_builtin_scheme(token, tlen); if(!h) return CURLE_UNSUPPORTED_PROTOCOL; @@ -262,43 +261,43 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Set the absolute number of maximum simultaneous alive connection that * libcurl is allowed to have. */ - uarg = va_arg(param, unsigned long); - if(uarg > UINT_MAX) + arg = va_arg(param, long); + if(arg < 0) return CURLE_BAD_FUNCTION_ARGUMENT; - data->set.maxconnects = (unsigned int)uarg; + data->set.maxconnects = arg; break; case CURLOPT_FORBID_REUSE: /* * When this transfer is done, it must not be left to be reused by a * subsequent transfer but shall be closed immediately. */ - data->set.reuse_forbid = (0 != va_arg(param, long)); + data->set.reuse_forbid = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_FRESH_CONNECT: /* * This transfer shall not use a previously cached connection but * should be made with a fresh new connect! */ - data->set.reuse_fresh = (0 != va_arg(param, long)); + data->set.reuse_fresh = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_VERBOSE: /* * Verbose means infof() calls that give a lot of information about * the connection and transfer procedures as well as internal choices. */ - data->set.verbose = (0 != va_arg(param, long)); + data->set.verbose = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_HEADER: /* * Set to include the header in the general data output stream. */ - data->set.include_header = (0 != va_arg(param, long)); + data->set.include_header = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_NOPROGRESS: /* * Shut off the internal supported progress meter */ - data->set.hide_progress = (0 != va_arg(param, long)); + data->set.hide_progress = (0 != va_arg(param, long)) ? TRUE : FALSE; if(data->set.hide_progress) data->progress.flags |= PGRS_HIDE; else @@ -308,7 +307,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * Do not include the body part in the output data stream. */ - data->set.opt_no_body = (0 != va_arg(param, long)); + data->set.opt_no_body = (0 != va_arg(param, long)) ? TRUE : FALSE; #ifndef CURL_DISABLE_HTTP if(data->set.opt_no_body) /* in HTTP lingo, no body means using the HEAD request... */ @@ -322,10 +321,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Don't output the >=400 error code HTML-page, but instead only * return error. */ - data->set.http_fail_on_error = (0 != va_arg(param, long)); + data->set.http_fail_on_error = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_KEEP_SENDING_ON_ERROR: - data->set.http_keep_sending_on_error = (0 != va_arg(param, long)); + data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ? + TRUE : FALSE; break; case CURLOPT_UPLOAD: case CURLOPT_PUT: @@ -353,7 +353,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Try to get the file time of the remote document. The time will * later (possibly) become available using curl_easy_getinfo(). */ - data->set.get_filetime = (0 != va_arg(param, long)); + data->set.get_filetime = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_SERVER_RESPONSE_TIMEOUT: /* @@ -379,7 +379,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * TFTP option that specifies the block size to use for data transmission. */ arg = va_arg(param, long); - if(arg > TFTP_BLKSIZE_MAX || arg < TFTP_BLKSIZE_MIN) + if(arg < 0) return CURLE_BAD_FUNCTION_ARGUMENT; data->set.tftp_blksize = arg; break; @@ -409,7 +409,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * * Transfer using ASCII (instead of BINARY). */ - data->set.prefer_ascii = (0 != va_arg(param, long)); + data->set.prefer_ascii = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_TIMECONDITION: /* @@ -577,7 +577,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * Switch on automatic referer that gets set if curl follows locations. */ - data->set.http_auto_referer = (0 != va_arg(param, long)); + data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_ACCEPT_ENCODING: @@ -592,23 +592,28 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) */ argptr = va_arg(param, char *); if(argptr && !*argptr) { - char all[256]; - Curl_all_content_encodings(all, sizeof(all)); - result = Curl_setstropt(&data->set.str[STRING_ENCODING], all); + argptr = Curl_all_content_encodings(); + if(!argptr) + result = CURLE_OUT_OF_MEMORY; + else { + result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr); + free(argptr); + } } else result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr); break; case CURLOPT_TRANSFER_ENCODING: - data->set.http_transfer_encoding = (0 != va_arg(param, long)); + data->set.http_transfer_encoding = (0 != va_arg(param, long)) ? + TRUE : FALSE; break; case CURLOPT_FOLLOWLOCATION: /* * Follow Location: header hints on an HTTP-server. */ - data->set.http_follow_location = (0 != va_arg(param, long)); + data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_UNRESTRICTED_AUTH: @@ -616,7 +621,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Send authentication (user+password) when following locations, even when * hostname changed. */ - data->set.allow_auth_to_other_hosts = (0 != va_arg(param, long)); + data->set.allow_auth_to_other_hosts = + (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_MAXREDIRS: @@ -730,7 +736,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Set header option. */ arg = va_arg(param, long); - data->set.sep_headers = !!(arg & CURLHEADER_SEPARATE); + data->set.sep_headers = (bool)((arg & CURLHEADER_SEPARATE)? TRUE: FALSE); break; #if !defined(CURL_DISABLE_COOKIES) @@ -754,18 +760,18 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) return CURLE_BAD_FUNCTION_ARGUMENT; /* append the cookie file name to the list of file names, and deal with them later */ - cl = curl_slist_append(data->state.cookielist, argptr); + cl = curl_slist_append(data->set.cookielist, argptr); if(!cl) { - curl_slist_free_all(data->state.cookielist); - data->state.cookielist = NULL; + curl_slist_free_all(data->set.cookielist); + data->set.cookielist = NULL; return CURLE_OUT_OF_MEMORY; } - data->state.cookielist = cl; /* store the list for later use */ + data->set.cookielist = cl; /* store the list for later use */ } else { /* clear the list of cookie files */ - curl_slist_free_all(data->state.cookielist); - data->state.cookielist = NULL; + curl_slist_free_all(data->set.cookielist); + data->set.cookielist = NULL; if(!data->share || !data->share->cookies) { /* throw away all existing cookies if this isn't a shared cookie @@ -805,8 +811,17 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * prevent the forthcoming read-cookies-from-file actions to accept * cookies that are marked as being session cookies, as they belong to a * previous session. + * + * In the original Netscape cookie spec, "session cookies" are cookies + * with no expire date set. RFC2109 describes the same action if no + * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds + * a 'Discard' action that can enforce the discard even for cookies that + * have a Max-Age. + * + * We run mostly with the original cookie spec, as hardly anyone implements + * anything else. */ - data->set.cookiesession = (0 != va_arg(param, long)); + data->set.cookiesession = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_COOKIELIST: @@ -941,7 +956,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) if(arg) return CURLE_BAD_FUNCTION_ARGUMENT; #else - data->set.http09_allowed = !!arg; + data->set.http09_allowed = arg ? TRUE : FALSE; #endif break; @@ -982,9 +997,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; case CURLOPT_MIME_OPTIONS: - arg = va_arg(param, long); - data->set.mime_formescape = !!(arg & CURLMIMEOPT_FORMESCAPE); - break; + data->set.mime_options = (unsigned int)va_arg(param, long); + break; # endif #endif @@ -1004,7 +1018,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* the DIGEST_IE bit is only used to set a special marker, for all the rest we need to handle it as normal DIGEST */ - data->state.authhost.iestyle = !!(auth & CURLAUTH_DIGEST_IE); + data->state.authhost.iestyle = + (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE); if(auth & CURLAUTH_DIGEST_IE) { auth |= CURLAUTH_DIGEST; /* set standard digest bit */ @@ -1057,7 +1072,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * Tunnel operations through the proxy instead of normal proxy use */ - data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)); + data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)) ? + TRUE : FALSE; break; case CURLOPT_PROXYPORT: @@ -1086,7 +1102,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* the DIGEST_IE bit is only used to set a special marker, for all the rest we need to handle it as normal DIGEST */ - data->state.authproxy.iestyle = !!(auth & CURLAUTH_DIGEST_IE); + data->state.authproxy.iestyle = + (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE); if(auth & CURLAUTH_DIGEST_IE) { auth |= CURLAUTH_DIGEST; /* set standard digest bit */ @@ -1186,7 +1203,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * Set flag for NEC SOCK5 support */ - data->set.socks5_gssapi_nec = (0 != va_arg(param, long)); + data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE; break; #endif #ifndef CURL_DISABLE_PROXY @@ -1234,7 +1251,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * An option that changes the command to one that asks for a list only, no * file info details. Used for FTP, POP3 and SFTP. */ - data->set.list_only = (0 != va_arg(param, long)); + data->set.list_only = (0 != va_arg(param, long)) ? TRUE : FALSE; break; #endif case CURLOPT_APPEND: @@ -1242,7 +1259,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * We want to upload and append to an existing file. Used for FTP and * SFTP. */ - data->set.remote_append = (0 != va_arg(param, long)); + data->set.remote_append = (0 != va_arg(param, long)) ? TRUE : FALSE; break; #ifndef CURL_DISABLE_FTP @@ -1253,7 +1270,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) arg = va_arg(param, long); if((arg < CURLFTPMETHOD_DEFAULT) || (arg >= CURLFTPMETHOD_LAST)) return CURLE_BAD_FUNCTION_ARGUMENT; - data->set.ftp_filemethod = (unsigned char)arg; + data->set.ftp_filemethod = (unsigned char)(curl_ftpfile)arg; break; case CURLOPT_FTPPORT: /* @@ -1261,26 +1278,26 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) */ result = Curl_setstropt(&data->set.str[STRING_FTPPORT], va_arg(param, char *)); - data->set.ftp_use_port = !!(data->set.str[STRING_FTPPORT]); + data->set.ftp_use_port = (data->set.str[STRING_FTPPORT]) ? TRUE : FALSE; break; case CURLOPT_FTP_USE_EPRT: - data->set.ftp_use_eprt = (0 != va_arg(param, long)); + data->set.ftp_use_eprt = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_FTP_USE_EPSV: - data->set.ftp_use_epsv = (0 != va_arg(param, long)); + data->set.ftp_use_epsv = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_FTP_USE_PRET: - data->set.ftp_use_pret = (0 != va_arg(param, long)); + data->set.ftp_use_pret = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_FTP_SSL_CCC: arg = va_arg(param, long); if((arg < CURLFTPSSL_CCC_NONE) || (arg >= CURLFTPSSL_CCC_LAST)) return CURLE_BAD_FUNCTION_ARGUMENT; - data->set.ftp_ccc = (unsigned char)arg; + data->set.ftp_ccc = (unsigned char)(curl_ftpccc)arg; break; case CURLOPT_FTP_SKIP_PASV_IP: @@ -1288,7 +1305,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the * bypass of the IP address in PASV responses. */ - data->set.ftp_skip_ip = (0 != va_arg(param, long)); + data->set.ftp_skip_ip = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_FTP_ACCOUNT: @@ -1316,7 +1333,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) */ result = Curl_setstropt(&data->set.str[STRING_KRB_LEVEL], va_arg(param, char *)); - data->set.krb = !!(data->set.str[STRING_KRB_LEVEL]); + data->set.krb = (data->set.str[STRING_KRB_LEVEL]) ? TRUE : FALSE; break; #endif #if !defined(CURL_DISABLE_FTP) || defined(USE_SSH) @@ -1850,14 +1867,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * Kludgy option to enable CRLF conversions. Subject for removal. */ - data->set.crlf = (0 != va_arg(param, long)); + data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE; break; #ifndef CURL_DISABLE_PROXY case CURLOPT_HAPROXYPROTOCOL: /* * Set to send the HAProxy Proxy Protocol header */ - data->set.haproxyprotocol = (0 != va_arg(param, long)); + data->set.haproxyprotocol = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_HAPROXY_CLIENT_IP: /* @@ -1909,17 +1926,22 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * Enable peer SSL verifying. */ - data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)); + data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ? + TRUE : FALSE; /* Update the current connection ssl_config. */ - Curl_ssl_conn_config_update(data, FALSE); + if(data->conn) { + data->conn->ssl_config.verifypeer = + data->set.ssl.primary.verifypeer; + } break; #ifndef CURL_DISABLE_DOH case CURLOPT_DOH_SSL_VERIFYPEER: /* * Enable peer SSL verifying for DoH. */ - data->set.doh_verifypeer = (0 != va_arg(param, long)); + data->set.doh_verifypeer = (0 != va_arg(param, long)) ? + TRUE : FALSE; break; #endif #ifndef CURL_DISABLE_PROXY @@ -1931,7 +1953,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) (0 != va_arg(param, long))?TRUE:FALSE; /* Update the current connection proxy_ssl_config. */ - Curl_ssl_conn_config_update(data, TRUE); + if(data->conn) { + data->conn->proxy_ssl_config.verifypeer = + data->set.proxy_ssl.primary.verifypeer; + } break; #endif case CURLOPT_SSL_VERIFYHOST: @@ -1943,10 +1968,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* Obviously people are not reading documentation and too many thought this argument took a boolean when it wasn't and misused it. Treat 1 and 2 the same */ - data->set.ssl.primary.verifyhost = !!(arg & 3); + data->set.ssl.primary.verifyhost = (bool)((arg & 3) ? TRUE : FALSE); /* Update the current connection ssl_config. */ - Curl_ssl_conn_config_update(data, FALSE); + if(data->conn) { + data->conn->ssl_config.verifyhost = + data->set.ssl.primary.verifyhost; + } break; #ifndef CURL_DISABLE_DOH case CURLOPT_DOH_SSL_VERIFYHOST: @@ -1956,7 +1984,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) arg = va_arg(param, long); /* Treat both 1 and 2 as TRUE */ - data->set.doh_verifyhost = !!(arg & 3); + data->set.doh_verifyhost = (bool)((arg & 3) ? TRUE : FALSE); break; #endif #ifndef CURL_DISABLE_PROXY @@ -1968,8 +1996,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* Treat both 1 and 2 as TRUE */ data->set.proxy_ssl.primary.verifyhost = (bool)((arg & 3)?TRUE:FALSE); + /* Update the current connection proxy_ssl_config. */ - Curl_ssl_conn_config_update(data, TRUE); + if(data->conn) { + data->conn->proxy_ssl_config.verifyhost = + data->set.proxy_ssl.primary.verifyhost; + } break; #endif case CURLOPT_SSL_VERIFYSTATUS: @@ -1981,10 +2013,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; } - data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)); + data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ? + TRUE : FALSE; /* Update the current connection ssl_config. */ - Curl_ssl_conn_config_update(data, FALSE); + if(data->conn) { + data->conn->ssl_config.verifystatus = + data->set.ssl.primary.verifystatus; + } break; #ifndef CURL_DISABLE_DOH case CURLOPT_DOH_SSL_VERIFYSTATUS: @@ -1996,7 +2032,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; } - data->set.doh_verifystatus = (0 != va_arg(param, long)); + data->set.doh_verifystatus = (0 != va_arg(param, long)) ? + TRUE : FALSE; break; #endif case CURLOPT_SSL_CTX_FUNCTION: @@ -2030,12 +2067,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; } - data->set.ssl.falsestart = (0 != va_arg(param, long)); + data->set.ssl.falsestart = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_CERTINFO: #ifdef USE_SSL if(Curl_ssl_supports(data, SSLSUPP_CERTINFO)) - data->set.ssl.certinfo = (0 != va_arg(param, long)); + data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE; else #endif result = CURLE_NOT_BUILT_IN; @@ -2081,14 +2118,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Specify entire PEM of the CA certificate */ #ifdef USE_SSL - if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB)) { + if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB)) result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO], va_arg(param, struct curl_blob *)); - break; - } else #endif return CURLE_NOT_BUILT_IN; + + break; #ifndef CURL_DISABLE_PROXY case CURLOPT_PROXY_CAINFO: /* @@ -2104,14 +2141,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Specify entire PEM of the CA certificate */ #ifdef USE_SSL - if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB)) { + if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB)) result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO_PROXY], va_arg(param, struct curl_blob *)); - break; - } else #endif return CURLE_NOT_BUILT_IN; + break; #endif case CURLOPT_CAPATH: /* @@ -2242,7 +2278,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * The application asks not to set any signal() or alarm() handlers, * even when using a timeout. */ - data->set.no_signal = (0 != va_arg(param, long)); + data->set.no_signal = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_SHARE: @@ -2417,11 +2453,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Enable or disable TCP_NODELAY, which will disable/enable the Nagle * algorithm */ - data->set.tcp_nodelay = (0 != va_arg(param, long)); + data->set.tcp_nodelay = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_IGNORE_CONTENT_LENGTH: - data->set.ignorecl = (0 != va_arg(param, long)); + data->set.ignorecl = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_CONNECT_ONLY: @@ -2496,7 +2532,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; case CURLOPT_SSL_SESSIONID_CACHE: - data->set.ssl.primary.sessionid = (0 != va_arg(param, long)); + data->set.ssl.primary.sessionid = (0 != va_arg(param, long)) ? + TRUE : FALSE; #ifndef CURL_DISABLE_PROXY data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid; #endif @@ -2585,7 +2622,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * disable libcurl transfer encoding is used */ #ifndef USE_HYPER - data->set.http_te_skip = (0 == va_arg(param, long)); + data->set.http_te_skip = (0 == va_arg(param, long)) ? TRUE : FALSE; break; #else return CURLE_NOT_BUILT_IN; /* hyper doesn't support */ @@ -2595,7 +2632,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * raw data passed to the application when content encoding is used */ - data->set.http_ce_skip = (0 == va_arg(param, long)); + data->set.http_ce_skip = (0 == va_arg(param, long)) ? TRUE : FALSE; break; #if !defined(CURL_DISABLE_FTP) || defined(USE_SSH) @@ -2696,7 +2733,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; case CURLOPT_MAIL_RCPT_ALLOWFAILS: /* allow RCPT TO command to fail for some recipients */ - data->set.mail_rcpt_allowfails = (0 != va_arg(param, long)); + data->set.mail_rcpt_allowfails = (0 != va_arg(param, long)) ? TRUE : FALSE; break; #endif @@ -2708,7 +2745,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) case CURLOPT_SASL_IR: /* Enable/disable SASL initial response */ - data->set.sasl_ir = (0 != va_arg(param, long)); + data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE; break; #ifndef CURL_DISABLE_RTSP case CURLOPT_RTSP_REQUEST: @@ -2822,7 +2859,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) #endif #ifndef CURL_DISABLE_FTP case CURLOPT_WILDCARDMATCH: - data->set.wildcard_enabled = (0 != va_arg(param, long)); + data->set.wildcard_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_CHUNK_BGN_FUNCTION: data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback); @@ -2905,7 +2942,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; #endif case CURLOPT_TCP_KEEPALIVE: - data->set.tcp_keepalive = (0 != va_arg(param, long)); + data->set.tcp_keepalive = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_TCP_KEEPIDLE: arg = va_arg(param, long); @@ -2934,7 +2971,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) case CURLOPT_SSL_ENABLE_NPN: break; case CURLOPT_SSL_ENABLE_ALPN: - data->set.ssl_enable_alpn = (0 != va_arg(param, long)); + data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE; break; #ifdef USE_UNIX_SOCKETS case CURLOPT_UNIX_SOCKET_PATH: @@ -2950,10 +2987,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) #endif case CURLOPT_PATH_AS_IS: - data->set.path_as_is = (0 != va_arg(param, long)); + data->set.path_as_is = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_PIPEWAIT: - data->set.pipewait = (0 != va_arg(param, long)); + data->set.pipewait = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_STREAM_WEIGHT: #if defined(USE_HTTP2) || defined(USE_HTTP3) @@ -2988,11 +3025,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; #ifndef CURL_DISABLE_SHUFFLE_DNS case CURLOPT_DNS_SHUFFLE_ADDRESSES: - data->set.dns_shuffle_addresses = (0 != va_arg(param, long)); + data->set.dns_shuffle_addresses = (0 != va_arg(param, long)) ? TRUE:FALSE; break; #endif case CURLOPT_DISALLOW_USERNAME_IN_URL: - data->set.disallow_username_in_url = (0 != va_arg(param, long)); + data->set.disallow_username_in_url = + (0 != va_arg(param, long)) ? TRUE : FALSE; break; #ifndef CURL_DISABLE_DOH case CURLOPT_DOH_URL: @@ -3057,18 +3095,18 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* this needs to build a list of file names to read from, so that it can read them later, as we might get a shared HSTS handle to load them into */ - h = curl_slist_append(data->state.hstslist, argptr); + h = curl_slist_append(data->set.hstslist, argptr); if(!h) { - curl_slist_free_all(data->state.hstslist); - data->state.hstslist = NULL; + curl_slist_free_all(data->set.hstslist); + data->set.hstslist = NULL; return CURLE_OUT_OF_MEMORY; } - data->state.hstslist = h; /* store the list for later use */ + data->set.hstslist = h; /* store the list for later use */ } else { /* clear the list of HSTS files */ - curl_slist_free_all(data->state.hstslist); - data->state.hstslist = NULL; + curl_slist_free_all(data->set.hstslist); + data->set.hstslist = NULL; if(!data->share || !data->share->hsts) /* throw away the HSTS cache unless shared */ Curl_hsts_cleanup(&data->hsts); diff --git a/deps/curl/lib/setup-win32.h b/deps/curl/lib/setup-win32.h index 4e034d4b..13948389 100644 --- a/deps/curl/lib/setup-win32.h +++ b/deps/curl/lib/setup-win32.h @@ -53,14 +53,14 @@ # ifndef NOGDI # define NOGDI # endif +# include +# include # ifdef HAVE_WINSOCK2_H # include # ifdef HAVE_WS2TCPIP_H # include # endif # endif -# include -# include # include # ifdef UNICODE typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str); @@ -96,12 +96,18 @@ #ifndef _WIN32_WINNT_WS03 #define _WIN32_WINNT_WS03 0x0502 /* Windows Server 2003 */ #endif +#ifndef _WIN32_WINNT_WIN6 +#define _WIN32_WINNT_WIN6 0x0600 /* Windows Vista */ +#endif #ifndef _WIN32_WINNT_VISTA #define _WIN32_WINNT_VISTA 0x0600 /* Windows Vista */ #endif #ifndef _WIN32_WINNT_WS08 #define _WIN32_WINNT_WS08 0x0600 /* Windows Server 2008 */ #endif +#ifndef _WIN32_WINNT_LONGHORN +#define _WIN32_WINNT_LONGHORN 0x0600 /* Windows Vista */ +#endif #ifndef _WIN32_WINNT_WIN7 #define _WIN32_WINNT_WIN7 0x0601 /* Windows 7 */ #endif @@ -111,6 +117,9 @@ #ifndef _WIN32_WINNT_WINBLUE #define _WIN32_WINNT_WINBLUE 0x0603 /* Windows 8.1 */ #endif +#ifndef _WIN32_WINNT_WINTHRESHOLD +#define _WIN32_WINNT_WINTHRESHOLD 0x0A00 /* Windows 10 */ +#endif #ifndef _WIN32_WINNT_WIN10 #define _WIN32_WINNT_WIN10 0x0A00 /* Windows 10 */ #endif diff --git a/deps/curl/lib/share.h b/deps/curl/lib/share.h index 632d9198..7f55aac8 100644 --- a/deps/curl/lib/share.h +++ b/deps/curl/lib/share.h @@ -31,6 +31,14 @@ #include "urldata.h" #include "conncache.h" +/* SalfordC says "A structure member may not be volatile". Hence: + */ +#ifdef __SALFORDC__ +#define CURL_VOLATILE +#else +#define CURL_VOLATILE volatile +#endif + #define CURL_GOOD_SHARE 0x7e117a1e #define GOOD_SHARE_HANDLE(x) ((x) && (x)->magic == CURL_GOOD_SHARE) @@ -38,7 +46,7 @@ struct Curl_share { unsigned int magic; /* CURL_GOOD_SHARE */ unsigned int specifier; - volatile unsigned int dirty; + CURL_VOLATILE unsigned int dirty; curl_lock_function lockfunc; curl_unlock_function unlockfunc; diff --git a/deps/curl/lib/smb.c b/deps/curl/lib/smb.c index 6c8a47c7..32c5137a 100644 --- a/deps/curl/lib/smb.c +++ b/deps/curl/lib/smb.c @@ -27,7 +27,7 @@ #if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) -#ifdef _WIN32 +#ifdef WIN32 #define getpid GetCurrentProcessId #endif @@ -1047,7 +1047,14 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done) break; } } + data->req.bytecount += len; data->req.offset += len; + result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount); + if(result) { + req->result = result; + next_state = SMB_CLOSE; + break; + } next_state = (len < MAX_PAYLOAD_SIZE) ? SMB_CLOSE : SMB_DOWNLOAD; break; diff --git a/deps/curl/lib/smtp.c b/deps/curl/lib/smtp.c index 65fbc5b6..81a17e38 100644 --- a/deps/curl/lib/smtp.c +++ b/deps/curl/lib/smtp.c @@ -1320,7 +1320,7 @@ static CURLcode smtp_init(struct Curl_easy *data) CURLcode result = CURLE_OK; struct SMTP *smtp; - smtp = data->req.p.smtp = calloc(1, sizeof(struct SMTP)); + smtp = data->req.p.smtp = calloc(sizeof(struct SMTP), 1); if(!smtp) result = CURLE_OUT_OF_MEMORY; diff --git a/deps/curl/lib/socketpair.c b/deps/curl/lib/socketpair.c index e3d40ff9..963e1406 100644 --- a/deps/curl/lib/socketpair.c +++ b/deps/curl/lib/socketpair.c @@ -28,7 +28,7 @@ #include "rand.h" #if !defined(HAVE_SOCKETPAIR) && !defined(CURL_DISABLE_SOCKETPAIR) -#ifdef _WIN32 +#ifdef WIN32 /* * This is a socketpair() implementation for Windows. */ @@ -50,7 +50,7 @@ #ifndef INADDR_LOOPBACK #define INADDR_LOOPBACK 0x7f000001 #endif /* !INADDR_LOOPBACK */ -#endif /* !_WIN32 */ +#endif /* !WIN32 */ #include "nonblock.h" /* for curlx_nonblock */ #include "timeval.h" /* needed before select.h */ @@ -87,7 +87,7 @@ int Curl_socketpair(int domain, int type, int protocol, socks[0] = socks[1] = CURL_SOCKET_BAD; -#if defined(_WIN32) || defined(__CYGWIN__) +#if defined(WIN32) || defined(__CYGWIN__) /* don't set SO_REUSEADDR on Windows */ (void)reuse; #ifdef SO_EXCLUSIVEADDRUSE diff --git a/deps/curl/lib/socketpair.h b/deps/curl/lib/socketpair.h index bd499abb..306ab5dc 100644 --- a/deps/curl/lib/socketpair.h +++ b/deps/curl/lib/socketpair.h @@ -25,23 +25,6 @@ ***************************************************************************/ #include "curl_setup.h" - -#ifdef HAVE_PIPE - -#define wakeup_write write -#define wakeup_read read -#define wakeup_close close -#define wakeup_create pipe - -#else /* HAVE_PIPE */ - -#define wakeup_write swrite -#define wakeup_read sread -#define wakeup_close sclose -#define wakeup_create(p) Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, p) - -#endif /* HAVE_PIPE */ - #ifndef HAVE_SOCKETPAIR #include diff --git a/deps/curl/lib/socks.c b/deps/curl/lib/socks.c index 3a396de6..a7b5ab07 100644 --- a/deps/curl/lib/socks.c +++ b/deps/curl/lib/socks.c @@ -339,8 +339,8 @@ static CURLproxycode do_SOCKS4(struct Curl_cfilter *cf, if(dns) { #ifdef CURLRES_ASYNCH - conn->resolve_async.dns = dns; - conn->resolve_async.done = TRUE; + data->state.async.dns = dns; + data->state.async.done = TRUE; #endif infof(data, "Hostname '%s' was found", sx->hostname); sxstate(sx, data, CONNECT_RESOLVED); @@ -402,11 +402,8 @@ CONNECT_REQ_INIT: socksreq[8] = 0; /* ensure empty userid is NUL-terminated */ if(sx->proxy_user) { size_t plen = strlen(sx->proxy_user); - if(plen > 255) { - /* there is no real size limit to this field in the protocol, but - SOCKS5 limits the proxy user field to 255 bytes and it seems likely - that a longer field is either a mistake or malicious input */ - failf(data, "Too long SOCKS proxy user name"); + if(plen >= (size_t)data->set.buffer_size - 8) { + failf(data, "Too long SOCKS proxy user name, can't use"); return CURLPX_LONG_USER; } /* copy the proxy name WITH trailing zero */ @@ -429,8 +426,7 @@ CONNECT_REQ_INIT: socksreq[7] = 1; /* append hostname */ hostnamelen = strlen(sx->hostname) + 1; /* length including NUL */ - if((hostnamelen <= 255) && - (packetsize + hostnamelen < data->set.buffer_size)) + if(hostnamelen <= 255) strcpy((char *)socksreq + packetsize, sx->hostname); else { failf(data, "SOCKS4: too long host name"); @@ -806,8 +802,8 @@ CONNECT_REQ_INIT: if(dns) { #ifdef CURLRES_ASYNCH - conn->resolve_async.dns = dns; - conn->resolve_async.done = TRUE; + data->state.async.dns = dns; + data->state.async.done = TRUE; #endif infof(data, "SOCKS5: hostname '%s' found", sx->hostname); } @@ -823,19 +819,10 @@ CONNECT_REQ_INIT: /* FALLTHROUGH */ CONNECT_RESOLVED: case CONNECT_RESOLVED: { - char dest[MAX_IPADR_LEN]; /* printable address */ + char dest[MAX_IPADR_LEN] = "unknown"; /* printable address */ struct Curl_addrinfo *hp = NULL; if(dns) hp = dns->addr; -#ifdef ENABLE_IPV6 - if(data->set.ipver != CURL_IPRESOLVE_WHATEVER) { - int wanted_family = data->set.ipver == CURL_IPRESOLVE_V4 ? - AF_INET : AF_INET6; - /* scan for the first proper address */ - while(hp && (hp->ai_family != wanted_family)) - hp = hp->ai_next; - } -#endif if(!hp) { failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.", sx->hostname); @@ -1132,7 +1119,7 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf, return result; if(!sx) { - sx = calloc(1, sizeof(*sx)); + sx = calloc(sizeof(*sx), 1); if(!sx) return CURLE_OUT_OF_MEMORY; cf->ctx = sx; @@ -1170,29 +1157,32 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf, return result; } -static void socks_cf_adjust_pollset(struct Curl_cfilter *cf, +static int socks_cf_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data, - struct easy_pollset *ps) + curl_socket_t *socks) { struct socks_state *sx = cf->ctx; + int fds; - if(!cf->connected && sx) { + fds = cf->next->cft->get_select_socks(cf->next, data, socks); + if(!fds && cf->next->connected && !cf->connected && sx) { /* If we are not connected, the filter below is and has nothing * to wait on, we determine what to wait for. */ - curl_socket_t sock = Curl_conn_cf_get_socket(cf, data); + socks[0] = Curl_conn_cf_get_socket(cf, data); switch(sx->state) { case CONNECT_RESOLVING: case CONNECT_SOCKS_READ: case CONNECT_AUTH_READ: case CONNECT_REQ_READ: case CONNECT_REQ_READ_MORE: - Curl_pollset_set_in_only(data, ps, sock); + fds = GETSOCK_READSOCK(0); break; default: - Curl_pollset_set_out_only(data, ps, sock); + fds = GETSOCK_WRITESOCK(0); break; } } + return fds; } static void socks_proxy_cf_close(struct Curl_cfilter *cf, @@ -1237,7 +1227,7 @@ struct Curl_cftype Curl_cft_socks_proxy = { socks_proxy_cf_connect, socks_proxy_cf_close, socks_cf_get_host, - socks_cf_adjust_pollset, + socks_cf_get_select_socks, Curl_cf_def_data_pending, Curl_cf_def_send, Curl_cf_def_recv, diff --git a/deps/curl/lib/strdup.c b/deps/curl/lib/strdup.c index 2578441c..07a61391 100644 --- a/deps/curl/lib/strdup.c +++ b/deps/curl/lib/strdup.c @@ -26,7 +26,7 @@ #include -#ifdef _WIN32 +#ifdef WIN32 #include #endif @@ -56,7 +56,7 @@ char *Curl_strdup(const char *str) } #endif -#ifdef _WIN32 +#ifdef WIN32 /*************************************************************************** * * Curl_wcsdup(source) @@ -99,30 +99,6 @@ void *Curl_memdup(const void *src, size_t length) return buffer; } -/*************************************************************************** - * - * Curl_strndup(source, length) - * - * Copies the 'source' string to a newly allocated buffer (that is returned). - * Copies not more than 'length' bytes (up to a null terminator) then adds a - * null terminator. - * - * Returns the new pointer or NULL on failure. - * - ***************************************************************************/ -void *Curl_strndup(const char *src, size_t length) -{ - char *buf = memchr(src, '\0', length); - if(buf) - length = buf - src; - buf = malloc(length + 1); - if(!buf) - return NULL; - memcpy(buf, src, length); - buf[length] = 0; - return buf; -} - /*************************************************************************** * * Curl_saferealloc(ptr, size) diff --git a/deps/curl/lib/strdup.h b/deps/curl/lib/strdup.h index 9f12b254..c3430b54 100644 --- a/deps/curl/lib/strdup.h +++ b/deps/curl/lib/strdup.h @@ -28,11 +28,10 @@ #ifndef HAVE_STRDUP char *Curl_strdup(const char *str); #endif -#ifdef _WIN32 +#ifdef WIN32 wchar_t* Curl_wcsdup(const wchar_t* src); #endif void *Curl_memdup(const void *src, size_t buffer_length); void *Curl_saferealloc(void *ptr, size_t size); -void *Curl_strndup(const char *src, size_t length); #endif /* HEADER_CURL_STRDUP_H */ diff --git a/deps/curl/lib/strerror.c b/deps/curl/lib/strerror.c index 0d5f9276..be419141 100644 --- a/deps/curl/lib/strerror.c +++ b/deps/curl/lib/strerror.c @@ -48,7 +48,7 @@ #include "curl_memory.h" #include "memdebug.h" -#if defined(_WIN32) || defined(_WIN32_WCE) +#if defined(WIN32) || defined(_WIN32_WCE) #define PRESERVE_WINDOWS_ERROR_CODE #endif @@ -762,7 +762,7 @@ get_winsock_error (int err, char *buf, size_t len) } #endif /* USE_WINSOCK */ -#if defined(_WIN32) || defined(_WIN32_WCE) +#if defined(WIN32) || defined(_WIN32_WCE) /* This is a helper function for Curl_strerror that converts Windows API error * codes (GetLastError) to error messages. * Returns NULL if no error message was found for error code. @@ -804,7 +804,7 @@ get_winapi_error(int err, char *buf, size_t buflen) return (*buf ? buf : NULL); } -#endif /* _WIN32 || _WIN32_WCE */ +#endif /* WIN32 || _WIN32_WCE */ /* * Our thread-safe and smart strerror() replacement. @@ -837,15 +837,15 @@ const char *Curl_strerror(int err, char *buf, size_t buflen) if(!buflen) return NULL; -#ifndef _WIN32 +#ifndef WIN32 DEBUGASSERT(err >= 0); #endif max = buflen - 1; *buf = '\0'; -#if defined(_WIN32) || defined(_WIN32_WCE) -#if defined(_WIN32) +#if defined(WIN32) || defined(_WIN32_WCE) +#if defined(WIN32) /* 'sys_nerr' is the maximum errno number, it is not widely portable */ if(err >= 0 && err < sys_nerr) strncpy(buf, sys_errlist[err], max); @@ -923,7 +923,7 @@ const char *Curl_strerror(int err, char *buf, size_t buflen) * Curl_winapi_strerror: * Variant of Curl_strerror if the error code is definitely Windows API. */ -#if defined(_WIN32) || defined(_WIN32_WCE) +#if defined(WIN32) || defined(_WIN32_WCE) const char *Curl_winapi_strerror(DWORD err, char *buf, size_t buflen) { #ifdef PRESERVE_WINDOWS_ERROR_CODE @@ -958,7 +958,7 @@ const char *Curl_winapi_strerror(DWORD err, char *buf, size_t buflen) return buf; } -#endif /* _WIN32 || _WIN32_WCE */ +#endif /* WIN32 || _WIN32_WCE */ #ifdef USE_WINDOWS_SSPI /* @@ -986,10 +986,6 @@ const char *Curl_sspi_strerror(int err, char *buf, size_t buflen) break; #define SEC2TXT(sec) case sec: txt = #sec; break SEC2TXT(CRYPT_E_REVOKED); - SEC2TXT(CRYPT_E_NO_REVOCATION_DLL); - SEC2TXT(CRYPT_E_NO_REVOCATION_CHECK); - SEC2TXT(CRYPT_E_REVOCATION_OFFLINE); - SEC2TXT(CRYPT_E_NOT_IN_REVOCATION_DATABASE); SEC2TXT(SEC_E_ALGORITHM_MISMATCH); SEC2TXT(SEC_E_BAD_BINDINGS); SEC2TXT(SEC_E_BAD_PKGID); diff --git a/deps/curl/lib/strerror.h b/deps/curl/lib/strerror.h index 68068673..399712f8 100644 --- a/deps/curl/lib/strerror.h +++ b/deps/curl/lib/strerror.h @@ -29,7 +29,7 @@ #define STRERROR_LEN 256 /* a suitable length */ const char *Curl_strerror(int err, char *buf, size_t buflen); -#if defined(_WIN32) || defined(_WIN32_WCE) +#if defined(WIN32) || defined(_WIN32_WCE) const char *Curl_winapi_strerror(DWORD err, char *buf, size_t buflen); #endif #ifdef USE_WINDOWS_SSPI diff --git a/deps/curl/lib/system_win32.c b/deps/curl/lib/system_win32.c index 9408d026..0cdaf3b2 100644 --- a/deps/curl/lib/system_win32.c +++ b/deps/curl/lib/system_win32.c @@ -24,7 +24,7 @@ #include "curl_setup.h" -#if defined(_WIN32) +#if defined(WIN32) #include #include "system_win32.h" @@ -238,4 +238,4 @@ HMODULE Curl_load_library(LPCTSTR filename) #endif } -#endif /* _WIN32 */ +#endif /* WIN32 */ diff --git a/deps/curl/lib/system_win32.h b/deps/curl/lib/system_win32.h index 25667666..6482643f 100644 --- a/deps/curl/lib/system_win32.h +++ b/deps/curl/lib/system_win32.h @@ -26,7 +26,7 @@ #include "curl_setup.h" -#if defined(_WIN32) +#if defined(WIN32) extern LARGE_INTEGER Curl_freq; extern bool Curl_isVistaOrGreater; @@ -42,8 +42,8 @@ extern IF_NAMETOINDEX_FN Curl_if_nametoindex; /* This is used to dynamically load DLLs */ HMODULE Curl_load_library(LPCTSTR filename); -#else /* _WIN32 */ +#else /* WIN32 */ #define Curl_win32_init(x) CURLE_OK -#endif /* !_WIN32 */ +#endif /* !WIN32 */ #endif /* HEADER_CURL_SYSTEM_WIN32_H */ diff --git a/deps/curl/lib/tftp.c b/deps/curl/lib/tftp.c index 66301550..e78140d5 100644 --- a/deps/curl/lib/tftp.c +++ b/deps/curl/lib/tftp.c @@ -70,6 +70,8 @@ /* RFC2348 allows the block size to be negotiated */ #define TFTP_BLKSIZE_DEFAULT 512 +#define TFTP_BLKSIZE_MIN 8 +#define TFTP_BLKSIZE_MAX 65464 #define TFTP_OPTION_BLKSIZE "blksize" /* from RFC2349: */ @@ -976,9 +978,11 @@ static CURLcode tftp_connect(struct Curl_easy *data, bool *done) return CURLE_OUT_OF_MEMORY; /* alloc pkt buffers based on specified blksize */ - if(data->set.tftp_blksize) - /* range checked when set */ + if(data->set.tftp_blksize) { blksize = (int)data->set.tftp_blksize; + if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN) + return CURLE_TFTP_ILLEGAL; + } need_blksize = blksize; /* default size is the fallback when no OACK is received */ @@ -1103,6 +1107,7 @@ static CURLcode tftp_receive_packet(struct Curl_easy *data) CURLcode result = CURLE_OK; struct connectdata *conn = data->conn; struct tftp_state_data *state = conn->proto.tftpc; + struct SingleRequest *k = &data->req; /* Receive the packet */ fromlen = sizeof(fromaddr); @@ -1136,6 +1141,11 @@ static CURLcode tftp_receive_packet(struct Curl_easy *data) result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)state->rpacket.data + 4, state->rbytes-4); + if(!result) { + k->bytecount += state->rbytes-4; + result = Curl_pgrsSetDownloadCounter(data, + (curl_off_t) k->bytecount); + } if(result) { tftp_state_machine(state, TFTP_EVENT_ERROR); return result; diff --git a/deps/curl/lib/tftp.h b/deps/curl/lib/tftp.h index 12404bf6..5d2d5da6 100644 --- a/deps/curl/lib/tftp.h +++ b/deps/curl/lib/tftp.h @@ -25,9 +25,6 @@ ***************************************************************************/ #ifndef CURL_DISABLE_TFTP extern const struct Curl_handler Curl_handler_tftp; - -#define TFTP_BLKSIZE_MIN 8 -#define TFTP_BLKSIZE_MAX 65464 #endif #endif /* HEADER_CURL_TFTP_H */ diff --git a/deps/curl/lib/timediff.c b/deps/curl/lib/timediff.c index d0824d14..1b762bbd 100644 --- a/deps/curl/lib/timediff.c +++ b/deps/curl/lib/timediff.c @@ -53,7 +53,7 @@ struct timeval *curlx_mstotv(struct timeval *tv, timediff_t ms) #endif tv->tv_sec = (time_t)tv_sec; tv->tv_usec = (suseconds_t)tv_usec; -#elif defined(_WIN32) /* maybe also others in the future */ +#elif defined(WIN32) /* maybe also others in the future */ #if TIMEDIFF_T_MAX > LONG_MAX /* tv_sec overflow check on Windows there we know it is long */ if(tv_sec > LONG_MAX) diff --git a/deps/curl/lib/timeval.c b/deps/curl/lib/timeval.c index 5a6727cb..026d9d17 100644 --- a/deps/curl/lib/timeval.c +++ b/deps/curl/lib/timeval.c @@ -24,10 +24,11 @@ #include "timeval.h" -#if defined(_WIN32) +#if defined(WIN32) && !defined(MSDOS) -#include -#include "system_win32.h" +/* set in win32_init() */ +extern LARGE_INTEGER Curl_freq; +extern bool Curl_isVistaOrGreater; /* In case of bug fix this function has a counterpart in tool_util.c */ struct curltime Curl_now(void) diff --git a/deps/curl/lib/transfer.c b/deps/curl/lib/transfer.c index 96f1fde7..6886764f 100644 --- a/deps/curl/lib/transfer.c +++ b/deps/curl/lib/transfer.c @@ -163,9 +163,9 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes, { size_t buffersize = bytes; size_t nread; + curl_read_callback readfunc = NULL; void *extra_data = NULL; - int eof_index = 0; #ifndef CURL_DISABLE_HTTP if(data->state.trailers_state == TRAILERS_INITIALIZED) { @@ -223,7 +223,6 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes, */ readfunc = trailers_read; extra_data = (void *)data; - eof_index = 1; } else #endif @@ -232,15 +231,10 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes, extra_data = data->state.in; } - if(!data->req.fread_eof[eof_index]) { - Curl_set_in_callback(data, true); - nread = readfunc(data->req.upload_fromhere, 1, buffersize, extra_data); - Curl_set_in_callback(data, false); - /* make sure the callback is not called again after EOF */ - data->req.fread_eof[eof_index] = !nread; - } - else - nread = 0; + Curl_set_in_callback(data, true); + nread = readfunc(data->req.upload_fromhere, 1, + buffersize, extra_data); + Curl_set_in_callback(data, false); if(nread == CURL_READFUNC_ABORT) { failf(data, "operation aborted by callback"); @@ -428,15 +422,16 @@ static CURLcode readwrite_data(struct Curl_easy *data, bool *comeback) { CURLcode result = CURLE_OK; - char *buf; - size_t blen; - size_t consumed; + ssize_t nread; /* number of bytes read */ + size_t excess = 0; /* excess bytes read */ + bool readmore = FALSE; /* used by RTP to signal for more data */ int maxloops = 100; curl_off_t max_recv = data->set.max_recv_speed? data->set.max_recv_speed : CURL_OFF_T_MAX; + char *buf = data->state.buffer; bool data_eof_handled = FALSE; + DEBUGASSERT(buf); - DEBUGASSERT(data->state.buffer); *done = FALSE; *comeback = FALSE; @@ -444,7 +439,8 @@ static CURLcode readwrite_data(struct Curl_easy *data, read or we get a CURLE_AGAIN */ do { bool is_empty_data = FALSE; - size_t bytestoread = data->set.buffer_size; + size_t buffersize = data->set.buffer_size; + size_t bytestoread = buffersize; /* For HTTP/2 and HTTP/3, read data without caring about the content length. This is safe because body in HTTP/2 is always segmented thanks to its framing layer. Meanwhile, we have to call Curl_read @@ -453,38 +449,31 @@ static CURLcode readwrite_data(struct Curl_easy *data, bool is_http3 = Curl_conn_is_http3(data, conn, FIRSTSOCKET); data_eof_handled = is_http3 || Curl_conn_is_http2(data, conn, FIRSTSOCKET); - /* Each loop iteration starts with a fresh buffer and handles - * all data read into it. */ - buf = data->state.buffer; - blen = 0; - - /* If we are reading BODY data and the connection does NOT handle EOF - * and we know the size of the BODY data, limit the read amount */ - if(!k->header && !data_eof_handled && k->size != -1) { + if(!data_eof_handled && k->size != -1 && !k->header) { + /* make sure we don't read too much */ curl_off_t totalleft = k->size - k->bytecount; - if(totalleft <= 0) - bytestoread = 0; - else if(totalleft < (curl_off_t)bytestoread) + if(totalleft < (curl_off_t)bytestoread) bytestoread = (size_t)totalleft; } if(bytestoread) { /* receive data from the network! */ - ssize_t nread; /* number of bytes read */ result = Curl_read(data, conn->sockfd, buf, bytestoread, &nread); + + /* read would've blocked */ if(CURLE_AGAIN == result) { result = CURLE_OK; break; /* get out of loop */ } - else if(result) + + if(result>0) goto out; - DEBUGASSERT(nread >= 0); - blen = (size_t)nread; } else { /* read nothing but since we wanted nothing we consider this an OK situation to proceed from */ DEBUGF(infof(data, "readwrite_data: we're done")); + nread = 0; } if(!k->bytecount) { @@ -496,17 +485,12 @@ static CURLcode readwrite_data(struct Curl_easy *data, *didwhat |= KEEP_RECV; /* indicates data of zero size, i.e. empty file */ - is_empty_data = ((blen == 0) && (k->bodywrites == 0)) ? TRUE : FALSE; + is_empty_data = ((nread == 0) && (k->bodywrites == 0)) ? TRUE : FALSE; - if(0 < blen || is_empty_data) { - /* data->state.buffer is allocated 1 byte larger than - * data->set.buffer_size admits. *wink* */ - /* TODO: we should really not rely on this being 0-terminated, since - * the actual data read might contain 0s. */ - buf[blen] = 0; + if(0 < nread || is_empty_data) { + buf[nread] = 0; } - - if(!blen) { + if(!nread) { /* if we receive 0 or less here, either the data transfer is done or the server closed the connection and we bail out from this! */ if(data_eof_handled) @@ -518,70 +502,48 @@ static CURLcode readwrite_data(struct Curl_easy *data, break; } + /* Default buffer to use when we write the buffer, it may be changed + in the flow below before the actual storing is done. */ + k->str = buf; + if(conn->handler->readwrite) { - bool readmore = FALSE; /* indicates data is incomplete, need more */ - consumed = 0; - result = conn->handler->readwrite(data, conn, buf, blen, - &consumed, &readmore); + result = conn->handler->readwrite(data, conn, &nread, &readmore); if(result) goto out; if(readmore) break; - buf += consumed; - blen -= consumed; - if(k->download_done) { - /* We've stopped dealing with input, get out of the do-while loop */ - if(blen > 0) { - infof(data, - "Excess found:" - " excess = %zu" - " url = %s (zero-length body)", - blen, data->state.up.path); - } - - /* we make sure that this socket isn't read more now */ - k->keepon &= ~KEEP_RECV; - break; - } } #ifndef CURL_DISABLE_HTTP /* Since this is a two-state thing, we check if we are parsing headers at the moment or not. */ if(k->header) { - consumed = 0; - result = Curl_http_readwrite_headers(data, conn, buf, blen, &consumed); + /* we are in parse-the-header-mode */ + bool stop_reading = FALSE; + result = Curl_http_readwrite_headers(data, conn, &nread, &stop_reading); if(result) goto out; - buf += consumed; - blen -= consumed; if(conn->handler->readwrite && - (k->maxdownload <= 0 && blen > 0)) { - bool readmore = FALSE; /* indicates data is incomplete, need more */ - consumed = 0; - result = conn->handler->readwrite(data, conn, buf, blen, - &consumed, &readmore); + (k->maxdownload <= 0 && nread > 0)) { + result = conn->handler->readwrite(data, conn, &nread, &readmore); if(result) goto out; if(readmore) break; - buf += consumed; - blen -= consumed; } - if(k->download_done) { + if(stop_reading) { /* We've stopped dealing with input, get out of the do-while loop */ - if(blen > 0) { + + if(nread > 0) { infof(data, "Excess found:" - " excess = %zu" + " excess = %zd" " url = %s (zero-length body)", - blen, data->state.up.path); + nread, data->state.up.path); } - /* we make sure that this socket isn't read more now */ - k->keepon &= ~KEEP_RECV; break; } } @@ -591,13 +553,11 @@ static CURLcode readwrite_data(struct Curl_easy *data, /* This is not an 'else if' since it may be a rest from the header parsing, where the beginning of the buffer is headers and the end is non-headers. */ - if(!k->header && (blen > 0 || is_empty_data)) { + if(!k->header && (nread > 0 || is_empty_data)) { - if(data->req.no_body && blen > 0) { + if(data->req.no_body) { /* data arrives although we want none, bail out */ streamclose(conn, "ignoring body"); - DEBUGF(infof(data, "did not want a BODY, but seeing %zu bytes", - blen)); *done = TRUE; result = CURLE_WEIRD_SERVER_REPLY; goto out; @@ -616,18 +576,34 @@ static CURLcode readwrite_data(struct Curl_easy *data, } /* this is the first time we write a body part */ #endif /* CURL_DISABLE_HTTP */ + k->bodywrites++; + + /* pass data to the debug function before it gets "dechunked" */ + if(data->set.verbose) { + if(k->badheader) { + Curl_debug(data, CURLINFO_DATA_IN, + Curl_dyn_ptr(&data->state.headerb), + Curl_dyn_len(&data->state.headerb)); + if(k->badheader == HEADER_PARTHEADER) + Curl_debug(data, CURLINFO_DATA_IN, + k->str, (size_t)nread); + } + else + Curl_debug(data, CURLINFO_DATA_IN, + k->str, (size_t)nread); + } + #ifndef CURL_DISABLE_HTTP if(k->chunk) { /* * Here comes a chunked transfer flying and we need to decode this * properly. While the name says read, this function both reads - * and writes away the data. + * and writes away the data. The returned 'nread' holds the number + * of actual data it wrote to the client. */ CURLcode extra; - CHUNKcode res; - - consumed = 0; - res = Curl_httpchunk_read(data, buf, blen, &consumed, &extra); + CHUNKcode res = + Curl_httpchunk_read(data, k->str, nread, &nread, &extra); if(CHUNKE_OK < res) { if(CHUNKE_PASSTHRU_ERROR == res) { @@ -639,14 +615,9 @@ static CURLcode readwrite_data(struct Curl_easy *data, result = CURLE_RECV_ERROR; goto out; } - - buf += consumed; - blen -= consumed; - if(CHUNKE_STOP == res) { + if(CHUNKE_STOP == res) { /* we're done reading chunks! */ k->keepon &= ~KEEP_RECV; /* read no more */ - /* chunks read successfully, download is complete */ - k->download_done = TRUE; /* N number of bytes at the end of the str buffer that weren't written to the client. */ @@ -660,57 +631,117 @@ static CURLcode readwrite_data(struct Curl_easy *data, } #endif /* CURL_DISABLE_HTTP */ - max_recv -= blen; + /* Account for body content stored in the header buffer */ + if((k->badheader == HEADER_PARTHEADER) && !k->ignorebody) { + size_t headlen = Curl_dyn_len(&data->state.headerb); + DEBUGF(infof(data, "Increasing bytecount by %zu", headlen)); + k->bytecount += headlen; + } - if(!k->chunk && (blen || k->badheader || is_empty_data)) { + if((-1 != k->maxdownload) && + (k->bytecount + nread >= k->maxdownload)) { + + excess = (size_t)(k->bytecount + nread - k->maxdownload); + if(excess > 0 && !k->ignorebody) { + infof(data, + "Excess found in a read:" + " excess = %zu" + ", size = %" CURL_FORMAT_CURL_OFF_T + ", maxdownload = %" CURL_FORMAT_CURL_OFF_T + ", bytecount = %" CURL_FORMAT_CURL_OFF_T, + excess, k->size, k->maxdownload, k->bytecount); + connclose(conn, "excess found in a read"); + } + + nread = (ssize_t) (k->maxdownload - k->bytecount); + if(nread < 0) /* this should be unusual */ + nread = 0; + + /* HTTP/3 over QUIC should keep reading until QUIC connection + is closed. In contrast to HTTP/2 which can stop reading + from TCP connection, HTTP/3 over QUIC needs ACK from server + to ensure stream closure. It should keep reading. */ + if(!is_http3) { + k->keepon &= ~KEEP_RECV; /* we're done reading */ + } + } + + k->bytecount += nread; + max_recv -= nread; + + result = Curl_pgrsSetDownloadCounter(data, k->bytecount); + if(result) + goto out; + + if(!k->chunk && (nread || k->badheader || is_empty_data)) { /* If this is chunky transfer, it was already written */ - if(k->badheader) { + if(k->badheader && !k->ignorebody) { /* we parsed a piece of data wrongly assuming it was a header and now we output it as body instead */ size_t headlen = Curl_dyn_len(&data->state.headerb); /* Don't let excess data pollute body writes */ - if(k->maxdownload != -1 && (curl_off_t)headlen > k->maxdownload) - headlen = (size_t)k->maxdownload; + if(k->maxdownload == -1 || (curl_off_t)headlen <= k->maxdownload) + result = Curl_client_write(data, CLIENTWRITE_BODY, + Curl_dyn_ptr(&data->state.headerb), + headlen); + else + result = Curl_client_write(data, CLIENTWRITE_BODY, + Curl_dyn_ptr(&data->state.headerb), + (size_t)k->maxdownload); - result = Curl_client_write(data, CLIENTWRITE_BODY, - Curl_dyn_ptr(&data->state.headerb), - headlen); if(result) goto out; } - - if(blen) { + if(k->badheader < HEADER_ALLBAD) { + /* This switch handles various content encodings. If there's an + error here, be sure to check over the almost identical code + in http_chunks.c. + Make sure that ALL_CONTENT_ENCODINGS contains all the + encodings handled here. */ + if(!k->ignorebody && nread) { #ifndef CURL_DISABLE_POP3 - if(conn->handler->protocol & PROTO_FAMILY_POP3) { - result = k->ignorebody? CURLE_OK : - Curl_pop3_write(data, buf, blen); - } - else + if(conn->handler->protocol & PROTO_FAMILY_POP3) + result = Curl_pop3_write(data, k->str, nread); + else #endif /* CURL_DISABLE_POP3 */ - result = Curl_client_write(data, CLIENTWRITE_BODY, buf, blen); + result = Curl_client_write(data, CLIENTWRITE_BODY, k->str, + nread); + } } - k->badheader = FALSE; /* taken care of now */ + k->badheader = HEADER_NORMAL; /* taken care of now */ if(result) goto out; } - if(k->download_done && !is_http3) { - /* HTTP/3 over QUIC should keep reading until QUIC connection - is closed. In contrast to HTTP/2 which can stop reading - from TCP connection, HTTP/3 over QUIC needs ACK from server - to ensure stream closure. It should keep reading. */ - k->keepon &= ~KEEP_RECV; /* we're done reading */ - } } /* if(!header and data to read) */ + if(conn->handler->readwrite && excess) { + /* Parse the excess data */ + k->str += nread; + + if(&k->str[excess] > &buf[data->set.buffer_size]) { + /* the excess amount was too excessive(!), make sure + it doesn't read out of buffer */ + excess = &buf[data->set.buffer_size] - k->str; + } + nread = (ssize_t)excess; + + result = conn->handler->readwrite(data, conn, &nread, &readmore); + if(result) + goto out; + + if(readmore) + k->keepon |= KEEP_RECV; /* we're not done reading */ + break; + } + if(is_empty_data) { /* if we received nothing, the server closed the connection and we are done */ k->keepon &= ~KEEP_RECV; - k->download_done = TRUE; } if((k->keepon & KEEP_RECV_PAUSE) || !(k->keepon & KEEP_RECV)) { @@ -733,7 +764,6 @@ static CURLcode readwrite_data(struct Curl_easy *data, on from our side, we need to stop that immediately. */ infof(data, "we are done reading and this is set to close, stop send"); k->keepon &= ~KEEP_SEND; /* no writing anymore either */ - k->keepon &= ~KEEP_SEND_PAUSE; /* no pausing anymore either */ } out: @@ -753,7 +783,7 @@ CURLcode Curl_done_sending(struct Curl_easy *data, return CURLE_OK; } -#if defined(_WIN32) && defined(USE_WINSOCK) +#if defined(WIN32) && defined(USE_WINSOCK) #ifndef SIO_IDEAL_SEND_BACKLOG_QUERY #define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747B #endif @@ -947,7 +977,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data, if(result) return result; -#if defined(_WIN32) && defined(USE_WINSOCK) +#if defined(WIN32) && defined(USE_WINSOCK) { struct curltime n = Curl_now(); if(Curl_timediff(n, k->last_sndbuf_update) > 1000) { @@ -1400,7 +1430,8 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) return CURLE_OUT_OF_MEMORY; } wc = data->wildcard; - if(wc->state < CURLWC_INIT) { + if((wc->state < CURLWC_INIT) || + (wc->state >= CURLWC_CLEAN)) { if(wc->ftpwc) wc->dtor(wc->ftpwc); Curl_safefree(wc->pattern); @@ -1604,7 +1635,7 @@ CURLcode Curl_follow(struct Curl_easy *data, return Curl_uc_to_curlcode(uc); } - p = Curl_get_scheme_handler(scheme); + p = Curl_builtin_scheme(scheme, CURL_ZERO_TERMINATED); if(p && (p->protocol != data->info.conn_protocol)) { infof(data, "Clear auth, redirects scheme from %s to %s", data->info.conn_scheme, scheme); diff --git a/deps/curl/lib/url.c b/deps/curl/lib/url.c index b81785fe..61dad442 100644 --- a/deps/curl/lib/url.c +++ b/deps/curl/lib/url.c @@ -168,6 +168,130 @@ static curl_prot_t get_protocol_family(const struct Curl_handler *h) return h->family; } + +/* + * Protocol table. Schemes (roughly) in 2019 popularity order: + * + * HTTPS, HTTP, FTP, FTPS, SFTP, FILE, SCP, SMTP, LDAP, IMAPS, TELNET, IMAP, + * LDAPS, SMTPS, TFTP, SMB, POP3, GOPHER POP3S, RTSP, RTMP, SMBS, DICT + */ +static const struct Curl_handler * const protocols[] = { + +#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) + &Curl_handler_https, +#endif + +#ifndef CURL_DISABLE_HTTP + &Curl_handler_http, +#endif + +#ifdef USE_WEBSOCKETS +#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) + &Curl_handler_wss, +#endif + +#ifndef CURL_DISABLE_HTTP + &Curl_handler_ws, +#endif +#endif + +#ifndef CURL_DISABLE_FTP + &Curl_handler_ftp, +#endif + +#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP) + &Curl_handler_ftps, +#endif + +#if defined(USE_SSH) + &Curl_handler_sftp, +#endif + +#ifndef CURL_DISABLE_FILE + &Curl_handler_file, +#endif + +#if defined(USE_SSH) && !defined(USE_WOLFSSH) + &Curl_handler_scp, +#endif + +#ifndef CURL_DISABLE_SMTP + &Curl_handler_smtp, +#ifdef USE_SSL + &Curl_handler_smtps, +#endif +#endif + +#ifndef CURL_DISABLE_LDAP + &Curl_handler_ldap, +#if !defined(CURL_DISABLE_LDAPS) && \ + ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ + (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) + &Curl_handler_ldaps, +#endif +#endif + +#ifndef CURL_DISABLE_IMAP + &Curl_handler_imap, +#ifdef USE_SSL + &Curl_handler_imaps, +#endif +#endif + +#ifndef CURL_DISABLE_TELNET + &Curl_handler_telnet, +#endif + +#ifndef CURL_DISABLE_TFTP + &Curl_handler_tftp, +#endif + +#ifndef CURL_DISABLE_POP3 + &Curl_handler_pop3, +#ifdef USE_SSL + &Curl_handler_pop3s, +#endif +#endif + +#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \ + (SIZEOF_CURL_OFF_T > 4) + &Curl_handler_smb, +#ifdef USE_SSL + &Curl_handler_smbs, +#endif +#endif + +#ifndef CURL_DISABLE_RTSP + &Curl_handler_rtsp, +#endif + +#ifndef CURL_DISABLE_MQTT + &Curl_handler_mqtt, +#endif + +#ifndef CURL_DISABLE_GOPHER + &Curl_handler_gopher, +#ifdef USE_SSL + &Curl_handler_gophers, +#endif +#endif + +#ifdef USE_LIBRTMP + &Curl_handler_rtmp, + &Curl_handler_rtmpt, + &Curl_handler_rtmpe, + &Curl_handler_rtmpte, + &Curl_handler_rtmps, + &Curl_handler_rtmpts, +#endif + +#ifndef CURL_DISABLE_DICT + &Curl_handler_dict, +#endif + + (struct Curl_handler *) NULL +}; + void Curl_freeset(struct Curl_easy *data) { /* Free all dynamic strings stored in the data->set substructure. */ @@ -196,8 +320,8 @@ void Curl_freeset(struct Curl_easy *data) Curl_mime_cleanpart(&data->set.mimepost); #ifndef CURL_DISABLE_COOKIES - curl_slist_free_all(data->state.cookielist); - data->state.cookielist = NULL; + curl_slist_free_all(data->set.cookielist); + data->set.cookielist = NULL; #endif } @@ -239,18 +363,16 @@ CURLcode Curl_close(struct Curl_easy **datap) /* Detach connection if any is left. This should not be normal, but can be the case for example with CONNECT_ONLY + recv/send (test 556) */ Curl_detach_connection(data); - if(!data->state.internal) { - if(data->multi) - /* This handle is still part of a multi handle, take care of this first - and detach this handle from there. */ - curl_multi_remove_handle(data->multi, data); + if(data->multi) + /* This handle is still part of a multi handle, take care of this first + and detach this handle from there. */ + curl_multi_remove_handle(data->multi, data); - if(data->multi_easy) { - /* when curl_easy_perform() is used, it creates its own multi handle to - use and this is the one */ - curl_multi_cleanup(data->multi_easy); - data->multi_easy = NULL; - } + if(data->multi_easy) { + /* when curl_easy_perform() is used, it creates its own multi handle to + use and this is the one */ + curl_multi_cleanup(data->multi_easy); + data->multi_easy = NULL; } data->magic = 0; /* force a clear AFTER the possibly enforced removal from @@ -290,7 +412,7 @@ CURLcode Curl_close(struct Curl_easy **datap) #ifndef CURL_DISABLE_HSTS if(!data->share || !data->share->hsts) Curl_hsts_cleanup(&data->hsts); - curl_slist_free_all(data->state.hstslist); /* clean up list */ + curl_slist_free_all(data->set.hstslist); /* clean up list */ #endif #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH) Curl_http_auth_cleanup_digest(data); @@ -298,6 +420,10 @@ CURLcode Curl_close(struct Curl_easy **datap) Curl_safefree(data->info.contenttype); Curl_safefree(data->info.wouldredirect); + /* this destroys the channel and we cannot use it anymore after this */ + Curl_resolver_cancel(data); + Curl_resolver_cleanup(data->state.async.resolver); + data_priority_cleanup(data); /* No longer a dirty share, if it exists */ @@ -331,8 +457,8 @@ CURLcode Curl_close(struct Curl_easy **datap) } #endif -#ifndef CURL_DISABLE_HTTP Curl_mime_cleanpart(data->state.formp); +#ifndef CURL_DISABLE_HTTP Curl_safefree(data->state.formp); #endif @@ -404,16 +530,26 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) Curl_mime_initpart(&set->mimepost); - Curl_ssl_easy_config_init(data); + /* + * libcurl 7.10 introduced SSL verification *by default*! This needs to be + * switched off unless wanted. + */ #ifndef CURL_DISABLE_DOH set->doh_verifyhost = TRUE; set->doh_verifypeer = TRUE; #endif + set->ssl.primary.verifypeer = TRUE; + set->ssl.primary.verifyhost = TRUE; #ifdef USE_SSH /* defaults to any auth type */ set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; set->new_directory_perms = 0755; /* Default permissions */ #endif + set->ssl.primary.sessionid = TRUE; /* session ID caching enabled by + default */ +#ifndef CURL_DISABLE_PROXY + set->proxy_ssl = set->ssl; +#endif set->new_file_perms = 0644; /* Default permissions */ set->allowed_protocols = (curl_prot_t) CURLPROTO_ALL; @@ -514,6 +650,13 @@ CURLcode Curl_open(struct Curl_easy **curl) data->magic = CURLEASY_MAGIC_NUMBER; + result = Curl_resolver_init(data, &data->state.async.resolver); + if(result) { + DEBUGF(fprintf(stderr, "Error: resolver_init failed\n")); + free(data); + return result; + } + result = Curl_init_userdefined(data); if(!result) { Curl_dyn_init(&data->state.headerb, CURL_MAX_HTTP_HEADER); @@ -530,6 +673,7 @@ CURLcode Curl_open(struct Curl_easy **curl) } if(result) { + Curl_resolver_cleanup(data->state.async.resolver); Curl_dyn_free(&data->state.headerb); Curl_freeset(data); free(data); @@ -563,7 +707,6 @@ static void conn_free(struct Curl_easy *data, struct connectdata *conn) Curl_conn_cf_discard_all(data, conn, (int)i); } - Curl_resolver_cleanup(conn->resolve_async.resolver); Curl_free_idnconverted_hostname(&conn->host); Curl_free_idnconverted_hostname(&conn->conn_to_host); #ifndef CURL_DISABLE_PROXY @@ -575,6 +718,7 @@ static void conn_free(struct Curl_easy *data, struct connectdata *conn) Curl_safefree(conn->socks_proxy.passwd); Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */ Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */ + Curl_free_primary_ssl_config(&conn->proxy_ssl_config); #endif Curl_safefree(conn->user); Curl_safefree(conn->passwd); @@ -589,7 +733,7 @@ static void conn_free(struct Curl_easy *data, struct connectdata *conn) Curl_safefree(conn->hostname_resolve); Curl_safefree(conn->secondaryhostname); Curl_safefree(conn->localdev); - Curl_ssl_conn_config_cleanup(conn); + Curl_free_primary_ssl_config(&conn->ssl_config); #ifdef USE_UNIX_SOCKETS Curl_safefree(conn->unix_domain_socket); @@ -663,7 +807,6 @@ void Curl_disconnect(struct Curl_easy *data, conn->handler->disconnect(data, conn, dead_connection); conn_shutdown(data); - Curl_resolver_cancel(data); /* detach it again */ Curl_detach_connection(data); @@ -916,11 +1059,11 @@ ConnectionExists(struct Curl_easy *data, bool *force_reuse, bool *waitpipe) { - struct connectdata *chosen = NULL; + struct connectdata *check; + struct connectdata *chosen = 0; bool foundPendingCandidate = FALSE; - bool canmultiplex = FALSE; + bool canmultiplex = IsMultiplexingPossible(data, needle); struct connectbundle *bundle; - struct Curl_llist_element *curr; #ifdef USE_NTLM bool wantNTLMhttp = ((data->state.authhost.want & @@ -939,368 +1082,395 @@ ConnectionExists(struct Curl_easy *data, bool h2upgrade = (data->state.httpwant == CURL_HTTP_VERSION_2_0) && (needle->handler->protocol & CURLPROTO_HTTP); - *usethis = NULL; *force_reuse = FALSE; *waitpipe = FALSE; /* Look up the bundle with all the connections to this particular host. Locks the connection cache, beware of early returns! */ bundle = Curl_conncache_find_bundle(data, needle, data->state.conn_cache); - if(!bundle) { - CONNCACHE_UNLOCK(data); - return FALSE; - } - infof(data, "Found bundle for host: %p [%s]", - (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ? - "can multiplex" : "serially")); + if(bundle) { + /* Max pipe length is zero (unlimited) for multiplexed connections */ + struct Curl_llist_element *curr; - /* We can only multiplex iff the transfer allows it AND we know - * that the server we want to talk to supports it as well. */ - canmultiplex = FALSE; - if(IsMultiplexingPossible(data, needle)) { - if(bundle->multiuse == BUNDLE_UNKNOWN) { - if(data->set.pipewait) { - infof(data, "Server doesn't support multiplex yet, wait"); - *waitpipe = TRUE; - CONNCACHE_UNLOCK(data); - return FALSE; /* no reuse */ + infof(data, "Found bundle for host: %p [%s]", + (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ? + "can multiplex" : "serially")); + + /* We can't multiplex if we don't know anything about the server */ + if(canmultiplex) { + if(bundle->multiuse == BUNDLE_UNKNOWN) { + if(data->set.pipewait) { + infof(data, "Server doesn't support multiplex yet, wait"); + *waitpipe = TRUE; + CONNCACHE_UNLOCK(data); + return FALSE; /* no reuse */ + } + + infof(data, "Server doesn't support multiplex (yet)"); + canmultiplex = FALSE; } - infof(data, "Server doesn't support multiplex (yet)"); - } - else if(bundle->multiuse == BUNDLE_MULTIPLEX) { - if(Curl_multiplex_wanted(data->multi)) - canmultiplex = TRUE; - else + if((bundle->multiuse == BUNDLE_MULTIPLEX) && + !Curl_multiplex_wanted(data->multi)) { infof(data, "Could multiplex, but not asked to"); - } - else if(bundle->multiuse == BUNDLE_NO_MULTIUSE) { - infof(data, "Can not multiplex, even if we wanted to"); - } - } - - curr = bundle->conn_list.head; - while(curr) { - struct connectdata *check = curr->ptr; - /* Get next node now. We might remove a dead `check` connection which - * would invalidate `curr` as well. */ - curr = curr->next; - - /* Note that if we use an HTTP proxy in normal mode (no tunneling), we - * check connections to that proxy and not to the actual remote server. - */ - if(check->connect_only || check->bits.close) - /* connect-only or to-be-closed connections will not be reused */ - continue; - - if(data->set.ipver != CURL_IPRESOLVE_WHATEVER - && data->set.ipver != check->ip_version) { - /* skip because the connection is not via the requested IP version */ - continue; + canmultiplex = FALSE; + } + if(bundle->multiuse == BUNDLE_NO_MULTIUSE) { + infof(data, "Can not multiplex, even if we wanted to"); + canmultiplex = FALSE; + } } - if(!canmultiplex) { - if(Curl_resolver_asynch() && - /* primary_ip[0] is NUL only if the resolving of the name hasn't - completed yet and until then we don't reuse this connection */ - !check->primary_ip[0]) + curr = bundle->conn_list.head; + while(curr) { + bool match = FALSE; + size_t multiplexed = 0; + + /* + * Note that if we use an HTTP proxy in normal mode (no tunneling), we + * check connections to that proxy and not to the actual remote server. + */ + check = curr->ptr; + curr = curr->next; + + if(check->connect_only || check->bits.close) + /* connect-only or to-be-closed connections will not be reused */ continue; - } - if(CONN_INUSE(check)) { - if(!canmultiplex) { - /* transfer can't be multiplexed and check is in use */ + if(extract_if_dead(check, data)) { + /* disconnect it */ + Curl_disconnect(data, check, TRUE); continue; } - else { - /* Could multiplex, but not when check belongs to another multi */ + + if(data->set.ipver != CURL_IPRESOLVE_WHATEVER + && data->set.ipver != check->ip_version) { + /* skip because the connection is not via the requested IP version */ + continue; + } + + if(bundle->multiuse == BUNDLE_MULTIPLEX) + multiplexed = CONN_INUSE(check); + + if(!canmultiplex) { + if(multiplexed) { + /* can only happen within multi handles, and means that another easy + handle is using this connection */ + continue; + } + + if(Curl_resolver_asynch() && + /* primary_ip[0] is NUL only if the resolving of the name hasn't + completed yet and until then we don't reuse this connection */ + !check->primary_ip[0]) + continue; + } + + if(!Curl_conn_is_connected(check, FIRSTSOCKET)) { + foundPendingCandidate = TRUE; + /* Don't pick a connection that hasn't connected yet */ + infof(data, "Connection #%" CURL_FORMAT_CURL_OFF_T + " isn't open enough, can't reuse", check->connection_id); + continue; + } + +#ifdef USE_UNIX_SOCKETS + if(needle->unix_domain_socket) { + if(!check->unix_domain_socket) + continue; + if(strcmp(needle->unix_domain_socket, check->unix_domain_socket)) + continue; + if(needle->bits.abstract_unix_socket != + check->bits.abstract_unix_socket) + continue; + } + else if(check->unix_domain_socket) + continue; +#endif + + if((needle->handler->flags&PROTOPT_SSL) != + (check->handler->flags&PROTOPT_SSL)) + /* don't do mixed SSL and non-SSL connections */ + if(get_protocol_family(check->handler) != + needle->handler->protocol || !check->bits.tls_upgraded) + /* except protocols that have been upgraded via TLS */ + continue; + +#ifndef CURL_DISABLE_PROXY + if(needle->bits.httpproxy != check->bits.httpproxy || + needle->bits.socksproxy != check->bits.socksproxy) + continue; + + if(needle->bits.socksproxy && + !socks_proxy_info_matches(&needle->socks_proxy, + &check->socks_proxy)) + continue; +#endif + if(needle->bits.conn_to_host != check->bits.conn_to_host) + /* don't mix connections that use the "connect to host" feature and + * connections that don't use this feature */ + continue; + + if(needle->bits.conn_to_port != check->bits.conn_to_port) + /* don't mix connections that use the "connect to port" feature and + * connections that don't use this feature */ + continue; + +#ifndef CURL_DISABLE_PROXY + if(needle->bits.httpproxy) { + if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy)) + continue; + + if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy) + continue; + + if(IS_HTTPS_PROXY(needle->http_proxy.proxytype)) { + /* use https proxy */ + if(needle->http_proxy.proxytype != + check->http_proxy.proxytype) + continue; + else if(needle->handler->flags&PROTOPT_SSL) { + /* use double layer ssl */ + if(!Curl_ssl_config_matches(&needle->proxy_ssl_config, + &check->proxy_ssl_config)) + continue; + } + else if(!Curl_ssl_config_matches(&needle->ssl_config, + &check->ssl_config)) + continue; + } + } +#endif + + if(h2upgrade && !check->httpversion && canmultiplex) { + if(data->set.pipewait) { + infof(data, "Server upgrade doesn't support multiplex yet, wait"); + *waitpipe = TRUE; + CONNCACHE_UNLOCK(data); + return FALSE; /* no reuse */ + } + infof(data, "Server upgrade cannot be used"); + continue; /* can't be used atm */ + } + + if(!canmultiplex && CONN_INUSE(check)) + /* this request can't be multiplexed but the checked connection is + already in use so we skip it */ + continue; + + if(CONN_INUSE(check)) { + /* Subject for multiplex use if 'checks' belongs to the same multi + handle as 'data' is. */ struct Curl_llist_element *e = check->easyq.head; struct Curl_easy *entry = e->ptr; if(entry->multi != data->multi) continue; } - } - if(!Curl_conn_is_connected(check, FIRSTSOCKET)) { - foundPendingCandidate = TRUE; - /* Don't pick a connection that hasn't connected yet */ - infof(data, "Connection #%" CURL_FORMAT_CURL_OFF_T - " isn't open enough, can't reuse", check->connection_id); - continue; - } + if(needle->localdev || needle->localport) { + /* If we are bound to a specific local end (IP+port), we must not + reuse a random other one, although if we didn't ask for a + particular one we can reuse one that was bound. - /* `check` is connected. if it is in use and does not support multiplex, - * we cannot use it. */ - if(!check->bits.multiplex && CONN_INUSE(check)) - continue; - -#ifdef USE_UNIX_SOCKETS - if(needle->unix_domain_socket) { - if(!check->unix_domain_socket) - continue; - if(strcmp(needle->unix_domain_socket, check->unix_domain_socket)) - continue; - if(needle->bits.abstract_unix_socket != - check->bits.abstract_unix_socket) - continue; - } - else if(check->unix_domain_socket) - continue; -#endif - - if((needle->handler->flags&PROTOPT_SSL) != - (check->handler->flags&PROTOPT_SSL)) - /* don't do mixed SSL and non-SSL connections */ - if(get_protocol_family(check->handler) != - needle->handler->protocol || !check->bits.tls_upgraded) - /* except protocols that have been upgraded via TLS */ - continue; - - if(needle->bits.conn_to_host != check->bits.conn_to_host) - /* don't mix connections that use the "connect to host" feature and - * connections that don't use this feature */ - continue; - - if(needle->bits.conn_to_port != check->bits.conn_to_port) - /* don't mix connections that use the "connect to port" feature and - * connections that don't use this feature */ - continue; - -#ifndef CURL_DISABLE_PROXY - if(needle->bits.httpproxy != check->bits.httpproxy || - needle->bits.socksproxy != check->bits.socksproxy) - continue; - - if(needle->bits.socksproxy && - !socks_proxy_info_matches(&needle->socks_proxy, - &check->socks_proxy)) - continue; - - if(needle->bits.httpproxy) { - if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy) - continue; - - if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy)) - continue; - - if(IS_HTTPS_PROXY(needle->http_proxy.proxytype)) { - /* https proxies come in different types, http/1.1, h2, ... */ - if(needle->http_proxy.proxytype != check->http_proxy.proxytype) + This comparison is a bit rough and too strict. Since the input + parameters can be specified in numerous ways and still end up the + same it would take a lot of processing to make it really accurate. + Instead, this matching will assume that reuses of bound connections + will most likely also reuse the exact same binding parameters and + missing out a few edge cases shouldn't hurt anyone very much. + */ + if((check->localport != needle->localport) || + (check->localportrange != needle->localportrange) || + (needle->localdev && + (!check->localdev || strcmp(check->localdev, needle->localdev)))) continue; - /* match SSL config to proxy */ - if(!Curl_ssl_conn_config_match(data, check, TRUE)) { - DEBUGF(infof(data, - "Connection #%" CURL_FORMAT_CURL_OFF_T - " has different SSL proxy parameters, can't reuse", - check->connection_id)); + } + + if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) { + /* This protocol requires credentials per connection, + so verify that we're using the same name and password as well */ + if(Curl_timestrcmp(needle->user, check->user) || + Curl_timestrcmp(needle->passwd, check->passwd) || + Curl_timestrcmp(needle->sasl_authzid, check->sasl_authzid) || + Curl_timestrcmp(needle->oauth_bearer, check->oauth_bearer)) { + /* one of them was different */ continue; } - /* the SSL config to the server, which may apply here is checked - * further below */ } - } -#endif - if(h2upgrade && !check->httpversion && canmultiplex) { - if(data->set.pipewait) { - infof(data, "Server upgrade doesn't support multiplex yet, wait"); - *waitpipe = TRUE; - CONNCACHE_UNLOCK(data); - return FALSE; /* no reuse */ - } - infof(data, "Server upgrade cannot be used"); - continue; /* can't be used atm */ - } - - if(needle->localdev || needle->localport) { - /* If we are bound to a specific local end (IP+port), we must not - reuse a random other one, although if we didn't ask for a - particular one we can reuse one that was bound. - - This comparison is a bit rough and too strict. Since the input - parameters can be specified in numerous ways and still end up the - same it would take a lot of processing to make it really accurate. - Instead, this matching will assume that reuses of bound connections - will most likely also reuse the exact same binding parameters and - missing out a few edge cases shouldn't hurt anyone very much. - */ - if((check->localport != needle->localport) || - (check->localportrange != needle->localportrange) || - (needle->localdev && - (!check->localdev || strcmp(check->localdev, needle->localdev)))) + /* GSS delegation differences do not actually affect every connection + and auth method, but this check takes precaution before efficiency */ + if(needle->gssapi_delegation != check->gssapi_delegation) continue; - } - if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) { - /* This protocol requires credentials per connection, - so verify that we're using the same name and password as well */ - if(Curl_timestrcmp(needle->user, check->user) || - Curl_timestrcmp(needle->passwd, check->passwd) || - Curl_timestrcmp(needle->sasl_authzid, check->sasl_authzid) || - Curl_timestrcmp(needle->oauth_bearer, check->oauth_bearer)) { - /* one of them was different */ + /* If multiplexing isn't enabled on the h2 connection and h1 is + explicitly requested, handle it: */ + if((needle->handler->protocol & PROTO_FAMILY_HTTP) && + (((check->httpversion >= 20) && + (data->state.httpwant < CURL_HTTP_VERSION_2_0)) + || ((check->httpversion >= 30) && + (data->state.httpwant < CURL_HTTP_VERSION_3)))) continue; - } - } - - /* GSS delegation differences do not actually affect every connection - and auth method, but this check takes precaution before efficiency */ - if(needle->gssapi_delegation != check->gssapi_delegation) - continue; - - /* If looking for HTTP and the HTTP version we want is less - * than the HTTP version of the check connection, continue looking */ - if((needle->handler->protocol & PROTO_FAMILY_HTTP) && - (((check->httpversion >= 20) && - (data->state.httpwant < CURL_HTTP_VERSION_2_0)) - || ((check->httpversion >= 30) && - (data->state.httpwant < CURL_HTTP_VERSION_3)))) - continue; #ifdef USE_SSH - else if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) { - if(!ssh_config_matches(needle, check)) - continue; - } + else if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) { + if(!ssh_config_matches(needle, check)) + continue; + } #endif #ifndef CURL_DISABLE_FTP - else if(get_protocol_family(needle->handler) & PROTO_FAMILY_FTP) { - /* Also match ACCOUNT, ALTERNATIVE-TO-USER, USE_SSL and CCC options */ - if(Curl_timestrcmp(needle->proto.ftpc.account, - check->proto.ftpc.account) || - Curl_timestrcmp(needle->proto.ftpc.alternative_to_user, - check->proto.ftpc.alternative_to_user) || - (needle->proto.ftpc.use_ssl != check->proto.ftpc.use_ssl) || - (needle->proto.ftpc.ccc != check->proto.ftpc.ccc)) - continue; - } -#endif - - /* Additional match requirements if talking TLS OR - * not talking to a HTTP proxy OR using a tunnel through a proxy */ - if((needle->handler->flags&PROTOPT_SSL) -#ifndef CURL_DISABLE_PROXY - || !needle->bits.httpproxy || needle->bits.tunnel_proxy -#endif - ) { - /* Talking the same protocol scheme or a TLS upgraded protocol in the - * same protocol family? */ - if(!strcasecompare(needle->handler->scheme, check->handler->scheme) && - (get_protocol_family(check->handler) != - needle->handler->protocol || !check->bits.tls_upgraded)) - continue; - - /* If needle has "conn_to_*" set, check must match this */ - if((needle->bits.conn_to_host && !strcasecompare( - needle->conn_to_host.name, check->conn_to_host.name)) || - (needle->bits.conn_to_port && - needle->conn_to_port != check->conn_to_port)) - continue; - - /* hostname and port must match */ - if(!strcasecompare(needle->host.name, check->host.name) || - needle->remote_port != check->remote_port) - continue; - - /* If talking TLS, check needs to use the same SSL options. */ - if((needle->handler->flags & PROTOPT_SSL) && - !Curl_ssl_conn_config_match(data, check, FALSE)) { - DEBUGF(infof(data, - "Connection #%" CURL_FORMAT_CURL_OFF_T - " has different SSL parameters, can't reuse", - check->connection_id)); - continue; + else if(get_protocol_family(needle->handler) & PROTO_FAMILY_FTP) { + /* Also match ACCOUNT, ALTERNATIVE-TO-USER, USE_SSL and CCC options */ + if(Curl_timestrcmp(needle->proto.ftpc.account, + check->proto.ftpc.account) || + Curl_timestrcmp(needle->proto.ftpc.alternative_to_user, + check->proto.ftpc.alternative_to_user) || + (needle->proto.ftpc.use_ssl != check->proto.ftpc.use_ssl) || + (needle->proto.ftpc.ccc != check->proto.ftpc.ccc)) + continue; } - } +#endif + if((needle->handler->flags&PROTOPT_SSL) +#ifndef CURL_DISABLE_PROXY + || !needle->bits.httpproxy || needle->bits.tunnel_proxy +#endif + ) { + /* The requested connection does not use an HTTP proxy or it uses SSL + or it is a non-SSL protocol tunneled or it is a non-SSL protocol + which is allowed to be upgraded via TLS */ + + if((strcasecompare(needle->handler->scheme, check->handler->scheme) || + (get_protocol_family(check->handler) == + needle->handler->protocol && check->bits.tls_upgraded)) && + (!needle->bits.conn_to_host || strcasecompare( + needle->conn_to_host.name, check->conn_to_host.name)) && + (!needle->bits.conn_to_port || + needle->conn_to_port == check->conn_to_port) && + strcasecompare(needle->host.name, check->host.name) && + needle->remote_port == check->remote_port) { + /* The schemes match or the protocol family is the same and the + previous connection was TLS upgraded, and the hostname and host + port match */ + if(needle->handler->flags & PROTOPT_SSL) { + /* This is a SSL connection so verify that we're using the same + SSL options as well */ + if(!Curl_ssl_config_matches(&needle->ssl_config, + &check->ssl_config)) { + DEBUGF(infof(data, + "Connection #%" CURL_FORMAT_CURL_OFF_T + " has different SSL parameters, can't reuse", + check->connection_id)); + continue; + } + } + match = TRUE; + } + } + else { + /* The requested connection is using the same HTTP proxy in normal + mode (no tunneling) */ + match = TRUE; + } + + if(match) { #if defined(USE_NTLM) - /* If we are looking for an HTTP+NTLM connection, check if this is - already authenticating with the right credentials. If not, keep - looking so that we can reuse NTLM connections if - possible. (Especially we must not reuse the same connection if - partway through a handshake!) */ - if(wantNTLMhttp) { - if(Curl_timestrcmp(needle->user, check->user) || - Curl_timestrcmp(needle->passwd, check->passwd)) { + /* If we are looking for an HTTP+NTLM connection, check if this is + already authenticating with the right credentials. If not, keep + looking so that we can reuse NTLM connections if + possible. (Especially we must not reuse the same connection if + partway through a handshake!) */ + if(wantNTLMhttp) { + if(Curl_timestrcmp(needle->user, check->user) || + Curl_timestrcmp(needle->passwd, check->passwd)) { - /* we prefer a credential match, but this is at least a connection - that can be reused and "upgraded" to NTLM */ - if(check->http_ntlm_state == NTLMSTATE_NONE) - chosen = check; - continue; - } - } - else if(check->http_ntlm_state != NTLMSTATE_NONE) { - /* Connection is using NTLM auth but we don't want NTLM */ - continue; - } + /* we prefer a credential match, but this is at least a connection + that can be reused and "upgraded" to NTLM */ + if(check->http_ntlm_state == NTLMSTATE_NONE) + chosen = check; + continue; + } + } + else if(check->http_ntlm_state != NTLMSTATE_NONE) { + /* Connection is using NTLM auth but we don't want NTLM */ + continue; + } #ifndef CURL_DISABLE_PROXY - /* Same for Proxy NTLM authentication */ - if(wantProxyNTLMhttp) { - /* Both check->http_proxy.user and check->http_proxy.passwd can be - * NULL */ - if(!check->http_proxy.user || !check->http_proxy.passwd) - continue; + /* Same for Proxy NTLM authentication */ + if(wantProxyNTLMhttp) { + /* Both check->http_proxy.user and check->http_proxy.passwd can be + * NULL */ + if(!check->http_proxy.user || !check->http_proxy.passwd) + continue; - if(Curl_timestrcmp(needle->http_proxy.user, - check->http_proxy.user) || - Curl_timestrcmp(needle->http_proxy.passwd, - check->http_proxy.passwd)) - continue; - } - else if(check->proxy_ntlm_state != NTLMSTATE_NONE) { - /* Proxy connection is using NTLM auth but we don't want NTLM */ - continue; - } + if(Curl_timestrcmp(needle->http_proxy.user, + check->http_proxy.user) || + Curl_timestrcmp(needle->http_proxy.passwd, + check->http_proxy.passwd)) + continue; + } + else if(check->proxy_ntlm_state != NTLMSTATE_NONE) { + /* Proxy connection is using NTLM auth but we don't want NTLM */ + continue; + } #endif - if(wantNTLMhttp || wantProxyNTLMhttp) { - /* Credentials are already checked, we may use this connection. - * With NTLM being weird as it is, we MUST use a - * connection where it has already been fully negotiated. - * If it has not, we keep on looking for a better one. */ - chosen = check; + if(wantNTLMhttp || wantProxyNTLMhttp) { + /* Credentials are already checked, we can use this connection */ + chosen = check; - if((wantNTLMhttp && - (check->http_ntlm_state != NTLMSTATE_NONE)) || - (wantProxyNTLMhttp && - (check->proxy_ntlm_state != NTLMSTATE_NONE))) { - /* We must use this connection, no other */ - *force_reuse = TRUE; - break; - } - /* Continue look up for a better connection */ - continue; - } + if((wantNTLMhttp && + (check->http_ntlm_state != NTLMSTATE_NONE)) || + (wantProxyNTLMhttp && + (check->proxy_ntlm_state != NTLMSTATE_NONE))) { + /* We must use this connection, no other */ + *force_reuse = TRUE; + break; + } + + /* Continue look up for a better connection */ + continue; + } #endif + if(canmultiplex) { + /* We can multiplex if we want to. Let's continue looking for + the optimal connection to use. */ - if(CONN_INUSE(check)) { - DEBUGASSERT(canmultiplex); - DEBUGASSERT(check->bits.multiplex); - /* If multiplexed, make sure we don't go over concurrency limit */ - if(CONN_INUSE(check) >= - Curl_multi_max_concurrent_streams(data->multi)) { - infof(data, "client side MAX_CONCURRENT_STREAMS reached" - ", skip (%zu)", CONN_INUSE(check)); - continue; - } - if(CONN_INUSE(check) >= - Curl_conn_get_max_concurrent(data, check, FIRSTSOCKET)) { - infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)", - CONN_INUSE(check)); - continue; - } - /* When not multiplexed, we have a match here! */ - infof(data, "Multiplexed connection found"); - } - else if(extract_if_dead(check, data)) { - /* disconnect it */ - Curl_disconnect(data, check, TRUE); - continue; - } + if(!multiplexed) { + /* We have the optimal connection. Let's stop looking. */ + chosen = check; + break; + } - /* We have found a connection. Let's stop searching. */ - chosen = check; - break; - } /* loop over connection bundle */ +#ifdef USE_NGHTTP2 + /* If multiplexed, make sure we don't go over concurrency limit */ + if(check->bits.multiplex) { + if(multiplexed >= Curl_conn_get_max_concurrent(data, check, + FIRSTSOCKET)) { + infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)", + multiplexed); + continue; + } + else if(multiplexed >= + Curl_multi_max_concurrent_streams(data->multi)) { + infof(data, "client side MAX_CONCURRENT_STREAMS reached" + ", skip (%zu)", + multiplexed); + continue; + } + } +#endif + /* When not multiplexed, we have a match here! */ + chosen = check; + infof(data, "Multiplexed connection found"); + break; + } + else { + /* We have found a connection. Let's stop searching. */ + chosen = check; + break; + } + } + } + } if(chosen) { /* mark it as used before releasing the lock */ @@ -1390,6 +1560,17 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) #ifndef CURL_DISABLE_FTP conn->bits.ftp_use_epsv = data->set.ftp_use_epsv; conn->bits.ftp_use_eprt = data->set.ftp_use_eprt; +#endif + conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus; + conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer; + conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost; + conn->ssl_config.ssl_options = data->set.ssl.primary.ssl_options; +#ifndef CURL_DISABLE_PROXY + conn->proxy_ssl_config.verifystatus = + data->set.proxy_ssl.primary.verifystatus; + conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer; + conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost; + conn->proxy_ssl_config.ssl_options = data->set.proxy_ssl.primary.ssl_options; #endif conn->ip_version = data->set.ipver; conn->connect_only = data->set.connect_only; @@ -1434,231 +1615,30 @@ error: return NULL; } -const struct Curl_handler *Curl_get_scheme_handler(const char *scheme) -{ - return Curl_getn_scheme_handler(scheme, strlen(scheme)); -} - /* returns the handler if the given scheme is built-in */ -const struct Curl_handler *Curl_getn_scheme_handler(const char *scheme, - size_t len) +const struct Curl_handler *Curl_builtin_scheme(const char *scheme, + size_t schemelen) { - /* table generated by schemetable.c: - 1. gcc schemetable.c && ./a.out - 2. check how small the table gets - 3. tweak the hash algorithm, then rerun from 1 - 4. when the table is good enough - 5. copy the table into this source code - 6. make sure this function uses the same hash function that worked for - schemetable.c - 7. if needed, adjust the #ifdefs in schemetable.c and rerun - */ - static const struct Curl_handler * const protocols[67] = { -#ifndef CURL_DISABLE_FILE - &Curl_handler_file, -#else - NULL, -#endif - NULL, NULL, -#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER) - &Curl_handler_gophers, -#else - NULL, -#endif - NULL, -#ifdef USE_LIBRTMP - &Curl_handler_rtmpe, -#else - NULL, -#endif -#ifndef CURL_DISABLE_SMTP - &Curl_handler_smtp, -#else - NULL, -#endif -#if defined(USE_SSH) - &Curl_handler_sftp, -#else - NULL, -#endif -#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \ - (SIZEOF_CURL_OFF_T > 4) - &Curl_handler_smb, -#else - NULL, -#endif -#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP) - &Curl_handler_smtps, -#else - NULL, -#endif -#ifndef CURL_DISABLE_TELNET - &Curl_handler_telnet, -#else - NULL, -#endif -#ifndef CURL_DISABLE_GOPHER - &Curl_handler_gopher, -#else - NULL, -#endif -#ifndef CURL_DISABLE_TFTP - &Curl_handler_tftp, -#else - NULL, -#endif - NULL, NULL, NULL, -#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP) - &Curl_handler_ftps, -#else - NULL, -#endif -#ifndef CURL_DISABLE_HTTP - &Curl_handler_http, -#else - NULL, -#endif -#ifndef CURL_DISABLE_IMAP - &Curl_handler_imap, -#else - NULL, -#endif -#ifdef USE_LIBRTMP - &Curl_handler_rtmps, -#else - NULL, -#endif -#ifdef USE_LIBRTMP - &Curl_handler_rtmpt, -#else - NULL, -#endif - NULL, NULL, NULL, -#if !defined(CURL_DISABLE_LDAP) && \ - !defined(CURL_DISABLE_LDAPS) && \ - ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ - (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) - &Curl_handler_ldaps, -#else - NULL, -#endif -#if defined(USE_WEBSOCKETS) && \ - defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) - &Curl_handler_wss, -#else - NULL, -#endif -#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) - &Curl_handler_https, -#else - NULL, -#endif - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -#ifndef CURL_DISABLE_RTSP - &Curl_handler_rtsp, -#else - NULL, -#endif -#if defined(USE_SSL) && !defined(CURL_DISABLE_SMB) && \ - defined(USE_CURL_NTLM_CORE) && (SIZEOF_CURL_OFF_T > 4) - &Curl_handler_smbs, -#else - NULL, -#endif -#if defined(USE_SSH) && !defined(USE_WOLFSSH) - &Curl_handler_scp, -#else - NULL, -#endif - NULL, NULL, NULL, -#ifndef CURL_DISABLE_POP3 - &Curl_handler_pop3, -#else - NULL, -#endif - NULL, NULL, -#ifdef USE_LIBRTMP - &Curl_handler_rtmp, -#else - NULL, -#endif - NULL, NULL, NULL, -#ifdef USE_LIBRTMP - &Curl_handler_rtmpte, -#else - NULL, -#endif - NULL, NULL, NULL, -#ifndef CURL_DISABLE_DICT - &Curl_handler_dict, -#else - NULL, -#endif - NULL, NULL, NULL, -#ifndef CURL_DISABLE_MQTT - &Curl_handler_mqtt, -#else - NULL, -#endif -#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3) - &Curl_handler_pop3s, -#else - NULL, -#endif -#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP) - &Curl_handler_imaps, -#else - NULL, -#endif - NULL, -#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP) - &Curl_handler_ws, -#else - NULL, -#endif - NULL, -#ifdef USE_LIBRTMP - &Curl_handler_rtmpts, -#else - NULL, -#endif -#ifndef CURL_DISABLE_LDAP - &Curl_handler_ldap, -#else - NULL, -#endif - NULL, NULL, -#ifndef CURL_DISABLE_FTP - &Curl_handler_ftp, -#else - NULL, -#endif - }; - - if(len && (len <= 7)) { - const char *s = scheme; - size_t l = len; - const struct Curl_handler *h; - unsigned int c = 978; - while(l) { - c <<= 5; - c += Curl_raw_tolower(*s); - s++; - l--; - } - - h = protocols[c % 67]; - if(h && strncasecompare(scheme, h->scheme, len) && !h->scheme[len]) - return h; - } - return NULL; + const struct Curl_handler * const *pp; + const struct Curl_handler *p; + /* Scan protocol handler table and match against 'scheme'. The handler may + be changed later when the protocol specific setup function is called. */ + if(schemelen == CURL_ZERO_TERMINATED) + schemelen = strlen(scheme); + for(pp = protocols; (p = *pp) != NULL; pp++) + if(strncasecompare(p->scheme, scheme, schemelen) && !p->scheme[schemelen]) + /* Protocol found in table. */ + return p; + return NULL; /* not found */ } + static CURLcode findprotocol(struct Curl_easy *data, struct connectdata *conn, const char *protostr) { - const struct Curl_handler *p = Curl_get_scheme_handler(protostr); + const struct Curl_handler *p = Curl_builtin_scheme(protostr, + CURL_ZERO_TERMINATED); if(p && /* Protocol found in table. Check if allowed */ (data->set.allowed_protocols & p->protocol)) { @@ -1672,6 +1652,7 @@ static CURLcode findprotocol(struct Curl_easy *data, else { /* Perform setup complement if some. */ conn->handler = conn->given = p; + /* 'port' and 'remote_port' are set in setup_connection_internals() */ return CURLE_OK; } @@ -1724,14 +1705,14 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data, conn->scope_id = (unsigned int)scope; #if defined(HAVE_IF_NAMETOINDEX) else { -#elif defined(_WIN32) +#elif defined(WIN32) else if(Curl_if_nametoindex) { #endif -#if defined(HAVE_IF_NAMETOINDEX) || defined(_WIN32) +#if defined(HAVE_IF_NAMETOINDEX) || defined(WIN32) /* Zone identifier is not numeric */ unsigned int scopeidx = 0; -#if defined(_WIN32) +#if defined(WIN32) scopeidx = Curl_if_nametoindex(zoneid); #else scopeidx = if_nametoindex(zoneid); @@ -1746,7 +1727,7 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data, else conn->scope_id = scopeidx; } -#endif /* HAVE_IF_NAMETOINDEX || _WIN32 */ +#endif /* HAVE_IF_NAMETOINDEX || WIN32 */ free(zoneid); } @@ -3615,10 +3596,85 @@ static CURLcode create_conn(struct Curl_easy *data, conn->send[SECONDARYSOCKET] = Curl_conn_send; conn->bits.tcp_fastopen = data->set.tcp_fastopen; - /* Complete the easy's SSL configuration for connection cache matching */ - result = Curl_ssl_easy_config_complete(data); - if(result) + /* Get a cloned copy of the SSL config situation stored in the + connection struct. But to get this going nicely, we must first make + sure that the strings in the master copy are pointing to the correct + strings in the session handle strings array! + + Keep in mind that the pointers in the master copy are pointing to strings + that will be freed as part of the Curl_easy struct, but all cloned + copies will be separately allocated. + */ + data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH]; + data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE]; + data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT]; + data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT]; + data->set.ssl.primary.cipher_list = + data->set.str[STRING_SSL_CIPHER_LIST]; + data->set.ssl.primary.cipher_list13 = + data->set.str[STRING_SSL_CIPHER13_LIST]; + data->set.ssl.primary.pinned_key = + data->set.str[STRING_SSL_PINNEDPUBLICKEY]; + data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT]; + data->set.ssl.primary.ca_info_blob = data->set.blobs[BLOB_CAINFO]; + data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES]; + +#ifndef CURL_DISABLE_PROXY + data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY]; + data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY]; + data->set.proxy_ssl.primary.cipher_list = + data->set.str[STRING_SSL_CIPHER_LIST_PROXY]; + data->set.proxy_ssl.primary.cipher_list13 = + data->set.str[STRING_SSL_CIPHER13_LIST_PROXY]; + data->set.proxy_ssl.primary.pinned_key = + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]; + data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY]; + data->set.proxy_ssl.primary.ca_info_blob = + data->set.blobs[BLOB_CAINFO_PROXY]; + data->set.proxy_ssl.primary.issuercert = + data->set.str[STRING_SSL_ISSUERCERT_PROXY]; + data->set.proxy_ssl.primary.issuercert_blob = + data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY]; + data->set.proxy_ssl.primary.CRLfile = + data->set.str[STRING_SSL_CRLFILE_PROXY]; + data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY]; + data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY]; + data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY]; + data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY]; + data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY]; + data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY]; +#endif + data->set.ssl.primary.CRLfile = data->set.str[STRING_SSL_CRLFILE]; + data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE]; + data->set.ssl.key = data->set.str[STRING_KEY]; + data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE]; + data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD]; + data->set.ssl.primary.clientcert = data->set.str[STRING_CERT]; +#ifdef USE_TLS_SRP + data->set.ssl.primary.username = data->set.str[STRING_TLSAUTH_USERNAME]; + data->set.ssl.primary.password = data->set.str[STRING_TLSAUTH_PASSWORD]; +#ifndef CURL_DISABLE_PROXY + data->set.proxy_ssl.primary.username = + data->set.str[STRING_TLSAUTH_USERNAME_PROXY]; + data->set.proxy_ssl.primary.password = + data->set.str[STRING_TLSAUTH_PASSWORD_PROXY]; +#endif +#endif + data->set.ssl.key_blob = data->set.blobs[BLOB_KEY]; + + if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary, + &conn->ssl_config)) { + result = CURLE_OUT_OF_MEMORY; goto out; + } + +#ifndef CURL_DISABLE_PROXY + if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary, + &conn->proxy_ssl_config)) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } +#endif prune_dead_connections(data); @@ -3733,41 +3789,7 @@ static CURLcode create_conn(struct Curl_easy *data, * This is a brand new connection, so let's store it in the connection * cache of ours! */ - result = Curl_ssl_conn_config_init(data, conn); - if(result) { - DEBUGF(fprintf(stderr, "Error: init connection ssl config\n")); - goto out; - } - - result = Curl_resolver_init(data, &conn->resolve_async.resolver); - if(result) { - DEBUGF(fprintf(stderr, "Error: resolver_init failed\n")); - goto out; - } - Curl_attach_connection(data, conn); - -#ifdef USE_ARES - result = Curl_set_dns_servers(data, data->set.str[STRING_DNS_SERVERS]); - if(result && result != CURLE_NOT_BUILT_IN) - goto out; - - result = Curl_set_dns_interface(data, - data->set.str[STRING_DNS_INTERFACE]); - if(result && result != CURLE_NOT_BUILT_IN) - goto out; - - result = Curl_set_dns_local_ip4(data, - data->set.str[STRING_DNS_LOCAL_IP4]); - if(result && result != CURLE_NOT_BUILT_IN) - goto out; - - result = Curl_set_dns_local_ip6(data, - data->set.str[STRING_DNS_LOCAL_IP6]); - if(result && result != CURLE_NOT_BUILT_IN) - goto out; -#endif /* USE_ARES */ - result = Curl_conncache_add_conn(data); if(result) goto out; @@ -3954,7 +3976,6 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn) k->bytecount = 0; k->ignorebody = FALSE; - Curl_client_cleanup(data); Curl_speedinit(data); Curl_pgrsSetUploadCounter(data, 0); Curl_pgrsSetDownloadCounter(data, 0); diff --git a/deps/curl/lib/url.h b/deps/curl/lib/url.h index 7c1a29bc..f6a5b257 100644 --- a/deps/curl/lib/url.h +++ b/deps/curl/lib/url.h @@ -46,13 +46,8 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len, char **userptr, char **passwdptr, char **optionsptr); -/* Get protocol handler for a URI scheme - * @param scheme URI scheme, case-insensitive - * @return NULL of handler not found - */ -const struct Curl_handler *Curl_get_scheme_handler(const char *scheme); -const struct Curl_handler *Curl_getn_scheme_handler(const char *scheme, - size_t len); +const struct Curl_handler *Curl_builtin_scheme(const char *scheme, + size_t schemelen); #define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */ #define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless diff --git a/deps/curl/lib/urlapi.c b/deps/curl/lib/urlapi.c index 0d11e48c..4efab611 100644 --- a/deps/curl/lib/urlapi.c +++ b/deps/curl/lib/urlapi.c @@ -206,7 +206,7 @@ size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen, (void)buflen; /* only used in debug-builds */ if(buf) buf[0] = 0; /* always leave a defined value in buf */ -#ifdef _WIN32 +#ifdef WIN32 if(guess_scheme && STARTS_WITH_DRIVE_PREFIX(url)) return 0; #endif @@ -446,7 +446,7 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u, /* if this is a known scheme, get some details */ if(u->scheme) - h = Curl_get_scheme_handler(u->scheme); + h = Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED); /* We could use the login information in the URL so extract it. Only parse options if the handler says we should. Note that 'h' might be NULL! */ @@ -1056,7 +1056,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) ptr += 9; /* now points to the slash after the host */ } else { -#if defined(_WIN32) +#if defined(WIN32) size_t len; /* the host name, NetBIOS computer name, can not contain disallowed @@ -1095,7 +1095,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) /* no host for file: URLs by default */ Curl_dyn_reset(&host); -#if !defined(_WIN32) && !defined(MSDOS) && !defined(__CYGWIN__) +#if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__) /* Don't allow Windows drive letters when not in Windows. * This catches both "file:/c:" and "file:c:" */ if(('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) || @@ -1129,7 +1129,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) } schemep = schemebuf; - if(!Curl_get_scheme_handler(schemep) && + if(!Curl_builtin_scheme(schemep, CURL_ZERO_TERMINATED) && !(flags & CURLU_NON_SUPPORT_SCHEME)) { result = CURLUE_UNSUPPORTED_SCHEME; goto fail; @@ -1224,14 +1224,14 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) if(flags & CURLU_URLENCODE) { struct dynbuf enc; Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH); - if(urlencode_str(&enc, fragment + 1, fraglen - 1, TRUE, FALSE)) { + if(urlencode_str(&enc, fragment + 1, fraglen, TRUE, FALSE)) { result = CURLUE_OUT_OF_MEMORY; goto fail; } u->fragment = Curl_dyn_ptr(&enc); } else { - u->fragment = Curl_strndup(fragment + 1, fraglen - 1); + u->fragment = Curl_memdup(fragment + 1, fraglen); if(!u->fragment) { result = CURLUE_OUT_OF_MEMORY; goto fail; @@ -1260,11 +1260,12 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) u->query = Curl_dyn_ptr(&enc); } else { - u->query = Curl_strndup(query + 1, qlen - 1); + u->query = Curl_memdup(query + 1, qlen); if(!u->query) { result = CURLUE_OUT_OF_MEMORY; goto fail; } + u->query[qlen - 1] = 0; } } else { @@ -1294,11 +1295,12 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) } else { if(!u->path) { - u->path = Curl_strndup(path, pathlen); + u->path = Curl_memdup(path, pathlen + 1); if(!u->path) { result = CURLUE_OUT_OF_MEMORY; goto fail; } + u->path[pathlen] = 0; path = u->path; } else if(flags & CURLU_URLENCODE) @@ -1350,7 +1352,7 @@ static CURLUcode parseurl_and_replace(const char *url, CURLU *u, */ CURLU *curl_url(void) { - return calloc(1, sizeof(struct Curl_URL)); + return calloc(sizeof(struct Curl_URL), 1); } void curl_url_cleanup(CURLU *u) @@ -1372,7 +1374,7 @@ void curl_url_cleanup(CURLU *u) CURLU *curl_url_dup(const CURLU *in) { - struct Curl_URL *u = calloc(1, sizeof(struct Curl_URL)); + struct Curl_URL *u = calloc(sizeof(struct Curl_URL), 1); if(u) { DUP(u, in, scheme); DUP(u, in, user); @@ -1445,7 +1447,8 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what, if(!ptr && (flags & CURLU_DEFAULT_PORT) && u->scheme) { /* there's no stored port number, but asked to deliver a default one for the scheme */ - const struct Curl_handler *h = Curl_get_scheme_handler(u->scheme); + const struct Curl_handler *h = + Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED); if(h) { msnprintf(portbuf, sizeof(portbuf), "%u", h->defport); ptr = portbuf; @@ -1454,7 +1457,8 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what, else if(ptr && u->scheme) { /* there is a stored port number, but ask to inhibit if it matches the default one for the scheme */ - const struct Curl_handler *h = Curl_get_scheme_handler(u->scheme); + const struct Curl_handler *h = + Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED); if(h && (h->defport == u->portnum) && (flags & CURLU_NO_DEFAULT_PORT)) ptr = NULL; @@ -1499,7 +1503,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what, else return CURLUE_NO_SCHEME; - h = Curl_get_scheme_handler(scheme); + h = Curl_builtin_scheme(scheme, CURL_ZERO_TERMINATED); if(!port && (flags & CURLU_DEFAULT_PORT)) { /* there's no stored port number, but asked to deliver a default one for the scheme */ @@ -1592,7 +1596,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what, if(ptr) { size_t partlen = strlen(ptr); size_t i = 0; - *part = Curl_strndup(ptr, partlen); + *part = Curl_memdup(ptr, partlen + 1); if(!*part) return CURLUE_OUT_OF_MEMORY; if(plusdecode) { @@ -1739,8 +1743,9 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what, if((plen > MAX_SCHEME_LEN) || (plen < 1)) /* too long or too short */ return CURLUE_BAD_SCHEME; - /* verify that it is a fine scheme */ - if(!(flags & CURLU_NON_SUPPORT_SCHEME) && !Curl_get_scheme_handler(part)) + if(!(flags & CURLU_NON_SUPPORT_SCHEME) && + /* verify that it is a fine scheme */ + !Curl_builtin_scheme(part, CURL_ZERO_TERMINATED)) return CURLUE_UNSUPPORTED_SCHEME; storep = &u->scheme; urlencode = FALSE; /* never */ @@ -1900,7 +1905,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what, } newp = Curl_dyn_ptr(&enc); - if(appendquery && newp) { + if(appendquery) { /* Append the 'newp' string onto the old query. Add a '&' separator if none is present at the end of the existing query already */ @@ -1929,8 +1934,8 @@ nomem: } } - else if(what == CURLUPART_HOST) { - size_t n = Curl_dyn_len(&enc); + if(what == CURLUPART_HOST) { + size_t n = strlen(newp); if(!n && (flags & CURLU_NO_AUTHORITY)) { /* Skip hostname check, it's allowed to be empty. */ } diff --git a/deps/curl/lib/urldata.h b/deps/curl/lib/urldata.h index ff661482..dff26e6b 100644 --- a/deps/curl/lib/urldata.h +++ b/deps/curl/lib/urldata.h @@ -266,13 +266,6 @@ typedef enum { /* SSL backend-specific data; declared differently by each SSL backend */ struct ssl_backend_data; -struct ssl_peer { - char *hostname; /* hostname for verification */ - char *dispname; /* display version of hostname */ - char *sni; /* SNI version of hostname or NULL if not usable */ - BIT(is_ip_address); /* if hostname is an IPv4|6 address */ -}; - struct ssl_primary_config { char *CApath; /* certificate dir (doesn't work on windows) */ char *CAfile; /* certificate to verify peer against */ @@ -578,13 +571,6 @@ struct hostname { #define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_PAUSE) #define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE) -/* transfer wants to send is not PAUSE or HOLD */ -#define CURL_WANT_SEND(data) \ - (((data)->req.keepon & KEEP_SENDBITS) == KEEP_SEND) -/* transfer receive is not on PAUSE or HOLD */ -#define CURL_WANT_RECV(data) \ - (!((data)->req.keepon & (KEEP_RECV_PAUSE|KEEP_RECV_HOLD))) - #if defined(CURLRES_ASYNCH) || !defined(CURL_DISABLE_DOH) #define USE_CURL_ASYNC struct Curl_async { @@ -603,15 +589,6 @@ struct Curl_async { #define FIRSTSOCKET 0 #define SECONDARYSOCKET 1 -/* Polling requested by an easy handle. - * `action` is CURL_POLL_IN, CURL_POLL_OUT or CURL_POLL_INOUT. - */ -struct easy_pollset { - curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE]; - unsigned int num; - unsigned char actions[MAX_SOCKSPEREASYHANDLE]; -}; - enum expect100 { EXP100_SEND_DATA, /* enough waiting, just send the body now */ EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */ @@ -672,8 +649,16 @@ struct SingleRequest { counter to make only a 100 reply (without a following second response code) result in a CURLE_GOT_NOTHING error code */ + enum { + HEADER_NORMAL, /* no bad header at all */ + HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest + is normal data */ + HEADER_ALLBAD /* all was believed to be header */ + } badheader; /* the header was deemed bad and will be + written as body */ int headerline; /* counts header lines to better track the first one */ + char *str; /* within buf */ curl_off_t offset; /* possible resume offset read from the Content-Range: header */ int httpcode; /* error code from the 'HTTP/1.? XXX' or @@ -684,7 +669,7 @@ struct SingleRequest { enum upgrade101 upgr101; /* 101 upgrade state */ /* Content unencoding stack. See sec 3.5, RFC2616. */ - struct Curl_cwriter *writer_stack; + struct contenc_writer *writer_stack; time_t timeofdoc; long bodywrites; char *location; /* This points to an allocated version of the Location: @@ -721,20 +706,16 @@ struct SingleRequest { #ifndef CURL_DISABLE_DOH struct dohdata *doh; /* DoH specific data for this request */ #endif -#if defined(_WIN32) && defined(USE_WINSOCK) +#if defined(WIN32) && defined(USE_WINSOCK) struct curltime last_sndbuf_update; /* last time readwrite_upload called win_update_buffer_size */ #endif - char fread_eof[2]; /* the body read callback (index 0) returned EOF or - the trailer read callback (index 1) returned EOF */ #ifndef CURL_DISABLE_COOKIES unsigned char setcookies; #endif unsigned char writer_stack_depth; /* Unencoding stack depth. */ BIT(header); /* incoming data has HTTP header */ - BIT(badheader); /* header parsing found sth not a header */ BIT(content_range); /* set TRUE if Content-Range: was found */ - BIT(download_done); /* set to TRUE when download is complete */ BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding upload and we're uploading the last chunk */ BIT(ignorebody); /* we read a response-body but we ignore it! */ @@ -818,8 +799,7 @@ struct Curl_handler { /* If used, this function gets called from transfer.c:readwrite_data() to allow the protocol to do extra reads/writes */ CURLcode (*readwrite)(struct Curl_easy *data, struct connectdata *conn, - const char *buf, size_t blen, - size_t *pconsumed, bool *readmore); + ssize_t *nread, bool *readmore); /* This function can perform various checks on the connection. See CONNCHECK_* for more information about the checks that can be performed, @@ -921,9 +901,6 @@ struct connectdata { multi_done(). This entry will be NULL if the connection is reused as then there is no name resolve done. */ struct Curl_dns_entry *dns_entry; -#ifdef USE_CURL_ASYNC - struct Curl_async resolve_async; /* asynchronous name resolver data */ -#endif /* 'remote_addr' is the particular IP we connected to. it is owned, set * and NULLed by the connected socket filter (if there is one). */ @@ -1348,8 +1325,7 @@ struct UrlState { curl_off_t recent_conn_id; /* The most recent connection used, might no * longer exist */ struct dynbuf headerb; /* buffer to store headers in */ - struct curl_slist *hstslist; /* list of HSTS files set by - curl_easy_setopt(HSTS) calls */ + char *buffer; /* download buffer */ char *ulbuf; /* allocated upload buffer or NULL */ curl_off_t current_speed; /* the ProgressShow() function sets this, @@ -1382,6 +1358,9 @@ struct UrlState { #endif struct auth authhost; /* auth details for host */ struct auth authproxy; /* auth details for proxy */ +#ifdef USE_CURL_ASYNC + struct Curl_async async; /* asynchronous name resolver data */ +#endif #if defined(USE_OPENSSL) /* void instead of ENGINE to avoid bleeding OpenSSL into this header */ @@ -1394,7 +1373,7 @@ struct UrlState { /* a place to store the most recently set (S)FTP entrypath */ char *most_recent_ftp_entrypath; -#if !defined(_WIN32) && !defined(MSDOS) && !defined(__EMX__) +#if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__) /* do FTP line-end conversions on most platforms */ #define CURL_DO_LINEEND_CONV /* for FTP downloads: track CRLF sequences that span blocks */ @@ -1432,7 +1411,7 @@ struct UrlState { this should be dealt with in pretransfer */ #ifndef CURL_DISABLE_HTTP curl_mimepart *mimepost; - curl_mimepart *formp; /* storage for old API form-posting, allocated on + curl_mimepart *formp; /* storage for old API form-posting, alloced on demand */ size_t trailers_bytes_sent; struct dynbuf trailers_buf; /* a buffer containing the compiled trailing @@ -1443,10 +1422,6 @@ struct UrlState { trailers_state trailers_state; /* whether we are sending trailers and what stage are we at */ #endif -#ifndef CURL_DISABLE_COOKIES - struct curl_slist *cookielist; /* list of cookie files set by - curl_easy_setopt(COOKIEFILE) calls */ -#endif #ifdef USE_HYPER bool hconnect; /* set if a CONNECT request */ CURLcode hresult; /* used to pass return codes back from hyper callbacks */ @@ -1523,9 +1498,6 @@ struct UrlState { though it will be discarded. We must call the data rewind callback before trying to send again. */ BIT(upload); /* upload request */ - BIT(internal); /* internal: true if this easy handle was created for - internal use and the user does not have ownership of the - handle. */ }; /* @@ -1702,7 +1674,13 @@ struct UserDefined { void *prereq_userp; /* pre-initial request user data */ void *seek_client; /* pointer to pass to the seek callback */ +#ifndef CURL_DISABLE_COOKIES + struct curl_slist *cookielist; /* list of cookie files set by + curl_easy_setopt(COOKIEFILE) calls */ +#endif #ifndef CURL_DISABLE_HSTS + struct curl_slist *hstslist; /* list of HSTS files set by + curl_easy_setopt(HSTS) calls */ curl_hstsread_callback hsts_read; void *hsts_read_userp; curl_hstswrite_callback hsts_write; @@ -1802,6 +1780,9 @@ struct UserDefined { #endif curl_prot_t allowed_protocols; curl_prot_t redir_protocols; +#ifndef CURL_DISABLE_MIME + unsigned int mime_options; /* Mime option flags. */ +#endif #ifndef CURL_DISABLE_RTSP void *rtp_out; /* write RTP to this if non-NULL */ /* Common RTSP header options */ @@ -1824,6 +1805,8 @@ struct UserDefined { int tcp_keepidle; /* seconds in idle before sending keepalive probe */ int tcp_keepintvl; /* seconds between TCP keepalive probes */ + size_t maxconnects; /* Max idle connections in the connection cache */ + long expect_100_timeout; /* in milliseconds */ #if defined(USE_HTTP2) || defined(USE_HTTP3) struct Curl_data_priority priority; @@ -1848,14 +1831,10 @@ struct UserDefined { BIT(mail_rcpt_allowfails); /* allow RCPT TO command to fail for some recipients */ #endif - unsigned int maxconnects; /* Max idle connections in the connection cache */ unsigned char use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or IMAP or POP3 or others! (type: curl_usessl)*/ unsigned char connect_only; /* make connection/request, then let application use the socket */ -#ifndef CURL_DISABLE_MIME - BIT(mime_formescape); -#endif BIT(is_fread_set); /* has read callback been set to non-NULL? */ #ifndef CURL_DISABLE_TFTP BIT(tftp_no_options); /* do not send TFTP options requests */ @@ -1992,7 +1971,10 @@ struct Curl_easy { particular order. Note that all sockets are added to the sockhash, where the state etc are also kept. This array is mostly used to detect when a socket is to be removed from the hash. See singlesocket(). */ - struct easy_pollset last_poll; + curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE]; + unsigned char actions[MAX_SOCKSPEREASYHANDLE]; /* action for each socket in + sockets[] */ + int numsocks; struct Names dns; struct Curl_multi *multi; /* if non-NULL, points to the multi handle @@ -2031,6 +2013,10 @@ struct Curl_easy { #ifdef USE_HYPER struct hyptransfer hyp; #endif + + /* internal: true if this easy handle was created for internal use and the + user does not have ownership of the handle. */ + bool internal; }; #define LIBCURL_NAME "libcurl" diff --git a/deps/curl/lib/vauth/digest.c b/deps/curl/lib/vauth/digest.c index 416da0fc..12c6f7dd 100644 --- a/deps/curl/lib/vauth/digest.c +++ b/deps/curl/lib/vauth/digest.c @@ -125,6 +125,7 @@ bool Curl_auth_digest_get_pair(const char *str, char *value, char *content, } else return FALSE; + break; } } diff --git a/deps/curl/lib/version.c b/deps/curl/lib/version.c index f957f085..47304259 100644 --- a/deps/curl/lib/version.c +++ b/deps/curl/lib/version.c @@ -39,7 +39,7 @@ #ifdef USE_ARES # if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \ - defined(_WIN32) + defined(WIN32) # define CARES_STATICLIB # endif # include @@ -409,8 +409,7 @@ static int idn_present(curl_version_info_data *info) #define idn_present NULL #endif -#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY) && \ - !defined(CURL_DISABLE_HTTP) +#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY) static int https_proxy_present(curl_version_info_data *info) { (void) info; @@ -455,14 +454,13 @@ static const struct feat features_table[] = { #ifndef CURL_DISABLE_HSTS FEATURE("HSTS", NULL, CURL_VERSION_HSTS), #endif -#if defined(USE_NGHTTP2) +#if defined(USE_NGHTTP2) || defined(USE_HYPER) FEATURE("HTTP2", NULL, CURL_VERSION_HTTP2), #endif #if defined(ENABLE_QUIC) FEATURE("HTTP3", NULL, CURL_VERSION_HTTP3), #endif -#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY) && \ - !defined(CURL_DISABLE_HTTP) +#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY) FEATURE("HTTPS-proxy", https_proxy_present, CURL_VERSION_HTTPS_PROXY), #endif #if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN) @@ -512,7 +510,7 @@ static const struct feat features_table[] = { #ifdef CURLDEBUG FEATURE("TrackMemory", NULL, CURL_VERSION_CURLDEBUG), #endif -#if defined(_WIN32) && defined(UNICODE) && defined(_UNICODE) +#if defined(WIN32) && defined(UNICODE) && defined(_UNICODE) FEATURE("Unicode", NULL, CURL_VERSION_UNICODE), #endif #ifdef USE_UNIX_SOCKETS diff --git a/deps/curl/lib/version_win32.c b/deps/curl/lib/version_win32.c index e0f239e1..872d5b4f 100644 --- a/deps/curl/lib/version_win32.c +++ b/deps/curl/lib/version_win32.c @@ -24,7 +24,7 @@ #include "curl_setup.h" -#if defined(_WIN32) +#if defined(WIN32) #include #include "version_win32.h" @@ -316,4 +316,4 @@ bool curlx_verify_windows_version(const unsigned int majorVersion, return matched; } -#endif /* _WIN32 */ +#endif /* WIN32 */ diff --git a/deps/curl/lib/version_win32.h b/deps/curl/lib/version_win32.h index 95c06611..3899174a 100644 --- a/deps/curl/lib/version_win32.h +++ b/deps/curl/lib/version_win32.h @@ -26,7 +26,7 @@ #include "curl_setup.h" -#if defined(_WIN32) +#if defined(WIN32) /* Version condition */ typedef enum { @@ -51,6 +51,6 @@ bool curlx_verify_windows_version(const unsigned int majorVersion, const PlatformIdentifier platform, const VersionCondition condition); -#endif /* _WIN32 */ +#endif /* WIN32 */ #endif /* HEADER_CURL_VERSION_WIN32_H */ diff --git a/deps/curl/lib/vquic/curl_msh3.c b/deps/curl/lib/vquic/curl_msh3.c index 8ae36724..6bd0d233 100644 --- a/deps/curl/lib/vquic/curl_msh3.c +++ b/deps/curl/lib/vquic/curl_msh3.c @@ -38,7 +38,6 @@ #include "http1.h" #include "curl_msh3.h" #include "socketpair.h" -#include "vtls/vtls.h" #include "vquic/vquic.h" /* The last 3 #include files should be in this order */ @@ -46,10 +45,6 @@ #include "curl_memory.h" #include "memdebug.h" -#ifdef CURL_DISABLE_SOCKETPAIR -#error "MSH3 cannot be build with CURL_DISABLE_SOCKETPAIR set" -#endif - #define H3_STREAM_WINDOW_SIZE (128 * 1024) #define H3_STREAM_CHUNK_SIZE (16 * 1024) #define H3_STREAM_RECV_CHUNKS \ @@ -677,25 +672,31 @@ out: return nwritten; } -static void cf_msh3_adjust_pollset(struct Curl_cfilter *cf, - struct Curl_easy *data, - struct easy_pollset *ps) +static int cf_msh3_get_select_socks(struct Curl_cfilter *cf, + struct Curl_easy *data, + curl_socket_t *socks) { struct cf_msh3_ctx *ctx = cf->ctx; struct stream_ctx *stream = H3_STREAM_CTX(data); + int bitmap = GETSOCK_BLANK; struct cf_call_data save; CF_DATA_SAVE(save, cf, data); if(stream && ctx->sock[SP_LOCAL] != CURL_SOCKET_BAD) { + socks[0] = ctx->sock[SP_LOCAL]; + if(stream->recv_error) { - Curl_pollset_add_in(data, ps, ctx->sock[SP_LOCAL]); + bitmap |= GETSOCK_READSOCK(0); drain_stream(cf, data); } else if(stream->req) { - Curl_pollset_add_out(data, ps, ctx->sock[SP_LOCAL]); + bitmap |= GETSOCK_READSOCK(0); drain_stream(cf, data); } } + CURL_TRC_CF(data, cf, "select_sock -> %d", bitmap); + CF_DATA_RESTORE(cf, save); + return bitmap; } static bool cf_msh3_data_pending(struct Curl_cfilter *cf, @@ -801,20 +802,14 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf, struct Curl_easy *data) { struct cf_msh3_ctx *ctx = cf->ctx; - struct ssl_primary_config *conn_config; + bool verify = !!cf->conn->ssl_config.verifypeer; MSH3_ADDR addr = {0}; CURLcode result; - bool verify; - - conn_config = Curl_ssl_cf_get_primary_config(cf); - if(!conn_config) - return CURLE_FAILED_INIT; - verify = !!conn_config->verifypeer; memcpy(&addr, &ctx->addr.sa_addr, ctx->addr.addrlen); MSH3_SET_PORT(&addr, (uint16_t)cf->conn->remote_port); - if(verify && (conn_config->CAfile || conn_config->CApath)) { + if(verify && (cf->conn->ssl_config.CAfile || cf->conn->ssl_config.CApath)) { /* TODO: need a way to provide trust anchors to MSH3 */ #ifdef DEBUGBUILD /* we need this for our test cases to run */ @@ -1030,7 +1025,7 @@ struct Curl_cftype Curl_cft_http3 = { cf_msh3_connect, cf_msh3_close, Curl_cf_def_get_host, - cf_msh3_adjust_pollset, + cf_msh3_get_select_socks, cf_msh3_data_pending, cf_msh3_send, cf_msh3_recv, @@ -1052,7 +1047,7 @@ CURLcode Curl_cf_msh3_create(struct Curl_cfilter **pcf, (void)data; (void)conn; (void)ai; /* TODO: msh3 resolves itself? */ - ctx = calloc(1, sizeof(*ctx)); + ctx = calloc(sizeof(*ctx), 1); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; diff --git a/deps/curl/lib/vquic/curl_ngtcp2.c b/deps/curl/lib/vquic/curl_ngtcp2.c index 8ba91916..7d681e58 100644 --- a/deps/curl/lib/vquic/curl_ngtcp2.c +++ b/deps/curl/lib/vquic/curl_ngtcp2.c @@ -78,6 +78,7 @@ #define QUIC_MAX_STREAMS (256*1024) #define QUIC_MAX_DATA (1*1024*1024) +#define QUIC_IDLE_TIMEOUT (60*NGTCP2_SECONDS) #define QUIC_HANDSHAKE_TIMEOUT (10*NGTCP2_SECONDS) /* A stream window is the maximum amount we need to buffer for @@ -133,7 +134,6 @@ void Curl_ngtcp2_ver(char *p, size_t len) struct cf_ngtcp2_ctx { struct cf_quic_ctx q; - struct ssl_peer peer; ngtcp2_path connected_path; ngtcp2_conn *qconn; ngtcp2_cid dcid; @@ -161,7 +161,6 @@ struct cf_ngtcp2_ctx { struct curltime reconnect_at; /* time the next attempt should start */ struct bufc_pool stream_bufcp; /* chunk pool for streams */ size_t max_stream_window; /* max flow window for one stream */ - uint64_t max_idle_ms; /* max idle time for QUIC connection */ int qlogfd; BIT(got_first_byte); /* if first byte was received */ #ifdef USE_OPENSSL @@ -192,7 +191,6 @@ struct h3_stream_ctx { bool closed; /* TRUE on stream close */ bool reset; /* TRUE on stream reset */ bool send_closed; /* stream is local closed */ - BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */ }; #define H3_STREAM_CTX(d) ((struct h3_stream_ctx *)(((d) && (d)->req.p.http)? \ @@ -238,20 +236,11 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf, static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data) { - struct cf_ngtcp2_ctx *ctx = cf->ctx; struct h3_stream_ctx *stream = H3_STREAM_CTX(data); (void)cf; if(stream) { CURL_TRC_CF(data, cf, "[%"PRId64"] easy handle is done", stream->id); - if(ctx->h3conn && !stream->closed) { - nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream->id); - nghttp3_conn_close_stream(ctx->h3conn, stream->id, - NGHTTP3_H3_REQUEST_CANCELLED); - nghttp3_conn_set_stream_user_data(ctx->h3conn, stream->id, NULL); - stream->closed = TRUE; - } - Curl_bufq_free(&stream->sendbuf); Curl_bufq_free(&stream->recvbuf); Curl_h1_req_parse_free(&stream->h1); @@ -260,43 +249,6 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data) } } -static struct Curl_easy *get_stream_easy(struct Curl_cfilter *cf, - struct Curl_easy *data, - int64_t stream_id) -{ - struct Curl_easy *sdata; - - (void)cf; - if(H3_STREAM_ID(data) == stream_id) { - return data; - } - else { - DEBUGASSERT(data->multi); - for(sdata = data->multi->easyp; sdata; sdata = sdata->next) { - if((sdata->conn == data->conn) && H3_STREAM_ID(sdata) == stream_id) { - return sdata; - } - } - } - return NULL; -} - -static void h3_drain_stream(struct Curl_cfilter *cf, - struct Curl_easy *data) -{ - struct h3_stream_ctx *stream = H3_STREAM_CTX(data); - unsigned char bits; - - (void)cf; - bits = CURL_CSELECT_IN; - if(stream && stream->upload_left && !stream->send_closed) - bits |= CURL_CSELECT_OUT; - if(data->state.dselect_bits != bits) { - data->state.dselect_bits = bits; - Curl_expire(data, 0, EXPIRE_RUN_NOW); - } -} - /* ngtcp2 default congestion controller does not perform pacing. Limit the maximum packet burst to MAX_PKT_BURST packets. */ #define MAX_PKT_BURST 10 @@ -309,14 +261,10 @@ struct pkt_io_ctx { ngtcp2_path_storage ps; }; -static void pktx_update_time(struct pkt_io_ctx *pktx, - struct Curl_cfilter *cf) +static ngtcp2_tstamp timestamp(void) { - struct cf_ngtcp2_ctx *ctx = cf->ctx; - - vquic_ctx_update_time(&ctx->q); - pktx->ts = ctx->q.last_op.tv_sec * NGTCP2_SECONDS + - ctx->q.last_op.tv_usec * NGTCP2_MICROSECONDS; + struct curltime ct = Curl_now(); + return ct.tv_sec * NGTCP2_SECONDS + ct.tv_usec * NGTCP2_MICROSECONDS; } static void pktx_init(struct pkt_io_ctx *pktx, @@ -325,9 +273,9 @@ static void pktx_init(struct pkt_io_ctx *pktx, { pktx->cf = cf; pktx->data = data; + pktx->ts = timestamp(); pktx->pkt_count = 0; ngtcp2_path_storage_zero(&pktx->ps); - pktx_update_time(pktx, cf); } static CURLcode cf_progress_ingress(struct Curl_cfilter *cf, @@ -406,7 +354,7 @@ static void quic_settings(struct cf_ngtcp2_ctx *ctx, t->initial_max_stream_data_uni = ctx->max_stream_window; t->initial_max_streams_bidi = QUIC_MAX_STREAMS; t->initial_max_streams_uni = QUIC_MAX_STREAMS; - t->max_idle_timeout = (ctx->max_idle_ms * NGTCP2_MILLISECONDS); + t->max_idle_timeout = QUIC_IDLE_TIMEOUT; if(ctx->qlogfd != -1) { s->qlog_write = qlog_callback; } @@ -450,19 +398,14 @@ static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx, struct Curl_cfilter *cf, struct Curl_easy *data) { struct cf_ngtcp2_ctx *ctx = cf->ctx; - struct ssl_primary_config *conn_config; + struct connectdata *conn = cf->conn; CURLcode result = CURLE_FAILED_INIT; - SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method()); + if(!ssl_ctx) { result = CURLE_OUT_OF_MEMORY; goto out; } - conn_config = Curl_ssl_cf_get_primary_config(cf); - if(!conn_config) { - result = CURLE_FAILED_INIT; - goto out; - } #if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC) if(ngtcp2_crypto_boringssl_configure_client_context(ssl_ctx) != 0) { @@ -479,8 +422,8 @@ static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx, SSL_CTX_set_default_verify_paths(ssl_ctx); { - const char *curves = conn_config->curves ? - conn_config->curves : QUIC_GROUPS; + const char *curves = conn->ssl_config.curves ? + conn->ssl_config.curves : QUIC_GROUPS; if(!SSL_CTX_set1_curves_list(ssl_ctx, curves)) { failf(data, "failed setting curves list for QUIC: '%s'", curves); return CURLE_SSL_CIPHER; @@ -489,8 +432,8 @@ static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx, #ifndef OPENSSL_IS_BORINGSSL { - const char *ciphers13 = conn_config->cipher_list13 ? - conn_config->cipher_list13 : QUIC_CIPHERS; + const char *ciphers13 = conn->ssl_config.cipher_list13 ? + conn->ssl_config.cipher_list13 : QUIC_CIPHERS; if(SSL_CTX_set_ciphersuites(ssl_ctx, ciphers13) != 1) { failf(data, "failed setting QUIC cipher suite: %s", ciphers13); return CURLE_SSL_CIPHER; @@ -509,7 +452,7 @@ static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx, * fail to connect if the verification fails, or if it should continue * anyway. In the latter case the result of the verification is checked with * SSL_get_verify_result() below. */ - SSL_CTX_set_verify(ssl_ctx, conn_config->verifypeer ? + SSL_CTX_set_verify(ssl_ctx, conn->ssl_config.verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL); /* give application a chance to interfere with SSL set up. */ @@ -548,7 +491,7 @@ static CURLcode quic_set_client_cert(struct Curl_cfilter *cf, SSL_CTX *ssl_ctx = ctx->sslctx; const struct ssl_config_data *ssl_config; - ssl_config = Curl_ssl_cf_get_config(cf, data); + ssl_config = Curl_ssl_get_config(data, FIRSTSOCKET); DEBUGASSERT(ssl_config); if(ssl_config->primary.clientcert || ssl_config->primary.cert_blob @@ -571,6 +514,7 @@ static CURLcode quic_init_ssl(struct Curl_cfilter *cf, struct cf_ngtcp2_ctx *ctx = cf->ctx; const uint8_t *alpn = NULL; size_t alpnlen = 0; + unsigned char checkip[16]; DEBUGASSERT(!ctx->ssl); ctx->ssl = SSL_new(ctx->sslctx); @@ -585,8 +529,13 @@ static CURLcode quic_init_ssl(struct Curl_cfilter *cf, SSL_set_alpn_protos(ctx->ssl, alpn, (int)alpnlen); /* set SNI */ - if(ctx->peer.sni) { - if(!SSL_set_tlsext_host_name(ctx->ssl, ctx->peer.sni)) { + if((0 == Curl_inet_pton(AF_INET, cf->conn->host.name, checkip)) +#ifdef ENABLE_IPV6 + && (0 == Curl_inet_pton(AF_INET6, cf->conn->host.name, checkip)) +#endif + ) { + char *snihost = Curl_ssl_snihost(data, cf->conn->host.name, NULL); + if(!snihost || !SSL_set_tlsext_host_name(ctx->ssl, snihost)) { failf(data, "Failed set SNI"); SSL_free(ctx->ssl); ctx->ssl = NULL; @@ -600,24 +549,20 @@ static CURLcode quic_init_ssl(struct Curl_cfilter *cf, struct Curl_easy *data) { struct cf_ngtcp2_ctx *ctx = cf->ctx; - struct ssl_primary_config *conn_config; CURLcode result; gnutls_datum_t alpn[2]; /* this will need some attention when HTTPS proxy over QUIC get fixed */ + const char * const hostname = cf->conn->host.name; long * const pverifyresult = &data->set.ssl.certverifyresult; int rc; - conn_config = Curl_ssl_cf_get_primary_config(cf); - if(!conn_config) - return CURLE_FAILED_INIT; - DEBUGASSERT(ctx->gtls == NULL); ctx->gtls = calloc(1, sizeof(*(ctx->gtls))); if(!ctx->gtls) return CURLE_OUT_OF_MEMORY; - result = gtls_client_init(data, conn_config, &data->set.ssl, - &ctx->peer, ctx->gtls, pverifyresult); + result = gtls_client_init(data, &cf->conn->ssl_config, &data->set.ssl, + hostname, ctx->gtls, pverifyresult); if(result) return result; @@ -657,17 +602,10 @@ static CURLcode quic_init_ssl(struct Curl_cfilter *cf, static CURLcode quic_ssl_ctx(WOLFSSL_CTX **pssl_ctx, struct Curl_cfilter *cf, struct Curl_easy *data) { + struct connectdata *conn = cf->conn; CURLcode result = CURLE_FAILED_INIT; - struct ssl_primary_config *conn_config; - WOLFSSL_CTX *ssl_ctx = NULL; + WOLFSSL_CTX *ssl_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()); - conn_config = Curl_ssl_cf_get_primary_config(cf); - if(!conn_config) { - result = CURLE_FAILED_INIT; - goto out; - } - - ssl_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()); if(!ssl_ctx) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -675,14 +613,13 @@ static CURLcode quic_ssl_ctx(WOLFSSL_CTX **pssl_ctx, if(ngtcp2_crypto_wolfssl_configure_client_context(ssl_ctx) != 0) { failf(data, "ngtcp2_crypto_wolfssl_configure_client_context failed"); - result = CURLE_FAILED_INIT; goto out; } wolfSSL_CTX_set_default_verify_paths(ssl_ctx); - if(wolfSSL_CTX_set_cipher_list(ssl_ctx, conn_config->cipher_list13 ? - conn_config->cipher_list13 : + if(wolfSSL_CTX_set_cipher_list(ssl_ctx, conn->ssl_config.cipher_list13 ? + conn->ssl_config.cipher_list13 : QUIC_CIPHERS) != 1) { char error_buffer[256]; ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer)); @@ -690,8 +627,8 @@ static CURLcode quic_ssl_ctx(WOLFSSL_CTX **pssl_ctx, goto out; } - if(wolfSSL_CTX_set1_groups_list(ssl_ctx, conn_config->curves ? - conn_config->curves : + if(wolfSSL_CTX_set1_groups_list(ssl_ctx, conn->ssl_config.curves ? + conn->ssl_config.curves : (char *)QUIC_GROUPS) != 1) { failf(data, "wolfSSL failed to set curves"); goto out; @@ -708,9 +645,9 @@ static CURLcode quic_ssl_ctx(WOLFSSL_CTX **pssl_ctx, #endif } - if(conn_config->verifypeer) { - const char * const ssl_cafile = conn_config->CAfile; - const char * const ssl_capath = conn_config->CApath; + if(conn->ssl_config.verifypeer) { + const char * const ssl_cafile = conn->ssl_config.CAfile; + const char * const ssl_capath = conn->ssl_config.CApath; wolfSSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL); if(ssl_cafile || ssl_capath) { @@ -879,7 +816,7 @@ cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id, (void)stream_user_data; rv = nghttp3_conn_add_ack_offset(ctx->h3conn, stream_id, datalen); - if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) { + if(rv) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -907,7 +844,7 @@ static int cb_stream_close(ngtcp2_conn *tconn, uint32_t flags, app_error_code); CURL_TRC_CF(data, cf, "[%" PRId64 "] quic close(err=%" PRIu64 ") -> %d", stream3_id, app_error_code, rv); - if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) { + if(rv) { ngtcp2_ccerr_set_application_error( &ctx->last_error, nghttp3_err_infer_quic_app_error_code(rv), NULL, 0); return NGTCP2_ERR_CALLBACK_FAILURE; @@ -931,7 +868,7 @@ static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id, rv = nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream_id); CURL_TRC_CF(data, cf, "[%" PRId64 "] reset -> %d", stream_id, rv); - if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) { + if(rv) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -950,7 +887,7 @@ static int cb_stream_stop_sending(ngtcp2_conn *tconn, int64_t stream_id, (void)stream_user_data; rv = nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream_id); - if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) { + if(rv) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -974,25 +911,16 @@ static int cb_extend_max_stream_data(ngtcp2_conn *tconn, int64_t stream_id, { struct Curl_cfilter *cf = user_data; struct cf_ngtcp2_ctx *ctx = cf->ctx; - struct Curl_easy *data = CF_DATA_CURRENT(cf); - struct Curl_easy *s_data; - struct h3_stream_ctx *stream; int rv; (void)tconn; (void)max_data; (void)stream_user_data; rv = nghttp3_conn_unblock_stream(ctx->h3conn, stream_id); - if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) { + if(rv) { return NGTCP2_ERR_CALLBACK_FAILURE; } - s_data = get_stream_easy(cf, data, stream_id); - stream = H3_STREAM_CTX(s_data); - if(stream && stream->quic_flow_blocked) { - CURL_TRC_CF(data, cf, "[%" PRId64 "] unblock quic flow", stream_id); - stream->quic_flow_blocked = FALSE; - h3_drain_stream(cf, data); - } + return 0; } @@ -1110,7 +1038,7 @@ static CURLcode check_and_set_expiry(struct Curl_cfilter *cf, pktx = &local_pktx; } else { - pktx_update_time(pktx, cf); + pktx->ts = timestamp(); } expiry = ngtcp2_conn_get_expiry(ctx->qconn); @@ -1145,29 +1073,46 @@ static CURLcode check_and_set_expiry(struct Curl_cfilter *cf, return CURLE_OK; } -static void cf_ngtcp2_adjust_pollset(struct Curl_cfilter *cf, +static int cf_ngtcp2_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data, - struct easy_pollset *ps) + curl_socket_t *socks) { struct cf_ngtcp2_ctx *ctx = cf->ctx; - bool want_recv = CURL_WANT_RECV(data); - bool want_send = CURL_WANT_SEND(data); + struct SingleRequest *k = &data->req; + int rv = GETSOCK_BLANK; + struct h3_stream_ctx *stream = H3_STREAM_CTX(data); + struct cf_call_data save; - if(ctx->qconn && (want_recv || want_send)) { - struct h3_stream_ctx *stream = H3_STREAM_CTX(data); - struct cf_call_data save; - bool c_exhaust, s_exhaust; + CF_DATA_SAVE(save, cf, data); + socks[0] = ctx->q.sockfd; - CF_DATA_SAVE(save, cf, data); - c_exhaust = !ngtcp2_conn_get_cwnd_left(ctx->qconn) || - !ngtcp2_conn_get_max_data_left(ctx->qconn); - s_exhaust = stream && stream->id >= 0 && stream->quic_flow_blocked; - want_recv = (want_recv || c_exhaust || s_exhaust); - want_send = (!s_exhaust && want_send) || - !Curl_bufq_is_empty(&ctx->q.sendbuf); + /* in HTTP/3 we can always get a frame, so check read */ + rv |= GETSOCK_READSOCK(0); - Curl_pollset_set(data, ps, ctx->q.sockfd, want_recv, want_send); - CF_DATA_RESTORE(cf, save); + /* we're still uploading or the HTTP/2 layer wants to send data */ + if((k->keepon & KEEP_SENDBITS) == KEEP_SEND && + ngtcp2_conn_get_cwnd_left(ctx->qconn) && + ngtcp2_conn_get_max_data_left(ctx->qconn) && + stream && nghttp3_conn_is_stream_writable(ctx->h3conn, stream->id)) + rv |= GETSOCK_WRITESOCK(0); + + CF_DATA_RESTORE(cf, save); + return rv; +} + +static void h3_drain_stream(struct Curl_cfilter *cf, + struct Curl_easy *data) +{ + struct h3_stream_ctx *stream = H3_STREAM_CTX(data); + unsigned char bits; + + (void)cf; + bits = CURL_CSELECT_IN; + if(stream && stream->upload_left && !stream->send_closed) + bits |= CURL_CSELECT_OUT; + if(data->state.dselect_bits != bits) { + data->state.dselect_bits = bits; + Curl_expire(data, 0, EXPIRE_RUN_NOW); } } @@ -1196,6 +1141,7 @@ static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id, else { CURL_TRC_CF(data, cf, "[%" PRId64 "] CLOSED", stream->id); } + data->req.keepon &= ~KEEP_SEND_HOLD; h3_drain_stream(cf, data); return 0; } @@ -1624,9 +1570,15 @@ static int cb_h3_acked_req_body(nghttp3_conn *conn, int64_t stream_id, /* Everything ACKed, we resume upload processing */ if(!stream->sendbuf_len_in_flight) { int rv = nghttp3_conn_resume_stream(conn, stream_id); - if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) { + if(rv) { return NGTCP2_ERR_CALLBACK_FAILURE; } + if((data->req.keepon & KEEP_SEND_HOLD) && + (data->req.keepon & KEEP_SEND)) { + data->req.keepon &= ~KEEP_SEND_HOLD; + h3_drain_stream(cf, data); + CURL_TRC_CF(data, cf, "[%" PRId64 "] unpausing acks", stream_id); + } } return 0; } @@ -1908,13 +1860,15 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data, if(stream && sent > 0 && stream->sendbuf_len_in_flight) { /* We have unacknowledged DATA and cannot report success to our * caller. Instead we EAGAIN and remember how much we have already - * "written" into our various internal connection buffers. */ + * "written" into our various internal connection buffers. + * We put the stream upload on HOLD, until this gets ACKed. */ stream->upload_blocked_len = sent; CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send(len=%zu), " "%zu bytes in flight -> EGAIN", stream->id, len, stream->sendbuf_len_in_flight); *err = CURLE_AGAIN; sent = -1; + data->req.keepon |= KEEP_SEND_HOLD; } out: @@ -1933,37 +1887,40 @@ static CURLcode qng_verify_peer(struct Curl_cfilter *cf, struct Curl_easy *data) { struct cf_ngtcp2_ctx *ctx = cf->ctx; - struct ssl_primary_config *conn_config; CURLcode result = CURLE_OK; + const char *hostname, *disp_hostname; + int port; + char *snihost; - conn_config = Curl_ssl_cf_get_primary_config(cf); - if(!conn_config) - return CURLE_FAILED_INIT; + Curl_conn_get_host(data, cf->sockindex, &hostname, &disp_hostname, &port); + snihost = Curl_ssl_snihost(data, hostname, NULL); + if(!snihost) + return CURLE_PEER_FAILED_VERIFICATION; cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */ cf->conn->httpversion = 30; cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX; - if(conn_config->verifyhost) { + if(cf->conn->ssl_config.verifyhost) { #ifdef USE_OPENSSL X509 *server_cert; - server_cert = SSL_get1_peer_certificate(ctx->ssl); + server_cert = SSL_get_peer_certificate(ctx->ssl); if(!server_cert) { return CURLE_PEER_FAILED_VERIFICATION; } - result = Curl_ossl_verifyhost(data, cf->conn, &ctx->peer, server_cert); + result = Curl_ossl_verifyhost(data, cf->conn, server_cert); X509_free(server_cert); if(result) return result; #elif defined(USE_GNUTLS) result = Curl_gtls_verifyserver(data, ctx->gtls->session, - conn_config, &data->set.ssl, &ctx->peer, + &cf->conn->ssl_config, &data->set.ssl, + hostname, disp_hostname, data->set.str[STRING_SSL_PINNEDPUBLICKEY]); if(result) return result; #elif defined(USE_WOLFSSL) - if(!ctx->peer.sni || - wolfSSL_check_domain_name(ctx->ssl, ctx->peer.sni) == SSL_FAILURE) + if(wolfSSL_check_domain_name(ctx->ssl, snihost) == SSL_FAILURE) return CURLE_PEER_FAILED_VERIFICATION; #endif infof(data, "Verified certificate just fine"); @@ -2036,7 +1993,7 @@ static CURLcode cf_progress_ingress(struct Curl_cfilter *cf, pktx = &local_pktx; } else { - pktx_update_time(pktx, cf); + pktx->ts = timestamp(); } #ifdef USE_OPENSSL @@ -2124,18 +2081,11 @@ static ssize_t read_pkt_to_send(void *userp, } else if(n < 0) { switch(n) { - case NGTCP2_ERR_STREAM_DATA_BLOCKED: { - struct h3_stream_ctx *stream = H3_STREAM_CTX(x->data); + case NGTCP2_ERR_STREAM_DATA_BLOCKED: DEBUGASSERT(ndatalen == -1); nghttp3_conn_block_stream(ctx->h3conn, stream_id); - CURL_TRC_CF(x->data, x->cf, "[%" PRId64 "] block quic flow", - stream_id); - DEBUGASSERT(stream); - if(stream) - stream->quic_flow_blocked = TRUE; n = 0; break; - } case NGTCP2_ERR_STREAM_SHUT_WR: DEBUGASSERT(ndatalen == -1); nghttp3_conn_shutdown_stream_write(ctx->h3conn, stream_id); @@ -2195,7 +2145,7 @@ static CURLcode cf_progress_egress(struct Curl_cfilter *cf, pktx = &local_pktx; } else { - pktx_update_time(pktx, cf); + pktx->ts = timestamp(); ngtcp2_path_storage_zero(&pktx->ps); } @@ -2332,12 +2282,10 @@ static CURLcode cf_ngtcp2_data_event(struct Curl_cfilter *cf, case CF_CTRL_DATA_PAUSE: result = h3_data_pause(cf, data, (arg1 != 0)); break; - case CF_CTRL_DATA_DETACH: - h3_data_done(cf, data); - break; - case CF_CTRL_DATA_DONE: + case CF_CTRL_DATA_DONE: { h3_data_done(cf, data); break; + } case CF_CTRL_DATA_DONE_SEND: { struct h3_stream_ctx *stream = H3_STREAM_CTX(data); if(stream && !stream->send_closed) { @@ -2396,7 +2344,6 @@ static void cf_ngtcp2_ctx_clear(struct cf_ngtcp2_ctx *ctx) if(ctx->qconn) ngtcp2_conn_del(ctx->qconn); Curl_bufcp_free(&ctx->stream_bufcp); - Curl_ssl_peer_cleanup(&ctx->peer); memset(ctx, 0, sizeof(*ctx)); ctx->qlogfd = -1; @@ -2411,15 +2358,15 @@ static void cf_ngtcp2_close(struct Curl_cfilter *cf, struct Curl_easy *data) CF_DATA_SAVE(save, cf, data); if(ctx && ctx->qconn) { char buffer[NGTCP2_MAX_UDP_PAYLOAD_SIZE]; - struct pkt_io_ctx pktx; + ngtcp2_tstamp ts; ngtcp2_ssize rc; CURL_TRC_CF(data, cf, "close"); - pktx_init(&pktx, cf, data); + ts = timestamp(); rc = ngtcp2_conn_write_connection_close(ctx->qconn, NULL, /* path */ NULL, /* pkt_info */ (uint8_t *)buffer, sizeof(buffer), - &ctx->last_error, pktx.ts); + &ctx->last_error, ts); if(rc > 0) { while((send(ctx->q.sockfd, buffer, (SEND_TYPE_ARG3)rc, 0) == -1) && SOCKERRNO == EINTR); @@ -2464,14 +2411,9 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf, ctx->version = NGTCP2_PROTO_VER_MAX; ctx->max_stream_window = H3_STREAM_WINDOW_SIZE; - ctx->max_idle_ms = CURL_QUIC_MAX_IDLE_MS; Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE, H3_STREAM_POOL_SPARES); - result = Curl_ssl_peer_init(&ctx->peer, cf); - if(result) - return result; - #ifdef USE_OPENSSL result = quic_ssl_ctx(&ctx->sslctx, cf, data); if(result) @@ -2617,9 +2559,27 @@ out: ngtcp2_conn_in_draining_period(ctx->qconn)) { /* When a QUIC server instance is shutting down, it may send us a * CONNECTION_CLOSE right away. Our connection then enters the DRAINING - * state. The CONNECT may work in the near future again. Indicate - * that as a "weird" reply. */ - result = CURLE_WEIRD_SERVER_REPLY; + * state. + * This may be a stopping of the service or it may be that the server + * is reloading and a new instance will start serving soon. + * In any case, we tear down our socket and start over with a new one. + * We re-open the underlying UDP cf right now, but do not start + * connecting until called again. + */ + int reconn_delay_ms = 200; + + CURL_TRC_CF(data, cf, "connect, remote closed, reconnect after %dms", + reconn_delay_ms); + Curl_conn_cf_close(cf->next, data); + cf_ngtcp2_ctx_clear(ctx); + result = Curl_conn_cf_connect(cf->next, data, FALSE, done); + if(!result && *done) { + *done = FALSE; + ctx->reconnect_at = now; + ctx->reconnect_at.tv_usec += reconn_delay_ms * 1000; + Curl_expire(data, reconn_delay_ms, EXPIRE_QUIC); + result = CURLE_OK; + } } #ifndef CURL_DISABLE_VERBOSE_STRINGS @@ -2697,32 +2657,9 @@ static bool cf_ngtcp2_conn_is_alive(struct Curl_cfilter *cf, struct Curl_easy *data, bool *input_pending) { - struct cf_ngtcp2_ctx *ctx = cf->ctx; bool alive = TRUE; - const ngtcp2_transport_params *rp; *input_pending = FALSE; - if(!ctx->qconn) - return FALSE; - - /* Both sides of the QUIC connection announce they max idle times in - * the transport parameters. Look at the minimum of both and if - * we exceed this, regard the connection as dead. The other side - * may have completely purged it and will no longer respond - * to any packets from us. */ - rp = ngtcp2_conn_get_remote_transport_params(ctx->qconn); - if(rp) { - timediff_t idletime; - uint64_t idle_ms = ctx->max_idle_ms; - - if(rp->max_idle_timeout && - (rp->max_idle_timeout / NGTCP2_MILLISECONDS) < idle_ms) - idle_ms = (rp->max_idle_timeout / NGTCP2_MILLISECONDS); - idletime = Curl_timediff(Curl_now(), ctx->q.last_io); - if(idletime > 0 && (uint64_t)idletime > idle_ms) - return FALSE; - } - if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending)) return FALSE; @@ -2749,7 +2686,7 @@ struct Curl_cftype Curl_cft_http3 = { cf_ngtcp2_connect, cf_ngtcp2_close, Curl_cf_def_get_host, - cf_ngtcp2_adjust_pollset, + cf_ngtcp2_get_select_socks, cf_ngtcp2_data_pending, cf_ngtcp2_send, cf_ngtcp2_recv, @@ -2769,7 +2706,7 @@ CURLcode Curl_cf_ngtcp2_create(struct Curl_cfilter **pcf, CURLcode result; (void)data; - ctx = calloc(1, sizeof(*ctx)); + ctx = calloc(sizeof(*ctx), 1); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; diff --git a/deps/curl/lib/vquic/curl_quiche.c b/deps/curl/lib/vquic/curl_quiche.c index 7123d63c..3f5d3274 100644 --- a/deps/curl/lib/vquic/curl_quiche.c +++ b/deps/curl/lib/vquic/curl_quiche.c @@ -55,10 +55,10 @@ #include "curl_memory.h" #include "memdebug.h" -/* HTTP/3 error values defined in RFC 9114, ch. 8.1 */ -#define CURL_H3_NO_ERROR (0x0100) +/* #define DEBUG_QUICHE */ #define QUIC_MAX_STREAMS (100) +#define QUIC_IDLE_TIMEOUT (60 * 1000) /* milliseconds */ #define H3_STREAM_WINDOW_SIZE (128 * 1024) #define H3_STREAM_CHUNK_SIZE (16 * 1024) @@ -92,7 +92,6 @@ static void keylog_callback(const SSL *ssl, const char *line) struct cf_quiche_ctx { struct cf_quic_ctx q; - struct ssl_peer peer; quiche_conn *qconn; quiche_config *cfg; quiche_h3_conn *h3c; @@ -106,7 +105,7 @@ struct cf_quiche_ctx { struct curltime reconnect_at; /* time the next attempt should start */ struct bufc_pool stream_bufcp; /* chunk pool for streams */ curl_off_t data_recvd; - uint64_t max_idle_ms; /* max idle time for QUIC conn */ + size_t sends_on_hold; /* # of streams with SEND_HOLD set */ BIT(goaway); /* got GOAWAY from server */ BIT(got_first_byte); /* if first byte was received */ BIT(x509_store_setup); /* if x509 store has been set up */ @@ -133,8 +132,6 @@ static void cf_quiche_ctx_clear(struct cf_quiche_ctx *ctx) if(ctx->cfg) quiche_config_free(ctx->cfg); Curl_bufcp_free(&ctx->stream_bufcp); - Curl_ssl_peer_cleanup(&ctx->peer); - memset(ctx, 0, sizeof(*ctx)); } } @@ -143,16 +140,11 @@ static CURLcode quic_x509_store_setup(struct Curl_cfilter *cf, struct Curl_easy *data) { struct cf_quiche_ctx *ctx = cf->ctx; - struct ssl_primary_config *conn_config; - - conn_config = Curl_ssl_cf_get_primary_config(cf); - if(!conn_config) - return CURLE_FAILED_INIT; if(!ctx->x509_store_setup) { - if(conn_config->verifypeer) { - const char * const ssl_cafile = conn_config->CAfile; - const char * const ssl_capath = conn_config->CApath; + if(cf->conn->ssl_config.verifypeer) { + const char * const ssl_cafile = cf->conn->ssl_config.CAfile; + const char * const ssl_capath = cf->conn->ssl_config.CApath; if(ssl_cafile || ssl_capath) { SSL_CTX_set_verify(ctx->sslctx, SSL_VERIFY_PEER, NULL); /* tell OpenSSL where to find CA certificates that are used to verify @@ -185,16 +177,9 @@ static CURLcode quic_x509_store_setup(struct Curl_cfilter *cf, static CURLcode quic_ssl_setup(struct Curl_cfilter *cf, struct Curl_easy *data) { struct cf_quiche_ctx *ctx = cf->ctx; - struct ssl_primary_config *conn_config; - CURLcode result; - - conn_config = Curl_ssl_cf_get_primary_config(cf); - if(!conn_config) - return CURLE_FAILED_INIT; - - result = Curl_ssl_peer_init(&ctx->peer, cf); - if(result) - return result; + unsigned char checkip[16]; + struct connectdata *conn = data->conn; + const char *curves = conn->ssl_config.curves; DEBUGASSERT(!ctx->sslctx); ctx->sslctx = SSL_CTX_new(TLS_method()); @@ -213,10 +198,8 @@ static CURLcode quic_ssl_setup(struct Curl_cfilter *cf, struct Curl_easy *data) SSL_CTX_set_keylog_callback(ctx->sslctx, keylog_callback); } - if(conn_config->curves && - !SSL_CTX_set1_curves_list(ctx->sslctx, conn_config->curves)) { - failf(data, "failed setting curves list for QUIC: '%s'", - conn_config->curves); + if(curves && !SSL_CTX_set1_curves_list(ctx->sslctx, curves)) { + failf(data, "failed setting curves list for QUIC: '%s'", curves); return CURLE_SSL_CIPHER; } @@ -226,8 +209,13 @@ static CURLcode quic_ssl_setup(struct Curl_cfilter *cf, struct Curl_easy *data) SSL_set_app_data(ctx->ssl, cf); - if(ctx->peer.sni) { - if(!SSL_set_tlsext_host_name(ctx->ssl, ctx->peer.sni)) { + if((0 == Curl_inet_pton(AF_INET, cf->conn->host.name, checkip)) +#ifdef ENABLE_IPV6 + && (0 == Curl_inet_pton(AF_INET6, cf->conn->host.name, checkip)) +#endif + ) { + char *snihost = Curl_ssl_snihost(data, cf->conn->host.name, NULL); + if(!snihost || !SSL_set_tlsext_host_name(ctx->ssl, snihost)) { failf(data, "Failed set SNI"); SSL_free(ctx->ssl); ctx->ssl = NULL; @@ -252,7 +240,6 @@ struct stream_ctx { bool send_closed; /* stream is locally closed */ bool resp_hds_complete; /* complete, final response has been received */ bool resp_got_header; /* TRUE when h3 stream has recvd some HEADER */ - BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */ }; #define H3_STREAM_CTX(d) ((struct stream_ctx *)(((d) && (d)->req.p.http)? \ @@ -262,20 +249,56 @@ struct stream_ctx { #define H3_STREAM_ID(d) (H3_STREAM_CTX(d)? \ H3_STREAM_CTX(d)->id : -2) +static bool stream_send_is_suspended(struct Curl_easy *data) +{ + return (data->req.keepon & KEEP_SEND_HOLD); +} + +static void stream_send_suspend(struct Curl_cfilter *cf, + struct Curl_easy *data) +{ + struct cf_quiche_ctx *ctx = cf->ctx; + + if((data->req.keepon & KEEP_SENDBITS) == KEEP_SEND) { + data->req.keepon |= KEEP_SEND_HOLD; + ++ctx->sends_on_hold; + if(H3_STREAM_ID(data) >= 0) + CURL_TRC_CF(data, cf, "[%"PRId64"] suspend sending", + H3_STREAM_ID(data)); + else + CURL_TRC_CF(data, cf, "[%s] suspend sending", data->state.url); + } +} + +static void stream_send_resume(struct Curl_cfilter *cf, + struct Curl_easy *data) +{ + struct cf_quiche_ctx *ctx = cf->ctx; + + if(stream_send_is_suspended(data)) { + data->req.keepon &= ~KEEP_SEND_HOLD; + --ctx->sends_on_hold; + if(H3_STREAM_ID(data) >= 0) + CURL_TRC_CF(data, cf, "[%"PRId64"] resume sending", + H3_STREAM_ID(data)); + else + CURL_TRC_CF(data, cf, "[%s] resume sending", data->state.url); + Curl_expire(data, 0, EXPIRE_RUN_NOW); + } +} + static void check_resumes(struct Curl_cfilter *cf, struct Curl_easy *data) { + struct cf_quiche_ctx *ctx = cf->ctx; struct Curl_easy *sdata; - struct stream_ctx *stream; - DEBUGASSERT(data->multi); - for(sdata = data->multi->easyp; sdata; sdata = sdata->next) { - if(sdata->conn == data->conn) { - stream = H3_STREAM_CTX(sdata); - if(stream && stream->quic_flow_blocked) { - stream->quic_flow_blocked = FALSE; - Curl_expire(data, 0, EXPIRE_RUN_NOW); - CURL_TRC_CF(data, cf, "[%"PRId64"] unblock", stream->id); + if(ctx->sends_on_hold) { + DEBUGASSERT(data->multi); + for(sdata = data->multi->easyp; + sdata && ctx->sends_on_hold; sdata = sdata->next) { + if(stream_send_is_suspended(sdata)) { + stream_send_resume(cf, sdata); } } } @@ -310,15 +333,9 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data) (void)cf; if(stream) { CURL_TRC_CF(data, cf, "[%"PRId64"] easy handle is done", stream->id); - if(ctx->qconn && !stream->closed) { - quiche_conn_stream_shutdown(ctx->qconn, stream->id, - QUICHE_SHUTDOWN_READ, CURL_H3_NO_ERROR); - if(!stream->send_closed) { - quiche_conn_stream_shutdown(ctx->qconn, stream->id, - QUICHE_SHUTDOWN_WRITE, CURL_H3_NO_ERROR); - stream->send_closed = TRUE; - } - stream->closed = TRUE; + if(stream_send_is_suspended(data)) { + data->req.keepon &= ~KEEP_SEND_HOLD; + --ctx->sends_on_hold; } Curl_bufq_free(&stream->recvbuf); Curl_h1_req_parse_free(&stream->h1); @@ -573,6 +590,7 @@ static CURLcode h3_process_event(struct Curl_cfilter *cf, } stream->closed = TRUE; streamclose(cf->conn, "End of stream"); + data->req.keepon &= ~KEEP_SEND_HOLD; break; case QUICHE_H3_EVENT_GOAWAY: @@ -865,8 +883,6 @@ static ssize_t cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data, ssize_t nread = -1; CURLcode result; - vquic_ctx_update_time(&ctx->q); - if(!stream) { *err = CURLE_RECV_ERROR; return -1; @@ -1019,8 +1035,9 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf, if(QUICHE_H3_ERR_STREAM_BLOCKED == stream3_id) { /* quiche seems to report this error if the connection window is * exhausted. Which happens frequently and intermittent. */ - CURL_TRC_CF(data, cf, "[%"PRId64"] blocked", stream->id); - stream->quic_flow_blocked = TRUE; + CURL_TRC_CF(data, cf, "send_request(%s) rejected with BLOCKED", + data->state.url); + stream_send_suspend(cf, data); *err = CURLE_AGAIN; nwritten = -1; goto out; @@ -1064,8 +1081,6 @@ static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data, CURLcode result; ssize_t nwritten; - vquic_ctx_update_time(&ctx->q); - *err = cf_process_ingress(cf, data); if(*err) { nwritten = -1; @@ -1089,7 +1104,7 @@ static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data, if(!quiche_conn_stream_writable(ctx->qconn, stream->id, len)) { CURL_TRC_CF(data, cf, "[%" PRId64 "] send_body(len=%zu) " "-> window exhausted", stream->id, len); - stream->quic_flow_blocked = TRUE; + stream_send_suspend(cf, data); } *err = CURLE_AGAIN; nwritten = -1; @@ -1158,32 +1173,30 @@ static bool stream_is_writeable(struct Curl_cfilter *cf, struct cf_quiche_ctx *ctx = cf->ctx; struct stream_ctx *stream = H3_STREAM_CTX(data); - return stream && (quiche_conn_stream_writable(ctx->qconn, - (uint64_t)stream->id, 1) > 0); + return stream && + quiche_conn_stream_writable(ctx->qconn, (uint64_t)stream->id, 1); } -static void cf_quiche_adjust_pollset(struct Curl_cfilter *cf, - struct Curl_easy *data, - struct easy_pollset *ps) +static int cf_quiche_get_select_socks(struct Curl_cfilter *cf, + struct Curl_easy *data, + curl_socket_t *socks) { struct cf_quiche_ctx *ctx = cf->ctx; - bool want_recv = CURL_WANT_RECV(data); - bool want_send = CURL_WANT_SEND(data); + struct SingleRequest *k = &data->req; + int rv = GETSOCK_BLANK; - if(ctx->qconn && (want_recv || want_send)) { - struct stream_ctx *stream = H3_STREAM_CTX(data); - bool c_exhaust, s_exhaust; + socks[0] = ctx->q.sockfd; - c_exhaust = FALSE; /* Have not found any call in quiche that tells - us if the connection itself is blocked */ - s_exhaust = stream && stream->id >= 0 && - (stream->quic_flow_blocked || !stream_is_writeable(cf, data)); - want_recv = (want_recv || c_exhaust || s_exhaust); - want_send = (!s_exhaust && want_send) || - !Curl_bufq_is_empty(&ctx->q.sendbuf); + /* in an HTTP/3 connection we can basically always get a frame so we should + always be ready for one */ + rv |= GETSOCK_READSOCK(0); - Curl_pollset_set(data, ps, ctx->q.sockfd, want_recv, want_send); - } + /* we're still uploading or the HTTP/3 layer wants to send data */ + if(((k->keepon & KEEP_SENDBITS) == KEEP_SEND) + && stream_is_writeable(cf, data)) + rv |= GETSOCK_WRITESOCK(0); + + return rv; } /* @@ -1225,12 +1238,10 @@ static CURLcode cf_quiche_data_event(struct Curl_cfilter *cf, case CF_CTRL_DATA_PAUSE: result = h3_data_pause(cf, data, (arg1 != 0)); break; - case CF_CTRL_DATA_DETACH: - h3_data_done(cf, data); - break; - case CF_CTRL_DATA_DONE: + case CF_CTRL_DATA_DONE: { h3_data_done(cf, data); break; + } case CF_CTRL_DATA_DONE_SEND: { struct stream_ctx *stream = H3_STREAM_CTX(data); if(stream && !stream->send_closed) { @@ -1265,25 +1276,20 @@ static CURLcode cf_verify_peer(struct Curl_cfilter *cf, struct Curl_easy *data) { struct cf_quiche_ctx *ctx = cf->ctx; - struct ssl_primary_config *conn_config; CURLcode result = CURLE_OK; - conn_config = Curl_ssl_cf_get_primary_config(cf); - if(!conn_config) - return CURLE_FAILED_INIT; - cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */ cf->conn->httpversion = 30; cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX; - if(conn_config->verifyhost) { + if(cf->conn->ssl_config.verifyhost) { X509 *server_cert; server_cert = SSL_get_peer_certificate(ctx->ssl); if(!server_cert) { result = CURLE_PEER_FAILED_VERIFICATION; goto out; } - result = Curl_ossl_verifyhost(data, cf->conn, &ctx->peer, server_cert); + result = Curl_ossl_verifyhost(data, cf->conn, server_cert); X509_free(server_cert); if(result) goto out; @@ -1339,7 +1345,6 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf, debug_log_init = 1; } #endif - ctx->max_idle_ms = CURL_QUIC_MAX_IDLE_MS; Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE, H3_STREAM_POOL_SPARES); ctx->data_recvd = 0; @@ -1354,7 +1359,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf, return CURLE_FAILED_INIT; } quiche_config_enable_pacing(ctx->cfg, false); - quiche_config_set_max_idle_timeout(ctx->cfg, ctx->max_idle_ms * 1000); + quiche_config_set_max_idle_timeout(ctx->cfg, QUIC_IDLE_TIMEOUT); quiche_config_set_initial_max_data(ctx->cfg, (1 * 1024 * 1024) /* (QUIC_MAX_STREAMS/2) * H3_STREAM_WINDOW_SIZE */); quiche_config_set_initial_max_streams_bidi(ctx->cfg, QUIC_MAX_STREAMS); @@ -1406,7 +1411,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf, } /* Known to not work on Windows */ -#if !defined(_WIN32) && defined(HAVE_QUICHE_CONN_SET_QLOG_FD) +#if !defined(WIN32) && defined(HAVE_QUICHE_CONN_SET_QLOG_FD) { int qfd; (void)Curl_qlogdir(data, ctx->scid, sizeof(ctx->scid), &qfd); @@ -1444,6 +1449,7 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf, { struct cf_quiche_ctx *ctx = cf->ctx; CURLcode result = CURLE_OK; + struct curltime now; if(cf->connected) { *done = TRUE; @@ -1458,10 +1464,9 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf, } *done = FALSE; - vquic_ctx_update_time(&ctx->q); + now = Curl_now(); - if(ctx->reconnect_at.tv_sec && - Curl_timediff(ctx->q.last_op, ctx->reconnect_at) < 0) { + if(ctx->reconnect_at.tv_sec && Curl_timediff(now, ctx->reconnect_at) < 0) { /* Not time yet to attempt the next connect */ CURL_TRC_CF(data, cf, "waiting for reconnect time"); goto out; @@ -1471,7 +1476,7 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf, result = cf_connect_start(cf, data); if(result) goto out; - ctx->started_at = ctx->q.last_op; + ctx->started_at = now; result = cf_flush_egress(cf, data); /* we do not expect to be able to recv anything yet */ goto out; @@ -1486,9 +1491,9 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf, goto out; if(quiche_conn_is_established(ctx->qconn)) { - ctx->handshake_at = ctx->q.last_op; CURL_TRC_CF(data, cf, "handshake complete after %dms", - (int)Curl_timediff(ctx->handshake_at, ctx->started_at)); + (int)Curl_timediff(now, ctx->started_at)); + ctx->handshake_at = now; result = cf_verify_peer(cf, data); if(!result) { CURL_TRC_CF(data, cf, "peer verified"); @@ -1501,9 +1506,27 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf, else if(quiche_conn_is_draining(ctx->qconn)) { /* When a QUIC server instance is shutting down, it may send us a * CONNECTION_CLOSE right away. Our connection then enters the DRAINING - * state. The CONNECT may work in the near future again. Indicate - * that as a "weird" reply. */ - result = CURLE_WEIRD_SERVER_REPLY; + * state. + * This may be a stopping of the service or it may be that the server + * is reloading and a new instance will start serving soon. + * In any case, we tear down our socket and start over with a new one. + * We re-open the underlying UDP cf right now, but do not start + * connecting until called again. + */ + int reconn_delay_ms = 200; + + CURL_TRC_CF(data, cf, "connect, remote closed, reconnect after %dms", + reconn_delay_ms); + Curl_conn_cf_close(cf->next, data); + cf_quiche_ctx_clear(ctx); + result = Curl_conn_cf_connect(cf->next, data, FALSE, done); + if(!result && *done) { + *done = FALSE; + ctx->reconnect_at = Curl_now(); + ctx->reconnect_at.tv_usec += reconn_delay_ms * 1000; + Curl_expire(data, reconn_delay_ms, EXPIRE_QUIC); + result = CURLE_OK; + } } out: @@ -1527,7 +1550,6 @@ static void cf_quiche_close(struct Curl_cfilter *cf, struct Curl_easy *data) if(ctx) { if(ctx->qconn) { - vquic_ctx_update_time(&ctx->q); (void)quiche_conn_close(ctx->qconn, TRUE, 0, NULL, 0); /* flushing the egress is not a failsafe way to deliver all the outstanding packets, but we also don't want to get stuck here... */ @@ -1595,32 +1617,9 @@ static bool cf_quiche_conn_is_alive(struct Curl_cfilter *cf, struct Curl_easy *data, bool *input_pending) { - struct cf_quiche_ctx *ctx = cf->ctx; bool alive = TRUE; *input_pending = FALSE; - if(!ctx->qconn) - return FALSE; - - /* Both sides of the QUIC connection announce they max idle times in - * the transport parameters. Look at the minimum of both and if - * we exceed this, regard the connection as dead. The other side - * may have completely purged it and will no longer respond - * to any packets from us. */ - { - quiche_transport_params qpeerparams; - timediff_t idletime; - uint64_t idle_ms = ctx->max_idle_ms; - - if(quiche_conn_peer_transport_params(ctx->qconn, &qpeerparams) && - qpeerparams.peer_max_idle_timeout && - qpeerparams.peer_max_idle_timeout < idle_ms) - idle_ms = qpeerparams.peer_max_idle_timeout; - idletime = Curl_timediff(Curl_now(), cf->conn->lastused); - if(idletime > 0 && (uint64_t)idletime > idle_ms) - return FALSE; - } - if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending)) return FALSE; @@ -1647,7 +1646,7 @@ struct Curl_cftype Curl_cft_http3 = { cf_quiche_connect, cf_quiche_close, Curl_cf_def_get_host, - cf_quiche_adjust_pollset, + cf_quiche_get_select_socks, cf_quiche_data_pending, cf_quiche_send, cf_quiche_recv, @@ -1668,7 +1667,7 @@ CURLcode Curl_cf_quiche_create(struct Curl_cfilter **pcf, (void)data; (void)conn; - ctx = calloc(1, sizeof(*ctx)); + ctx = calloc(sizeof(*ctx), 1); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; diff --git a/deps/curl/lib/vquic/vquic.c b/deps/curl/lib/vquic/vquic.c index 523b807b..9a1a1bbb 100644 --- a/deps/curl/lib/vquic/vquic.c +++ b/deps/curl/lib/vquic/vquic.c @@ -100,7 +100,6 @@ CURLcode vquic_ctx_init(struct cf_quic_ctx *qctx) } } #endif - vquic_ctx_update_time(qctx); return CURLE_OK; } @@ -110,11 +109,6 @@ void vquic_ctx_free(struct cf_quic_ctx *qctx) Curl_bufq_free(&qctx->sendbuf); } -void vquic_ctx_update_time(struct cf_quic_ctx *qctx) -{ - qctx->last_op = Curl_now(); -} - static CURLcode send_packet_no_gso(struct Curl_cfilter *cf, struct Curl_easy *data, struct cf_quic_ctx *qctx, @@ -248,7 +242,6 @@ static CURLcode vquic_send_packets(struct Curl_cfilter *cf, const uint8_t *pkt, size_t pktlen, size_t gsolen, size_t *psent) { - CURLcode result; #ifdef DEBUGBUILD /* simulate network blocking/partial writes */ if(qctx->wblock_percent > 0) { @@ -261,14 +254,10 @@ static CURLcode vquic_send_packets(struct Curl_cfilter *cf, } #endif if(qctx->no_gso && pktlen > gsolen) { - result = send_packet_no_gso(cf, data, qctx, pkt, pktlen, gsolen, psent); + return send_packet_no_gso(cf, data, qctx, pkt, pktlen, gsolen, psent); } - else { - result = do_sendmsg(cf, data, qctx, pkt, pktlen, gsolen, psent); - } - if(!result) - qctx->last_io = qctx->last_op; - return result; + + return do_sendmsg(cf, data, qctx, pkt, pktlen, gsolen, psent); } CURLcode vquic_flush(struct Curl_cfilter *cf, struct Curl_easy *data, @@ -535,17 +524,13 @@ CURLcode vquic_recv_packets(struct Curl_cfilter *cf, size_t max_pkts, vquic_recv_pkt_cb *recv_cb, void *userp) { - CURLcode result; #if defined(HAVE_SENDMMSG) - result = recvmmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp); + return recvmmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp); #elif defined(HAVE_SENDMSG) - result = recvmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp); + return recvmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp); #else - result = recvfrom_packets(cf, data, qctx, max_pkts, recv_cb, userp); + return recvfrom_packets(cf, data, qctx, max_pkts, recv_cb, userp); #endif - if(!result) - qctx->last_io = qctx->last_op; - return result; } /* diff --git a/deps/curl/lib/vquic/vquic_int.h b/deps/curl/lib/vquic/vquic_int.h index a820f39a..dbcd009d 100644 --- a/deps/curl/lib/vquic/vquic_int.h +++ b/deps/curl/lib/vquic/vquic_int.h @@ -31,8 +31,6 @@ #define MAX_PKT_BURST 10 #define MAX_UDP_PAYLOAD_SIZE 1452 -/* Default QUIC connection timeout we announce from our side */ -#define CURL_QUIC_MAX_IDLE_MS (120 * 1000) struct cf_quic_ctx { curl_socket_t sockfd; /* connected UDP socket */ @@ -40,8 +38,6 @@ struct cf_quic_ctx { socklen_t local_addrlen; /* length of local address */ struct bufq sendbuf; /* buffer for sending one or more packets */ - struct curltime last_op; /* last (attempted) send/recv operation */ - struct curltime last_io; /* last successful socket IO */ size_t gsolen; /* length of individual packets in send buf */ size_t split_len; /* if != 0, buffer length after which GSO differs */ size_t split_gsolen; /* length of individual packets after split_len */ @@ -54,8 +50,6 @@ struct cf_quic_ctx { CURLcode vquic_ctx_init(struct cf_quic_ctx *qctx); void vquic_ctx_free(struct cf_quic_ctx *qctx); -void vquic_ctx_update_time(struct cf_quic_ctx *qctx); - void vquic_push_blocked_pkt(struct Curl_cfilter *cf, struct cf_quic_ctx *qctx, const uint8_t *pkt, size_t pktlen, size_t gsolen); diff --git a/deps/curl/lib/vssh/libssh.c b/deps/curl/lib/vssh/libssh.c index 97143c47..b0f49d60 100644 --- a/deps/curl/lib/vssh/libssh.c +++ b/deps/curl/lib/vssh/libssh.c @@ -93,7 +93,6 @@ #if defined(__GNUC__) && \ (LIBSSH_VERSION_MINOR >= 10) || \ (LIBSSH_VERSION_MAJOR > 0) -#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif @@ -1160,23 +1159,13 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) break; } else if(statvfs) { - #ifdef _MSC_VER - #define LIBSSH_VFS_SIZE_MASK "I64u" - #else - #define LIBSSH_VFS_SIZE_MASK PRIu64 - #endif char *tmp = aprintf("statvfs:\n" - "f_bsize: %" LIBSSH_VFS_SIZE_MASK "\n" - "f_frsize: %" LIBSSH_VFS_SIZE_MASK "\n" - "f_blocks: %" LIBSSH_VFS_SIZE_MASK "\n" - "f_bfree: %" LIBSSH_VFS_SIZE_MASK "\n" - "f_bavail: %" LIBSSH_VFS_SIZE_MASK "\n" - "f_files: %" LIBSSH_VFS_SIZE_MASK "\n" - "f_ffree: %" LIBSSH_VFS_SIZE_MASK "\n" - "f_favail: %" LIBSSH_VFS_SIZE_MASK "\n" - "f_fsid: %" LIBSSH_VFS_SIZE_MASK "\n" - "f_flag: %" LIBSSH_VFS_SIZE_MASK "\n" - "f_namemax: %" LIBSSH_VFS_SIZE_MASK "\n", + "f_bsize: %llu\n" "f_frsize: %llu\n" + "f_blocks: %llu\n" "f_bfree: %llu\n" + "f_bavail: %llu\n" "f_files: %llu\n" + "f_ffree: %llu\n" "f_favail: %llu\n" + "f_fsid: %llu\n" "f_flag: %llu\n" + "f_namemax: %llu\n", statvfs->f_bsize, statvfs->f_frsize, statvfs->f_blocks, statvfs->f_bfree, statvfs->f_bavail, statvfs->f_files, @@ -1477,7 +1466,13 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) state(data, SSH_STOP); break; } + /* since this counts what we send to the client, we include the + newline in this counter */ + data->req.bytecount += sshc->readdir_len + 1; + /* output debug output if that is requested */ + Curl_debug(data, CURLINFO_DATA_OUT, (char *)sshc->readdir_filename, + sshc->readdir_len); } else { if(Curl_dyn_add(&sshc->readdir_buf, sshc->readdir_longentry)) { @@ -1569,6 +1564,12 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) Curl_dyn_ptr(&sshc->readdir_buf), Curl_dyn_len(&sshc->readdir_buf)); + if(!result) { + /* output debug output if that is requested */ + Curl_debug(data, CURLINFO_DATA_OUT, Curl_dyn_ptr(&sshc->readdir_buf), + Curl_dyn_len(&sshc->readdir_buf)); + data->req.bytecount += Curl_dyn_len(&sshc->readdir_buf); + } ssh_string_free_char(sshc->readdir_tmp); sshc->readdir_tmp = NULL; @@ -1962,9 +1963,10 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) ssh_disconnect(sshc->ssh_session); if(!ssh_version(SSH_VERSION_INT(0, 10, 0))) { /* conn->sock[FIRSTSOCKET] is closed by ssh_disconnect behind our back, - tell the connection to forget about it. This libssh + explicitly mark it as closed with the memdebug macro. This libssh bug is fixed in 0.10.0. */ - Curl_conn_forget_socket(data, FIRSTSOCKET); + fake_sclose(conn->sock[FIRSTSOCKET]); + conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD; } SSH_STRING_FREE_CHAR(sshc->homedir); @@ -2957,10 +2959,4 @@ void Curl_ssh_version(char *buffer, size_t buflen) (void)msnprintf(buffer, buflen, "libssh/%s", ssh_version(0)); } -#if defined(__GNUC__) && \ - (LIBSSH_VERSION_MINOR >= 10) || \ - (LIBSSH_VERSION_MAJOR > 0) -#pragma GCC diagnostic pop -#endif - #endif /* USE_LIBSSH */ diff --git a/deps/curl/lib/vssh/libssh2.c b/deps/curl/lib/vssh/libssh2.c index 11f5f4fd..f539b393 100644 --- a/deps/curl/lib/vssh/libssh2.c +++ b/deps/curl/lib/vssh/libssh2.c @@ -1537,137 +1537,139 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) state(data, SSH_SFTP_NEXT_QUOTE); break; } + { + /* + * the arguments following the command must be separated from the + * command with a space so we can check for it unconditionally + */ + cp = strchr(cmd, ' '); + if(!cp) { + failf(data, "Syntax error command '%s', missing parameter", + cmd); + state(data, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = CURLE_QUOTE_ERROR; + break; + } - /* - * the arguments following the command must be separated from the - * command with a space so we can check for it unconditionally - */ - cp = strchr(cmd, ' '); - if(!cp) { - failf(data, "Syntax error command '%s', missing parameter", - cmd); + /* + * also, every command takes at least one argument so we get that + * first argument right now + */ + result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error: Bad first parameter to '%s'", cmd); + state(data, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + break; + } + + /* + * SFTP is a binary protocol, so we don't send text commands + * to the server. Instead, we scan for commands used by + * OpenSSH's sftp program and call the appropriate libssh2 + * functions. + */ + if(strncasecompare(cmd, "chgrp ", 6) || + strncasecompare(cmd, "chmod ", 6) || + strncasecompare(cmd, "chown ", 6) || + strncasecompare(cmd, "atime ", 6) || + strncasecompare(cmd, "mtime ", 6)) { + /* attribute change */ + + /* sshc->quote_path1 contains the mode to set */ + /* get the destination */ + result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error in %s: Bad second parameter", cmd); + Curl_safefree(sshc->quote_path1); + state(data, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + break; + } + memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); + state(data, SSH_SFTP_QUOTE_STAT); + break; + } + if(strncasecompare(cmd, "ln ", 3) || + strncasecompare(cmd, "symlink ", 8)) { + /* symbolic linking */ + /* sshc->quote_path1 is the source */ + /* get the destination */ + result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, + "Syntax error in ln/symlink: Bad second parameter"); + Curl_safefree(sshc->quote_path1); + state(data, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + break; + } + state(data, SSH_SFTP_QUOTE_SYMLINK); + break; + } + else if(strncasecompare(cmd, "mkdir ", 6)) { + /* create dir */ + state(data, SSH_SFTP_QUOTE_MKDIR); + break; + } + else if(strncasecompare(cmd, "rename ", 7)) { + /* rename file */ + /* first param is the source path */ + /* second param is the dest. path */ + result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); + if(result) { + if(result == CURLE_OUT_OF_MEMORY) + failf(data, "Out of memory"); + else + failf(data, "Syntax error in rename: Bad second parameter"); + Curl_safefree(sshc->quote_path1); + state(data, SSH_SFTP_CLOSE); + sshc->nextstate = SSH_NO_STATE; + sshc->actualcode = result; + break; + } + state(data, SSH_SFTP_QUOTE_RENAME); + break; + } + else if(strncasecompare(cmd, "rmdir ", 6)) { + /* delete dir */ + state(data, SSH_SFTP_QUOTE_RMDIR); + break; + } + else if(strncasecompare(cmd, "rm ", 3)) { + state(data, SSH_SFTP_QUOTE_UNLINK); + break; + } +#ifdef HAS_STATVFS_SUPPORT + else if(strncasecompare(cmd, "statvfs ", 8)) { + state(data, SSH_SFTP_QUOTE_STATVFS); + break; + } +#endif + + failf(data, "Unknown SFTP command"); + Curl_safefree(sshc->quote_path1); + Curl_safefree(sshc->quote_path2); state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; break; } - - /* - * also, every command takes at least one argument so we get that - * first argument right now - */ - result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir); - if(result) { - if(result == CURLE_OUT_OF_MEMORY) - failf(data, "Out of memory"); - else - failf(data, "Syntax error: Bad first parameter to '%s'", cmd); - state(data, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = result; - break; - } - - /* - * SFTP is a binary protocol, so we don't send text commands - * to the server. Instead, we scan for commands used by - * OpenSSH's sftp program and call the appropriate libssh2 - * functions. - */ - if(strncasecompare(cmd, "chgrp ", 6) || - strncasecompare(cmd, "chmod ", 6) || - strncasecompare(cmd, "chown ", 6) || - strncasecompare(cmd, "atime ", 6) || - strncasecompare(cmd, "mtime ", 6)) { - /* attribute change */ - - /* sshc->quote_path1 contains the mode to set */ - /* get the destination */ - result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); - if(result) { - if(result == CURLE_OUT_OF_MEMORY) - failf(data, "Out of memory"); - else - failf(data, "Syntax error in %s: Bad second parameter", cmd); - Curl_safefree(sshc->quote_path1); - state(data, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = result; - break; - } - memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); - state(data, SSH_SFTP_QUOTE_STAT); - break; - } - if(strncasecompare(cmd, "ln ", 3) || - strncasecompare(cmd, "symlink ", 8)) { - /* symbolic linking */ - /* sshc->quote_path1 is the source */ - /* get the destination */ - result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); - if(result) { - if(result == CURLE_OUT_OF_MEMORY) - failf(data, "Out of memory"); - else - failf(data, - "Syntax error in ln/symlink: Bad second parameter"); - Curl_safefree(sshc->quote_path1); - state(data, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = result; - break; - } - state(data, SSH_SFTP_QUOTE_SYMLINK); - break; - } - else if(strncasecompare(cmd, "mkdir ", 6)) { - /* create dir */ - state(data, SSH_SFTP_QUOTE_MKDIR); - break; - } - else if(strncasecompare(cmd, "rename ", 7)) { - /* rename file */ - /* first param is the source path */ - /* second param is the dest. path */ - result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir); - if(result) { - if(result == CURLE_OUT_OF_MEMORY) - failf(data, "Out of memory"); - else - failf(data, "Syntax error in rename: Bad second parameter"); - Curl_safefree(sshc->quote_path1); - state(data, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = result; - break; - } - state(data, SSH_SFTP_QUOTE_RENAME); - break; - } - else if(strncasecompare(cmd, "rmdir ", 6)) { - /* delete dir */ - state(data, SSH_SFTP_QUOTE_RMDIR); - break; - } - else if(strncasecompare(cmd, "rm ", 3)) { - state(data, SSH_SFTP_QUOTE_UNLINK); - break; - } -#ifdef HAS_STATVFS_SUPPORT - else if(strncasecompare(cmd, "statvfs ", 8)) { - state(data, SSH_SFTP_QUOTE_STATVFS); - break; - } -#endif - - failf(data, "Unknown SFTP command"); - Curl_safefree(sshc->quote_path1); - Curl_safefree(sshc->quote_path2); - state(data, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; - break; } + break; case SSH_SFTP_NEXT_QUOTE: Curl_safefree(sshc->quote_path1); @@ -1960,23 +1962,13 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) break; } else if(rc == 0) { - #ifdef _MSC_VER - #define LIBSSH2_VFS_SIZE_MASK "I64u" - #else - #define LIBSSH2_VFS_SIZE_MASK "llu" - #endif char *tmp = aprintf("statvfs:\n" - "f_bsize: %" LIBSSH2_VFS_SIZE_MASK "\n" - "f_frsize: %" LIBSSH2_VFS_SIZE_MASK "\n" - "f_blocks: %" LIBSSH2_VFS_SIZE_MASK "\n" - "f_bfree: %" LIBSSH2_VFS_SIZE_MASK "\n" - "f_bavail: %" LIBSSH2_VFS_SIZE_MASK "\n" - "f_files: %" LIBSSH2_VFS_SIZE_MASK "\n" - "f_ffree: %" LIBSSH2_VFS_SIZE_MASK "\n" - "f_favail: %" LIBSSH2_VFS_SIZE_MASK "\n" - "f_fsid: %" LIBSSH2_VFS_SIZE_MASK "\n" - "f_flag: %" LIBSSH2_VFS_SIZE_MASK "\n" - "f_namemax: %" LIBSSH2_VFS_SIZE_MASK "\n", + "f_bsize: %llu\n" "f_frsize: %llu\n" + "f_blocks: %llu\n" "f_bfree: %llu\n" + "f_bavail: %llu\n" "f_files: %llu\n" + "f_ffree: %llu\n" "f_favail: %llu\n" + "f_fsid: %llu\n" "f_flag: %llu\n" + "f_namemax: %llu\n", statvfs.f_bsize, statvfs.f_frsize, statvfs.f_blocks, statvfs.f_bfree, statvfs.f_bavail, statvfs.f_files, @@ -2349,7 +2341,14 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) state(data, SSH_STOP); break; } + /* since this counts what we send to the client, we include the + newline in this counter */ + data->req.bytecount += readdir_len + 1; + /* output debug output if that is requested */ + Curl_debug(data, CURLINFO_DATA_IN, sshp->readdir_filename, + readdir_len); + Curl_debug(data, CURLINFO_DATA_IN, (char *)"\n", 1); } else { result = Curl_dyn_add(&sshp->readdir, sshp->readdir_longentry); @@ -2428,6 +2427,13 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) Curl_dyn_ptr(&sshp->readdir), Curl_dyn_len(&sshp->readdir)); + if(!result) { + /* output debug output if that is requested */ + Curl_debug(data, CURLINFO_DATA_IN, + Curl_dyn_ptr(&sshp->readdir), + Curl_dyn_len(&sshp->readdir)); + data->req.bytecount += Curl_dyn_len(&sshp->readdir); + } if(result) { Curl_dyn_free(&sshp->readdir); state(data, SSH_STOP); diff --git a/deps/curl/lib/vssh/ssh.h b/deps/curl/lib/vssh/ssh.h index ca0533aa..1e1b1379 100644 --- a/deps/curl/lib/vssh/ssh.h +++ b/deps/curl/lib/vssh/ssh.h @@ -267,7 +267,6 @@ void Curl_ssh_attach(struct Curl_easy *data, /* for non-SSH builds */ #define Curl_ssh_cleanup() #define Curl_ssh_attach(x,y) -#define Curl_ssh_init() 0 #endif #endif /* HEADER_CURL_SSH_H */ diff --git a/deps/curl/lib/vssh/wolfssh.c b/deps/curl/lib/vssh/wolfssh.c index 4da7e9de..39cee507 100644 --- a/deps/curl/lib/vssh/wolfssh.c +++ b/deps/curl/lib/vssh/wolfssh.c @@ -343,6 +343,9 @@ static CURLcode wssh_setup_connection(struct Curl_easy *data, return CURLE_OK; } +static Curl_recv wscp_recv, wsftp_recv; +static Curl_send wscp_send, wsftp_send; + static int userauth(byte authtype, WS_UserAuthData* authdata, void *ctx) diff --git a/deps/curl/lib/vtls/bearssl.c b/deps/curl/lib/vtls/bearssl.c index a6566f4d..934149c1 100644 --- a/deps/curl/lib/vtls/bearssl.c +++ b/deps/curl/lib/vtls/bearssl.c @@ -582,12 +582,17 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf, const char * const ssl_cafile = /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */ (ca_info_blob ? NULL : conn_config->CAfile); - const char *hostname = connssl->peer.hostname; + const char *hostname = connssl->hostname; const bool verifypeer = conn_config->verifypeer; const bool verifyhost = conn_config->verifyhost; CURLcode ret; unsigned version_min, version_max; int session_set = 0; +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif DEBUGASSERT(backend); CURL_TRC_CF(data, cf, "connect_step1"); @@ -701,7 +706,11 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf, infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data); } - if(connssl->peer.is_ip_address) { + if((1 == Curl_inet_pton(AF_INET, hostname, &addr)) +#ifdef ENABLE_IPV6 + || (1 == Curl_inet_pton(AF_INET6, hostname, &addr)) +#endif + ) { if(verifyhost) { failf(data, "BearSSL: " "host verification of IP address is not supported"); @@ -710,11 +719,12 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf, hostname = NULL; } else { - if(!connssl->peer.sni) { + char *snihost = Curl_ssl_snihost(data, hostname, NULL); + if(!snihost) { failf(data, "Failed to set SNI"); return CURLE_SSL_CONNECT_ERROR; } - hostname = connssl->peer.sni; + hostname = snihost; CURL_TRC_CF(data, cf, "connect_step1, SNI set"); } @@ -739,26 +749,26 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf, return CURLE_OK; } -static void bearssl_adjust_pollset(struct Curl_cfilter *cf, - struct Curl_easy *data, - struct easy_pollset *ps) +static int bearssl_get_select_socks(struct Curl_cfilter *cf, + struct Curl_easy *data, + curl_socket_t *socks) { - if(!cf->connected) { - curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data); - if(sock != CURL_SOCKET_BAD) { - struct ssl_connect_data *connssl = cf->ctx; - struct bearssl_ssl_backend_data *backend = - (struct bearssl_ssl_backend_data *)connssl->backend; - unsigned state = br_ssl_engine_current_state(&backend->ctx.eng); + struct ssl_connect_data *connssl = cf->ctx; + curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data); - if(state & BR_SSL_SENDREC) { - Curl_pollset_set_out_only(data, ps, sock); - } - else { - Curl_pollset_set_in_only(data, ps, sock); - } + if(sock == CURL_SOCKET_BAD) + return GETSOCK_BLANK; + else { + struct bearssl_ssl_backend_data *backend = + (struct bearssl_ssl_backend_data *)connssl->backend; + unsigned state = br_ssl_engine_current_state(&backend->ctx.eng); + if(state & BR_SSL_SENDREC) { + socks[0] = sock; + return GETSOCK_WRITESOCK(0); } } + socks[0] = sock; + return GETSOCK_READSOCK(0); } static CURLcode bearssl_run_until(struct Curl_cfilter *cf, @@ -1200,7 +1210,7 @@ const struct Curl_ssl Curl_ssl_bearssl = { Curl_none_cert_status_request, /* cert_status_request */ bearssl_connect, /* connect */ bearssl_connect_nonblocking, /* connect_nonblocking */ - bearssl_adjust_pollset, /* adjust_pollset */ + bearssl_get_select_socks, /* getsock */ bearssl_get_internals, /* get_internals */ bearssl_close, /* close_one */ Curl_none_close_all, /* close_all */ diff --git a/deps/curl/lib/vtls/gtls.c b/deps/curl/lib/vtls/gtls.c index 4e337f5d..c538a966 100644 --- a/deps/curl/lib/vtls/gtls.c +++ b/deps/curl/lib/vtls/gtls.c @@ -402,13 +402,18 @@ set_ssl_version_min_max(struct Curl_easy *data, CURLcode gtls_client_init(struct Curl_easy *data, struct ssl_primary_config *config, struct ssl_config_data *ssl_config, - struct ssl_peer *peer, + const char *hostname, struct gtls_instance *gtls, long *pverifyresult) { unsigned int init_flags; int rc; bool sni = TRUE; /* default is SNI enabled */ +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif const char *prioritylist; const char *err = NULL; const char *tls13support; @@ -455,61 +460,51 @@ CURLcode gtls_client_init(struct Curl_easy *data, } #endif - if(config->verifypeer) { - bool imported_native_ca = false; + if(config->CAfile) { + /* set the trusted CA cert bundle file */ + gnutls_certificate_set_verify_flags(gtls->cred, + GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); - if(ssl_config->native_ca_store) { - rc = gnutls_certificate_set_x509_system_trust(gtls->cred); - if(rc < 0) - infof(data, "error reading native ca store (%s), continuing anyway", - gnutls_strerror(rc)); - else { - infof(data, "found %d certificates in native ca store", rc); - if(rc > 0) - imported_native_ca = true; + rc = gnutls_certificate_set_x509_trust_file(gtls->cred, + config->CAfile, + GNUTLS_X509_FMT_PEM); + if(rc < 0) { + infof(data, "error reading ca cert file %s (%s)", + config->CAfile, gnutls_strerror(rc)); + if(config->verifypeer) { + *pverifyresult = rc; + return CURLE_SSL_CACERT_BADFILE; } } - - if(config->CAfile) { - /* set the trusted CA cert bundle file */ - gnutls_certificate_set_verify_flags(gtls->cred, - GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); - - rc = gnutls_certificate_set_x509_trust_file(gtls->cred, - config->CAfile, - GNUTLS_X509_FMT_PEM); - if(rc < 0) { - infof(data, "error reading ca cert file %s (%s)%s", - config->CAfile, gnutls_strerror(rc), - (imported_native_ca ? ", continuing anyway" : "")); - if(!imported_native_ca) { - *pverifyresult = rc; - return CURLE_SSL_CACERT_BADFILE; - } - } - else - infof(data, "found %d certificates in %s", rc, config->CAfile); - } - - if(config->CApath) { - /* set the trusted CA cert directory */ - rc = gnutls_certificate_set_x509_trust_dir(gtls->cred, - config->CApath, - GNUTLS_X509_FMT_PEM); - if(rc < 0) { - infof(data, "error reading ca cert file %s (%s)%s", - config->CApath, gnutls_strerror(rc), - (imported_native_ca ? ", continuing anyway" : "")); - if(!imported_native_ca) { - *pverifyresult = rc; - return CURLE_SSL_CACERT_BADFILE; - } - } - else - infof(data, "found %d certificates in %s", rc, config->CApath); - } + else + infof(data, "found %d certificates in %s", rc, config->CAfile); } + if(config->CApath) { + /* set the trusted CA cert directory */ + rc = gnutls_certificate_set_x509_trust_dir(gtls->cred, + config->CApath, + GNUTLS_X509_FMT_PEM); + if(rc < 0) { + infof(data, "error reading ca cert file %s (%s)", + config->CApath, gnutls_strerror(rc)); + if(config->verifypeer) { + *pverifyresult = rc; + return CURLE_SSL_CACERT_BADFILE; + } + } + else + infof(data, "found %d certificates in %s", rc, config->CApath); + } + +#ifdef CURL_CA_FALLBACK + /* use system ca certificate store as fallback */ + if(config->verifypeer && !(config->CAfile || config->CApath)) { + /* this ignores errors on purpose */ + gnutls_certificate_set_x509_system_trust(gtls->cred); + } +#endif + if(config->CRLfile) { /* set the CRL list file */ rc = gnutls_certificate_set_x509_crl_file(gtls->cred, @@ -542,9 +537,15 @@ CURLcode gtls_client_init(struct Curl_easy *data, return CURLE_SSL_CONNECT_ERROR; } - if(sni && peer->sni) { - if(gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS, - peer->sni, strlen(peer->sni)) < 0) { + if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) && +#ifdef ENABLE_IPV6 + (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) && +#endif + sni) { + size_t snilen; + char *snihost = Curl_ssl_snihost(data, hostname, &snilen); + if(!snihost || gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS, + snihost, snilen) < 0) { failf(data, "Failed to set SNI"); return CURLE_SSL_CONNECT_ERROR; } @@ -698,7 +699,7 @@ gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_OK; result = gtls_client_init(data, conn_config, ssl_config, - &connssl->peer, + connssl->hostname, &backend->gtls, pverifyresult); if(result) return result; @@ -810,7 +811,8 @@ Curl_gtls_verifyserver(struct Curl_easy *data, gnutls_session_t session, struct ssl_primary_config *config, struct ssl_config_data *ssl_config, - struct ssl_peer *peer, + const char *hostname, + const char *dispname, const char *pinned_key) { unsigned int cert_list_size; @@ -1066,7 +1068,7 @@ Curl_gtls_verifyserver(struct Curl_easy *data, in RFC2818 (HTTPS), which takes into account wildcards, and the subject alternative name PKIX extension. Returns non zero on success, and zero on failure. */ - rc = gnutls_x509_crt_check_hostname(x509_cert, peer->hostname); + rc = gnutls_x509_crt_check_hostname(x509_cert, hostname); #if GNUTLS_VERSION_NUMBER < 0x030306 /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP addresses. */ @@ -1079,10 +1081,10 @@ Curl_gtls_verifyserver(struct Curl_easy *data, unsigned char addrbuf[sizeof(struct use_addr)]; size_t addrlen = 0; - if(Curl_inet_pton(AF_INET, peer->hostname, addrbuf) > 0) + if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0) addrlen = 4; #ifdef ENABLE_IPV6 - else if(Curl_inet_pton(AF_INET6, peer->hostname, addrbuf) > 0) + else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0) addrlen = 16; #endif @@ -1112,13 +1114,13 @@ Curl_gtls_verifyserver(struct Curl_easy *data, if(!rc) { if(config->verifyhost) { failf(data, "SSL: certificate subject name (%s) does not match " - "target host name '%s'", certname, peer->dispname); + "target host name '%s'", certname, dispname); gnutls_x509_crt_deinit(x509_cert); return CURLE_PEER_FAILED_VERIFICATION; } else infof(data, " common name: %s (does not match '%s')", - certname, peer->dispname); + certname, dispname); } else infof(data, " common name: %s (matched)", certname); @@ -1251,7 +1253,8 @@ static CURLcode gtls_verifyserver(struct Curl_cfilter *cf, CURLcode result; result = Curl_gtls_verifyserver(data, session, conn_config, ssl_config, - &connssl->peer, pinned_key); + connssl->hostname, connssl->dispname, + pinned_key); if(result) goto out; @@ -1659,7 +1662,7 @@ const struct Curl_ssl Curl_ssl_gnutls = { gtls_cert_status_request, /* cert_status_request */ gtls_connect, /* connect */ gtls_connect_nonblocking, /* connect_nonblocking */ - Curl_ssl_adjust_pollset, /* adjust_pollset */ + Curl_ssl_get_select_socks, /* getsock */ gtls_get_internals, /* get_internals */ gtls_close, /* close_one */ Curl_none_close_all, /* close_all */ diff --git a/deps/curl/lib/vtls/gtls.h b/deps/curl/lib/vtls/gtls.h index 1a81c01e..ac141e1c 100644 --- a/deps/curl/lib/vtls/gtls.h +++ b/deps/curl/lib/vtls/gtls.h @@ -43,7 +43,6 @@ struct Curl_easy; struct Curl_cfilter; struct ssl_primary_config; struct ssl_config_data; -struct ssl_peer; struct gtls_instance { gnutls_session_t session; @@ -57,7 +56,7 @@ CURLcode gtls_client_init(struct Curl_easy *data, struct ssl_primary_config *config, struct ssl_config_data *ssl_config, - struct ssl_peer *peer, + const char *hostname, struct gtls_instance *gtls, long *pverifyresult); @@ -66,7 +65,8 @@ Curl_gtls_verifyserver(struct Curl_easy *data, gnutls_session_t session, struct ssl_primary_config *config, struct ssl_config_data *ssl_config, - struct ssl_peer *peer, + const char *hostname, + const char *dispname, const char *pinned_key); extern const struct Curl_ssl Curl_ssl_gnutls; diff --git a/deps/curl/lib/vtls/keylog.c b/deps/curl/lib/vtls/keylog.c index fbcb25cf..d37bb183 100644 --- a/deps/curl/lib/vtls/keylog.c +++ b/deps/curl/lib/vtls/keylog.c @@ -23,11 +23,6 @@ ***************************************************************************/ #include "curl_setup.h" -#if defined(USE_OPENSSL) || \ - defined(USE_WOLFSSL) || \ - (defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || \ - defined(USE_QUICHE) - #include "keylog.h" #include @@ -60,7 +55,7 @@ Curl_tls_keylog_open(void) if(keylog_file_name) { keylog_file_fp = fopen(keylog_file_name, FOPEN_APPENDTEXT); if(keylog_file_fp) { -#ifdef _WIN32 +#ifdef WIN32 if(setvbuf(keylog_file_fp, NULL, _IONBF, 0)) #else if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096)) @@ -162,5 +157,3 @@ Curl_tls_keylog_write(const char *label, fputs(line, keylog_file_fp); return true; } - -#endif /* TLS or QUIC backend */ diff --git a/deps/curl/lib/vtls/mbedtls.c b/deps/curl/lib/vtls/mbedtls.c index 38f7de7f..2f994d74 100644 --- a/deps/curl/lib/vtls/mbedtls.c +++ b/deps/curl/lib/vtls/mbedtls.c @@ -322,7 +322,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) char * const ssl_cert = ssl_config->primary.clientcert; const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob; const char * const ssl_crlfile = ssl_config->primary.CRLfile; - const char *hostname = connssl->peer.hostname; + const char *hostname = connssl->hostname; int ret = -1; char errorbuf[128]; @@ -639,9 +639,9 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) mbedtls_ssl_conf_own_cert(&backend->config, &backend->clicert, &backend->pk); } - - if(connssl->peer.sni) { - if(mbedtls_ssl_set_hostname(&backend->ssl, connssl->peer.sni)) { + { + char *snihost = Curl_ssl_snihost(data, hostname, NULL); + if(!snihost || mbedtls_ssl_set_hostname(&backend->ssl, snihost)) { /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks and the name to set in the SNI extension. So even if curl connects to a host specified as an IP address, this function must be used. */ @@ -1274,7 +1274,7 @@ const struct Curl_ssl Curl_ssl_mbedtls = { Curl_none_cert_status_request, /* cert_status_request */ mbedtls_connect, /* connect */ mbedtls_connect_nonblocking, /* connect_nonblocking */ - Curl_ssl_adjust_pollset, /* adjust_pollset */ + Curl_ssl_get_select_socks, /* getsock */ mbedtls_get_internals, /* get_internals */ mbedtls_close, /* close_one */ mbedtls_close_all, /* close_all */ diff --git a/deps/curl/lib/vtls/mbedtls_threadlock.c b/deps/curl/lib/vtls/mbedtls_threadlock.c index 22b1b221..bcb7106a 100644 --- a/deps/curl/lib/vtls/mbedtls_threadlock.c +++ b/deps/curl/lib/vtls/mbedtls_threadlock.c @@ -51,7 +51,7 @@ int Curl_mbedtlsthreadlock_thread_setup(void) { int i; - mutex_buf = calloc(1, NUMT * sizeof(MBEDTLS_MUTEX_T)); + mutex_buf = calloc(NUMT * sizeof(MBEDTLS_MUTEX_T), 1); if(!mutex_buf) return 0; /* error, no number of threads defined */ diff --git a/deps/curl/lib/vtls/openssl.c b/deps/curl/lib/vtls/openssl.c index 8c8f43e8..9f9c8d13 100644 --- a/deps/curl/lib/vtls/openssl.c +++ b/deps/curl/lib/vtls/openssl.c @@ -79,8 +79,6 @@ #include #include #include -#include -#include #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_OCSP) #include @@ -98,9 +96,6 @@ #include "curl_memory.h" #include "memdebug.h" -#ifndef ARRAYSIZE -#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) -#endif /* Uncomment the ALLOW_RENEG line to a real #define if you want to allow TLS renegotiations when built with BoringSSL. Renegotiating is non-compliant @@ -178,6 +173,8 @@ #if (OPENSSL_VERSION_NUMBER >= 0x30000000L) #define HAVE_EVP_PKEY_GET_PARAMS 1 +#else +#define SSL_get1_peer_certificate SSL_get_peer_certificate #endif #ifdef HAVE_EVP_PKEY_GET_PARAMS @@ -238,11 +235,7 @@ #elif defined(OPENSSL_IS_AWSLC) #define OSSL_PACKAGE "AWS-LC" #else -# if defined(USE_NGTCP2) && defined(USE_NGHTTP3) -# define OSSL_PACKAGE "quictls" -# else -# define OSSL_PACKAGE "OpenSSL" -#endif +#define OSSL_PACKAGE "OpenSSL" #endif #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) @@ -545,9 +538,9 @@ CURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl) #else RSA_get0_key(rsa, &n, &e, NULL); #endif /* HAVE_EVP_PKEY_GET_PARAMS */ - BIO_printf(mem, "%d", n ? BN_num_bits(n) : 0); + BIO_printf(mem, "%d", BN_num_bits(n)); #else - BIO_printf(mem, "%d", rsa->n ? BN_num_bits(rsa->n) : 0); + BIO_printf(mem, "%d", BN_num_bits(rsa->n)); #endif /* HAVE_OPAQUE_RSA_DSA_DH */ push_certinfo("RSA Public Key", i); print_pubkey_BN(rsa, n, i); @@ -2105,6 +2098,22 @@ static bool subj_alt_hostcheck(struct Curl_easy *data, return FALSE; } +static CURLcode +ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, + X509 *server_cert, const char *hostname, + const char *dispname); + +CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, + X509 *server_cert) +{ + const char *hostname, *dispname; + int port; + + (void)conn; + Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &dispname, &port); + return ossl_verifyhost(data, conn, server_cert, hostname, dispname); +} + /* Quote from RFC2818 section 3.1 "Server Identity" If a subjectAltName extension of type dNSName is present, that MUST @@ -2127,8 +2136,10 @@ static bool subj_alt_hostcheck(struct Curl_easy *data, This function is now used from ngtcp2 (QUIC) as well. */ -CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, - struct ssl_peer *peer, X509 *server_cert) +static CURLcode +ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, + X509 *server_cert, const char *hostname, + const char *dispname) { bool matched = FALSE; int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */ @@ -2145,21 +2156,25 @@ CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, size_t hostlen; (void)conn; - hostlen = strlen(peer->hostname); - if(peer->is_ip_address) { -#ifdef ENABLE_IPV6 - if(conn->bits.ipv6_ip && - Curl_inet_pton(AF_INET6, peer->hostname, &addr)) { - target = GEN_IPADD; - addrlen = sizeof(struct in6_addr); - } - else + hostlen = strlen(hostname); + +#ifndef ENABLE_IPV6 + /* Silence compiler warnings for unused params */ + (void) conn; #endif - if(Curl_inet_pton(AF_INET, peer->hostname, &addr)) { - target = GEN_IPADD; - addrlen = sizeof(struct in_addr); - } + +#ifdef ENABLE_IPV6 + if(conn->bits.ipv6_ip && + Curl_inet_pton(AF_INET6, hostname, &addr)) { + target = GEN_IPADD; + addrlen = sizeof(struct in6_addr); } + else +#endif + if(Curl_inet_pton(AF_INET, hostname, &addr)) { + target = GEN_IPADD; + addrlen = sizeof(struct in_addr); + } /* get a "list" of alternative names */ altnames = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL); @@ -2209,9 +2224,9 @@ CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, if((altlen == strlen(altptr)) && /* if this isn't true, there was an embedded zero in the name string and we cannot match it. */ - subj_alt_hostcheck(data, altptr, altlen, - peer->hostname, hostlen, - peer->dispname)) { + subj_alt_hostcheck(data, + altptr, + altlen, hostname, hostlen, dispname)) { dnsmatched = TRUE; } break; @@ -2223,7 +2238,7 @@ CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, ipmatched = TRUE; infof(data, " subjectAltName: host \"%s\" matched cert's IP address!", - peer->dispname); + dispname); } break; } @@ -2239,9 +2254,9 @@ CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, /* an alternative name matched */ ; else if(dNSName || iPAddress) { - infof(data, " subjectAltName does not match %s", peer->dispname); + infof(data, " subjectAltName does not match %s", dispname); failf(data, "SSL: no alternative certificate subject name matches " - "target host name '%s'", peer->dispname); + "target host name '%s'", dispname); result = CURLE_PEER_FAILED_VERIFICATION; } else { @@ -2305,9 +2320,9 @@ CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, result = CURLE_PEER_FAILED_VERIFICATION; } else if(!Curl_cert_hostcheck((const char *)peer_CN, - peerlen, peer->hostname, hostlen)) { + peerlen, hostname, hostlen)) { failf(data, "SSL: certificate subject name '%s' does not match " - "target host name '%s'", peer_CN, peer->dispname); + "target host name '%s'", peer_CN, dispname); result = CURLE_PEER_FAILED_VERIFICATION; } else { @@ -2716,6 +2731,12 @@ static void ossl_trace(int direction, int ssl_ver, int content_type, #ifdef USE_OPENSSL /* ====================================================== */ +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME +# define use_sni(x) sni = (x) +#else +# define use_sni(x) Curl_nop_stmt +#endif + /* Check for OpenSSL 1.0.2 which has ALPN support. */ #undef HAS_ALPN #if OPENSSL_VERSION_NUMBER >= 0x10002000L \ @@ -3011,151 +3032,6 @@ static CURLcode load_cacert_from_memory(X509_STORE *store, return (count > 0) ? CURLE_OK : CURLE_SSL_CACERT_BADFILE; } -#if defined(USE_WIN32_CRYPTO) -static CURLcode import_windows_cert_store(struct Curl_easy *data, - const char *name, - X509_STORE *store, - bool *imported) -{ - CURLcode result = CURLE_OK; - HCERTSTORE hStore; - - *imported = false; - - hStore = CertOpenSystemStoreA(0, name); - if(hStore) { - PCCERT_CONTEXT pContext = NULL; - /* The array of enhanced key usage OIDs will vary per certificate and - is declared outside of the loop so that rather than malloc/free each - iteration we can grow it with realloc, when necessary. */ - CERT_ENHKEY_USAGE *enhkey_usage = NULL; - DWORD enhkey_usage_size = 0; - - /* This loop makes a best effort to import all valid certificates from - the MS root store. If a certificate cannot be imported it is - skipped. 'result' is used to store only hard-fail conditions (such - as out of memory) that cause an early break. */ - result = CURLE_OK; - for(;;) { - X509 *x509; - FILETIME now; - BYTE key_usage[2]; - DWORD req_size; - const unsigned char *encoded_cert; -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - char cert_name[256]; -#endif - - pContext = CertEnumCertificatesInStore(hStore, pContext); - if(!pContext) - break; - -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, - NULL, cert_name, sizeof(cert_name))) { - strcpy(cert_name, "Unknown"); - } - infof(data, "SSL: Checking cert \"%s\"", cert_name); -#endif - encoded_cert = (const unsigned char *)pContext->pbCertEncoded; - if(!encoded_cert) - continue; - - GetSystemTimeAsFileTime(&now); - if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 || - CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0) - continue; - - /* If key usage exists check for signing attribute */ - if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType, - pContext->pCertInfo, - key_usage, sizeof(key_usage))) { - if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE)) - continue; - } - else if(GetLastError()) - continue; - - /* If enhanced key usage exists check for server auth attribute. - * - * Note "In a Microsoft environment, a certificate might also have - * EKU extended properties that specify valid uses for the - * certificate." The call below checks both, and behavior varies - * depending on what is found. For more details see - * CertGetEnhancedKeyUsage doc. - */ - if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) { - if(req_size && req_size > enhkey_usage_size) { - void *tmp = realloc(enhkey_usage, req_size); - - if(!tmp) { - failf(data, "SSL: Out of memory allocating for OID list"); - result = CURLE_OUT_OF_MEMORY; - break; - } - - enhkey_usage = (CERT_ENHKEY_USAGE *)tmp; - enhkey_usage_size = req_size; - } - - if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) { - if(!enhkey_usage->cUsageIdentifier) { - /* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate - is good for all uses. If it returns zero, the certificate - has no valid uses." */ - if((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND) - continue; - } - else { - DWORD i; - bool found = false; - - for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) { - if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */, - enhkey_usage->rgpszUsageIdentifier[i])) { - found = true; - break; - } - } - - if(!found) - continue; - } - } - else - continue; - } - else - continue; - - x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded); - if(!x509) - continue; - - /* Try to import the certificate. This may fail for legitimate - reasons such as duplicate certificate, which is allowed by MS but - not OpenSSL. */ - if(X509_STORE_add_cert(store, x509) == 1) { -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - infof(data, "SSL: Imported cert \"%s\"", cert_name); -#endif - *imported = true; - } - X509_free(x509); - } - - free(enhkey_usage); - CertFreeCertificateContext(pContext); - CertCloseStore(hStore, 0); - - if(result) - return result; - } - - return result; -} -#endif - static CURLcode populate_x509_store(struct Curl_cfilter *cf, struct Curl_easy *data, X509_STORE *store) @@ -3185,25 +3061,140 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, https://github.com/d3x0r/SACK/blob/master/src/netlib/ssl_layer.c#L1037 https://datatracker.ietf.org/doc/html/rfc5280 */ if(ssl_config->native_ca_store) { - const char *storeNames[] = { - "ROOT", /* Trusted Root Certification Authorities */ - "CA" /* Intermediate Certification Authorities */ - }; - size_t i; - for(i = 0; i < ARRAYSIZE(storeNames); ++i) { - bool imported = false; - result = import_windows_cert_store(data, storeNames[i], store, - &imported); + HCERTSTORE hStore = CertOpenSystemStore(0, TEXT("ROOT")); + + if(hStore) { + PCCERT_CONTEXT pContext = NULL; + /* The array of enhanced key usage OIDs will vary per certificate and + is declared outside of the loop so that rather than malloc/free each + iteration we can grow it with realloc, when necessary. */ + CERT_ENHKEY_USAGE *enhkey_usage = NULL; + DWORD enhkey_usage_size = 0; + + /* This loop makes a best effort to import all valid certificates from + the MS root store. If a certificate cannot be imported it is + skipped. 'result' is used to store only hard-fail conditions (such + as out of memory) that cause an early break. */ + result = CURLE_OK; + for(;;) { + X509 *x509; + FILETIME now; + BYTE key_usage[2]; + DWORD req_size; + const unsigned char *encoded_cert; +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + char cert_name[256]; +#endif + + pContext = CertEnumCertificatesInStore(hStore, pContext); + if(!pContext) + break; + +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, + NULL, cert_name, sizeof(cert_name))) { + strcpy(cert_name, "Unknown"); + } + infof(data, "SSL: Checking cert \"%s\"", cert_name); +#endif + encoded_cert = (const unsigned char *)pContext->pbCertEncoded; + if(!encoded_cert) + continue; + + GetSystemTimeAsFileTime(&now); + if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 || + CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0) + continue; + + /* If key usage exists check for signing attribute */ + if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType, + pContext->pCertInfo, + key_usage, sizeof(key_usage))) { + if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE)) + continue; + } + else if(GetLastError()) + continue; + + /* If enhanced key usage exists check for server auth attribute. + * + * Note "In a Microsoft environment, a certificate might also have + * EKU extended properties that specify valid uses for the + * certificate." The call below checks both, and behavior varies + * depending on what is found. For more details see + * CertGetEnhancedKeyUsage doc. + */ + if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) { + if(req_size && req_size > enhkey_usage_size) { + void *tmp = realloc(enhkey_usage, req_size); + + if(!tmp) { + failf(data, "SSL: Out of memory allocating for OID list"); + result = CURLE_OUT_OF_MEMORY; + break; + } + + enhkey_usage = (CERT_ENHKEY_USAGE *)tmp; + enhkey_usage_size = req_size; + } + + if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) { + if(!enhkey_usage->cUsageIdentifier) { + /* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate + is good for all uses. If it returns zero, the certificate + has no valid uses." */ + if((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND) + continue; + } + else { + DWORD i; + bool found = false; + + for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) { + if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */, + enhkey_usage->rgpszUsageIdentifier[i])) { + found = true; + break; + } + } + + if(!found) + continue; + } + } + else + continue; + } + else + continue; + + x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded); + if(!x509) + continue; + + /* Try to import the certificate. This may fail for legitimate + reasons such as duplicate certificate, which is allowed by MS but + not OpenSSL. */ + if(X509_STORE_add_cert(store, x509) == 1) { +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + infof(data, "SSL: Imported cert \"%s\"", cert_name); +#endif + imported_native_ca = true; + } + X509_free(x509); + } + + free(enhkey_usage); + CertFreeCertificateContext(pContext); + CertCloseStore(hStore, 0); + if(result) return result; - if(imported) { - infof(data, "successfully imported Windows %s store", storeNames[i]); - imported_native_ca = true; - } - else - infof(data, "error importing Windows %s store, continuing anyway", - storeNames[i]); } + if(imported_native_ca) + infof(data, "successfully imported Windows CA store"); + else + infof(data, "error importing Windows CA store, continuing anyway"); } #endif if(ca_info_blob) { @@ -3219,7 +3210,7 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, } if(ssl_cafile || ssl_capath) { -#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) +#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */ if(ssl_cafile && !X509_STORE_load_file(store, ssl_cafile)) { if(!imported_native_ca && !imported_ca_info_blob) { @@ -3348,7 +3339,6 @@ static X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf, struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi; X509_STORE *store = NULL; - DEBUGASSERT(multi); if(multi && multi->ssl_backend_data && multi->ssl_backend_data->store && @@ -3368,7 +3358,6 @@ static void set_cached_x509_store(struct Curl_cfilter *cf, struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi; struct multi_ssl_backend_data *mbackend; - DEBUGASSERT(multi); if(!multi) return; @@ -3460,6 +3449,17 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); BIO *bio; + +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + bool sni; + const char *hostname = connssl->hostname; + +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif +#endif const long int ssl_version = conn_config->version; char * const ssl_cert = ssl_config->primary.clientcert; const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob; @@ -3494,6 +3494,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, #else req_method = SSLv23_client_method(); #endif + use_sni(TRUE); break; case CURL_SSLVERSION_SSLv2: failf(data, "No SSLv2 support"); @@ -3786,8 +3787,13 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, backend->server_cert = 0x0; #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME - if(connssl->peer.sni) { - if(!SSL_set_tlsext_host_name(backend->handle, connssl->peer.sni)) { + if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) && +#ifdef ENABLE_IPV6 + (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) && +#endif + sni) { + char *snihost = Curl_ssl_snihost(data, hostname, NULL); + if(!snihost || !SSL_set_tlsext_host_name(backend->handle, snihost)) { failf(data, "Failed set SNI"); return CURLE_SSL_CONNECT_ERROR; } @@ -3796,7 +3802,6 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, SSL_set_app_data(backend->handle, cf); - connssl->reused_session = FALSE; if(ssl_config->primary.sessionid) { Curl_ssl_sessionid_lock(data); if(!Curl_ssl_getsessionid(cf, data, &ssl_sessionid, NULL)) { @@ -3810,7 +3815,6 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, } /* Informational message */ infof(data, "SSL reusing session ID"); - connssl->reused_session = TRUE; } Curl_ssl_sessionid_unlock(data); } @@ -3971,7 +3975,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, Curl_strerror(sockerr, extramsg, sizeof(extramsg)); failf(data, OSSL_PACKAGE " SSL_connect: %s in connection to %s:%d ", extramsg[0] ? extramsg : SSL_ERROR_to_str(detail), - connssl->peer.hostname, connssl->port); + connssl->hostname, connssl->port); return result; } @@ -3982,28 +3986,13 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, } } else { - int psigtype_nid = NID_undef; - const char *negotiated_group_name = NULL; - /* we connected fine, we're not waiting for anything else. */ connssl->connecting_state = ssl_connect_3; -#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) - SSL_get_peer_signature_type_nid(backend->handle, &psigtype_nid); -#if (OPENSSL_VERSION_NUMBER >= 0x30200000L) - negotiated_group_name = SSL_get0_group_name(backend->handle); -#else - negotiated_group_name = - OBJ_nid2sn(SSL_get_negotiated_group(backend->handle) & 0x0000FFFF); -#endif -#endif - /* Informational message */ - infof(data, "SSL connection using %s / %s / %s / %s", + infof(data, "SSL connection using %s / %s", SSL_get_version(backend->handle), - SSL_get_cipher(backend->handle), - negotiated_group_name? negotiated_group_name : "[blank]", - OBJ_nid2sn(psigtype_nid)); + SSL_get_cipher(backend->handle)); #ifdef HAS_ALPN /* Sets data and len to negotiated protocol, len is 0 if no protocol was @@ -4080,75 +4069,6 @@ static CURLcode ossl_pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert, return result; } -#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \ - !(defined(LIBRESSL_VERSION_NUMBER) && \ - LIBRESSL_VERSION_NUMBER < 0x3060000fL) && \ - !defined(OPENSSL_IS_BORINGSSL) && \ - !defined(OPENSSL_IS_AWSLC) && \ - !defined(CURL_DISABLE_VERBOSE_STRINGS) -static void infof_certstack(struct Curl_easy *data, const SSL *ssl) -{ - STACK_OF(X509) *certstack; - long verify_result; - int num_cert_levels; - int cert_level; - - verify_result = SSL_get_verify_result(ssl); - if(verify_result != X509_V_OK) - certstack = SSL_get_peer_cert_chain(ssl); - else - certstack = SSL_get0_verified_chain(ssl); - num_cert_levels = sk_X509_num(certstack); - - for(cert_level = 0; cert_level < num_cert_levels; cert_level++) { - char cert_algorithm[80] = ""; - char group_name_final[80] = ""; - const X509_ALGOR *palg_cert = NULL; - const ASN1_OBJECT *paobj_cert = NULL; - X509 *current_cert; - EVP_PKEY *current_pkey; - int key_bits; - int key_sec_bits; - int get_group_name; - const char *type_name; - - current_cert = sk_X509_value(certstack, cert_level); - - X509_get0_signature(NULL, &palg_cert, current_cert); - X509_ALGOR_get0(&paobj_cert, NULL, NULL, palg_cert); - OBJ_obj2txt(cert_algorithm, sizeof(cert_algorithm), paobj_cert, 0); - - current_pkey = X509_get0_pubkey(current_cert); - key_bits = EVP_PKEY_bits(current_pkey); -#if (OPENSSL_VERSION_NUMBER < 0x30000000L) -#define EVP_PKEY_get_security_bits EVP_PKEY_security_bits -#endif - key_sec_bits = EVP_PKEY_get_security_bits(current_pkey); -#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) - { - char group_name[80] = ""; - get_group_name = EVP_PKEY_get_group_name(current_pkey, group_name, - sizeof(group_name), NULL); - msnprintf(group_name_final, sizeof(group_name_final), "/%s", group_name); - } - type_name = EVP_PKEY_get0_type_name(current_pkey); -#else - get_group_name = 0; - type_name = NULL; -#endif - - infof(data, - " Certificate level %d: " - "Public key type %s%s (%d/%d Bits/secBits), signed using %s", - cert_level, type_name ? type_name : "?", - get_group_name == 0 ? "" : group_name_final, - key_bits, key_sec_bits, cert_algorithm); - } -} -#else -#define infof_certstack(data, ssl) -#endif - /* * Get the server cert, verify it and show it, etc., only call failf() if the * 'strict' argument is TRUE as otherwise all this is for informational @@ -4227,8 +4147,8 @@ static CURLcode servercert(struct Curl_cfilter *cf, BIO_free(mem); if(conn_config->verifyhost) { - result = Curl_ossl_verifyhost(data, conn, &connssl->peer, - backend->server_cert); + result = ossl_verifyhost(data, conn, backend->server_cert, + connssl->hostname, connssl->dispname); if(result) { X509_free(backend->server_cert); backend->server_cert = NULL; @@ -4338,12 +4258,9 @@ static CURLcode servercert(struct Curl_cfilter *cf, infof(data, " SSL certificate verify ok."); } - infof_certstack(data, backend->handle); - #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ !defined(OPENSSL_NO_OCSP) - if(conn_config->verifystatus && !connssl->reused_session) { - /* don't do this after Session ID reuse */ + if(conn_config->verifystatus) { result = verifystatus(cf, data); if(result) { X509_free(backend->server_cert); @@ -4605,9 +4522,22 @@ static ssize_t ossl_send(struct Curl_cfilter *cf, case SSL_ERROR_SSL: { /* A failure in the SSL library occurred, usually a protocol error. The OpenSSL error queue contains more information on the error. */ + struct Curl_cfilter *cf_ssl_next = Curl_ssl_cf_get_ssl(cf->next); + struct ssl_connect_data *connssl_next = cf_ssl_next? + cf_ssl_next->ctx : NULL; sslerror = ERR_get_error(); - failf(data, "SSL_write() error: %s", - ossl_strerror(sslerror, error_buffer, sizeof(error_buffer))); + if(ERR_GET_LIB(sslerror) == ERR_LIB_SSL && + ERR_GET_REASON(sslerror) == SSL_R_BIO_NOT_SET && + connssl->state == ssl_connection_complete && + (connssl_next && connssl_next->state == ssl_connection_complete) + ) { + char ver[120]; + (void)ossl_version(ver, sizeof(ver)); + failf(data, "Error: %s does not support double SSL tunneling.", ver); + } + else + failf(data, "SSL_write() error: %s", + ossl_strerror(sslerror, error_buffer, sizeof(error_buffer))); *curlcode = CURLE_SEND_ERROR; rc = -1; goto out; @@ -4912,7 +4842,7 @@ const struct Curl_ssl Curl_ssl_openssl = { ossl_cert_status_request, /* cert_status_request */ ossl_connect, /* connect */ ossl_connect_nonblocking, /* connect_nonblocking */ - Curl_ssl_adjust_pollset, /* adjust_pollset */ + Curl_ssl_get_select_socks,/* getsock */ ossl_get_internals, /* get_internals */ ossl_close, /* close_one */ ossl_close_all, /* close_all */ diff --git a/deps/curl/lib/vtls/openssl.h b/deps/curl/lib/vtls/openssl.h index e802363a..950faab8 100644 --- a/deps/curl/lib/vtls/openssl.h +++ b/deps/curl/lib/vtls/openssl.h @@ -31,21 +31,24 @@ * This header should only be needed to get included by vtls.c, openssl.c * and ngtcp2.c */ -#include #include #include "urldata.h" -#if (OPENSSL_VERSION_NUMBER < 0x30000000L) -#define SSL_get1_peer_certificate SSL_get_peer_certificate -#endif - +/* + * In an effort to avoid using 'X509 *' here, we instead use the struct + * x509_st version of the type so that we can forward-declare it here without + * having to include . Including that header causes name + * conflicts when libcurl is built with both Schannel and OpenSSL support. + */ +struct x509_st; CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, - struct ssl_peer *peer, X509 *server_cert); + struct x509_st *server_cert); extern const struct Curl_ssl Curl_ssl_openssl; +struct ssl_ctx_st; CURLcode Curl_ossl_set_client_cert(struct Curl_easy *data, - SSL_CTX *ctx, char *cert_file, + struct ssl_ctx_st *ctx, char *cert_file, const struct curl_blob *cert_blob, const char *cert_type, char *key_file, const struct curl_blob *key_blob, @@ -62,9 +65,5 @@ CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf, struct Curl_easy *data, SSL_CTX *ssl_ctx); -CURLcode Curl_ossl_ctx_configure(struct Curl_cfilter *cf, - struct Curl_easy *data, - SSL_CTX *ssl_ctx); - #endif /* USE_OPENSSL */ #endif /* HEADER_CURL_SSLUSE_H */ diff --git a/deps/curl/lib/vtls/rustls.c b/deps/curl/lib/vtls/rustls.c index 70b200ad..a3e9d964 100644 --- a/deps/curl/lib/vtls/rustls.c +++ b/deps/curl/lib/vtls/rustls.c @@ -386,7 +386,7 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */ (ca_info_blob ? NULL : conn_config->CAfile); const bool verifypeer = conn_config->verifypeer; - const char *hostname = connssl->peer.hostname; + const char *hostname = connssl->hostname; char errorbuf[256]; size_t errorlen; int result; @@ -458,11 +458,12 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, backend->config = rustls_client_config_builder_build(config_builder); DEBUGASSERT(rconn == NULL); { - /* rustls claims to manage ip address hostnames as well here. So, - * if we have an SNI, we use it, otherwise we pass the hostname */ - char *server = connssl->peer.sni? - connssl->peer.sni : connssl->peer.hostname; - result = rustls_client_connection_new(backend->config, server, &rconn); + char *snihost = Curl_ssl_snihost(data, hostname, NULL); + if(!snihost) { + failf(data, "rustls: failed to get SNI"); + return CURLE_SSL_CONNECT_ERROR; + } + result = rustls_client_connection_new(backend->config, snihost, &rconn); } if(result != RUSTLS_RESULT_OK) { rustls_error(result, errorbuf, sizeof(errorbuf), &errorlen); @@ -588,28 +589,32 @@ cr_connect_nonblocking(struct Curl_cfilter *cf, DEBUGASSERT(false); } -static void cr_adjust_pollset(struct Curl_cfilter *cf, - struct Curl_easy *data, - struct easy_pollset *ps) +/* returns a bitmap of flags for this connection's first socket indicating + whether we want to read or write */ +static int +cr_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data, + curl_socket_t *socks) { - if(!cf->connected) { - curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data); - struct ssl_connect_data *const connssl = cf->ctx; - struct rustls_ssl_backend_data *const backend = - (struct rustls_ssl_backend_data *)connssl->backend; - struct rustls_connection *rconn = NULL; + struct ssl_connect_data *const connssl = cf->ctx; + curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data); + struct rustls_ssl_backend_data *const backend = + (struct rustls_ssl_backend_data *)connssl->backend; + struct rustls_connection *rconn = NULL; - (void)data; - DEBUGASSERT(backend); - rconn = backend->conn; + (void)data; + DEBUGASSERT(backend); + rconn = backend->conn; - if(rustls_connection_wants_write(rconn)) { - Curl_pollset_add_out(data, ps, sock); - } - if(rustls_connection_wants_read(rconn)) { - Curl_pollset_add_in(data, ps, sock); - } + if(rustls_connection_wants_write(rconn)) { + socks[0] = sockfd; + return GETSOCK_WRITESOCK(0); } + if(rustls_connection_wants_read(rconn)) { + socks[0] = sockfd; + return GETSOCK_READSOCK(0); + } + + return GETSOCK_BLANK; } static void * @@ -672,7 +677,7 @@ const struct Curl_ssl Curl_ssl_rustls = { Curl_none_cert_status_request, /* cert_status_request */ cr_connect, /* connect */ cr_connect_nonblocking, /* connect_nonblocking */ - cr_adjust_pollset, /* adjust_pollset */ + cr_get_select_socks, /* get_select_socks */ cr_get_internals, /* get_internals */ cr_close, /* close_one */ Curl_none_close_all, /* close_all */ diff --git a/deps/curl/lib/vtls/schannel.c b/deps/curl/lib/vtls/schannel.c index ae7f2956..410a5c4e 100644 --- a/deps/curl/lib/vtls/schannel.c +++ b/deps/curl/lib/vtls/schannel.c @@ -1063,12 +1063,17 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) #endif SECURITY_STATUS sspi_status = SEC_E_OK; struct Curl_schannel_cred *old_cred = NULL; + struct in_addr addr; +#ifdef ENABLE_IPV6 + struct in6_addr addr6; +#endif CURLcode result; + const char *hostname = connssl->hostname; DEBUGASSERT(backend); DEBUGF(infof(data, "schannel: SSL/TLS connection with %s port %d (step 1/3)", - connssl->peer.hostname, connssl->port)); + hostname, connssl->port)); if(curlx_verify_windows_version(5, 1, 0, PLATFORM_WINNT, VERSION_LESS_THAN_EQUAL)) { @@ -1149,14 +1154,22 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) /* A hostname associated with the credential is needed by InitializeSecurityContext for SNI and other reasons. */ - snihost = connssl->peer.sni? connssl->peer.sni : connssl->peer.hostname; + snihost = Curl_ssl_snihost(data, hostname, NULL); + if(!snihost) { + failf(data, "Failed to set SNI"); + return CURLE_SSL_CONNECT_ERROR; + } backend->cred->sni_hostname = curlx_convert_UTF8_to_tchar(snihost); if(!backend->cred->sni_hostname) return CURLE_OUT_OF_MEMORY; } /* Warn if SNI is disabled due to use of an IP address */ - if(connssl->peer.is_ip_address) { + if(Curl_inet_pton(AF_INET, hostname, &addr) +#ifdef ENABLE_IPV6 + || Curl_inet_pton(AF_INET6, hostname, &addr6) +#endif + ) { infof(data, "schannel: using IP address, SNI is not supported by OS."); } @@ -1333,7 +1346,7 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) DEBUGF(infof(data, "schannel: SSL/TLS connection with %s port %d (step 2/3)", - connssl->peer.hostname, connssl->port)); + connssl->hostname, connssl->port)); if(!backend->cred || !backend->ctxt) return CURLE_SSL_CONNECT_ERROR; @@ -1687,7 +1700,7 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data) DEBUGF(infof(data, "schannel: SSL/TLS connection with %s port %d (step 3/3)", - connssl->peer.hostname, connssl->port)); + connssl->hostname, connssl->port)); if(!backend->cred) return CURLE_SSL_CONNECT_ERROR; @@ -2485,7 +2498,7 @@ static int schannel_shutdown(struct Curl_cfilter *cf, if(backend->ctxt) { infof(data, "schannel: shutting down SSL/TLS connection with %s port %d", - connssl->peer.hostname, connssl->port); + connssl->hostname, connssl->port); } if(backend->cred && backend->ctxt) { @@ -2741,151 +2754,6 @@ static void *schannel_get_internals(struct ssl_connect_data *connssl, return &backend->ctxt->ctxt_handle; } -HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf, - const struct Curl_easy *data) -{ - struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); - struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi; - const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; - struct schannel_multi_ssl_backend_data *mbackend; - const struct ssl_general_config *cfg = &data->set.general_ssl; - timediff_t timeout_ms; - timediff_t elapsed_ms; - struct curltime now; - unsigned char info_blob_digest[CURL_SHA256_DIGEST_LENGTH]; - - DEBUGASSERT(multi); - - if(!multi || !multi->ssl_backend_data) { - return NULL; - } - - mbackend = (struct schannel_multi_ssl_backend_data *)multi->ssl_backend_data; - if(!mbackend->cert_store) { - return NULL; - } - - /* zero ca_cache_timeout completely disables caching */ - if(!cfg->ca_cache_timeout) { - return NULL; - } - - /* check for cache timeout by using the cached_x509_store_expired timediff - calculation pattern from openssl.c. - negative timeout means retain forever. */ - timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000; - if(timeout_ms >= 0) { - now = Curl_now(); - elapsed_ms = Curl_timediff(now, mbackend->time); - if(elapsed_ms >= timeout_ms) { - return NULL; - } - } - - if(ca_info_blob) { - if(!mbackend->CAinfo_blob_digest) { - return NULL; - } - if(mbackend->CAinfo_blob_size != ca_info_blob->len) { - return NULL; - } - schannel_sha256sum((const unsigned char *)ca_info_blob->data, - ca_info_blob->len, - info_blob_digest, - CURL_SHA256_DIGEST_LENGTH); - if(memcmp(mbackend->CAinfo_blob_digest, - info_blob_digest, - CURL_SHA256_DIGEST_LENGTH)) { - return NULL; - } - } - else { - if(!conn_config->CAfile || !mbackend->CAfile || - strcmp(mbackend->CAfile, conn_config->CAfile)) { - return NULL; - } - } - - return mbackend->cert_store; -} - -bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf, - const struct Curl_easy *data, - HCERTSTORE cert_store) -{ - struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); - struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi; - const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; - struct schannel_multi_ssl_backend_data *mbackend; - unsigned char *CAinfo_blob_digest = NULL; - size_t CAinfo_blob_size = 0; - char *CAfile = NULL; - - DEBUGASSERT(multi); - - if(!multi) { - return false; - } - - if(!multi->ssl_backend_data) { - multi->ssl_backend_data = - calloc(1, sizeof(struct schannel_multi_ssl_backend_data)); - if(!multi->ssl_backend_data) { - return false; - } - } - - mbackend = (struct schannel_multi_ssl_backend_data *)multi->ssl_backend_data; - - - if(ca_info_blob) { - CAinfo_blob_digest = malloc(CURL_SHA256_DIGEST_LENGTH); - if(!CAinfo_blob_digest) { - return false; - } - schannel_sha256sum((const unsigned char *)ca_info_blob->data, - ca_info_blob->len, - CAinfo_blob_digest, - CURL_SHA256_DIGEST_LENGTH); - CAinfo_blob_size = ca_info_blob->len; - } - else { - if(conn_config->CAfile) { - CAfile = strdup(conn_config->CAfile); - if(!CAfile) { - return false; - } - } - } - - /* free old cache data */ - if(mbackend->cert_store) { - CertCloseStore(mbackend->cert_store, 0); - } - free(mbackend->CAinfo_blob_digest); - free(mbackend->CAfile); - - mbackend->time = Curl_now(); - mbackend->cert_store = cert_store; - mbackend->CAinfo_blob_digest = CAinfo_blob_digest; - mbackend->CAinfo_blob_size = CAinfo_blob_size; - mbackend->CAfile = CAfile; - return true; -} - -static void schannel_free_multi_ssl_backend_data( - struct multi_ssl_backend_data *msbd) -{ - struct schannel_multi_ssl_backend_data *mbackend = - (struct schannel_multi_ssl_backend_data*)msbd; - if(mbackend->cert_store) { - CertCloseStore(mbackend->cert_store, 0); - } - free(mbackend->CAinfo_blob_digest); - free(mbackend->CAfile); - free(mbackend); -} - const struct Curl_ssl Curl_ssl_schannel = { { CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */ @@ -2909,7 +2777,7 @@ const struct Curl_ssl Curl_ssl_schannel = { Curl_none_cert_status_request, /* cert_status_request */ schannel_connect, /* connect */ schannel_connect_nonblocking, /* connect_nonblocking */ - Curl_ssl_adjust_pollset, /* adjust_pollset */ + Curl_ssl_get_select_socks, /* getsock */ schannel_get_internals, /* get_internals */ schannel_close, /* close_one */ Curl_none_close_all, /* close_all */ @@ -2921,7 +2789,7 @@ const struct Curl_ssl Curl_ssl_schannel = { schannel_sha256sum, /* sha256sum */ NULL, /* associate_connection */ NULL, /* disassociate_connection */ - schannel_free_multi_ssl_backend_data, /* free_multi_ssl_backend_data */ + NULL, /* free_multi_ssl_backend_data */ schannel_recv, /* recv decrypted data */ schannel_send, /* send data to encrypt */ }; diff --git a/deps/curl/lib/vtls/schannel_int.h b/deps/curl/lib/vtls/schannel_int.h index fe7450d4..a128e04f 100644 --- a/deps/curl/lib/vtls/schannel_int.h +++ b/deps/curl/lib/vtls/schannel_int.h @@ -149,22 +149,5 @@ struct schannel_ssl_backend_data { #endif }; -struct schannel_multi_ssl_backend_data { - unsigned char *CAinfo_blob_digest; /* CA info blob digest */ - size_t CAinfo_blob_size; /* CA info blob size */ - char *CAfile; /* CAfile path used to generate - certificate store */ - HCERTSTORE cert_store; /* cached certificate store or - NULL if none */ - struct curltime time; /* when the cached store was created */ -}; - -HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf, - const struct Curl_easy *data); - -bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf, - const struct Curl_easy *data, - HCERTSTORE cert_store); - #endif /* USE_SCHANNEL */ #endif /* HEADER_CURL_SCHANNEL_INT_H */ diff --git a/deps/curl/lib/vtls/schannel_verify.c b/deps/curl/lib/vtls/schannel_verify.c index e7c8bc66..a5d5c98b 100644 --- a/deps/curl/lib/vtls/schannel_verify.c +++ b/deps/curl/lib/vtls/schannel_verify.c @@ -470,7 +470,7 @@ CURLcode Curl_verify_host(struct Curl_cfilter *cf, CERT_CONTEXT *pCertContextServer = NULL; TCHAR *cert_hostname_buff = NULL; size_t cert_hostname_buff_index = 0; - const char *conn_hostname = connssl->peer.hostname; + const char *conn_hostname = connssl->hostname; size_t hostlen = strlen(conn_hostname); DWORD len = 0; DWORD actual_len = 0; @@ -600,7 +600,6 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf, const CERT_CHAIN_CONTEXT *pChainContext = NULL; HCERTCHAINENGINE cert_chain_engine = NULL; HCERTSTORE trust_store = NULL; - HCERTSTORE own_trust_store = NULL; DEBUGASSERT(BACKEND); @@ -631,46 +630,31 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf, result = CURLE_SSL_CACERT_BADFILE; } else { - /* try cache */ - trust_store = Curl_schannel_get_cached_cert_store(cf, data); - - if(trust_store) { - infof(data, "schannel: reusing certificate store from cache"); + /* Open the certificate store */ + trust_store = CertOpenStore(CERT_STORE_PROV_MEMORY, + 0, + (HCRYPTPROV)NULL, + CERT_STORE_CREATE_NEW_FLAG, + NULL); + if(!trust_store) { + char buffer[STRERROR_LEN]; + failf(data, "schannel: failed to create certificate store: %s", + Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer))); + result = CURLE_SSL_CACERT_BADFILE; } else { - /* Open the certificate store */ - trust_store = CertOpenStore(CERT_STORE_PROV_MEMORY, - 0, - (HCRYPTPROV)NULL, - CERT_STORE_CREATE_NEW_FLAG, - NULL); - if(!trust_store) { - char buffer[STRERROR_LEN]; - failf(data, "schannel: failed to create certificate store: %s", - Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer))); - result = CURLE_SSL_CACERT_BADFILE; + const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; + if(ca_info_blob) { + result = add_certs_data_to_store(trust_store, + (const char *)ca_info_blob->data, + ca_info_blob->len, + "(memory blob)", + data); } else { - const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; - own_trust_store = trust_store; - - if(ca_info_blob) { - result = add_certs_data_to_store(trust_store, - (const char *)ca_info_blob->data, - ca_info_blob->len, - "(memory blob)", - data); - } - else { - result = add_certs_file_to_store(trust_store, - conn_config->CAfile, - data); - } - if(result == CURLE_OK) { - if(Curl_schannel_set_cached_cert_store(cf, data, trust_store)) { - own_trust_store = NULL; - } - } + result = add_certs_file_to_store(trust_store, + conn_config->CAfile, + data); } } } @@ -770,8 +754,8 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf, CertFreeCertificateChainEngine(cert_chain_engine); } - if(own_trust_store) { - CertCloseStore(own_trust_store, 0); + if(trust_store) { + CertCloseStore(trust_store, 0); } if(pChainContext) diff --git a/deps/curl/lib/vtls/sectransp.c b/deps/curl/lib/vtls/sectransp.c index 0a22ff60..3378f761 100644 --- a/deps/curl/lib/vtls/sectransp.c +++ b/deps/curl/lib/vtls/sectransp.c @@ -46,10 +46,8 @@ #endif /* __clang__ */ #ifdef __GNUC__ -#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Waddress" #pragma GCC diagnostic ignored "-Wundef" -#pragma GCC diagnostic ignored "-Wunreachable-code" #endif #include @@ -1015,7 +1013,7 @@ static CURLcode CopyCertSubject(struct Curl_easy *data, } else { size_t cbuf_size = ((size_t)CFStringGetLength(c) * 4) + 1; - cbuf = calloc(1, cbuf_size); + cbuf = calloc(cbuf_size, 1); if(cbuf) { if(!CFStringGetCString(c, cbuf, cbuf_size, kCFStringEncodingUTF8)) { @@ -1653,6 +1651,11 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf, const bool verifypeer = conn_config->verifypeer; char * const ssl_cert = ssl_config->primary.clientcert; const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob; +#ifdef ENABLE_IPV6 + struct in6_addr addr; +#else + struct in_addr addr; +#endif /* ENABLE_IPV6 */ char *ciphers; OSStatus err = noErr; #if CURL_BUILD_MAC @@ -2000,9 +2003,13 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf, * Both hostname check and SNI require SSLSetPeerDomainName(). * Also: the verifyhost setting influences SNI usage */ if(conn_config->verifyhost) { - char *server = connssl->peer.sni? - connssl->peer.sni : connssl->peer.hostname; - err = SSLSetPeerDomainName(backend->ssl_ctx, server, strlen(server)); + size_t snilen; + char *snihost = Curl_ssl_snihost(data, connssl->hostname, &snilen); + if(!snihost) { + failf(data, "Failed to set SNI"); + return CURLE_SSL_CONNECT_ERROR; + } + err = SSLSetPeerDomainName(backend->ssl_ctx, snihost, snilen); if(err != noErr) { failf(data, "SSL: SSLSetPeerDomainName() failed: OSStatus %d", @@ -2010,7 +2017,11 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf, return CURLE_SSL_CONNECT_ERROR; } - if(connssl->peer.is_ip_address) { + if((Curl_inet_pton(AF_INET, connssl->hostname, &addr)) + #ifdef ENABLE_IPV6 + || (Curl_inet_pton(AF_INET6, connssl->hostname, &addr)) + #endif + ) { infof(data, "WARNING: using IP address, SNI is being disabled by " "the OS."); } @@ -2068,7 +2079,7 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf, ssl_sessionid = aprintf("%s:%d:%d:%s:%d", ssl_cafile ? ssl_cafile : "(blob memory)", - verifypeer, conn_config->verifyhost, connssl->peer.hostname, + verifypeer, conn_config->verifyhost, connssl->hostname, connssl->port); ssl_sessionid_len = strlen(ssl_sessionid); @@ -2654,7 +2665,7 @@ check_handshake: host name: */ case errSSLHostNameMismatch: failf(data, "SSL certificate peer verification failed, the " - "certificate did not match \"%s\"\n", connssl->peer.dispname); + "certificate did not match \"%s\"\n", connssl->dispname); return CURLE_PEER_FAILED_VERIFICATION; /* Problem with SSL / TLS negotiation */ @@ -2746,7 +2757,7 @@ check_handshake: default: /* May also return codes listed in Security Framework Result Codes */ failf(data, "Unknown SSL protocol error in connection to %s:%d", - connssl->peer.hostname, err); + connssl->hostname, err); break; } return CURLE_SSL_CONNECT_ERROR; @@ -3404,6 +3415,7 @@ again: } *curlcode = CURLE_AGAIN; return -1L; + break; /* errSSLClosedGraceful - server gracefully shut down the SSL session errSSLClosedNoNotify - server hung up on us instead of sending a @@ -3413,6 +3425,7 @@ again: case errSSLClosedNoNotify: *curlcode = CURLE_OK; return 0; + break; /* The below is errSSLPeerAuthCompleted; it's not defined in Leopard's headers */ @@ -3432,6 +3445,7 @@ again: failf(data, "SSLRead() return error %d", err); *curlcode = CURLE_RECV_ERROR; return -1L; + break; } } return (ssize_t)processed; @@ -3469,7 +3483,7 @@ const struct Curl_ssl Curl_ssl_sectransp = { Curl_none_cert_status_request, /* cert_status_request */ sectransp_connect, /* connect */ sectransp_connect_nonblocking, /* connect_nonblocking */ - Curl_ssl_adjust_pollset, /* adjust_pollset */ + Curl_ssl_get_select_socks, /* getsock */ sectransp_get_internals, /* get_internals */ sectransp_close, /* close_one */ Curl_none_close_all, /* close_all */ @@ -3486,10 +3500,6 @@ const struct Curl_ssl Curl_ssl_sectransp = { sectransp_send, /* send data to encrypt */ }; -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - #ifdef __clang__ #pragma clang diagnostic pop #endif diff --git a/deps/curl/lib/vtls/vtls.c b/deps/curl/lib/vtls/vtls.c index 34eda3e5..494b660a 100644 --- a/deps/curl/lib/vtls/vtls.c +++ b/deps/curl/lib/vtls/vtls.c @@ -67,7 +67,6 @@ #include "warnless.h" #include "curl_base64.h" #include "curl_printf.h" -#include "inet_pton.h" #include "strdup.h" /* The last #include files should be: */ @@ -132,6 +131,9 @@ static bool blobcmp(struct curl_blob *first, struct curl_blob *second) } #ifdef USE_SSL +static const struct alpn_spec ALPN_SPEC_H10 = { + { ALPN_HTTP_1_0 }, 1 +}; static const struct alpn_spec ALPN_SPEC_H11 = { { ALPN_HTTP_1_1 }, 1 }; @@ -145,83 +147,51 @@ static const struct alpn_spec *alpn_get_spec(int httpwant, bool use_alpn) { if(!use_alpn) return NULL; + if(httpwant == CURL_HTTP_VERSION_1_0) + return &ALPN_SPEC_H10; #ifdef USE_HTTP2 if(httpwant >= CURL_HTTP_VERSION_2) return &ALPN_SPEC_H2_H11; -#else - (void)httpwant; #endif - /* Use the ALPN protocol "http/1.1" for HTTP/1.x. - Avoid "http/1.0" because some servers don't support it. */ return &ALPN_SPEC_H11; } #endif /* USE_SSL */ -void Curl_ssl_easy_config_init(struct Curl_easy *data) +bool +Curl_ssl_config_matches(struct ssl_primary_config *data, + struct ssl_primary_config *needle) { - /* - * libcurl 7.10 introduced SSL verification *by default*! This needs to be - * switched off unless wanted. - */ - data->set.ssl.primary.verifypeer = TRUE; - data->set.ssl.primary.verifyhost = TRUE; - data->set.ssl.primary.sessionid = TRUE; /* session ID caching by default */ -#ifndef CURL_DISABLE_PROXY - data->set.proxy_ssl = data->set.ssl; -#endif -} - -static bool -match_ssl_primary_config(struct Curl_easy *data, - struct ssl_primary_config *c1, - struct ssl_primary_config *c2) -{ - (void)data; - if((c1->version == c2->version) && - (c1->version_max == c2->version_max) && - (c1->ssl_options == c2->ssl_options) && - (c1->verifypeer == c2->verifypeer) && - (c1->verifyhost == c2->verifyhost) && - (c1->verifystatus == c2->verifystatus) && - blobcmp(c1->cert_blob, c2->cert_blob) && - blobcmp(c1->ca_info_blob, c2->ca_info_blob) && - blobcmp(c1->issuercert_blob, c2->issuercert_blob) && - Curl_safecmp(c1->CApath, c2->CApath) && - Curl_safecmp(c1->CAfile, c2->CAfile) && - Curl_safecmp(c1->issuercert, c2->issuercert) && - Curl_safecmp(c1->clientcert, c2->clientcert) && + if((data->version == needle->version) && + (data->version_max == needle->version_max) && + (data->ssl_options == needle->ssl_options) && + (data->verifypeer == needle->verifypeer) && + (data->verifyhost == needle->verifyhost) && + (data->verifystatus == needle->verifystatus) && + blobcmp(data->cert_blob, needle->cert_blob) && + blobcmp(data->ca_info_blob, needle->ca_info_blob) && + blobcmp(data->issuercert_blob, needle->issuercert_blob) && + Curl_safecmp(data->CApath, needle->CApath) && + Curl_safecmp(data->CAfile, needle->CAfile) && + Curl_safecmp(data->issuercert, needle->issuercert) && + Curl_safecmp(data->clientcert, needle->clientcert) && #ifdef USE_TLS_SRP - !Curl_timestrcmp(c1->username, c2->username) && - !Curl_timestrcmp(c1->password, c2->password) && + !Curl_timestrcmp(data->username, needle->username) && + !Curl_timestrcmp(data->password, needle->password) && #endif - strcasecompare(c1->cipher_list, c2->cipher_list) && - strcasecompare(c1->cipher_list13, c2->cipher_list13) && - strcasecompare(c1->curves, c2->curves) && - strcasecompare(c1->CRLfile, c2->CRLfile) && - strcasecompare(c1->pinned_key, c2->pinned_key)) + strcasecompare(data->cipher_list, needle->cipher_list) && + strcasecompare(data->cipher_list13, needle->cipher_list13) && + strcasecompare(data->curves, needle->curves) && + strcasecompare(data->CRLfile, needle->CRLfile) && + strcasecompare(data->pinned_key, needle->pinned_key)) return TRUE; return FALSE; } -bool Curl_ssl_conn_config_match(struct Curl_easy *data, - struct connectdata *candidate, - bool proxy) -{ -#ifndef CURL_DISABLE_PROXY - if(proxy) - return match_ssl_primary_config(data, &data->set.proxy_ssl.primary, - &candidate->proxy_ssl_config); -#else - (void)proxy; -#endif - return match_ssl_primary_config(data, &data->set.ssl.primary, - &candidate->ssl_config); -} - -static bool clone_ssl_primary_config(struct ssl_primary_config *source, - struct ssl_primary_config *dest) +bool +Curl_clone_primary_ssl_config(struct ssl_primary_config *source, + struct ssl_primary_config *dest) { dest->version = source->version; dest->version_max = source->version_max; @@ -251,7 +221,7 @@ static bool clone_ssl_primary_config(struct ssl_primary_config *source, return TRUE; } -static void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc) +void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc) { Curl_safefree(sslc->CApath); Curl_safefree(sslc->CAfile); @@ -271,111 +241,6 @@ static void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc) #endif } -CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data) -{ - data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH]; - data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE]; - data->set.ssl.primary.CRLfile = data->set.str[STRING_SSL_CRLFILE]; - data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT]; - data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT]; - data->set.ssl.primary.cipher_list = - data->set.str[STRING_SSL_CIPHER_LIST]; - data->set.ssl.primary.cipher_list13 = - data->set.str[STRING_SSL_CIPHER13_LIST]; - data->set.ssl.primary.pinned_key = - data->set.str[STRING_SSL_PINNEDPUBLICKEY]; - data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT]; - data->set.ssl.primary.ca_info_blob = data->set.blobs[BLOB_CAINFO]; - data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES]; -#ifdef USE_TLS_SRP - data->set.ssl.primary.username = data->set.str[STRING_TLSAUTH_USERNAME]; - data->set.ssl.primary.password = data->set.str[STRING_TLSAUTH_PASSWORD]; -#endif - data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE]; - data->set.ssl.key = data->set.str[STRING_KEY]; - data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE]; - data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD]; - data->set.ssl.primary.clientcert = data->set.str[STRING_CERT]; - data->set.ssl.key_blob = data->set.blobs[BLOB_KEY]; - -#ifndef CURL_DISABLE_PROXY - data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY]; - data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY]; - data->set.proxy_ssl.primary.cipher_list = - data->set.str[STRING_SSL_CIPHER_LIST_PROXY]; - data->set.proxy_ssl.primary.cipher_list13 = - data->set.str[STRING_SSL_CIPHER13_LIST_PROXY]; - data->set.proxy_ssl.primary.pinned_key = - data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]; - data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY]; - data->set.proxy_ssl.primary.ca_info_blob = - data->set.blobs[BLOB_CAINFO_PROXY]; - data->set.proxy_ssl.primary.issuercert = - data->set.str[STRING_SSL_ISSUERCERT_PROXY]; - data->set.proxy_ssl.primary.issuercert_blob = - data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY]; - data->set.proxy_ssl.primary.CRLfile = - data->set.str[STRING_SSL_CRLFILE_PROXY]; - data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY]; - data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY]; - data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY]; - data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY]; - data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY]; - data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY]; -#ifdef USE_TLS_SRP - data->set.proxy_ssl.primary.username = - data->set.str[STRING_TLSAUTH_USERNAME_PROXY]; - data->set.proxy_ssl.primary.password = - data->set.str[STRING_TLSAUTH_PASSWORD_PROXY]; -#endif -#endif /* CURL_DISABLE_PROXY */ - - return CURLE_OK; -} - -CURLcode Curl_ssl_conn_config_init(struct Curl_easy *data, - struct connectdata *conn) -{ - /* Clone "primary" SSL configurations from the esay handle to - * the connection. They are used for connection cache matching and - * probably outlive the easy handle */ - if(!clone_ssl_primary_config(&data->set.ssl.primary, &conn->ssl_config)) - return CURLE_OUT_OF_MEMORY; -#ifndef CURL_DISABLE_PROXY - if(!clone_ssl_primary_config(&data->set.proxy_ssl.primary, - &conn->proxy_ssl_config)) - return CURLE_OUT_OF_MEMORY; -#endif - return CURLE_OK; -} - -void Curl_ssl_conn_config_cleanup(struct connectdata *conn) -{ - Curl_free_primary_ssl_config(&conn->ssl_config); -#ifndef CURL_DISABLE_PROXY - Curl_free_primary_ssl_config(&conn->proxy_ssl_config); -#endif -} - -void Curl_ssl_conn_config_update(struct Curl_easy *data, bool for_proxy) -{ - /* May be called on an easy that has no connection yet */ - if(data->conn) { - struct ssl_primary_config *src, *dest; -#ifndef CURL_DISABLE_PROXY - src = for_proxy? &data->set.proxy_ssl.primary : &data->set.ssl.primary; - dest = for_proxy? &data->conn->proxy_ssl_config : &data->conn->ssl_config; -#else - (void)for_proxy; - src = &data->set.ssl.primary; - dest = &data->conn->ssl_config; -#endif - dest->verifyhost = src->verifyhost; - dest->verifypeer = src->verifypeer; - dest->verifystatus = src->verifystatus; - } -} - #ifdef USE_SSL static int multissl_setup(const struct Curl_ssl *backend); #endif @@ -567,7 +432,7 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf, if(!check->sessionid) /* not session ID means blank entry */ continue; - if(strcasecompare(connssl->peer.hostname, check->name) && + if(strcasecompare(connssl->hostname, check->name) && ((!cf->conn->bits.conn_to_host && !check->conn_to_host) || (cf->conn->bits.conn_to_host && check->conn_to_host && strcasecompare(cf->conn->conn_to_host.name, check->conn_to_host))) && @@ -576,7 +441,7 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf, cf->conn->conn_to_port == check->conn_to_port)) && (connssl->port == check->remote_port) && strcasecompare(cf->conn->handler->scheme, check->scheme) && - match_ssl_primary_config(data, conn_config, &check->ssl_config)) { + Curl_ssl_config_matches(conn_config, &check->ssl_config)) { /* yes, we have a session ID! */ (*general_age)++; /* increase general age */ check->age = *general_age; /* set this as used in this age */ @@ -591,8 +456,7 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf, DEBUGF(infof(data, "%s Session ID in cache for %s %s://%s:%d", no_match? "Didn't find": "Found", Curl_ssl_cf_is_proxy(cf) ? "proxy" : "host", - cf->conn->handler->scheme, connssl->peer.hostname, - connssl->port)); + cf->conn->handler->scheme, connssl->hostname, connssl->port)); return no_match; } @@ -668,7 +532,7 @@ CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf, (void)ssl_config; DEBUGASSERT(ssl_config->primary.sessionid); - clone_host = strdup(connssl->peer.hostname); + clone_host = strdup(connssl->hostname); if(!clone_host) return CURLE_OUT_OF_MEMORY; /* bail out */ @@ -726,7 +590,7 @@ CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf, store->remote_port = connssl->port; store->scheme = cf->conn->handler->scheme; - if(!clone_ssl_primary_config(conn_config, &store->ssl_config)) { + if(!Curl_clone_primary_ssl_config(conn_config, &store->ssl_config)) { Curl_free_primary_ssl_config(&store->ssl_config); store->sessionid = NULL; /* let caller free sessionid */ free(clone_host); @@ -765,21 +629,22 @@ void Curl_ssl_close_all(struct Curl_easy *data) Curl_ssl->close_all(data); } -void Curl_ssl_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data, - struct easy_pollset *ps) +int Curl_ssl_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data, + curl_socket_t *socks) { - if(!cf->connected) { - struct ssl_connect_data *connssl = cf->ctx; - curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data); - if(sock != CURL_SOCKET_BAD) { - if(connssl->connecting_state == ssl_connect_2_writing) { - Curl_pollset_set_out_only(data, ps, sock); - } - else { - Curl_pollset_set_in_only(data, ps, sock); - } - } + struct ssl_connect_data *connssl = cf->ctx; + curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data); + + if(sock == CURL_SOCKET_BAD) + return GETSOCK_BLANK; + + if(connssl->connecting_state == ssl_connect_2_writing) { + /* we are only interested in writing */ + socks[0] = sock; + return GETSOCK_WRITESOCK(0); } + socks[0] = sock; + return GETSOCK_READSOCK(0); } /* Selects an SSL crypto engine @@ -920,6 +785,32 @@ CURLcode Curl_ssl_random(struct Curl_easy *data, return Curl_ssl->random(data, entropy, length); } +/* + * Curl_ssl_snihost() converts the input host name to a suitable SNI name put + * in data->state.buffer. Returns a pointer to the name (or NULL if a problem) + * and stores the new length in 'olen'. + * + * SNI fields must not have any trailing dot and while RFC 6066 section 3 says + * the SNI field is case insensitive, browsers always send the data lowercase + * and subsequently there are numerous servers out there that don't work + * unless the name is lowercased. + */ + +char *Curl_ssl_snihost(struct Curl_easy *data, const char *host, size_t *olen) +{ + size_t len = strlen(host); + if(len && (host[len-1] == '.')) + len--; + if(len >= data->set.buffer_size) + return NULL; + + Curl_strntolower(data->state.buffer, host, len); + data->state.buffer[len] = 0; + if(olen) + *olen = len; + return data->state.buffer; +} + /* * Public key pem to der conversion */ @@ -1265,13 +1156,13 @@ static CURLcode multissl_connect_nonblocking(struct Curl_cfilter *cf, return Curl_ssl->connect_nonblocking(cf, data, done); } -static void multissl_adjust_pollset(struct Curl_cfilter *cf, +static int multissl_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data, - struct easy_pollset *ps) + curl_socket_t *socks) { if(multissl_setup(NULL)) - return; - Curl_ssl->adjust_pollset(cf, data, ps); + return 0; + return Curl_ssl->get_select_socks(cf, data, socks); } static void *multissl_get_internals(struct ssl_connect_data *connssl, @@ -1323,7 +1214,7 @@ static const struct Curl_ssl Curl_ssl_multi = { Curl_none_cert_status_request, /* cert_status_request */ multissl_connect, /* connect */ multissl_connect_nonblocking, /* connect_nonblocking */ - multissl_adjust_pollset, /* adjust_pollset */ + multissl_get_select_socks, /* getsock */ multissl_get_internals, /* get_internals */ multissl_close, /* close_one */ Curl_none_close_all, /* close_all */ @@ -1518,14 +1409,12 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name, #ifdef USE_SSL -void Curl_ssl_peer_cleanup(struct ssl_peer *peer) +static void free_hostname(struct ssl_connect_data *connssl) { - if(peer->dispname != peer->hostname) - free(peer->dispname); - free(peer->sni); - free(peer->hostname); - peer->hostname = peer->sni = peer->dispname = NULL; - peer->is_ip_address = FALSE; + if(connssl->dispname != connssl->hostname) + free(connssl->dispname); + free(connssl->hostname); + connssl->hostname = connssl->dispname = NULL; } static void cf_close(struct Curl_cfilter *cf, struct Curl_easy *data) @@ -1534,26 +1423,12 @@ static void cf_close(struct Curl_cfilter *cf, struct Curl_easy *data) if(connssl) { Curl_ssl->close(cf, data); connssl->state = ssl_connection_none; - Curl_ssl_peer_cleanup(&connssl->peer); + free_hostname(connssl); } cf->connected = FALSE; } -static int is_ip_address(const char *hostname) -{ -#ifdef ENABLE_IPV6 - struct in6_addr addr; -#else - struct in_addr addr; -#endif - return (hostname && hostname[0] && (Curl_inet_pton(AF_INET, hostname, &addr) -#ifdef ENABLE_IPV6 - || Curl_inet_pton(AF_INET6, hostname, &addr) -#endif - )); -} - -CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf) +static CURLcode reinit_hostname(struct Curl_cfilter *cf) { struct ssl_connect_data *connssl = cf->ctx; const char *ehostname, *edispname; @@ -1579,43 +1454,23 @@ CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf) } /* change if ehostname changed */ - if(ehostname && (!peer->hostname - || strcmp(ehostname, peer->hostname))) { - Curl_ssl_peer_cleanup(peer); - peer->hostname = strdup(ehostname); - if(!peer->hostname) { - Curl_ssl_peer_cleanup(peer); + if(ehostname && (!connssl->hostname + || strcmp(ehostname, connssl->hostname))) { + free_hostname(connssl); + connssl->hostname = strdup(ehostname); + if(!connssl->hostname) { + free_hostname(connssl); return CURLE_OUT_OF_MEMORY; } if(!edispname || !strcmp(ehostname, edispname)) - peer->dispname = peer->hostname; + connssl->dispname = connssl->hostname; else { - peer->dispname = strdup(edispname); - if(!peer->dispname) { - Curl_ssl_peer_cleanup(peer); + connssl->dispname = strdup(edispname); + if(!connssl->dispname) { + free_hostname(connssl); return CURLE_OUT_OF_MEMORY; } } - - peer->sni = NULL; - peer->is_ip_address = is_ip_address(peer->hostname)? TRUE : FALSE; - if(peer->hostname[0] && !peer->is_ip_address) { - /* not an IP address, normalize according to RCC 6066 ch. 3, - * max len of SNI is 2^16-1, no trailing dot */ - size_t len = strlen(peer->hostname); - if(len && (peer->hostname[len-1] == '.')) - len--; - if(len < USHRT_MAX) { - peer->sni = calloc(1, len + 1); - if(!peer->sni) { - Curl_ssl_peer_cleanup(peer); - return CURLE_OUT_OF_MEMORY; - } - Curl_strntolower(peer->sni, peer->hostname, len); - peer->sni[len] = 0; - } - } - } connssl->port = eport; return CURLE_OK; @@ -1670,7 +1525,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf, goto out; *done = FALSE; - result = Curl_ssl_peer_init(&connssl->peer, cf); + result = reinit_hostname(cf); if(result) goto out; @@ -1744,17 +1599,22 @@ static ssize_t ssl_cf_recv(struct Curl_cfilter *cf, return nread; } -static void ssl_cf_adjust_pollset(struct Curl_cfilter *cf, +static int ssl_cf_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data, - struct easy_pollset *ps) + curl_socket_t *socks) { struct cf_call_data save; + int fds = GETSOCK_BLANK; - if(!cf->connected) { + if(!cf->next->connected) { + fds = cf->next->cft->get_select_socks(cf->next, data, socks); + } + else if(!cf->connected) { CF_DATA_SAVE(save, cf, data); - Curl_ssl->adjust_pollset(cf, data, ps); + fds = Curl_ssl->get_select_socks(cf, data, socks); CF_DATA_RESTORE(cf, save); } + return fds; } static CURLcode ssl_cf_cntrl(struct Curl_cfilter *cf, @@ -1845,7 +1705,7 @@ struct Curl_cftype Curl_cft_ssl = { ssl_cf_connect, ssl_cf_close, Curl_cf_def_get_host, - ssl_cf_adjust_pollset, + ssl_cf_get_select_socks, ssl_cf_data_pending, ssl_cf_send, ssl_cf_recv, @@ -1863,7 +1723,7 @@ struct Curl_cftype Curl_cft_ssl_proxy = { ssl_cf_connect, ssl_cf_close, Curl_cf_def_get_host, - ssl_cf_adjust_pollset, + ssl_cf_get_select_socks, ssl_cf_data_pending, ssl_cf_send, ssl_cf_recv, @@ -1977,16 +1837,6 @@ bool Curl_ssl_supports(struct Curl_easy *data, int option) return (Curl_ssl->supports & option)? TRUE : FALSE; } -static struct Curl_cfilter *get_ssl_filter(struct Curl_cfilter *cf) -{ - for(; cf; cf = cf->next) { - if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy) - return cf; - } - return NULL; -} - - void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex, CURLINFO info, int n) { @@ -1994,8 +1844,8 @@ void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex, (void)n; if(data->conn) { struct Curl_cfilter *cf; - /* get first SSL filter in chain, if any is present */ - cf = get_ssl_filter(data->conn->cfilter[sockindex]); + /* get first filter in chain, if any is present */ + cf = Curl_ssl_cf_get_ssl(data->conn->cfilter[sockindex]); if(cf) { struct cf_call_data save; CF_DATA_SAVE(save, cf, data); @@ -2025,6 +1875,23 @@ CURLcode Curl_ssl_cfilter_remove(struct Curl_easy *data, return result; } +static struct Curl_cfilter *get_ssl_cf_engaged(struct connectdata *conn, + int sockindex) +{ + struct Curl_cfilter *cf, *lowest_ssl_cf = NULL; + + for(cf = conn->cfilter[sockindex]; cf; cf = cf->next) { + if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy) { + lowest_ssl_cf = cf; + if(cf->connected || (cf->next && cf->next->connected)) { + /* connected or about to start */ + return cf; + } + } + } + return lowest_ssl_cf; +} + bool Curl_ssl_cf_is_proxy(struct Curl_cfilter *cf) { return (cf->cft == &Curl_cft_ssl_proxy); @@ -2041,6 +1908,17 @@ Curl_ssl_cf_get_config(struct Curl_cfilter *cf, struct Curl_easy *data) #endif } +struct ssl_config_data * +Curl_ssl_get_config(struct Curl_easy *data, int sockindex) +{ + struct Curl_cfilter *cf; + + (void)data; + DEBUGASSERT(data->conn); + cf = get_ssl_cf_engaged(data->conn, sockindex); + return cf? Curl_ssl_cf_get_config(cf, data) : &data->set.ssl; +} + struct ssl_primary_config * Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf) { @@ -2052,6 +1930,15 @@ Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf) #endif } +struct Curl_cfilter *Curl_ssl_cf_get_ssl(struct Curl_cfilter *cf) +{ + for(; cf; cf = cf->next) { + if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy) + return cf; + } + return NULL; +} + CURLcode Curl_alpn_to_proto_buf(struct alpn_proto_buf *buf, const struct alpn_spec *spec) { @@ -2118,6 +2005,10 @@ CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf, !memcmp(ALPN_HTTP_1_1, proto, ALPN_HTTP_1_1_LENGTH)) { *palpn = CURL_HTTP_VERSION_1_1; } + else if(proto_len == ALPN_HTTP_1_0_LENGTH && + !memcmp(ALPN_HTTP_1_0, proto, ALPN_HTTP_1_0_LENGTH)) { + *palpn = CURL_HTTP_VERSION_1_0; + } #ifdef USE_HTTP2 else if(proto_len == ALPN_H2_LENGTH && !memcmp(ALPN_H2, proto, ALPN_H2_LENGTH)) { diff --git a/deps/curl/lib/vtls/vtls.h b/deps/curl/lib/vtls/vtls.h index f1856bd3..8ad1cf6d 100644 --- a/deps/curl/lib/vtls/vtls.h +++ b/deps/curl/lib/vtls/vtls.h @@ -65,54 +65,15 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name, #define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */ #endif +char *Curl_ssl_snihost(struct Curl_easy *data, const char *host, size_t *olen); +bool Curl_ssl_config_matches(struct ssl_primary_config *data, + struct ssl_primary_config *needle); +bool Curl_clone_primary_ssl_config(struct ssl_primary_config *source, + struct ssl_primary_config *dest); +void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc); + curl_sslbackend Curl_ssl_backend(void); -/** - * Init ssl config for a new easy handle. - */ -void Curl_ssl_easy_config_init(struct Curl_easy *data); - -/** - * Init the `data->set.ssl` and `data->set.proxy_ssl` for - * connection matching use. - */ -CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data); - -/** - * Init SSL configs (main + proxy) for a new connection from the easy handle. - */ -CURLcode Curl_ssl_conn_config_init(struct Curl_easy *data, - struct connectdata *conn); - -/** - * Free allocated resources in SSL configs (main + proxy) for - * the given connection. - */ -void Curl_ssl_conn_config_cleanup(struct connectdata *conn); - -/** - * Return TRUE iff SSL configuration from `conn` is functionally the - * same as the one on `candidate`. - * @param proxy match the proxy SSL config or the main one - */ -bool Curl_ssl_conn_config_match(struct Curl_easy *data, - struct connectdata *candidate, - bool proxy); - -/* Update certain connection SSL config flags after they have - * been changed on the easy handle. Will work for `verifypeer`, - * `verifyhost` and `verifystatus`. */ -void Curl_ssl_conn_config_update(struct Curl_easy *data, bool for_proxy); - -/** - * Init SSL peer information for filter. Can be called repeatedly. - */ -CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf); -/** - * Free all allocated data and reset peer information. - */ -void Curl_ssl_peer_cleanup(struct ssl_peer *peer); - #ifdef USE_SSL int Curl_ssl_init(void); void Curl_ssl_cleanup(void); @@ -198,6 +159,18 @@ CURLcode Curl_cf_ssl_proxy_insert_after(struct Curl_cfilter *cf_at, struct Curl_easy *data); #endif /* !CURL_DISABLE_PROXY */ +/** + * Get the SSL configuration that is used on the connection. + * This returns NULL if no SSL is configured. + * Otherwise it returns the config of the first (highest) one that is + * either connected, in handshake or about to start + * (e.g. all filters below it are connected). If SSL filters are present, + * but neither can start operating, return the config of the lowest one + * that will first come into effect when connecting. + */ +struct ssl_config_data *Curl_ssl_get_config(struct Curl_easy *data, + int sockindex); + /** * True iff the underlying SSL implementation supports the option. * Option is one of the defined SSLSUPP_* values. @@ -215,18 +188,6 @@ bool Curl_ssl_supports(struct Curl_easy *data, int ssl_option); void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex, CURLINFO info, int n); -/** - * Get the ssl_config_data in `data` that is relevant for cfilter `cf`. - */ -struct ssl_config_data *Curl_ssl_cf_get_config(struct Curl_cfilter *cf, - struct Curl_easy *data); - -/** - * Get the primary config relevant for the filter from its connection. - */ -struct ssl_primary_config * - Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf); - extern struct Curl_cftype Curl_cft_ssl; extern struct Curl_cftype Curl_cft_ssl_proxy; @@ -248,9 +209,8 @@ extern struct Curl_cftype Curl_cft_ssl_proxy; #define Curl_ssl_get_internals(a,b,c,d) NULL #define Curl_ssl_supports(a,b) FALSE #define Curl_ssl_cfilter_add(a,b,c) CURLE_NOT_BUILT_IN +#define Curl_ssl_get_config(a,b) NULL #define Curl_ssl_cfilter_remove(a,b) CURLE_OK -#define Curl_ssl_cf_get_config(a,b) NULL -#define Curl_ssl_cf_get_primary_config(a) NULL #endif #endif /* HEADER_CURL_VTLS_H */ diff --git a/deps/curl/lib/vtls/vtls_int.h b/deps/curl/lib/vtls/vtls_int.h index af7ae552..a6e4544a 100644 --- a/deps/curl/lib/vtls/vtls_int.h +++ b/deps/curl/lib/vtls/vtls_int.h @@ -32,6 +32,8 @@ /* see https://www.iana.org/assignments/tls-extensiontype-values/ */ #define ALPN_HTTP_1_1_LENGTH 8 #define ALPN_HTTP_1_1 "http/1.1" +#define ALPN_HTTP_1_0_LENGTH 8 +#define ALPN_HTTP_1_0 "http/1.0" #define ALPN_H2_LENGTH 2 #define ALPN_H2 "h2" #define ALPN_H3_LENGTH 2 @@ -68,14 +70,14 @@ CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf, struct ssl_connect_data { ssl_connection_state state; ssl_connect_state connecting_state; - struct ssl_peer peer; + char *hostname; /* hostname for verification */ + char *dispname; /* display version of hostname */ const struct alpn_spec *alpn; /* ALPN to use or NULL for none */ void *backend; /* vtls backend specific props */ struct cf_call_data call_data; /* data handle used in current call */ struct curltime handshake_done; /* time when handshake finished */ int port; /* remote port at origin */ BIT(use_alpn); /* if ALPN shall be used in handshake */ - BIT(reused_session); /* session-ID was reused for this */ }; @@ -116,11 +118,14 @@ struct Curl_ssl { struct Curl_easy *data, bool *done); - /* During handshake, adjust the pollset to include the socket - * for POLLOUT or POLLIN as needed. - * Mandatory. */ - void (*adjust_pollset)(struct Curl_cfilter *cf, struct Curl_easy *data, - struct easy_pollset *ps); + /* If the SSL backend wants to read or write on this connection during a + handshake, set socks[0] to the connection's FIRSTSOCKET, and return + a bitmap indicating read or write with GETSOCK_WRITESOCK(0) or + GETSOCK_READSOCK(0). Otherwise return GETSOCK_BLANK. + Mandatory. */ + int (*get_select_socks)(struct Curl_cfilter *cf, struct Curl_easy *data, + curl_socket_t *socks); + void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info); void (*close)(struct Curl_cfilter *cf, struct Curl_easy *data); void (*close_all)(struct Curl_easy *data); @@ -164,8 +169,25 @@ CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine); CURLcode Curl_none_set_engine_default(struct Curl_easy *data); struct curl_slist *Curl_none_engines_list(struct Curl_easy *data); bool Curl_none_false_start(void); -void Curl_ssl_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data, - struct easy_pollset *ps); +int Curl_ssl_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data, + curl_socket_t *socks); + +/** + * Get the ssl_config_data in `data` that is relevant for cfilter `cf`. + */ +struct ssl_config_data *Curl_ssl_cf_get_config(struct Curl_cfilter *cf, + struct Curl_easy *data); + +/** + * Get the primary config relevant for the filter from its connection. + */ +struct ssl_primary_config * + Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf); + +/** + * Get the first SSL filter in the chain starting with `cf`, or NULL. + */ +struct Curl_cfilter *Curl_ssl_cf_get_ssl(struct Curl_cfilter *cf); /** * Get the SSL filter below the given one or NULL if there is none. diff --git a/deps/curl/lib/vtls/wolfssl.c b/deps/curl/lib/vtls/wolfssl.c index 5890bb60..b1384a64 100644 --- a/deps/curl/lib/vtls/wolfssl.c +++ b/deps/curl/lib/vtls/wolfssl.c @@ -480,7 +480,6 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_SSL_CONNECT_ERROR; } #endif - default: break; } @@ -514,7 +513,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) } } -#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SYS_CA_CERTS) +#ifndef NO_FILESYSTEM /* load native CA certificates */ if(ssl_config->native_ca_store) { if(wolfSSL_CTX_load_system_CA_certs(backend->ctx) != WOLFSSL_SUCCESS) { @@ -609,12 +608,24 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) SSL_VERIFY_NONE, NULL); #ifdef HAVE_SNI - if(sni && connssl->peer.sni) { - size_t sni_len = strlen(connssl->peer.sni); - if((sni_len < USHRT_MAX)) { - if(wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME, - connssl->peer.sni, - (unsigned short)sni_len) != 1) { + if(sni) { + struct in_addr addr4; +#ifdef ENABLE_IPV6 + struct in6_addr addr6; +#endif + size_t hostname_len = strlen(connssl->hostname); + + if((hostname_len < USHRT_MAX) && + !Curl_inet_pton(AF_INET, connssl->hostname, &addr4) +#ifdef ENABLE_IPV6 + && !Curl_inet_pton(AF_INET6, connssl->hostname, &addr6) +#endif + ) { + size_t snilen; + char *snihost = Curl_ssl_snihost(data, connssl->hostname, &snilen); + if(!snihost || + wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME, snihost, + (unsigned short)snilen) != 1) { failf(data, "Failed to set SNI"); return CURLE_SSL_CONNECT_ERROR; } @@ -752,9 +763,9 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) /* Enable RFC2818 checks */ if(conn_config->verifyhost) { - char *snihost = connssl->peer.sni? - connssl->peer.sni : connssl->peer.hostname; - if(wolfSSL_check_domain_name(backend->handle, snihost) == SSL_FAILURE) + char *snihost = Curl_ssl_snihost(data, connssl->hostname, NULL); + if(!snihost || + (wolfSSL_check_domain_name(backend->handle, snihost) == SSL_FAILURE)) return CURLE_SSL_CONNECT_ERROR; } @@ -802,7 +813,7 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) else if(DOMAIN_NAME_MISMATCH == detail) { #if 1 failf(data, " subject alt name(s) or common name do not match \"%s\"", - connssl->peer.dispname); + connssl->dispname); return CURLE_PEER_FAILED_VERIFICATION; #else /* When the wolfssl_check_domain_name() is used and you desire to @@ -1387,7 +1398,7 @@ const struct Curl_ssl Curl_ssl_wolfssl = { Curl_none_cert_status_request, /* cert_status_request */ wolfssl_connect, /* connect */ wolfssl_connect_nonblocking, /* connect_nonblocking */ - Curl_ssl_adjust_pollset, /* adjust_pollset */ + Curl_ssl_get_select_socks, /* getsock */ wolfssl_get_internals, /* get_internals */ wolfssl_close, /* close_one */ Curl_none_close_all, /* close_all */ diff --git a/deps/curl/lib/vtls/x509asn1.c b/deps/curl/lib/vtls/x509asn1.c index 8b1eed63..c3fd3a30 100644 --- a/deps/curl/lib/vtls/x509asn1.c +++ b/deps/curl/lib/vtls/x509asn1.c @@ -1317,16 +1317,16 @@ CURLcode Curl_verifyhost(struct Curl_cfilter *cf, if(Curl_parseX509(&cert, beg, end)) return CURLE_PEER_FAILED_VERIFICATION; - hostlen = strlen(connssl->peer.hostname); + hostlen = strlen(connssl->hostname); /* Get the server IP address. */ #ifdef ENABLE_IPV6 if(cf->conn->bits.ipv6_ip && - Curl_inet_pton(AF_INET6, connssl->peer.hostname, &addr)) + Curl_inet_pton(AF_INET6, connssl->hostname, &addr)) addrlen = sizeof(struct in6_addr); else #endif - if(Curl_inet_pton(AF_INET, connssl->peer.hostname, &addr)) + if(Curl_inet_pton(AF_INET, connssl->hostname, &addr)) addrlen = sizeof(struct in_addr); /* Process extensions. */ @@ -1361,7 +1361,7 @@ CURLcode Curl_verifyhost(struct Curl_cfilter *cf, name.beg, name.end); if(len > 0 && (size_t)len == strlen(dnsname)) matched = Curl_cert_hostcheck(dnsname, (size_t)len, - connssl->peer.hostname, hostlen); + connssl->hostname, hostlen); else matched = 0; free(dnsname); @@ -1421,7 +1421,7 @@ CURLcode Curl_verifyhost(struct Curl_cfilter *cf, if(strlen(dnsname) != (size_t) len) /* Nul byte in string ? */ failf(data, "SSL: illegal cert name field"); else if(Curl_cert_hostcheck((const char *) dnsname, - len, connssl->peer.hostname, hostlen)) { + len, connssl->hostname, hostlen)) { infof(data, " common name: %s (matched)", dnsname); free(dnsname); return CURLE_OK; diff --git a/deps/curl/lib/warnless.c b/deps/curl/lib/warnless.c index c80937b8..7e077f8d 100644 --- a/deps/curl/lib/warnless.c +++ b/deps/curl/lib/warnless.c @@ -37,7 +37,7 @@ #include "warnless.h" -#ifdef _WIN32 +#ifdef WIN32 #undef read #undef write #endif @@ -367,7 +367,7 @@ curl_socket_t curlx_sitosk(int i) #endif /* USE_WINSOCK */ -#if defined(_WIN32) +#if defined(WIN32) ssize_t curlx_read(int fd, void *buf, size_t count) { @@ -379,8 +379,8 @@ ssize_t curlx_write(int fd, const void *buf, size_t count) return (ssize_t)write(fd, buf, curlx_uztoui(count)); } -#endif /* _WIN32 */ +/* Ensure that warnless.h continues to have an effect in "unity" builds. */ +#undef HEADER_CURL_WARNLESS_H + +#endif /* WIN32 */ -/* Ensure that warnless.h redefinitions continue to have an effect - in "unity" builds. */ -#undef HEADER_CURL_WARNLESS_H_REDEFS diff --git a/deps/curl/lib/warnless.h b/deps/curl/lib/warnless.h index e5a02c8d..2a530162 100644 --- a/deps/curl/lib/warnless.h +++ b/deps/curl/lib/warnless.h @@ -69,13 +69,18 @@ curl_socket_t curlx_sitosk(int i); #endif /* USE_WINSOCK */ -#if defined(_WIN32) +#if defined(WIN32) ssize_t curlx_read(int fd, void *buf, size_t count); ssize_t curlx_write(int fd, const void *buf, size_t count); -#endif /* _WIN32 */ +#undef read +#define read(fd, buf, count) curlx_read(fd, buf, count) +#undef write +#define write(fd, buf, count) curlx_write(fd, buf, count) + +#endif /* WIN32 */ #if defined(__INTEL_COMPILER) && defined(__unix__) @@ -92,15 +97,3 @@ unsigned short curlx_ntohs(unsigned short usnum); #endif /* __INTEL_COMPILER && __unix__ */ #endif /* HEADER_CURL_WARNLESS_H */ - -#ifndef HEADER_CURL_WARNLESS_H_REDEFS -#define HEADER_CURL_WARNLESS_H_REDEFS - -#if defined(_WIN32) -#undef read -#define read(fd, buf, count) curlx_read(fd, buf, count) -#undef write -#define write(fd, buf, count) curlx_write(fd, buf, count) -#endif - -#endif /* HEADER_CURL_WARNLESS_H_REDEFS */ diff --git a/deps/curl/lib/ws.c b/deps/curl/lib/ws.c index adde531f..3c1964b8 100644 --- a/deps/curl/lib/ws.c +++ b/deps/curl/lib/ws.c @@ -274,8 +274,8 @@ static CURLcode ws_dec_pass_payload(struct ws_decoder *dec, dec->payload_offset += (curl_off_t)nwritten; remain = dec->payload_len - dec->payload_offset; /* infof(data, "WS-DEC: passed %zd bytes payload, %" - CURL_FORMAT_CURL_OFF_T " remain", - nwritten, remain); */ + CURL_FORMAT_CURL_OFF_T " remain", + nwritten, remain); */ } return remain? CURLE_AGAIN : CURLE_OK; @@ -925,8 +925,8 @@ CURL_EXTERN CURLcode curl_ws_recv(struct Curl_easy *data, void *buffer, *metap = &ws->frame; *nread = ws->frame.len; /* infof(data, "curl_ws_recv(len=%zu) -> %zu bytes (frame at %" - CURL_FORMAT_CURL_OFF_T ", %" CURL_FORMAT_CURL_OFF_T " left)", - buflen, *nread, ws->frame.offset, ws->frame.bytesleft); */ + CURL_FORMAT_CURL_OFF_T ", %" CURL_FORMAT_CURL_OFF_T " left)", + buflen, *nread, ws->frame.offset, ws->frame.bytesleft); */ return CURLE_OK; } diff --git a/deps/curl/m4/curl-amissl.m4 b/deps/curl/m4/curl-amissl.m4 index 48067e72..95208f0c 100644 --- a/deps/curl/m4/curl-amissl.m4 +++ b/deps/curl/m4/curl-amissl.m4 @@ -33,7 +33,7 @@ if test "$HAVE_PROTO_BSDSOCKET_H" = "1"; then #include ]],[[ #if defined(AMISSL_CURRENT_VERSION) && defined(AMISSL_V3xx) && \ - (OPENSSL_VERSION_NUMBER >= 0x30000000L) && \ + defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) && \ defined(PROTO_AMISSL_H) return 0; #else diff --git a/deps/curl/m4/curl-compilers.m4 b/deps/curl/m4/curl-compilers.m4 index 35ba1986..caa2b14c 100644 --- a/deps/curl/m4/curl-compilers.m4 +++ b/deps/curl/m4/curl-compilers.m4 @@ -48,6 +48,7 @@ AC_DEFUN([CURL_CHECK_COMPILER], [ CURL_CHECK_COMPILER_INTEL_C CURL_CHECK_COMPILER_CLANG CURL_CHECK_COMPILER_GNU_C + CURL_CHECK_COMPILER_LCC CURL_CHECK_COMPILER_SGI_MIPSPRO_C CURL_CHECK_COMPILER_SGI_MIPS_C CURL_CHECK_COMPILER_SUNPRO_C @@ -91,40 +92,19 @@ AC_DEFUN([CURL_CHECK_COMPILER_CLANG], [ AC_MSG_RESULT([no]) compiler_id="CLANG" fi - AC_MSG_CHECKING([compiler version]) fullclangver=`$CC -v 2>&1 | grep version` - if echo $fullclangver | grep 'Apple' >/dev/null; then - appleclang=1 - else - appleclang=0 - fi clangver=`echo $fullclangver | grep "based on LLVM " | "$SED" 's/.*(based on LLVM \(@<:@0-9@:>@*\.@<:@0-9@:>@*\).*)/\1/'` if test -z "$clangver"; then - clangver=`echo $fullclangver | "$SED" 's/.*version \(@<:@0-9@:>@*\.@<:@0-9@:>@*\).*/\1/'` - oldapple=0 - else - oldapple=1 + if echo $fullclangver | grep "Apple LLVM version " >/dev/null; then + dnl Starting with XCode 7 / clang 3.7, Apple clang won't tell its upstream version + clangver="3.7" + else + clangver=`echo $fullclangver | "$SED" 's/.*version \(@<:@0-9@:>@*\.@<:@0-9@:>@*\).*/\1/'` + fi fi clangvhi=`echo $clangver | cut -d . -f1` clangvlo=`echo $clangver | cut -d . -f2` compiler_num=`(expr $clangvhi "*" 100 + $clangvlo) 2>/dev/null` - if test "$appleclang" = '1' && test "$oldapple" = '0'; then - dnl Starting with Xcode 7 / clang 3.7, Apple clang won't tell its upstream version - if test "$compiler_num" -ge '1300'; then compiler_num='1200' - elif test "$compiler_num" -ge '1205'; then compiler_num='1101' - elif test "$compiler_num" -ge '1204'; then compiler_num='1000' - elif test "$compiler_num" -ge '1107'; then compiler_num='900' - elif test "$compiler_num" -ge '1103'; then compiler_num='800' - elif test "$compiler_num" -ge '1003'; then compiler_num='700' - elif test "$compiler_num" -ge '1001'; then compiler_num='600' - elif test "$compiler_num" -ge '904'; then compiler_num='500' - elif test "$compiler_num" -ge '902'; then compiler_num='400' - elif test "$compiler_num" -ge '803'; then compiler_num='309' - elif test "$compiler_num" -ge '703'; then compiler_num='308' - else compiler_num='307' - fi - fi - AC_MSG_RESULT([clang '$compiler_num' (raw: '$fullclangver' / '$clangver')]) flags_dbg_yes="-g" flags_opt_all="-O -O0 -O1 -O2 -Os -O3 -O4" flags_opt_yes="-O2" @@ -179,17 +159,10 @@ AC_DEFUN([CURL_CHECK_COMPILER_GNU_C], [ test "$compiler_id" = "unknown"; then AC_MSG_RESULT([yes]) compiler_id="GNU_C" - AC_MSG_CHECKING([compiler version]) - # strip '-suffix' parts, e.g. Ubuntu Windows cross-gcc returns '10-win32' - gccver=`$CC -dumpversion | sed -E 's/-.+$//'` + gccver=`$CC -dumpversion` gccvhi=`echo $gccver | cut -d . -f1` - if echo $gccver | grep -F '.' >/dev/null; then - gccvlo=`echo $gccver | cut -d . -f2` - else - gccvlo="0" - fi + gccvlo=`echo $gccver | cut -d . -f2` compiler_num=`(expr $gccvhi "*" 100 + $gccvlo) 2>/dev/null` - AC_MSG_RESULT([gcc '$compiler_num' (raw: '$gccver')]) flags_dbg_yes="-g" flags_opt_all="-O -O0 -O1 -O2 -O3 -Os -Og -Ofast" flags_opt_yes="-O2" @@ -259,9 +232,7 @@ AC_DEFUN([CURL_CHECK_COMPILER_INTEL_C], [ CURL_CHECK_DEF([__INTEL_COMPILER], [], [silent]) if test "$curl_cv_have_def___INTEL_COMPILER" = "yes"; then AC_MSG_RESULT([yes]) - AC_MSG_CHECKING([compiler version]) compiler_num="$curl_cv_def___INTEL_COMPILER" - AC_MSG_RESULT([Intel C '$compiler_num']) CURL_CHECK_DEF([__unix__], [], [silent]) if test "$curl_cv_have_def___unix__" = "yes"; then compiler_id="INTEL_UNIX_C" @@ -282,6 +253,26 @@ AC_DEFUN([CURL_CHECK_COMPILER_INTEL_C], [ ]) +dnl CURL_CHECK_COMPILER_LCC +dnl ------------------------------------------------- +dnl Verify if compiler being used is LCC. + +AC_DEFUN([CURL_CHECK_COMPILER_LCC], [ + AC_MSG_CHECKING([if compiler is LCC]) + CURL_CHECK_DEF([__LCC__], [], [silent]) + if test "$curl_cv_have_def___LCC__" = "yes"; then + AC_MSG_RESULT([yes]) + compiler_id="LCC" + flags_dbg_yes="-g" + flags_opt_all="" + flags_opt_yes="" + flags_opt_off="" + else + AC_MSG_RESULT([no]) + fi +]) + + dnl CURL_CHECK_COMPILER_SGI_MIPS_C dnl ------------------------------------------------- dnl Verify if compiler being used is SGI MIPS C. @@ -589,6 +580,12 @@ AC_DEFUN([CURL_SET_COMPILER_BASIC_OPTS], [ tmp_CFLAGS="$tmp_CFLAGS" ;; # + LCC) + # + dnl Disallow run-time dereferencing of null pointers + tmp_CFLAGS="$tmp_CFLAGS -n" + ;; + # SGI_MIPS_C) # dnl Placeholder @@ -790,8 +787,7 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-prototypes]) tmp_CFLAGS="$tmp_CFLAGS -Wno-long-long" CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [float-equal]) - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [sign-compare]) - tmp_CFLAGS="$tmp_CFLAGS -Wno-multichar" + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [no-multichar sign-compare]) CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [undef]) tmp_CFLAGS="$tmp_CFLAGS -Wno-format-nonliteral" CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [endif-labels strict-prototypes]) @@ -805,46 +801,29 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unused]) fi # - dnl Only clang 2.7 or later - if test "$compiler_num" -ge "207"; then - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [address]) - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [attributes]) - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [bad-function-cast]) - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [conversion]) - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [div-by-zero format-security]) - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [empty-body]) - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-field-initializers]) - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-noreturn]) - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [old-style-definition]) - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [redundant-decls]) - # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [switch-enum]) # Not used because this basically disallows default case - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [type-limits]) - # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unused-macros]) # Not practical - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unreachable-code unused-parameter]) - fi - # dnl Only clang 2.8 or later if test "$compiler_num" -ge "208"; then - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [ignored-qualifiers]) CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [vla]) fi # dnl Only clang 2.9 or later if test "$compiler_num" -ge "209"; then - tmp_CFLAGS="$tmp_CFLAGS -Wno-sign-conversion" CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [shift-sign-overflow]) - # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [padded]) # Not used because we cannot change public structs fi # - dnl Only clang 3.0 or later + dnl Only clang 3.0 or later (possibly earlier) if test "$compiler_num" -ge "300"; then - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [language-extension-token]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [bad-function-cast]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [conversion]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [empty-body]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [ignored-qualifiers]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [type-limits]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [no-sign-conversion]) fi # dnl Only clang 3.2 or later if test "$compiler_num" -ge "302"; then CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [enum-conversion]) - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [sometimes-uninitialized]) case $host_os in cygwin* | mingw*) dnl skip missing-variable-declarations warnings for cygwin and @@ -858,16 +837,9 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [ # dnl Only clang 3.4 or later if test "$compiler_num" -ge "304"; then - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [header-guard]) CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unused-const-variable]) fi # - dnl Only clang 3.5 or later - if test "$compiler_num" -ge "305"; then - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [pragmas]) - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unreachable-code-break]) - fi - # dnl Only clang 3.6 or later if test "$compiler_num" -ge "306"; then CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [double-promotion]) @@ -905,6 +877,7 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [ GNU_C) # if test "$want_warnings" = "yes"; then + tmp_CFLAGS="$tmp_CFLAGS -std=gnu89" # dnl Do not enable -pedantic when cross-compiling with a gcc older dnl than 3.0, to avoid warnings from third party system headers. @@ -985,26 +958,6 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [ tmp_CFLAGS="$tmp_CFLAGS -Wstrict-aliasing=3" fi # - dnl Only gcc 4.1 or later - if test "$compiler_num" -ge "401"; then - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [attributes]) - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [div-by-zero format-security]) - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-field-initializers]) - case $host in - *-*-msys*) - ;; - *) - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-noreturn]) # Seen to clash with libtool-generated stub code - ;; - esac - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unreachable-code unused-parameter]) - # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [padded]) # Not used because we cannot change public structs - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [pragmas]) - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [redundant-decls]) - # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [switch-enum]) # Not used because this basically disallows default case - # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unused-macros]) # Not practical - fi - # dnl Only gcc 4.2 or later if test "$compiler_num" -ge "402"; then CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [cast-align]) @@ -1012,7 +965,6 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [ # dnl Only gcc 4.3 or later if test "$compiler_num" -ge "403"; then - CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [address]) CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [type-limits old-style-declaration]) CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-parameter-type empty-body]) CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [clobbered ignored-qualifiers]) @@ -1153,6 +1105,17 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [ tmp_CFLAGS="$tmp_CFLAGS" ;; # + LCC) + # + if test "$want_warnings" = "yes"; then + dnl Highest warning level is double -A, next is single -A. + dnl Due to the big number of warnings these trigger on third + dnl party header files it is impractical for us to use any of + dnl them here. If you want them simply define it in CPPFLAGS. + tmp_CFLAGS="$tmp_CFLAGS" + fi + ;; + # SGI_MIPS_C) # if test "$want_warnings" = "yes"; then diff --git a/deps/curl/m4/curl-functions.m4 b/deps/curl/m4/curl-functions.m4 index 28f4b8b9..7fefa396 100644 --- a/deps/curl/m4/curl-functions.m4 +++ b/deps/curl/m4/curl-functions.m4 @@ -108,6 +108,35 @@ curl_includes_ifaddrs="\ ]) +dnl CURL_INCLUDES_INTTYPES +dnl ------------------------------------------------- +dnl Set up variable with list of headers that must be +dnl included when inttypes.h is to be included. + +AC_DEFUN([CURL_INCLUDES_INTTYPES], [ +curl_includes_inttypes="\ +/* includes start */ +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +/* includes end */" + case $host_os in + irix*) + ac_cv_header_stdint_h="no" + ;; + esac + AC_CHECK_HEADERS( + sys/types.h stdint.h inttypes.h, + [], [], [$curl_includes_inttypes]) +]) + + dnl CURL_INCLUDES_LIBGEN dnl ------------------------------------------------- dnl Set up variable with list of headers that must be @@ -418,10 +447,10 @@ curl_includes_winsock2="\ # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN # endif +# include # ifdef HAVE_WINSOCK2_H # include # endif -# include #endif /* includes end */" CURL_CHECK_HEADER_WINDOWS @@ -441,13 +470,13 @@ curl_includes_ws2tcpip="\ # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN # endif +# include # ifdef HAVE_WINSOCK2_H # include # ifdef HAVE_WS2TCPIP_H # include # endif # endif -# include #endif /* includes end */" CURL_CHECK_HEADER_WINDOWS diff --git a/deps/curl/m4/curl-openssl.m4 b/deps/curl/m4/curl-openssl.m4 index 608653c5..a4811d2a 100644 --- a/deps/curl/m4/curl-openssl.m4 +++ b/deps/curl/m4/curl-openssl.m4 @@ -312,7 +312,7 @@ if test "x$OPT_OPENSSL" != xno; then AC_LANG_PROGRAM([[ #include ]],[[ - #if (OPENSSL_VERSION_NUMBER >= 0x30000000L) + #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) return 0; #else #error older than 3 diff --git a/deps/curl/projects/Windows/VC14.20/.gitignore b/deps/curl/projects/Windows/VC14.20/.gitignore deleted file mode 100644 index 11504d2c..00000000 --- a/deps/curl/projects/Windows/VC14.20/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (C) Daniel Stenberg, , et al. -# -# SPDX-License-Identifier: curl - -/*.opendb -/*.opensdf -/*.sdf -/*.vc.db -/.vs diff --git a/deps/curl/projects/Windows/VC14.20/curl-all.sln b/deps/curl/projects/Windows/VC14.20/curl-all.sln deleted file mode 100644 index 99231009..00000000 --- a/deps/curl/projects/Windows/VC14.20/curl-all.sln +++ /dev/null @@ -1,298 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 16 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "curl", "src\curl.vcxproj", "{5228E9CE-A216-422F-A5E6-58E95E2DD71D}" - ProjectSection(ProjectDependencies) = postProject - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB} = {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcurl", "lib\libcurl.vcxproj", "{DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32 = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32 - DLL Debug - DLL OpenSSL - DLL LibSSH2|x64 = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64 - DLL Debug - DLL OpenSSL|Win32 = DLL Debug - DLL OpenSSL|Win32 - DLL Debug - DLL OpenSSL|x64 = DLL Debug - DLL OpenSSL|x64 - DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32 = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32 - DLL Debug - DLL Windows SSPI - DLL WinIDN|x64 = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64 - DLL Debug - DLL Windows SSPI|Win32 = DLL Debug - DLL Windows SSPI|Win32 - DLL Debug - DLL Windows SSPI|x64 = DLL Debug - DLL Windows SSPI|x64 - DLL Debug - DLL wolfSSL|Win32 = DLL Debug - DLL wolfSSL|Win32 - DLL Debug - DLL wolfSSL|x64 = DLL Debug - DLL wolfSSL|x64 - DLL Debug|Win32 = DLL Debug|Win32 - DLL Debug|x64 = DLL Debug|x64 - DLL Release - DLL OpenSSL - DLL LibSSH2|Win32 = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32 - DLL Release - DLL OpenSSL - DLL LibSSH2|x64 = DLL Release - DLL OpenSSL - DLL LibSSH2|x64 - DLL Release - DLL OpenSSL|Win32 = DLL Release - DLL OpenSSL|Win32 - DLL Release - DLL OpenSSL|x64 = DLL Release - DLL OpenSSL|x64 - DLL Release - DLL Windows SSPI - DLL WinIDN|Win32 = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32 - DLL Release - DLL Windows SSPI - DLL WinIDN|x64 = DLL Release - DLL Windows SSPI - DLL WinIDN|x64 - DLL Release - DLL Windows SSPI|Win32 = DLL Release - DLL Windows SSPI|Win32 - DLL Release - DLL Windows SSPI|x64 = DLL Release - DLL Windows SSPI|x64 - DLL Release - DLL wolfSSL|Win32 = DLL Release - DLL wolfSSL|Win32 - DLL Release - DLL wolfSSL|x64 = DLL Release - DLL wolfSSL|x64 - DLL Release|Win32 = DLL Release|Win32 - DLL Release|x64 = DLL Release|x64 - LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32 = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32 - LIB Debug - DLL OpenSSL - DLL LibSSH2|x64 = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64 - LIB Debug - DLL OpenSSL|Win32 = LIB Debug - DLL OpenSSL|Win32 - LIB Debug - DLL OpenSSL|x64 = LIB Debug - DLL OpenSSL|x64 - LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32 = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32 - LIB Debug - DLL Windows SSPI - DLL WinIDN|x64 = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64 - LIB Debug - DLL Windows SSPI|Win32 = LIB Debug - DLL Windows SSPI|Win32 - LIB Debug - DLL Windows SSPI|x64 = LIB Debug - DLL Windows SSPI|x64 - LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32 = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32 - LIB Debug - LIB OpenSSL - LIB LibSSH2|x64 = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64 - LIB Debug - LIB OpenSSL|Win32 = LIB Debug - LIB OpenSSL|Win32 - LIB Debug - LIB OpenSSL|x64 = LIB Debug - LIB OpenSSL|x64 - LIB Debug - LIB wolfSSL|Win32 = LIB Debug - LIB wolfSSL|Win32 - LIB Debug - LIB wolfSSL|x64 = LIB Debug - LIB wolfSSL|x64 - LIB Debug|Win32 = LIB Debug|Win32 - LIB Debug|x64 = LIB Debug|x64 - LIB Release - DLL OpenSSL - DLL LibSSH2|Win32 = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32 - LIB Release - DLL OpenSSL - DLL LibSSH2|x64 = LIB Release - DLL OpenSSL - DLL LibSSH2|x64 - LIB Release - DLL OpenSSL|Win32 = LIB Release - DLL OpenSSL|Win32 - LIB Release - DLL OpenSSL|x64 = LIB Release - DLL OpenSSL|x64 - LIB Release - DLL Windows SSPI - DLL WinIDN|Win32 = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32 - LIB Release - DLL Windows SSPI - DLL WinIDN|x64 = LIB Release - DLL Windows SSPI - DLL WinIDN|x64 - LIB Release - DLL Windows SSPI|Win32 = LIB Release - DLL Windows SSPI|Win32 - LIB Release - DLL Windows SSPI|x64 = LIB Release - DLL Windows SSPI|x64 - LIB Release - LIB OpenSSL - LIB LibSSH2|Win32 = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32 - LIB Release - LIB OpenSSL - LIB LibSSH2|x64 = LIB Release - LIB OpenSSL - LIB LibSSH2|x64 - LIB Release - LIB OpenSSL|Win32 = LIB Release - LIB OpenSSL|Win32 - LIB Release - LIB OpenSSL|x64 = LIB Release - LIB OpenSSL|x64 - LIB Release - LIB wolfSSL|Win32 = LIB Release - LIB wolfSSL|Win32 - LIB Release - LIB wolfSSL|x64 = LIB Release - LIB wolfSSL|x64 - LIB Release|Win32 = LIB Release|Win32 - LIB Release|x64 = LIB Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL|Win32.ActiveCfg = DLL Debug - DLL OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL|Win32.Build.0 = DLL Debug - DLL OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL|x64.ActiveCfg = DLL Debug - DLL OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL|x64.Build.0 = DLL Debug - DLL OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI|Win32.ActiveCfg = DLL Debug - DLL Windows SSPI|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI|Win32.Build.0 = DLL Debug - DLL Windows SSPI|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI|x64.ActiveCfg = DLL Debug - DLL Windows SSPI|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI|x64.Build.0 = DLL Debug - DLL Windows SSPI|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL wolfSSL|Win32.ActiveCfg = DLL Debug - DLL wolfSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL wolfSSL|Win32.Build.0 = DLL Debug - DLL wolfSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL wolfSSL|x64.ActiveCfg = DLL Debug - DLL wolfSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL wolfSSL|x64.Build.0 = DLL Debug - DLL wolfSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug|Win32.Build.0 = DLL Debug|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug|x64.ActiveCfg = DLL Debug|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug|x64.Build.0 = DLL Debug|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = DLL Release - DLL OpenSSL - DLL LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = DLL Release - DLL OpenSSL - DLL LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL|Win32.ActiveCfg = DLL Release - DLL OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL|Win32.Build.0 = DLL Release - DLL OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL|x64.ActiveCfg = DLL Release - DLL OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL|x64.Build.0 = DLL Release - DLL OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = DLL Release - DLL Windows SSPI - DLL WinIDN|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = DLL Release - DLL Windows SSPI - DLL WinIDN|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI|Win32.ActiveCfg = DLL Release - DLL Windows SSPI|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI|Win32.Build.0 = DLL Release - DLL Windows SSPI|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI|x64.ActiveCfg = DLL Release - DLL Windows SSPI|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI|x64.Build.0 = DLL Release - DLL Windows SSPI|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL wolfSSL|Win32.ActiveCfg = DLL Release - DLL wolfSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL wolfSSL|Win32.Build.0 = DLL Release - DLL wolfSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL wolfSSL|x64.ActiveCfg = DLL Release - DLL wolfSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL wolfSSL|x64.Build.0 = DLL Release - DLL wolfSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release|Win32.Build.0 = DLL Release|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release|x64.ActiveCfg = DLL Release|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release|x64.Build.0 = DLL Release|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL|Win32.ActiveCfg = LIB Debug - DLL OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL|Win32.Build.0 = LIB Debug - DLL OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL|x64.ActiveCfg = LIB Debug - DLL OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL|x64.Build.0 = LIB Debug - DLL OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI|Win32.ActiveCfg = LIB Debug - DLL Windows SSPI|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI|Win32.Build.0 = LIB Debug - DLL Windows SSPI|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI|x64.ActiveCfg = LIB Debug - DLL Windows SSPI|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI|x64.Build.0 = LIB Debug - DLL Windows SSPI|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32.ActiveCfg = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32.Build.0 = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL - LIB LibSSH2|x64.ActiveCfg = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL - LIB LibSSH2|x64.Build.0 = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL|Win32.ActiveCfg = LIB Debug - LIB OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL|Win32.Build.0 = LIB Debug - LIB OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL|x64.ActiveCfg = LIB Debug - LIB OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL|x64.Build.0 = LIB Debug - LIB OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB wolfSSL|Win32.ActiveCfg = LIB Debug - LIB wolfSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB wolfSSL|Win32.Build.0 = LIB Debug - LIB wolfSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB wolfSSL|x64.ActiveCfg = LIB Debug - LIB wolfSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB wolfSSL|x64.Build.0 = LIB Debug - LIB wolfSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug|Win32.ActiveCfg = LIB Debug|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug|Win32.Build.0 = LIB Debug|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug|x64.ActiveCfg = LIB Debug|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug|x64.Build.0 = LIB Debug|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = LIB Release - DLL OpenSSL - DLL LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = LIB Release - DLL OpenSSL - DLL LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL|Win32.ActiveCfg = LIB Release - DLL OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL|Win32.Build.0 = LIB Release - DLL OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL|x64.ActiveCfg = LIB Release - DLL OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL|x64.Build.0 = LIB Release - DLL OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = LIB Release - DLL Windows SSPI - DLL WinIDN|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = LIB Release - DLL Windows SSPI - DLL WinIDN|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI|Win32.ActiveCfg = LIB Release - DLL Windows SSPI|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI|Win32.Build.0 = LIB Release - DLL Windows SSPI|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI|x64.ActiveCfg = LIB Release - DLL Windows SSPI|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI|x64.Build.0 = LIB Release - DLL Windows SSPI|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL - LIB LibSSH2|Win32.ActiveCfg = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL - LIB LibSSH2|Win32.Build.0 = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL - LIB LibSSH2|x64.ActiveCfg = LIB Release - LIB OpenSSL - LIB LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL - LIB LibSSH2|x64.Build.0 = LIB Release - LIB OpenSSL - LIB LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL|Win32.ActiveCfg = LIB Release - LIB OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL|Win32.Build.0 = LIB Release - LIB OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL|x64.ActiveCfg = LIB Release - LIB OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL|x64.Build.0 = LIB Release - LIB OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB wolfSSL|Win32.ActiveCfg = LIB Release - LIB wolfSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB wolfSSL|Win32.Build.0 = LIB Release - LIB wolfSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB wolfSSL|x64.ActiveCfg = LIB Release - LIB wolfSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB wolfSSL|x64.Build.0 = LIB Release - LIB wolfSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release|Win32.ActiveCfg = LIB Release|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release|Win32.Build.0 = LIB Release|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release|x64.ActiveCfg = LIB Release|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release|x64.Build.0 = LIB Release|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL|Win32.ActiveCfg = DLL Debug - DLL OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL|Win32.Build.0 = DLL Debug - DLL OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL|x64.ActiveCfg = DLL Debug - DLL OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL|x64.Build.0 = DLL Debug - DLL OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI|Win32.ActiveCfg = DLL Debug - DLL Windows SSPI|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI|Win32.Build.0 = DLL Debug - DLL Windows SSPI|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI|x64.ActiveCfg = DLL Debug - DLL Windows SSPI|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI|x64.Build.0 = DLL Debug - DLL Windows SSPI|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL wolfSSL|Win32.ActiveCfg = DLL Debug - DLL wolfSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL wolfSSL|Win32.Build.0 = DLL Debug - DLL wolfSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL wolfSSL|x64.ActiveCfg = DLL Debug - DLL wolfSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL wolfSSL|x64.Build.0 = DLL Debug - DLL wolfSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug|Win32.Build.0 = DLL Debug|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug|x64.ActiveCfg = DLL Debug|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug|x64.Build.0 = DLL Debug|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = DLL Release - DLL OpenSSL - DLL LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = DLL Release - DLL OpenSSL - DLL LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL|Win32.ActiveCfg = DLL Release - DLL OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL|Win32.Build.0 = DLL Release - DLL OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL|x64.ActiveCfg = DLL Release - DLL OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL|x64.Build.0 = DLL Release - DLL OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = DLL Release - DLL Windows SSPI - DLL WinIDN|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = DLL Release - DLL Windows SSPI - DLL WinIDN|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI|Win32.ActiveCfg = DLL Release - DLL Windows SSPI|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI|Win32.Build.0 = DLL Release - DLL Windows SSPI|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI|x64.ActiveCfg = DLL Release - DLL Windows SSPI|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI|x64.Build.0 = DLL Release - DLL Windows SSPI|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL wolfSSL|Win32.ActiveCfg = DLL Release - DLL wolfSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL wolfSSL|Win32.Build.0 = DLL Release - DLL wolfSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL wolfSSL|x64.ActiveCfg = DLL Release - DLL wolfSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL wolfSSL|x64.Build.0 = DLL Release - DLL wolfSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release|Win32.Build.0 = DLL Release|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release|x64.ActiveCfg = DLL Release|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release|x64.Build.0 = DLL Release|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL|Win32.ActiveCfg = LIB Debug - DLL OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL|Win32.Build.0 = LIB Debug - DLL OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL|x64.ActiveCfg = LIB Debug - DLL OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL|x64.Build.0 = LIB Debug - DLL OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI|Win32.ActiveCfg = LIB Debug - DLL Windows SSPI|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI|Win32.Build.0 = LIB Debug - DLL Windows SSPI|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI|x64.ActiveCfg = LIB Debug - DLL Windows SSPI|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI|x64.Build.0 = LIB Debug - DLL Windows SSPI|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32.ActiveCfg = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32.Build.0 = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL - LIB LibSSH2|x64.ActiveCfg = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL - LIB LibSSH2|x64.Build.0 = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL|Win32.ActiveCfg = LIB Debug - LIB OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL|Win32.Build.0 = LIB Debug - LIB OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL|x64.ActiveCfg = LIB Debug - LIB OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL|x64.Build.0 = LIB Debug - LIB OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB wolfSSL|Win32.ActiveCfg = LIB Debug - LIB wolfSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB wolfSSL|Win32.Build.0 = LIB Debug - LIB wolfSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB wolfSSL|x64.ActiveCfg = LIB Debug - LIB wolfSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB wolfSSL|x64.Build.0 = LIB Debug - LIB wolfSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug|Win32.ActiveCfg = LIB Debug|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug|Win32.Build.0 = LIB Debug|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug|x64.ActiveCfg = LIB Debug|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug|x64.Build.0 = LIB Debug|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = LIB Release - DLL OpenSSL - DLL LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = LIB Release - DLL OpenSSL - DLL LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL|Win32.ActiveCfg = LIB Release - DLL OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL|Win32.Build.0 = LIB Release - DLL OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL|x64.ActiveCfg = LIB Release - DLL OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL|x64.Build.0 = LIB Release - DLL OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = LIB Release - DLL Windows SSPI - DLL WinIDN|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = LIB Release - DLL Windows SSPI - DLL WinIDN|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI|Win32.ActiveCfg = LIB Release - DLL Windows SSPI|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI|Win32.Build.0 = LIB Release - DLL Windows SSPI|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI|x64.ActiveCfg = LIB Release - DLL Windows SSPI|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI|x64.Build.0 = LIB Release - DLL Windows SSPI|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL - LIB LibSSH2|Win32.ActiveCfg = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL - LIB LibSSH2|Win32.Build.0 = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL - LIB LibSSH2|x64.ActiveCfg = LIB Release - LIB OpenSSL - LIB LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL - LIB LibSSH2|x64.Build.0 = LIB Release - LIB OpenSSL - LIB LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL|Win32.ActiveCfg = LIB Release - LIB OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL|Win32.Build.0 = LIB Release - LIB OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL|x64.ActiveCfg = LIB Release - LIB OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL|x64.Build.0 = LIB Release - LIB OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB wolfSSL|Win32.ActiveCfg = LIB Release - LIB wolfSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB wolfSSL|Win32.Build.0 = LIB Release - LIB wolfSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB wolfSSL|x64.ActiveCfg = LIB Release - LIB wolfSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB wolfSSL|x64.Build.0 = LIB Release - LIB wolfSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release|Win32.ActiveCfg = LIB Release|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release|Win32.Build.0 = LIB Release|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release|x64.ActiveCfg = LIB Release|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release|x64.Build.0 = LIB Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/deps/curl/projects/Windows/VC14.20/lib/.gitignore b/deps/curl/projects/Windows/VC14.20/lib/.gitignore deleted file mode 100644 index 5baee834..00000000 --- a/deps/curl/projects/Windows/VC14.20/lib/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (C) Daniel Stenberg, , et al. -# -# SPDX-License-Identifier: curl - -/*.opensdf -/*.sdf -/*.user -/*.vc.db -/*.vcxproj -/.vs diff --git a/deps/curl/projects/Windows/VC14.20/lib/libcurl.sln b/deps/curl/projects/Windows/VC14.20/lib/libcurl.sln deleted file mode 100644 index e34b5eb5..00000000 --- a/deps/curl/projects/Windows/VC14.20/lib/libcurl.sln +++ /dev/null @@ -1,181 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 17 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcurl", "libcurl.vcxproj", "{DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32 = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32 - DLL Debug - DLL OpenSSL - DLL LibSSH2|x64 = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64 - DLL Debug - DLL OpenSSL|Win32 = DLL Debug - DLL OpenSSL|Win32 - DLL Debug - DLL OpenSSL|x64 = DLL Debug - DLL OpenSSL|x64 - DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32 = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32 - DLL Debug - DLL Windows SSPI - DLL WinIDN|x64 = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64 - DLL Debug - DLL Windows SSPI|Win32 = DLL Debug - DLL Windows SSPI|Win32 - DLL Debug - DLL Windows SSPI|x64 = DLL Debug - DLL Windows SSPI|x64 - DLL Debug - DLL wolfSSL|Win32 = DLL Debug - DLL wolfSSL|Win32 - DLL Debug - DLL wolfSSL|x64 = DLL Debug - DLL wolfSSL|x64 - DLL Debug|Win32 = DLL Debug|Win32 - DLL Debug|x64 = DLL Debug|x64 - DLL Release - DLL OpenSSL - DLL LibSSH2|Win32 = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32 - DLL Release - DLL OpenSSL - DLL LibSSH2|x64 = DLL Release - DLL OpenSSL - DLL LibSSH2|x64 - DLL Release - DLL OpenSSL|Win32 = DLL Release - DLL OpenSSL|Win32 - DLL Release - DLL OpenSSL|x64 = DLL Release - DLL OpenSSL|x64 - DLL Release - DLL Windows SSPI - DLL WinIDN|Win32 = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32 - DLL Release - DLL Windows SSPI - DLL WinIDN|x64 = DLL Release - DLL Windows SSPI - DLL WinIDN|x64 - DLL Release - DLL Windows SSPI|Win32 = DLL Release - DLL Windows SSPI|Win32 - DLL Release - DLL Windows SSPI|x64 = DLL Release - DLL Windows SSPI|x64 - DLL Release - DLL wolfSSL|Win32 = DLL Release - DLL wolfSSL|Win32 - DLL Release - DLL wolfSSL|x64 = DLL Release - DLL wolfSSL|x64 - DLL Release|Win32 = DLL Release|Win32 - DLL Release|x64 = DLL Release|x64 - LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32 = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32 - LIB Debug - DLL OpenSSL - DLL LibSSH2|x64 = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64 - LIB Debug - DLL OpenSSL|Win32 = LIB Debug - DLL OpenSSL|Win32 - LIB Debug - DLL OpenSSL|x64 = LIB Debug - DLL OpenSSL|x64 - LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32 = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32 - LIB Debug - DLL Windows SSPI - DLL WinIDN|x64 = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64 - LIB Debug - DLL Windows SSPI|Win32 = LIB Debug - DLL Windows SSPI|Win32 - LIB Debug - DLL Windows SSPI|x64 = LIB Debug - DLL Windows SSPI|x64 - LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32 = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32 - LIB Debug - LIB OpenSSL - LIB LibSSH2|x64 = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64 - LIB Debug - LIB OpenSSL|Win32 = LIB Debug - LIB OpenSSL|Win32 - LIB Debug - LIB OpenSSL|x64 = LIB Debug - LIB OpenSSL|x64 - LIB Debug - LIB wolfSSL|Win32 = LIB Debug - LIB wolfSSL|Win32 - LIB Debug - LIB wolfSSL|x64 = LIB Debug - LIB wolfSSL|x64 - LIB Debug|Win32 = LIB Debug|Win32 - LIB Debug|x64 = LIB Debug|x64 - LIB Release - DLL OpenSSL - DLL LibSSH2|Win32 = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32 - LIB Release - DLL OpenSSL - DLL LibSSH2|x64 = LIB Release - DLL OpenSSL - DLL LibSSH2|x64 - LIB Release - DLL OpenSSL|Win32 = LIB Release - DLL OpenSSL|Win32 - LIB Release - DLL OpenSSL|x64 = LIB Release - DLL OpenSSL|x64 - LIB Release - DLL Windows SSPI - DLL WinIDN|Win32 = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32 - LIB Release - DLL Windows SSPI - DLL WinIDN|x64 = LIB Release - DLL Windows SSPI - DLL WinIDN|x64 - LIB Release - DLL Windows SSPI|Win32 = LIB Release - DLL Windows SSPI|Win32 - LIB Release - DLL Windows SSPI|x64 = LIB Release - DLL Windows SSPI|x64 - LIB Release - LIB OpenSSL - LIB LibSSH2|Win32 = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32 - LIB Release - LIB OpenSSL - LIB LibSSH2|x64 = LIB Release - LIB OpenSSL - LIB LibSSH2|x64 - LIB Release - LIB OpenSSL|Win32 = LIB Release - LIB OpenSSL|Win32 - LIB Release - LIB OpenSSL|x64 = LIB Release - LIB OpenSSL|x64 - LIB Release - LIB wolfSSL|Win32 = LIB Release - LIB wolfSSL|Win32 - LIB Release - LIB wolfSSL|x64 = LIB Release - LIB wolfSSL|x64 - LIB Release|Win32 = LIB Release|Win32 - LIB Release|x64 = LIB Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL|Win32.ActiveCfg = DLL Debug - DLL OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL|Win32.Build.0 = DLL Debug - DLL OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL|x64.ActiveCfg = DLL Debug - DLL OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL|x64.Build.0 = DLL Debug - DLL OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI|Win32.ActiveCfg = DLL Debug - DLL Windows SSPI|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI|Win32.Build.0 = DLL Debug - DLL Windows SSPI|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI|x64.ActiveCfg = DLL Debug - DLL Windows SSPI|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI|x64.Build.0 = DLL Debug - DLL Windows SSPI|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL wolfSSL|Win32.ActiveCfg = DLL Debug - DLL wolfSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL wolfSSL|Win32.Build.0 = DLL Debug - DLL wolfSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL wolfSSL|x64.ActiveCfg = DLL Debug - DLL wolfSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL wolfSSL|x64.Build.0 = DLL Debug - DLL wolfSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug|Win32.Build.0 = DLL Debug|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug|x64.ActiveCfg = DLL Debug|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug|x64.Build.0 = DLL Debug|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = DLL Release - DLL OpenSSL - DLL LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = DLL Release - DLL OpenSSL - DLL LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL|Win32.ActiveCfg = DLL Release - DLL OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL|Win32.Build.0 = DLL Release - DLL OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL|x64.ActiveCfg = DLL Release - DLL OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL|x64.Build.0 = DLL Release - DLL OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = DLL Release - DLL Windows SSPI - DLL WinIDN|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = DLL Release - DLL Windows SSPI - DLL WinIDN|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI|Win32.ActiveCfg = DLL Release - DLL Windows SSPI|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI|Win32.Build.0 = DLL Release - DLL Windows SSPI|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI|x64.ActiveCfg = DLL Release - DLL Windows SSPI|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI|x64.Build.0 = DLL Release - DLL Windows SSPI|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL wolfSSL|Win32.ActiveCfg = DLL Release - DLL wolfSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL wolfSSL|Win32.Build.0 = DLL Release - DLL wolfSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL wolfSSL|x64.ActiveCfg = DLL Release - DLL wolfSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL wolfSSL|x64.Build.0 = DLL Release - DLL wolfSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release|Win32.Build.0 = DLL Release|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release|x64.ActiveCfg = DLL Release|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release|x64.Build.0 = DLL Release|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL|Win32.ActiveCfg = LIB Debug - DLL OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL|Win32.Build.0 = LIB Debug - DLL OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL|x64.ActiveCfg = LIB Debug - DLL OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL|x64.Build.0 = LIB Debug - DLL OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI|Win32.ActiveCfg = LIB Debug - DLL Windows SSPI|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI|Win32.Build.0 = LIB Debug - DLL Windows SSPI|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI|x64.ActiveCfg = LIB Debug - DLL Windows SSPI|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI|x64.Build.0 = LIB Debug - DLL Windows SSPI|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32.ActiveCfg = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32.Build.0 = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL - LIB LibSSH2|x64.ActiveCfg = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL - LIB LibSSH2|x64.Build.0 = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL|Win32.ActiveCfg = LIB Debug - LIB OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL|Win32.Build.0 = LIB Debug - LIB OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL|x64.ActiveCfg = LIB Debug - LIB OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL|x64.Build.0 = LIB Debug - LIB OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB wolfSSL|Win32.ActiveCfg = LIB Debug - LIB wolfSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB wolfSSL|Win32.Build.0 = LIB Debug - LIB wolfSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB wolfSSL|x64.ActiveCfg = LIB Debug - LIB wolfSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB wolfSSL|x64.Build.0 = LIB Debug - LIB wolfSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug|Win32.ActiveCfg = LIB Debug|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug|Win32.Build.0 = LIB Debug|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug|x64.ActiveCfg = LIB Debug|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug|x64.Build.0 = LIB Debug|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = LIB Release - DLL OpenSSL - DLL LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = LIB Release - DLL OpenSSL - DLL LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL|Win32.ActiveCfg = LIB Release - DLL OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL|Win32.Build.0 = LIB Release - DLL OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL|x64.ActiveCfg = LIB Release - DLL OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL|x64.Build.0 = LIB Release - DLL OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = LIB Release - DLL Windows SSPI - DLL WinIDN|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = LIB Release - DLL Windows SSPI - DLL WinIDN|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI|Win32.ActiveCfg = LIB Release - DLL Windows SSPI|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI|Win32.Build.0 = LIB Release - DLL Windows SSPI|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI|x64.ActiveCfg = LIB Release - DLL Windows SSPI|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI|x64.Build.0 = LIB Release - DLL Windows SSPI|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL - LIB LibSSH2|Win32.ActiveCfg = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL - LIB LibSSH2|Win32.Build.0 = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL - LIB LibSSH2|x64.ActiveCfg = LIB Release - LIB OpenSSL - LIB LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL - LIB LibSSH2|x64.Build.0 = LIB Release - LIB OpenSSL - LIB LibSSH2|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL|Win32.ActiveCfg = LIB Release - LIB OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL|Win32.Build.0 = LIB Release - LIB OpenSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL|x64.ActiveCfg = LIB Release - LIB OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL|x64.Build.0 = LIB Release - LIB OpenSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB wolfSSL|Win32.ActiveCfg = LIB Release - LIB wolfSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB wolfSSL|Win32.Build.0 = LIB Release - LIB wolfSSL|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB wolfSSL|x64.ActiveCfg = LIB Release - LIB wolfSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB wolfSSL|x64.Build.0 = LIB Release - LIB wolfSSL|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release|Win32.ActiveCfg = LIB Release|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release|Win32.Build.0 = LIB Release|Win32 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release|x64.ActiveCfg = LIB Release|x64 - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release|x64.Build.0 = LIB Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/deps/curl/projects/Windows/VC14.20/lib/libcurl.tmpl b/deps/curl/projects/Windows/VC14.20/lib/libcurl.tmpl deleted file mode 100644 index ff88b422..00000000 --- a/deps/curl/projects/Windows/VC14.20/lib/libcurl.tmpl +++ /dev/null @@ -1,2381 +0,0 @@ - - - - - DLL Debug - DLL wolfSSL - Win32 - - - DLL Debug - DLL wolfSSL - x64 - - - DLL Debug - DLL OpenSSL - DLL LibSSH2 - Win32 - - - DLL Debug - DLL OpenSSL - DLL LibSSH2 - x64 - - - DLL Debug - DLL OpenSSL - Win32 - - - DLL Debug - DLL OpenSSL - x64 - - - DLL Debug - DLL Windows SSPI - DLL WinIDN - Win32 - - - DLL Debug - DLL Windows SSPI - DLL WinIDN - x64 - - - DLL Debug - DLL Windows SSPI - Win32 - - - DLL Debug - DLL Windows SSPI - x64 - - - DLL Debug - Win32 - - - DLL Debug - x64 - - - DLL Release - DLL wolfSSL - Win32 - - - DLL Release - DLL wolfSSL - x64 - - - DLL Release - DLL OpenSSL - DLL LibSSH2 - Win32 - - - DLL Release - DLL OpenSSL - DLL LibSSH2 - x64 - - - DLL Release - DLL OpenSSL - Win32 - - - DLL Release - DLL OpenSSL - x64 - - - DLL Release - DLL Windows SSPI - DLL WinIDN - Win32 - - - DLL Release - DLL Windows SSPI - DLL WinIDN - x64 - - - DLL Release - DLL Windows SSPI - Win32 - - - DLL Release - DLL Windows SSPI - x64 - - - DLL Release - Win32 - - - DLL Release - x64 - - - LIB Debug - DLL OpenSSL - DLL LibSSH2 - Win32 - - - LIB Debug - DLL OpenSSL - DLL LibSSH2 - x64 - - - LIB Debug - DLL OpenSSL - Win32 - - - LIB Debug - DLL OpenSSL - x64 - - - LIB Debug - DLL Windows SSPI - DLL WinIDN - Win32 - - - LIB Debug - DLL Windows SSPI - DLL WinIDN - x64 - - - LIB Debug - DLL Windows SSPI - Win32 - - - LIB Debug - DLL Windows SSPI - x64 - - - LIB Debug - LIB wolfSSL - Win32 - - - LIB Debug - LIB wolfSSL - x64 - - - LIB Debug - LIB OpenSSL - LIB LibSSH2 - Win32 - - - LIB Debug - LIB OpenSSL - LIB LibSSH2 - x64 - - - LIB Debug - LIB OpenSSL - Win32 - - - LIB Debug - LIB OpenSSL - x64 - - - LIB Debug - Win32 - - - LIB Debug - x64 - - - LIB Release - DLL OpenSSL - DLL LibSSH2 - Win32 - - - LIB Release - DLL OpenSSL - DLL LibSSH2 - x64 - - - LIB Release - DLL OpenSSL - Win32 - - - LIB Release - DLL OpenSSL - x64 - - - LIB Release - DLL Windows SSPI - DLL WinIDN - Win32 - - - LIB Release - DLL Windows SSPI - DLL WinIDN - x64 - - - LIB Release - DLL Windows SSPI - Win32 - - - LIB Release - DLL Windows SSPI - x64 - - - LIB Release - LIB wolfSSL - Win32 - - - LIB Release - LIB wolfSSL - x64 - - - LIB Release - LIB OpenSSL - LIB LibSSH2 - Win32 - - - LIB Release - LIB OpenSSL - LIB LibSSH2 - x64 - - - LIB Release - LIB OpenSSL - Win32 - - - LIB Release - LIB OpenSSL - x64 - - - LIB Release - Win32 - - - LIB Release - x64 - - - - {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB} - libcurl - - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - StaticLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - DynamicLibrary - false - Unicode - v142 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)lib\ - $(OutDir)lib\ - false - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)lib\ - $(OutDir)lib\ - false - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)lib\ - $(OutDir)lib\ - false - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)lib\ - $(OutDir)lib\ - false - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)lib\ - $(OutDir)lib\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)lib\ - $(OutDir)lib\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)lib\ - $(OutDir)lib\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)lib\ - $(OutDir)lib\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)lib\ - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)lib\ - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)lib\ - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)lib\ - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)lib\ - $(OutDir)lib\ - false - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)lib\ - $(OutDir)lib\ - false - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)lib\ - $(OutDir)lib\ - false - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)lib\ - $(OutDir)lib\ - false - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)lib\ - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)lib\ - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)lib\ - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)lib\ - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)lib\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)lib\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)lib\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)lib\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)lib\ - $(OutDir)lib\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)lib\ - $(OutDir)lib\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)lib\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)lib\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)lib\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)lib\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)lib\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)lib\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)lib\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)lib\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)lib\ - $(OutDir)lib\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)lib\ - $(OutDir)lib\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)lib\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)lib\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)lib\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)lib\ - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - - - - _DEBUG;%(PreprocessorDefinitions) - true - Win32 - $(OutDir)$(ProjectName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - ws2_32.lib;wldap32.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - %(AdditionalLibraryDirectories) - $(IntDir)$(TargetFileName).intermediate.manifest - true - $(TargetDir)$(TargetName).pdb - $(TargetDir)$(TargetName).lib - MachineX86 - - - - - _DEBUG;%(PreprocessorDefinitions) - true - Win32 - $(OutDir)$(ProjectName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\wolfssl;..\..\..\..\..\wolfssl\wolfssl;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WOLFSSL;USE_IPV6;WOLFSSL_DLL;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - 4214 - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - ws2_32.lib;wldap32.lib;wolfssl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\..\wolfssl\build\Win32\VC14.20\DLL Debug;%(AdditionalLibraryDirectories) - $(IntDir)$(TargetFileName).intermediate.manifest - true - $(TargetDir)$(TargetName).pdb - $(TargetDir)$(TargetName).lib - MachineX86 - - - - - _DEBUG;%(PreprocessorDefinitions) - true - X64 - $(OutDir)$(ProjectName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - ws2_32.lib;wldap32.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - %(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - $(TargetDir)$(TargetName).lib - MachineX64 - - - - - _DEBUG;%(PreprocessorDefinitions) - true - X64 - $(OutDir)$(ProjectName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\wolfssl;..\..\..\..\..\wolfssl\wolfssl;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WOLFSSL;USE_IPV6;WOLFSSL_DLL;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - 4214 - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - ws2_32.lib;wldap32.lib;wolfssl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\..\wolfssl\build\Win64\VC14.20\DLL Debug;%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - $(TargetDir)$(TargetName).lib - MachineX64 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - Win32 - $(OutDir)$(ProjectName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - ws2_32.lib;wldap32.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - %(AdditionalLibraryDirectories) - $(IntDir)$(TargetFileName).intermediate.manifest - $(TargetDir)$(TargetName).lib - MachineX86 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - Win32 - $(OutDir)$(ProjectName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\wolfssl;..\..\..\..\..\wolfssl\wolfssl;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;USE_WOLFSSL;USE_IPV6;WOLFSSL_DLL;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - 4214 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - ws2_32.lib;wldap32.lib;wolfssl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\..\wolfssl\build\Win32\VC14.20\DLL Release;%(AdditionalLibraryDirectories) - $(IntDir)$(TargetFileName).intermediate.manifest - $(TargetDir)$(TargetName).lib - MachineX86 - true - $(TargetDir)$(TargetName).pdb - - - - - NDEBUG;%(PreprocessorDefinitions) - true - X64 - $(OutDir)$(ProjectName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - ws2_32.lib;wldap32.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - %(AdditionalLibraryDirectories) - $(TargetDir)$(TargetName).lib - MachineX64 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - X64 - $(OutDir)$(ProjectName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\wolfssl;..\..\..\..\..\wolfssl\wolfssl;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;USE_WOLFSSL;USE_IPV6;WOLFSSL_DLL;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - 4214 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - ws2_32.lib;wldap32.lib;wolfssl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\..\wolfssl\build\Win64\VC14.20\DLL Release;%(AdditionalLibraryDirectories) - $(TargetDir)$(TargetName).lib - MachineX64 - true - $(TargetDir)$(TargetName).pdb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX86 - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\wolfssl;..\..\..\..\..\wolfssl\wolfssl;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WOLFSSL;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - 4214 - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX86 - - - - - X64 - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX64 - - - - - X64 - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\wolfssl;..\..\..\..\..\wolfssl\wolfssl;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WOLFSSL;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - 4214 - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX64 - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\wolfssl;..\..\..\..\..\wolfssl\wolfssl;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WOLFSSL;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - 4214 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX86 - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX64 - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\wolfssl;..\..\..\..\..\wolfssl\wolfssl;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WOLFSSL;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - 4214 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX64 - - - - - _DEBUG;%(PreprocessorDefinitions) - true - Win32 - $(OutDir)$(ProjectName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\DLL Debug\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\..\openssl\build\Win32\VC14.20\DLL Debug;%(AdditionalLibraryDirectories) - $(IntDir)$(TargetFileName).intermediate.manifest - true - $(TargetDir)$(TargetName).pdb - $(TargetDir)$(TargetName).lib - MachineX86 - - - - - _DEBUG;%(PreprocessorDefinitions) - true - X64 - $(OutDir)$(ProjectName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\DLL Debug\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\..\openssl\build\Win64\VC14.20\DLL Debug;%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - $(TargetDir)$(TargetName).lib - MachineX64 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - Win32 - $(OutDir)$(ProjectName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\DLL Release\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\..\openssl\build\Win32\VC14.20\DLL Release;%(AdditionalLibraryDirectories) - $(IntDir)$(TargetFileName).intermediate.manifest - $(TargetDir)$(TargetName).lib - MachineX86 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - X64 - $(OutDir)$(ProjectName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\DLL Release\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\..\openssl\build\Win64\VC14.20\DLL Release;%(AdditionalLibraryDirectories) - $(TargetDir)$(TargetName).lib - MachineX64 - - - - - _DEBUG;%(PreprocessorDefinitions) - true - Win32 - $(OutDir)$(ProjectName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - ws2_32.lib;wldap32.lib;crypt32.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - %(AdditionalLibraryDirectories) - $(IntDir)$(TargetFileName).intermediate.manifest - true - $(TargetDir)$(TargetName).pdb - $(TargetDir)$(TargetName).lib - MachineX86 - - - - - _DEBUG;%(PreprocessorDefinitions) - true - Win32 - $(OutDir)$(ProjectName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - ws2_32.lib;wldap32.lib;crypt32.lib;normaliz.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - %(AdditionalLibraryDirectories) - $(IntDir)$(TargetFileName).intermediate.manifest - true - $(TargetDir)$(TargetName).pdb - $(TargetDir)$(TargetName).lib - MachineX86 - - - - - _DEBUG;%(PreprocessorDefinitions) - true - X64 - $(OutDir)$(ProjectName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - ws2_32.lib;wldap32.lib;crypt32.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - %(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - $(TargetDir)$(TargetName).lib - MachineX64 - - - - - _DEBUG;%(PreprocessorDefinitions) - true - X64 - $(OutDir)$(ProjectName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - ws2_32.lib;wldap32.lib;crypt32.lib;normaliz.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - %(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - $(TargetDir)$(TargetName).lib - MachineX64 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - Win32 - $(OutDir)$(ProjectName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - ws2_32.lib;wldap32.lib;crypt32.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - %(AdditionalLibraryDirectories) - $(IntDir)$(TargetFileName).intermediate.manifest - $(TargetDir)$(TargetName).lib - MachineX86 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - Win32 - $(OutDir)$(ProjectName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - ws2_32.lib;wldap32.lib;crypt32.lib;normaliz.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - %(AdditionalLibraryDirectories) - $(IntDir)$(TargetFileName).intermediate.manifest - $(TargetDir)$(TargetName).lib - MachineX86 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - X64 - $(OutDir)$(ProjectName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - ws2_32.lib;wldap32.lib;crypt32.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - %(AdditionalLibraryDirectories) - $(TargetDir)$(TargetName).lib - MachineX64 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - X64 - $(OutDir)$(ProjectName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - ws2_32.lib;wldap32.lib;crypt32.lib;normaliz.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - %(AdditionalLibraryDirectories) - $(TargetDir)$(TargetName).lib - MachineX64 - - - - - _DEBUG;%(PreprocessorDefinitions) - true - Win32 - $(OutDir)$(ProjectName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcrypto.lib;libssl.lib;libssh2d.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\..\openssl\build\Win32\VC14.20\DLL Debug;..\..\..\..\..\libssh2\build\Win32\VC14.20\DLL Debug;%(AdditionalLibraryDirectories) - $(IntDir)$(TargetFileName).intermediate.manifest - true - $(TargetDir)$(TargetName).pdb - $(TargetDir)$(TargetName).lib - MachineX86 - - - - - _DEBUG;%(PreprocessorDefinitions) - true - X64 - $(OutDir)$(ProjectName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcrypto.lib;libssl.lib;libssh2d.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\..\openssl\build\Win64\VC14.20\DLL Debug;..\..\..\..\..\libssh2\build\Win64\VC14.20\DLL Debug;%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - $(TargetDir)$(TargetName).lib - MachineX64 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - Win32 - $(OutDir)$(ProjectName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcrypto.lib;libssl.lib;libssh2.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\..\openssl\build\Win32\VC14.20\DLL Release;..\..\..\..\..\libssh2\build\Win32\VC14.20\DLL Release;%(AdditionalLibraryDirectories) - $(IntDir)$(TargetFileName).intermediate.manifest - $(TargetDir)$(TargetName).lib - MachineX86 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - X64 - $(OutDir)$(ProjectName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcrypto.lib;libssl.lib;libssh2.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\..\openssl\build\Win64\VC14.20\DLL Release;..\..\..\..\..\libssh2\build\Win64\VC14.20\DLL Release;%(AdditionalLibraryDirectories) - $(TargetDir)$(TargetName).lib - MachineX64 - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\DLL Debug\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX86 - - - - - X64 - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\DLL Debug\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX64 - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX86 - - - - - X64 - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX64 - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX86 - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX86 - - - - - X64 - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX64 - - - - - X64 - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX64 - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\LIB Debug\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX86 - - - - - X64 - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\LIB Debug\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX64 - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\LIB Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX86 - - - - - X64 - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\LIB Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories) - _DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX64 - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\DLL Release\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX86 - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\DLL Release\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX64 - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX86 - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX64 - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX86 - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX64 - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX64 - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\LIB Release\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX86 - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\LIB Release\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX64 - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\LIB Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX86 - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\LIB Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories) - NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - $(OutDir)$(TargetName)$(TargetExt) - MachineX64 - - - -CURL_LIB_C_FILES -CURL_LIB_VAUTH_C_FILES -CURL_LIB_VQUIC_C_FILES -CURL_LIB_VSSH_C_FILES -CURL_LIB_VTLS_C_FILES - - -CURL_LIB_H_FILES -CURL_LIB_VAUTH_H_FILES -CURL_LIB_VQUIC_H_FILES -CURL_LIB_VSSH_H_FILES -CURL_LIB_VTLS_H_FILES - - -CURL_LIB_RC_FILES - - - - - \ No newline at end of file diff --git a/deps/curl/projects/Windows/VC14.20/lib/libcurl.vcxproj.filters b/deps/curl/projects/Windows/VC14.20/lib/libcurl.vcxproj.filters deleted file mode 100644 index 4d6341d7..00000000 --- a/deps/curl/projects/Windows/VC14.20/lib/libcurl.vcxproj.filters +++ /dev/null @@ -1,17 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - \ No newline at end of file diff --git a/deps/curl/projects/Windows/VC14.20/src/.gitignore b/deps/curl/projects/Windows/VC14.20/src/.gitignore deleted file mode 100644 index 5baee834..00000000 --- a/deps/curl/projects/Windows/VC14.20/src/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (C) Daniel Stenberg, , et al. -# -# SPDX-License-Identifier: curl - -/*.opensdf -/*.sdf -/*.user -/*.vc.db -/*.vcxproj -/.vs diff --git a/deps/curl/projects/Windows/VC14.20/src/curl.sln b/deps/curl/projects/Windows/VC14.20/src/curl.sln deleted file mode 100644 index 5cfa4ce2..00000000 --- a/deps/curl/projects/Windows/VC14.20/src/curl.sln +++ /dev/null @@ -1,181 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 16 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "curl", "curl.vcxproj", "{5228E9CE-A216-422F-A5E6-58E95E2DD71D}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32 = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32 - DLL Debug - DLL OpenSSL - DLL LibSSH2|x64 = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64 - DLL Debug - DLL OpenSSL|Win32 = DLL Debug - DLL OpenSSL|Win32 - DLL Debug - DLL OpenSSL|x64 = DLL Debug - DLL OpenSSL|x64 - DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32 = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32 - DLL Debug - DLL Windows SSPI - DLL WinIDN|x64 = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64 - DLL Debug - DLL Windows SSPI|Win32 = DLL Debug - DLL Windows SSPI|Win32 - DLL Debug - DLL Windows SSPI|x64 = DLL Debug - DLL Windows SSPI|x64 - DLL Debug - DLL wolfSSL|Win32 = DLL Debug - DLL wolfSSL|Win32 - DLL Debug - DLL wolfSSL|x64 = DLL Debug - DLL wolfSSL|x64 - DLL Debug|Win32 = DLL Debug|Win32 - DLL Debug|x64 = DLL Debug|x64 - DLL Release - DLL OpenSSL - DLL LibSSH2|Win32 = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32 - DLL Release - DLL OpenSSL - DLL LibSSH2|x64 = DLL Release - DLL OpenSSL - DLL LibSSH2|x64 - DLL Release - DLL OpenSSL|Win32 = DLL Release - DLL OpenSSL|Win32 - DLL Release - DLL OpenSSL|x64 = DLL Release - DLL OpenSSL|x64 - DLL Release - DLL Windows SSPI - DLL WinIDN|Win32 = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32 - DLL Release - DLL Windows SSPI - DLL WinIDN|x64 = DLL Release - DLL Windows SSPI - DLL WinIDN|x64 - DLL Release - DLL Windows SSPI|Win32 = DLL Release - DLL Windows SSPI|Win32 - DLL Release - DLL Windows SSPI|x64 = DLL Release - DLL Windows SSPI|x64 - DLL Release - DLL wolfSSL|Win32 = DLL Release - DLL wolfSSL|Win32 - DLL Release - DLL wolfSSL|x64 = DLL Release - DLL wolfSSL|x64 - DLL Release|Win32 = DLL Release|Win32 - DLL Release|x64 = DLL Release|x64 - LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32 = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32 - LIB Debug - DLL OpenSSL - DLL LibSSH2|x64 = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64 - LIB Debug - DLL OpenSSL|Win32 = LIB Debug - DLL OpenSSL|Win32 - LIB Debug - DLL OpenSSL|x64 = LIB Debug - DLL OpenSSL|x64 - LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32 = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32 - LIB Debug - DLL Windows SSPI - DLL WinIDN|x64 = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64 - LIB Debug - DLL Windows SSPI|Win32 = LIB Debug - DLL Windows SSPI|Win32 - LIB Debug - DLL Windows SSPI|x64 = LIB Debug - DLL Windows SSPI|x64 - LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32 = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32 - LIB Debug - LIB OpenSSL - LIB LibSSH2|x64 = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64 - LIB Debug - LIB OpenSSL|Win32 = LIB Debug - LIB OpenSSL|Win32 - LIB Debug - LIB OpenSSL|x64 = LIB Debug - LIB OpenSSL|x64 - LIB Debug - LIB wolfSSL|Win32 = LIB Debug - LIB wolfSSL|Win32 - LIB Debug - LIB wolfSSL|x64 = LIB Debug - LIB wolfSSL|x64 - LIB Debug|Win32 = LIB Debug|Win32 - LIB Debug|x64 = LIB Debug|x64 - LIB Release - DLL OpenSSL - DLL LibSSH2|Win32 = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32 - LIB Release - DLL OpenSSL - DLL LibSSH2|x64 = LIB Release - DLL OpenSSL - DLL LibSSH2|x64 - LIB Release - DLL OpenSSL|Win32 = LIB Release - DLL OpenSSL|Win32 - LIB Release - DLL OpenSSL|x64 = LIB Release - DLL OpenSSL|x64 - LIB Release - DLL Windows SSPI - DLL WinIDN|Win32 = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32 - LIB Release - DLL Windows SSPI - DLL WinIDN|x64 = LIB Release - DLL Windows SSPI - DLL WinIDN|x64 - LIB Release - DLL Windows SSPI|Win32 = LIB Release - DLL Windows SSPI|Win32 - LIB Release - DLL Windows SSPI|x64 = LIB Release - DLL Windows SSPI|x64 - LIB Release - LIB OpenSSL - LIB LibSSH2|Win32 = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32 - LIB Release - LIB OpenSSL - LIB LibSSH2|x64 = LIB Release - LIB OpenSSL - LIB LibSSH2|x64 - LIB Release - LIB OpenSSL|Win32 = LIB Release - LIB OpenSSL|Win32 - LIB Release - LIB OpenSSL|x64 = LIB Release - LIB OpenSSL|x64 - LIB Release - LIB wolfSSL|Win32 = LIB Release - LIB wolfSSL|Win32 - LIB Release - LIB wolfSSL|x64 = LIB Release - LIB wolfSSL|x64 - LIB Release|Win32 = LIB Release|Win32 - LIB Release|x64 = LIB Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL|Win32.ActiveCfg = DLL Debug - DLL OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL|Win32.Build.0 = DLL Debug - DLL OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL|x64.ActiveCfg = DLL Debug - DLL OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL|x64.Build.0 = DLL Debug - DLL OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI|Win32.ActiveCfg = DLL Debug - DLL Windows SSPI|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI|Win32.Build.0 = DLL Debug - DLL Windows SSPI|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI|x64.ActiveCfg = DLL Debug - DLL Windows SSPI|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI|x64.Build.0 = DLL Debug - DLL Windows SSPI|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL wolfSSL|Win32.ActiveCfg = DLL Debug - DLL wolfSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL wolfSSL|Win32.Build.0 = DLL Debug - DLL wolfSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL wolfSSL|x64.ActiveCfg = DLL Debug - DLL wolfSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL wolfSSL|x64.Build.0 = DLL Debug - DLL wolfSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug|Win32.Build.0 = DLL Debug|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug|x64.ActiveCfg = DLL Debug|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug|x64.Build.0 = DLL Debug|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = DLL Release - DLL OpenSSL - DLL LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = DLL Release - DLL OpenSSL - DLL LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL|Win32.ActiveCfg = DLL Release - DLL OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL|Win32.Build.0 = DLL Release - DLL OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL|x64.ActiveCfg = DLL Release - DLL OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL|x64.Build.0 = DLL Release - DLL OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = DLL Release - DLL Windows SSPI - DLL WinIDN|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = DLL Release - DLL Windows SSPI - DLL WinIDN|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI|Win32.ActiveCfg = DLL Release - DLL Windows SSPI|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI|Win32.Build.0 = DLL Release - DLL Windows SSPI|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI|x64.ActiveCfg = DLL Release - DLL Windows SSPI|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI|x64.Build.0 = DLL Release - DLL Windows SSPI|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL wolfSSL|Win32.ActiveCfg = DLL Release - DLL wolfSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL wolfSSL|Win32.Build.0 = DLL Release - DLL wolfSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL wolfSSL|x64.ActiveCfg = DLL Release - DLL wolfSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL wolfSSL|x64.Build.0 = DLL Release - DLL wolfSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release|Win32.Build.0 = DLL Release|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release|x64.ActiveCfg = DLL Release|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release|x64.Build.0 = DLL Release|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL|Win32.ActiveCfg = LIB Debug - DLL OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL|Win32.Build.0 = LIB Debug - DLL OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL|x64.ActiveCfg = LIB Debug - DLL OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL|x64.Build.0 = LIB Debug - DLL OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI|Win32.ActiveCfg = LIB Debug - DLL Windows SSPI|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI|Win32.Build.0 = LIB Debug - DLL Windows SSPI|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI|x64.ActiveCfg = LIB Debug - DLL Windows SSPI|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI|x64.Build.0 = LIB Debug - DLL Windows SSPI|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32.ActiveCfg = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32.Build.0 = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL - LIB LibSSH2|x64.ActiveCfg = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL - LIB LibSSH2|x64.Build.0 = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL|Win32.ActiveCfg = LIB Debug - LIB OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL|Win32.Build.0 = LIB Debug - LIB OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL|x64.ActiveCfg = LIB Debug - LIB OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL|x64.Build.0 = LIB Debug - LIB OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB wolfSSL|Win32.ActiveCfg = LIB Debug - LIB wolfSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB wolfSSL|Win32.Build.0 = LIB Debug - LIB wolfSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB wolfSSL|x64.ActiveCfg = LIB Debug - LIB wolfSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB wolfSSL|x64.Build.0 = LIB Debug - LIB wolfSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug|Win32.ActiveCfg = LIB Debug|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug|Win32.Build.0 = LIB Debug|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug|x64.ActiveCfg = LIB Debug|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug|x64.Build.0 = LIB Debug|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = LIB Release - DLL OpenSSL - DLL LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = LIB Release - DLL OpenSSL - DLL LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL|Win32.ActiveCfg = LIB Release - DLL OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL|Win32.Build.0 = LIB Release - DLL OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL|x64.ActiveCfg = LIB Release - DLL OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL|x64.Build.0 = LIB Release - DLL OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = LIB Release - DLL Windows SSPI - DLL WinIDN|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = LIB Release - DLL Windows SSPI - DLL WinIDN|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI|Win32.ActiveCfg = LIB Release - DLL Windows SSPI|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI|Win32.Build.0 = LIB Release - DLL Windows SSPI|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI|x64.ActiveCfg = LIB Release - DLL Windows SSPI|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI|x64.Build.0 = LIB Release - DLL Windows SSPI|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL - LIB LibSSH2|Win32.ActiveCfg = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL - LIB LibSSH2|Win32.Build.0 = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL - LIB LibSSH2|x64.ActiveCfg = LIB Release - LIB OpenSSL - LIB LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL - LIB LibSSH2|x64.Build.0 = LIB Release - LIB OpenSSL - LIB LibSSH2|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL|Win32.ActiveCfg = LIB Release - LIB OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL|Win32.Build.0 = LIB Release - LIB OpenSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL|x64.ActiveCfg = LIB Release - LIB OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL|x64.Build.0 = LIB Release - LIB OpenSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB wolfSSL|Win32.ActiveCfg = LIB Release - LIB wolfSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB wolfSSL|Win32.Build.0 = LIB Release - LIB wolfSSL|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB wolfSSL|x64.ActiveCfg = LIB Release - LIB wolfSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB wolfSSL|x64.Build.0 = LIB Release - LIB wolfSSL|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release|Win32.ActiveCfg = LIB Release|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release|Win32.Build.0 = LIB Release|Win32 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release|x64.ActiveCfg = LIB Release|x64 - {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release|x64.Build.0 = LIB Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/deps/curl/projects/Windows/VC14.20/src/curl.tmpl b/deps/curl/projects/Windows/VC14.20/src/curl.tmpl deleted file mode 100644 index 85c71768..00000000 --- a/deps/curl/projects/Windows/VC14.20/src/curl.tmpl +++ /dev/null @@ -1,2671 +0,0 @@ - - - - - DLL Debug - DLL wolfSSL - Win32 - - - DLL Debug - DLL wolfSSL - x64 - - - DLL Debug - DLL OpenSSL - DLL LibSSH2 - Win32 - - - DLL Debug - DLL OpenSSL - DLL LibSSH2 - x64 - - - DLL Debug - DLL OpenSSL - Win32 - - - DLL Debug - DLL OpenSSL - x64 - - - DLL Debug - DLL Windows SSPI - DLL WinIDN - Win32 - - - DLL Debug - DLL Windows SSPI - DLL WinIDN - x64 - - - DLL Debug - DLL Windows SSPI - Win32 - - - DLL Debug - DLL Windows SSPI - x64 - - - DLL Debug - Win32 - - - DLL Debug - x64 - - - DLL Release - DLL wolfSSL - Win32 - - - DLL Release - DLL wolfSSL - x64 - - - DLL Release - DLL OpenSSL - DLL LibSSH2 - Win32 - - - DLL Release - DLL OpenSSL - DLL LibSSH2 - x64 - - - DLL Release - DLL OpenSSL - Win32 - - - DLL Release - DLL OpenSSL - x64 - - - DLL Release - DLL Windows SSPI - DLL WinIDN - Win32 - - - DLL Release - DLL Windows SSPI - DLL WinIDN - x64 - - - DLL Release - DLL Windows SSPI - Win32 - - - DLL Release - DLL Windows SSPI - x64 - - - DLL Release - Win32 - - - DLL Release - x64 - - - LIB Debug - DLL OpenSSL - DLL LibSSH2 - Win32 - - - LIB Debug - DLL OpenSSL - DLL LibSSH2 - x64 - - - LIB Debug - DLL OpenSSL - Win32 - - - LIB Debug - DLL OpenSSL - x64 - - - LIB Debug - DLL Windows SSPI - DLL WinIDN - Win32 - - - LIB Debug - DLL Windows SSPI - DLL WinIDN - x64 - - - LIB Debug - DLL Windows SSPI - Win32 - - - LIB Debug - DLL Windows SSPI - x64 - - - LIB Debug - LIB wolfSSL - Win32 - - - LIB Debug - LIB wolfSSL - x64 - - - LIB Debug - LIB OpenSSL - LIB LibSSH2 - Win32 - - - LIB Debug - LIB OpenSSL - LIB LibSSH2 - x64 - - - LIB Debug - LIB OpenSSL - Win32 - - - LIB Debug - LIB OpenSSL - x64 - - - LIB Debug - Win32 - - - LIB Debug - x64 - - - LIB Release - DLL OpenSSL - DLL LibSSH2 - Win32 - - - LIB Release - DLL OpenSSL - DLL LibSSH2 - x64 - - - LIB Release - DLL OpenSSL - Win32 - - - LIB Release - DLL OpenSSL - x64 - - - LIB Release - DLL Windows SSPI - DLL WinIDN - Win32 - - - LIB Release - DLL Windows SSPI - DLL WinIDN - x64 - - - LIB Release - DLL Windows SSPI - Win32 - - - LIB Release - DLL Windows SSPI - x64 - - - LIB Release - LIB wolfSSL - Win32 - - - LIB Release - LIB wolfSSL - x64 - - - LIB Release - LIB OpenSSL - LIB LibSSH2 - Win32 - - - LIB Release - LIB OpenSSL - LIB LibSSH2 - x64 - - - LIB Release - LIB OpenSSL - Win32 - - - LIB Release - LIB OpenSSL - x64 - - - LIB Release - Win32 - - - LIB Release - x64 - - - - {5228E9CE-A216-422F-A5E6-58E95E2DD71D} - curl - - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - Application - false - Unicode - v142 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)src\ - $(OutDir)src\ - false - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)src\ - $(OutDir)src\ - false - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)src\ - $(OutDir)src\ - false - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)src\ - $(OutDir)src\ - false - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)src\ - $(OutDir)src\ - false - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)src\ - $(OutDir)src\ - false - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)src\ - $(OutDir)src\ - false - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)src\ - $(OutDir)src\ - false - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)src\ - $(OutDir)src\ - false - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)src\ - $(OutDir)src\ - false - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)src\ - $(OutDir)src\ - false - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)src\ - $(OutDir)src\ - false - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)src\ - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)src\ - $(OutDir)src\ - false - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)src\ - $(OutDir)src\ - false - false - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win32\VC14.20\$(Configuration)\ - $(OutDir)src\ - $(OutDir)src\ - false - false - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - ..\..\..\..\build\Win64\VC14.20\$(Configuration)\ - $(OutDir)src\ - $(OutDir)src\ - false - false - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName)d - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - $(ProjectName) - - - - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - Console - MachineX86 - true - $(TargetDir)$(TargetName).pdb - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - Console - MachineX64 - true - $(TargetDir)$(TargetName).pdb - - - - - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurl.lib;wolfssl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);..\..\..\..\..\wolfssl\build\Win32\VC14.20\LIB Release;%(AdditionalLibraryDirectories) - Console - MachineX86 - true - $(TargetDir)$(TargetName).pdb - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurl.lib;wolfssl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);..\..\..\..\..\wolfssl\build\Win64\VC14.20\LIB Release;%(AdditionalLibraryDirectories) - Console - MachineX64 - true - $(TargetDir)$(TargetName).pdb - - - - - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX86 - - - - - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurld.lib;wolfssl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);..\..\..\..\..\wolfssl\build\Win32\VC14.20\LIB Debug;%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX86 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX64 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurld.lib;wolfssl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);..\..\..\..\..\wolfssl\build\Win64\VC14.20\LIB Debug;%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX64 - - - - - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX86 - - - - - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX86 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX64 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX64 - - - - - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX86 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX64 - - - - - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX86 - - - - - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX86 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX64 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX64 - - - - - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX86 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX64 - - - - - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcurld.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win32\VC14.20\LIB Debug;%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX86 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcurld.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win64\VC14.20\LIB Debug;%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX64 - - - - - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcurl.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win32\VC14.20\LIB Release;%(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcurl.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win64\VC14.20\LIB Release;%(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcurld.lib;libcrypto.lib;libssl.lib;libssh2d.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win32\VC14.20\LIB Debug;..\..\..\..\..\libssh2\build\Win32\VC14.20\LIB Debug;%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX86 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcurld.lib;libcrypto.lib;libssl.lib;libssh2d.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win64\VC14.20\LIB Debug;..\..\..\..\..\libssh2\build\Win64\VC14.20\LIB Debug;%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX64 - - - - - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcurl.lib;libcrypto.lib;libssl.lib;libssh2.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win32\VC14.20\LIB Release;..\..\..\..\..\libssh2\build\Win32\VC14.20\LIB Release;%(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcurl.lib;libcrypto.lib;libssl.lib;libssh2.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win64\VC14.20\LIB Release;..\..\..\..\..\libssh2\build\Win64\VC14.20\LIB Release;%(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcurld.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win32\VC14.20\DLL Debug;%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX86 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcurld.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win64\VC14.20\DLL Debug;%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX64 - - - - - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcurl.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win32\VC14.20\DLL Release;%(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcurl.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win64\VC14.20\DLL Release;%(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcurld.lib;libcrypto.lib;libssl.lib;libssh2d.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win32\VC14.20\DLL Debug;..\..\..\..\..\libssh2\build\Win32\VC14.20\DLL Debug;%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX86 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcurld.lib;libcrypto.lib;libssl.lib;libssh2d.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win64\VC14.20\DLL Debug;..\..\..\..\..\libssh2\build\Win64\VC14.20\DLL Debug;%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX64 - - - - - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcurl.lib;libcrypto.lib;libssl.lib;libssh2.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win32\VC14.20\DLL Release;..\..\..\..\..\libssh2\build\Win32\VC14.20\DLL Release;%(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - crypt32.lib;ws2_32.lib;wldap32.lib;libcurl.lib;libssh2.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win64\VC14.20\DLL Release;..\..\..\..\..\libssh2\build\Win64\VC14.20\DLL Release;%(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;crypt32.lib;libcurld.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX86 - - - - - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;crypt32.lib;normaliz.lib;libcurld.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX86 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;crypt32.lib;libcurld.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX64 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - Disabled - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - _DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level4 - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;crypt32.lib;normaliz.lib;libcurld.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - true - $(TargetDir)$(TargetName).pdb - Console - MachineX64 - - - - - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;crypt32.lib;libcurl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;crypt32.lib;normaliz.lib;libcurl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - Console - MachineX86 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;crypt32.lib;libcurl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - Console - MachineX64 - - - - - X64 - $(TargetDir)$(TargetName).tlb - - - - - MaxSpeed - OnlyExplicitInline - ..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level4 - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - ..\..\..\..\include;%(AdditionalIncludeDirectories) - - - ws2_32.lib;wldap32.lib;crypt32.lib;normaliz.lib;libcurl.lib;%(AdditionalDependencies) - $(OutDir)$(TargetName)$(TargetExt) - ..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories) - Console - MachineX64 - - - -CURL_SRC_X_C_FILES -CURL_SRC_C_FILES - - -CURL_SRC_X_H_FILES -CURL_SRC_H_FILES - - -CURL_SRC_RC_FILES - - - - - \ No newline at end of file diff --git a/deps/curl/projects/Windows/VC14.20/src/curl.vcxproj.filters b/deps/curl/projects/Windows/VC14.20/src/curl.vcxproj.filters deleted file mode 100644 index 4d6341d7..00000000 --- a/deps/curl/projects/Windows/VC14.20/src/curl.vcxproj.filters +++ /dev/null @@ -1,17 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - \ No newline at end of file diff --git a/deps/curl/projects/Windows/VC14.30/src/curl.sln b/deps/curl/projects/Windows/VC14.30/src/curl.sln index 2c16858f..2af09591 100644 --- a/deps/curl/projects/Windows/VC14.30/src/curl.sln +++ b/deps/curl/projects/Windows/VC14.30/src/curl.sln @@ -1,5 +1,5 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 17 +# Visual Studio 15 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "curl", "curl.vcxproj", "{5228E9CE-A216-422F-A5E6-58E95E2DD71D}" EndProject Global diff --git a/deps/curl/projects/generate.bat b/deps/curl/projects/generate.bat index 7156a173..d57d4ebb 100644 --- a/deps/curl/projects/generate.bat +++ b/deps/curl/projects/generate.bat @@ -56,9 +56,7 @@ rem *************************************************************************** set VERSION=VC14 ) else if /i "%~1" == "vc14.10" ( set VERSION=VC14.10 - ) else if /i "%~1" == "vc14.20" ( - set VERSION=VC14.20 - )else if /i "%~1" == "vc14.30" ( + ) else if /i "%~1" == "vc14.30" ( set VERSION=VC14.30 ) else if /i "%~1" == "-clean" ( set MODE=CLEAN @@ -90,7 +88,6 @@ rem *************************************************************************** if "%VERSION%" == "VC12" goto vc12 if "%VERSION%" == "VC14" goto vc14 if "%VERSION%" == "VC14.10" goto vc14.10 - if "%VERSION%" == "VC14.20" goto vc14.20 if "%VERSION%" == "VC14.30" goto vc14.30 :vc10 @@ -167,21 +164,6 @@ rem *************************************************************************** ) if not "%VERSION%" == "ALL" goto success - -:vc14.20 - echo. - - if "%MODE%" == "GENERATE" ( - echo Generating VC14.20 project files - call :generate vcxproj Windows\VC14.20\src\curl.tmpl Windows\VC14.20\src\curl.vcxproj - call :generate vcxproj Windows\VC14.20\lib\libcurl.tmpl Windows\VC14.20\lib\libcurl.vcxproj - ) else ( - echo Removing VC14.20 project files - call :clean Windows\VC14.20\src\curl.vcxproj - call :clean Windows\VC14.20\lib\libcurl.vcxproj - ) - - if not "%VERSION%" == "ALL" goto success :vc14.30 echo. @@ -200,7 +182,7 @@ rem *************************************************************************** rem Main generate function. rem -rem %1 - Project Type (vcxproj for VC10, VC11, VC12, VC14, VC14.10, VC14.20 and VC14.30) +rem %1 - Project Type (vcxproj for VC10, VC11, VC12, VC14, VC14.10 and VC14.30) rem %2 - Input template file rem %3 - Output project file rem @@ -281,7 +263,7 @@ rem rem Generates a single file xml element. rem -rem %1 - Project Type (vcxproj for VC10, VC11, VC12, VC14, VC14.10, VC14.20 and VC14.30) +rem %1 - Project Type (vcxproj for VC10, VC11, VC12, VC14, VC14.10 and VC14.30) rem %2 - Directory (src, lib, lib\vauth, lib\vquic, lib\vssh, lib\vtls) rem %3 - Source filename rem %4 - Output project file @@ -377,7 +359,6 @@ rem echo vc12 - Use Visual Studio 2013 echo vc14 - Use Visual Studio 2015 echo vc14.10 - Use Visual Studio 2017 - echo vc14.20 - Use Visual Studio 2019 echo vc14.30 - Use Visual Studio 2022 echo. echo -clean - Removes the project files diff --git a/deps/curl/scripts/Makefile.am b/deps/curl/scripts/Makefile.am index 9d69cff9..fcb78eab 100644 --- a/deps/curl/scripts/Makefile.am +++ b/deps/curl/scripts/Makefile.am @@ -23,7 +23,7 @@ ########################################################################### EXTRA_DIST = updatemanpages.pl coverage.sh completion.pl firefox-db2pem.sh \ - checksrc.pl mk-ca-bundle.pl schemetable.c + checksrc.pl mk-ca-bundle.pl ZSH_FUNCTIONS_DIR = @ZSH_FUNCTIONS_DIR@ FISH_FUNCTIONS_DIR = @FISH_FUNCTIONS_DIR@ diff --git a/deps/curl/scripts/checksrc.pl b/deps/curl/scripts/checksrc.pl index 34664585..b85b56b4 100644 --- a/deps/curl/scripts/checksrc.pl +++ b/deps/curl/scripts/checksrc.pl @@ -59,7 +59,6 @@ my %warnings = ( 'ASTERISKSPACE' => 'pointer declared with space after asterisk', 'BADCOMMAND' => 'bad !checksrc! instruction', 'BANNEDFUNC' => 'a banned function was used', - 'BANNEDPREPROC' => 'a banned symbol was used on a preprocessor line', 'BRACEELSE' => '} else on the same line', 'BRACEPOS' => 'wrong position for an open brace', 'BRACEWHILE' => 'A single space between open brace and while', @@ -893,18 +892,6 @@ sub scanfile { "multiple spaces"); } preproc: - if($prep) { - # scan for use of banned symbols on a preprocessor line - if($l =~ /^(^|.*\W) - (WIN32) - (\W|$) - /x) { - checkwarn("BANNEDPREPROC", - $line, length($1), $file, $ol, - "use of $2 is banned from preprocessor lines" . - (($2 eq "WIN32") ? ", use _WIN32 instead" : "")); - } - } $line++; $prevp = $prep; $prevl = $ol if(!$prep); diff --git a/deps/curl/scripts/ciconfig.pl b/deps/curl/scripts/ciconfig.pl index e232e3e5..7c31f8e4 100644 --- a/deps/curl/scripts/ciconfig.pl +++ b/deps/curl/scripts/ciconfig.pl @@ -58,12 +58,7 @@ my %defaulton = ( 'threaded-resolver' => 1, 'pthreads' => 1, 'verbose' => 1, - 'basic-auth' => 1, - 'bearer-auth' => 1, - 'digest-auth' => 1, - 'kerberos-auth' => 1, - 'negotiate-auth' => 1, - 'aws' => 1, + 'crypto-auth' => 1, 'ntlm' => 1, 'ntlm-wb' => 1, 'tls-srp' => 1, diff --git a/deps/curl/scripts/cijobs.pl b/deps/curl/scripts/cijobs.pl index 4c047973..a73b3f5b 100644 --- a/deps/curl/scripts/cijobs.pl +++ b/deps/curl/scripts/cijobs.pl @@ -232,7 +232,7 @@ sub appveyor { while() { $line++; - if($_ =~ /^( - |install)/) { + if($_ =~ /^( - |install)/) { if($job{'image'}) { $job{'os'} = "windows"; submit(\%job); @@ -240,37 +240,37 @@ sub appveyor { } } $job{'line'} = $line; - if($_ =~ /^ APPVEYOR_BUILD_WORKER_IMAGE: \'(.*)\'/) { + if($_ =~ /^ APPVEYOR_BUILD_WORKER_IMAGE: \"(.*)\"/) { $job{'image'}= $1; } - elsif($_ =~ /^ BUILD_SYSTEM: (.*)/) { + elsif($_ =~ /^ BUILD_SYSTEM: (.*)/) { $job{'build'} = lc($1); } - elsif($_ =~ /^ PRJ_GEN: \'(.*)\'/) { + elsif($_ =~ /^ PRJ_GEN: \"(.*)\"/) { $job{'compiler'} = $1; } - elsif($_ =~ /^ PRJ_CFG: (.*)/) { + elsif($_ =~ /^ PRJ_CFG: (.*)/) { $job{'config'} = $1; } - elsif($_ =~ /^ OPENSSL: \'(.*)\'/) { + elsif($_ =~ /^ OPENSSL: (.*)/) { $job{'openssl'} = $1 eq "ON" ? "true": "false"; } - elsif($_ =~ /^ SCHANNEL: \'(.*)\'/) { + elsif($_ =~ /^ SCHANNEL: (.*)/) { $job{'schannel'} = $1 eq "ON" ? "true": "false"; } - elsif($_ =~ /^ ENABLE_UNICODE: \'(.*)\'/) { + elsif($_ =~ /^ ENABLE_UNICODE: (.*)/) { $job{'unicode'} = $1 eq "ON" ? "true": "false"; } - elsif($_ =~ /^ HTTP_ONLY: \'(.*)\'/) { + elsif($_ =~ /^ HTTP_ONLY: (.*)/) { $job{'http-only'} = $1 eq "ON" ? "true": "false"; } - elsif($_ =~ /^ TESTING: \'(.*)\'/) { + elsif($_ =~ /^ TESTING: (.*)/) { $job{'testing'} = $1 eq "ON" ? "true": "false"; } - elsif($_ =~ /^ SHARED: \'(.*)\'/) { + elsif($_ =~ /^ SHARED: (.*)/) { $job{'shared'} = $1 eq "ON" ? "true": "false"; } - elsif($_ =~ /^ TARGET: \'-A (.*)\'/) { + elsif($_ =~ /^ TARGET: \"-A (.*)\"/) { $job{'target'} = $1; } } diff --git a/deps/curl/scripts/cmp-config.pl b/deps/curl/scripts/cmp-config.pl index e36fcdd3..b1717cde 100644 --- a/deps/curl/scripts/cmp-config.pl +++ b/deps/curl/scripts/cmp-config.pl @@ -43,7 +43,6 @@ my %remove = ( '#define HAVE_DECL_GETPWUID_R 1' => 1, '#define HAVE_DLFCN_H 1' => 1, '#define HAVE_GETHOSTBYNAME 1' => 1, - '#define HAVE_INTTYPES_H 1' => 1, '#define HAVE_IOCTL 1' => 1, '#define HAVE_LDAP_SSL 1' => 1, '#define HAVE_LIBBROTLIDEC 1' => 1, @@ -58,7 +57,6 @@ my %remove = ( '#define HAVE_OPENSSL_X509_H 1' => 1, '#define HAVE_SA_FAMILY_T 1' => 1, '#define HAVE_SETJMP_H 1' => 1, - '#define HAVE_STDINT_H 1' => 1, '#define HAVE_STDIO_H 1' => 1, '#define HAVE_STDLIB_H 1' => 1, '#define HAVE_STRING_H 1' => 1, diff --git a/deps/curl/scripts/schemetable.c b/deps/curl/scripts/schemetable.c deleted file mode 100644 index ae79eaa0..00000000 --- a/deps/curl/scripts/schemetable.c +++ /dev/null @@ -1,207 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at https://curl.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - * SPDX-License-Identifier: curl - * - ***************************************************************************/ -#include -#include - -/* - * Use this tool to generate an updated table for the Curl_getn_scheme_handler - * function in url.c. - */ - -struct detail { - const char *n; - const char *ifdef; -}; - -static const struct detail scheme[] = { - {"dict", "#ifndef CURL_DISABLE_DICT" }, - {"file", "#ifndef CURL_DISABLE_FILE" }, - {"ftp", "#ifndef CURL_DISABLE_FTP" }, - {"ftps", "#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)" }, - {"gopher", "#ifndef CURL_DISABLE_GOPHER" }, - {"gophers", "#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER)" }, - {"http", "#ifndef CURL_DISABLE_HTTP" }, - {"https", "#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)" }, - {"imap", "#ifndef CURL_DISABLE_IMAP" }, - {"imaps", "#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP)" }, - {"ldap", "#ifndef CURL_DISABLE_LDAP" }, - {"ldaps", "#if !defined(CURL_DISABLE_LDAP) && \\\n" - " !defined(CURL_DISABLE_LDAPS) && \\\n" - " ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \\\n" - " (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))" }, - {"mqtt", "#ifndef CURL_DISABLE_MQTT" }, - {"pop3", "#ifndef CURL_DISABLE_POP3" }, - {"pop3s", "#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3)" }, - {"rtmp", "#ifdef USE_LIBRTMP" }, - {"rtmpt", "#ifdef USE_LIBRTMP" }, - {"rtmpe", "#ifdef USE_LIBRTMP" }, - {"rtmpte", "#ifdef USE_LIBRTMP" }, - {"rtmps", "#ifdef USE_LIBRTMP" }, - {"rtmpts", "#ifdef USE_LIBRTMP" }, - {"rtsp", "#ifndef CURL_DISABLE_RTSP" }, - {"scp", "#if defined(USE_SSH) && !defined(USE_WOLFSSH)" }, - {"sftp", "#if defined(USE_SSH)" }, - {"smb", "#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \\\n" - " (SIZEOF_CURL_OFF_T > 4)" }, - {"smbs", "#if defined(USE_SSL) && !defined(CURL_DISABLE_SMB) && \\\n" - " defined(USE_CURL_NTLM_CORE) && (SIZEOF_CURL_OFF_T > 4)" }, - {"smtp", "#ifndef CURL_DISABLE_SMTP" }, - {"smtps", "#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP)" }, - {"telnet", "#ifndef CURL_DISABLE_TELNET" }, - {"tftp", "#ifndef CURL_DISABLE_TFTP" }, - {"ws", "#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)" }, - {"wss", "#if defined(USE_WEBSOCKETS) && \\\n" - " defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)" }, - { NULL, NULL } -}; - -unsigned int calc(const char *s, int add, int shift) -{ - const char *so = s; - unsigned int c = add; - while(*s) { - c <<= shift; - c += *s; - s++; - } - return c; -} - -unsigned int num[100]; -unsigned int ix[100]; - -static void showtable(int try, int init, int shift) -{ - int nulls = 0; - int i; - for(i = 0; scheme[i].n; ++i) - num[i] = calc(scheme[i].n, init, shift); - for(i = 0; scheme[i].n; ++i) - ix[i] = num[i] % try; - printf("/*\n" - " unsigned int c = %d\n" - " while(l) {\n" - " c <<= %d;\n" - " c += Curl_raw_tolower(*s);\n" - " s++;\n" - " l--;\n" - " }\n" - "*/\n", init, shift); - - printf(" static const struct Curl_handler * const protocols[%d] = {", try); - - /* generate table */ - for(i=0; i < try; i++) { - int match = 0; - int j; - for(j=0; scheme[j].n; j++) { - if(ix[j] == i) { - printf("\n"); - printf("%s\n", scheme[j].ifdef); - printf(" &Curl_handler_%s,\n", scheme[j].n); - printf("#else\n NULL,\n"); - printf("#endif"); - match = 1; - nulls = 0; - break; - } - } - if(!match) { - if(!nulls || (nulls>10)) { - printf("\n "); - nulls = 0; - } - printf(" NULL,", nulls); - nulls++; - } - } - printf("\n };\n"); -} - -int main(void) -{ - int i; - int try; - int besttry = 9999; - int bestadd = 0; - int bestshift = 0; - int add; - int shift; - for(shift = 0; shift < 8; shift++) { - for(add = 0; add < 999; add++) { - for(i = 0; scheme[i].n; ++i) { - unsigned int v = calc(scheme[i].n, add, shift); - int j; - int badcombo = 0; - for(j=0; j < i; j++) { - - if(num[j] == v) { - /* - printf("NOPE: %u is a dupe (%s and %s)\n", - v, scheme[i], scheme[j]); - */ - badcombo = 1; - break; - } - } - if(badcombo) - break; - num[i] = v; - } -#if 0 - for(i = 0; scheme[i].n; ++i) { - printf("%u - %s\n", num[i], scheme[i].n); - } -#endif - /* try different remainders to find smallest possible table */ - for(try = 28; try < 199; try++) { - int good = 1; - for(i = 0; scheme[i].n; ++i) { - ix[i] = num[i] % try; - } - /* check for dupes */ - for(i = 0; scheme[i].n && good; ++i) { - int j; - for(j=0; j < i; j++) { - if(ix[j] == ix[i]) { - /* printf("NOPE, try %u causes dupes (%d and %d)\n", try, j, i); */ - good = 0; - break; - } - } - } - if(good) { - if(try < besttry) { - besttry = try; - bestadd = add; - bestshift = shift; - } - break; - } - } - } - } - - showtable(besttry, bestadd, bestshift); -} diff --git a/deps/curl/src/Makefile.am b/deps/curl/src/Makefile.am index dced53e0..ddeb7007 100644 --- a/deps/curl/src/Makefile.am +++ b/deps/curl/src/Makefile.am @@ -61,8 +61,6 @@ curl_SOURCES += $(CURL_RCFILES) $(CURL_RCFILES): tool_version.h endif -curl_LDFLAGS = $(AM_LDFLAGS) $(CURL_LDFLAGS_BIN) - # This might hold -Werror CFLAGS += @CURL_CFLAG_EXTRAS@ @@ -91,7 +89,7 @@ CLEANFILES = tool_hugehelp.c NROFF=env LC_ALL=C @NROFF@ @MANOPT@ 2>/dev/null # figured out by the configure script EXTRA_DIST = mkhelp.pl \ - Makefile.mk curl.rc Makefile.inc CMakeLists.txt .checksrc + Makefile.mk curl.rc Makefile.inc CMakeLists.txt # Use absolute directory to disable VPATH MANPAGE=$(abs_top_builddir)/docs/curl.1 diff --git a/deps/curl/src/Makefile.inc b/deps/curl/src/Makefile.inc index c1d202a0..25389353 100644 --- a/deps/curl/src/Makefile.inc +++ b/deps/curl/src/Makefile.inc @@ -79,7 +79,6 @@ CURL_CFILES = \ tool_help.c \ tool_helpers.c \ tool_hugehelp.c \ - tool_ipfs.c \ tool_libinfo.c \ tool_listhelp.c \ tool_main.c \ @@ -123,7 +122,6 @@ CURL_HFILES = \ tool_help.h \ tool_helpers.h \ tool_hugehelp.h \ - tool_ipfs.h \ tool_libinfo.h \ tool_main.h \ tool_msgs.h \ diff --git a/deps/curl/src/curl.rc b/deps/curl/src/curl.rc index 6fcaf353..11d52842 100644 --- a/deps/curl/src/curl.rc +++ b/deps/curl/src/curl.rc @@ -53,7 +53,7 @@ BEGIN VALUE "OriginalFilename", "curl.exe\0" VALUE "ProductName", "The curl executable\0" VALUE "ProductVersion", CURL_VERSION "\0" - VALUE "LegalCopyright", "Copyright (C) " CURL_COPYRIGHT "\0" + VALUE "LegalCopyright", "\xa9 " CURL_COPYRIGHT "\0" /* a9: Copyright symbol */ VALUE "License", "https://curl.se/docs/copyright.html\0" END END diff --git a/deps/curl/src/tool_cb_hdr.c b/deps/curl/src/tool_cb_hdr.c index 198a8d05..df44f7aa 100644 --- a/deps/curl/src/tool_cb_hdr.c +++ b/deps/curl/src/tool_cb_hdr.c @@ -41,9 +41,9 @@ static char *parse_filename(const char *ptr, size_t len); -#ifdef _WIN32 -#define BOLD "\x1b[1m" -#define BOLDOFF "\x1b[22m" +#ifdef WIN32 +#define BOLD +#define BOLDOFF #else #define BOLD "\x1b[1m" /* Switch off bold by setting "all attributes off" since the explicit @@ -87,7 +87,7 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) } #endif -#ifdef _WIN32 +#ifdef WIN32 /* Discard incomplete UTF-8 sequence buffered from body */ if(outs->utf8seq[0]) memset(outs->utf8seq, 0, sizeof(outs->utf8seq)); @@ -150,19 +150,16 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) char *filename; size_t len; - while((p < end) && *p && !ISALPHA(*p)) + while(*p && (p < end) && !ISALPHA(*p)) p++; if(p > end - 9) break; if(memcmp(p, "filename=", 9)) { /* no match, find next parameter */ - while((p < end) && *p && (*p != ';')) + while((p < end) && (*p != ';')) p++; - if((p < end) && *p) - continue; - else - break; + continue; } p += 9; @@ -212,11 +209,7 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) if(!outs->stream && !tool_create_output_file(outs, per->config)) return CURL_WRITEFUNC_ERROR; - if(hdrcbdata->global->isatty && -#ifdef _WIN32 - tool_term_has_bold && -#endif - hdrcbdata->global->styled_output) + if(hdrcbdata->global->isatty && hdrcbdata->global->styled_output) value = memchr(ptr, ':', cb); if(value) { size_t namelen = value - ptr; @@ -304,7 +297,7 @@ static char *parse_filename(const char *ptr, size_t len) if(copy != p) memmove(copy, p, strlen(p) + 1); -#if defined(_WIN32) || defined(MSDOS) +#if defined(MSDOS) || defined(WIN32) { char *sanitized; SANITIZEcode sc = sanitize_file_name(&sanitized, copy, 0); @@ -313,7 +306,7 @@ static char *parse_filename(const char *ptr, size_t len) return NULL; copy = sanitized; } -#endif /* _WIN32 || MSDOS */ +#endif /* MSDOS || WIN32 */ /* in case we built debug enabled, we allow an environment variable * named CURL_TESTDIR to prefix the given file name to put it into a diff --git a/deps/curl/src/tool_cb_prg.c b/deps/curl/src/tool_cb_prg.c index ef47b42d..47ec3ef3 100644 --- a/deps/curl/src/tool_cb_prg.c +++ b/deps/curl/src/tool_cb_prg.c @@ -38,8 +38,6 @@ #include "memdebug.h" /* keep this as LAST include */ -#define MAX_BARLENGTH 256 - #ifdef HAVE_TERMIOS_H # include #elif defined(HAVE_TERMIO_H) @@ -80,16 +78,11 @@ static const unsigned int sinus[] = { static void fly(struct ProgressData *bar, bool moved) { - char buf[MAX_BARLENGTH + 2]; + char buf[256]; int pos; int check = bar->width - 2; - /* bar->width is range checked when assigned */ - DEBUGASSERT(bar->width <= MAX_BARLENGTH); - memset(buf, ' ', bar->width); - buf[bar->width] = '\r'; - buf[bar->width + 1] = '\0'; - + msnprintf(buf, sizeof(buf), "%*s\r", bar->width-1, " "); memcpy(&buf[bar->bar], "-=O=-", 5); pos = sinus[bar->tick%200] / (1000000 / check); @@ -121,6 +114,8 @@ static void fly(struct ProgressData *bar, bool moved) ** callback for CURLOPT_XFERINFOFUNCTION */ +#define MAX_BARLENGTH 256 + #if (SIZEOF_CURL_OFF_T < 8) #error "too small curl_off_t" #else @@ -254,7 +249,7 @@ void progressbarinit(struct ProgressData *bar, struct winsize ts; if(!ioctl(STDIN_FILENO, TIOCGWINSZ, &ts)) cols = ts.ws_col; -#elif defined(_WIN32) +#elif defined(WIN32) { HANDLE stderr_hnd = GetStdHandle(STD_ERROR_HANDLE); CONSOLE_SCREEN_BUFFER_INFO console_info; diff --git a/deps/curl/src/tool_cb_rea.c b/deps/curl/src/tool_cb_rea.c index 8cb5bbe8..d70a9b90 100644 --- a/deps/curl/src/tool_cb_rea.c +++ b/deps/curl/src/tool_cb_rea.c @@ -62,7 +62,7 @@ size_t tool_read_cb(char *buffer, size_t sz, size_t nmemb, void *userdata) if(msdelta > config->timeout_ms) /* timeout */ return 0; -#ifndef _WIN32 +#ifndef WIN32 /* this logic waits on read activity on a file descriptor that is not a socket which makes it not work with select() on Windows */ else { diff --git a/deps/curl/src/tool_cb_see.c b/deps/curl/src/tool_cb_see.c index bce57bb2..8351473c 100644 --- a/deps/curl/src/tool_cb_see.c +++ b/deps/curl/src/tool_cb_see.c @@ -93,6 +93,21 @@ int tool_seek_cb(void *userdata, curl_off_t offset, int whence) #ifdef USE_TOOL_FTRUNCATE +#ifdef __BORLANDC__ +/* 64-bit lseek-like function unavailable */ +# define _lseeki64(hnd,ofs,whence) lseek(hnd,ofs,whence) +#endif + +#ifdef __POCC__ +# if(__POCC__ < 450) +/* 64-bit lseek-like function unavailable */ +# define _lseeki64(hnd,ofs,whence) _lseek(hnd,ofs,whence) +# else +# undef _lseeki64 +# define _lseeki64(hnd,ofs,whence) _lseek64(hnd,ofs,whence) +# endif +#endif + #ifdef _WIN32_WCE /* 64-bit lseek-like function unavailable */ # undef _lseeki64 diff --git a/deps/curl/src/tool_cb_see.h b/deps/curl/src/tool_cb_see.h index b5d7bf98..14bbc426 100644 --- a/deps/curl/src/tool_cb_see.h +++ b/deps/curl/src/tool_cb_see.h @@ -25,7 +25,7 @@ ***************************************************************************/ #include "tool_setup.h" -#if defined(_WIN32) && !defined(HAVE_FTRUNCATE) +#if defined(WIN32) && !defined(HAVE_FTRUNCATE) int tool_ftruncate64(int fd, curl_off_t where); @@ -35,7 +35,7 @@ int tool_ftruncate64(int fd, curl_off_t where); #define HAVE_FTRUNCATE 1 #define USE_TOOL_FTRUNCATE 1 -#endif /* _WIN32 && ! HAVE_FTRUNCATE */ +#endif /* WIN32 && ! HAVE_FTRUNCATE */ /* ** callback for CURLOPT_SEEKFUNCTION diff --git a/deps/curl/src/tool_cb_wrt.c b/deps/curl/src/tool_cb_wrt.c index 98063c39..b7838664 100644 --- a/deps/curl/src/tool_cb_wrt.c +++ b/deps/curl/src/tool_cb_wrt.c @@ -44,7 +44,7 @@ #ifndef O_BINARY #define O_BINARY 0 #endif -#ifdef _WIN32 +#ifdef WIN32 #define OPENMODE S_IREAD | S_IWRITE #else #define OPENMODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH @@ -159,7 +159,7 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata) struct OperationConfig *config = per->config; size_t bytes = sz * nmemb; bool is_tty = config->global->isatty; -#ifdef _WIN32 +#ifdef WIN32 CONSOLE_SCREEN_BUFFER_INFO console_info; intptr_t fhnd; #endif @@ -231,13 +231,13 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata) } } -#ifdef _WIN32 +#ifdef WIN32 fhnd = _get_osfhandle(fileno(outs->stream)); /* if windows console then UTF-8 must be converted to UTF-16 */ if(isatty(fileno(outs->stream)) && GetConsoleScreenBufferInfo((HANDLE)fhnd, &console_info)) { wchar_t *wc_buf; - DWORD wc_len, chars_written; + DWORD wc_len; unsigned char *rbuf = (unsigned char *)buffer; DWORD rlen = (DWORD)bytes; @@ -292,7 +292,7 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata) (HANDLE) fhnd, prefix, prefix[1] ? 2 : 1, - &chars_written, + NULL, NULL)) { return CURL_WRITEFUNC_ERROR; } @@ -351,7 +351,7 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata) (HANDLE) fhnd, wc_buf, wc_len, - &chars_written, + NULL, NULL)) { free(wc_buf); return CURL_WRITEFUNC_ERROR; diff --git a/deps/curl/src/tool_dirhie.c b/deps/curl/src/tool_dirhie.c index 1cadbd0b..16765c3a 100644 --- a/deps/curl/src/tool_dirhie.c +++ b/deps/curl/src/tool_dirhie.c @@ -25,7 +25,7 @@ #include -#ifdef _WIN32 +#ifdef WIN32 # include #endif @@ -38,7 +38,7 @@ #include "memdebug.h" /* keep this as LAST include */ -#if defined(_WIN32) || (defined(MSDOS) && !defined(__DJGPP__)) +#if defined(WIN32) || (defined(MSDOS) && !defined(__DJGPP__)) # define mkdir(x,y) (mkdir)((x)) # ifndef F_OK # define F_OK 0 @@ -88,7 +88,7 @@ static void show_dir_errno(struct GlobalConfig *global, const char *name) * should create all the dir* automagically */ -#if defined(_WIN32) || defined(__DJGPP__) +#if defined(WIN32) || defined(__DJGPP__) /* systems that may use either or when specifying a path */ #define PATH_DELIMITERS "\\/" #else @@ -132,7 +132,7 @@ CURLcode create_dir_hierarchy(const char *outfile, struct GlobalConfig *global) msnprintf(&dirbuildup[dlen], outlen - dlen, "%s%s", DIR_CHAR, tempdir); else { if(outdup == tempdir) { -#if defined(_WIN32) || defined(MSDOS) +#if defined(MSDOS) || defined(WIN32) /* Skip creating a drive's current directory. It may seem as though that would harmlessly fail but it could be a corner case if X: did not exist, since we would be creating it diff --git a/deps/curl/src/tool_doswin.c b/deps/curl/src/tool_doswin.c index db2b8b78..faa5755e 100644 --- a/deps/curl/src/tool_doswin.c +++ b/deps/curl/src/tool_doswin.c @@ -23,13 +23,13 @@ ***************************************************************************/ #include "tool_setup.h" -#if defined(_WIN32) || defined(MSDOS) +#if defined(MSDOS) || defined(WIN32) #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME) # include #endif -#ifdef _WIN32 +#ifdef WIN32 # include # include # include "tool_cfgable.h" @@ -42,7 +42,7 @@ #include "curlx.h" #include "memdebug.h" /* keep this as LAST include */ -#ifdef _WIN32 +#ifdef WIN32 # undef PATH_MAX # define PATH_MAX MAX_PATH #endif @@ -55,7 +55,7 @@ # endif #endif -#ifdef _WIN32 +#ifdef WIN32 # define _use_lfn(f) (1) /* long file names always available */ #elif !defined(__DJGPP__) || (__DJGPP__ < 2) /* DJGPP 2.0 has _use_lfn() */ # define _use_lfn(f) (0) /* long file names never available */ @@ -597,7 +597,7 @@ char **__crt0_glob_function(char *arg) #endif /* MSDOS && (__DJGPP__ || __GO32__) */ -#ifdef _WIN32 +#ifdef WIN32 /* * Function to find CACert bundle on a Win32 platform using SearchPath. @@ -714,8 +714,6 @@ static struct TerminalSettings { #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 #endif -bool tool_term_has_bold; - static void restore_terminal(void) { if(InterlockedExchange(&TerminalSettings.valid, (LONG)FALSE)) @@ -735,23 +733,16 @@ static BOOL WINAPI signal_handler(DWORD type) static void init_terminal(void) { TerminalSettings.hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); - /* * Enable VT (Virtual Terminal) output. * Note: VT mode flag can be set on any version of Windows, but VT - * processing only performed on Win10 >= version 1709 (OS build 16299) - * Creator's Update. Also, ANSI bold on/off supported since then. + * processing only performed on Win10 >= Creators Update) */ - if(TerminalSettings.hStdOut == INVALID_HANDLE_VALUE || - !GetConsoleMode(TerminalSettings.hStdOut, - &TerminalSettings.dwOutputMode) || - !curlx_verify_windows_version(10, 0, 16299, PLATFORM_WINNT, - VERSION_GREATER_THAN_EQUAL)) - return; - - if((TerminalSettings.dwOutputMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING)) - tool_term_has_bold = true; - else { + if((TerminalSettings.hStdOut != INVALID_HANDLE_VALUE) && + GetConsoleMode(TerminalSettings.hStdOut, + &TerminalSettings.dwOutputMode) && + !(TerminalSettings.dwOutputMode & + ENABLE_VIRTUAL_TERMINAL_PROCESSING)) { /* The signal handler is set before attempting to change the console mode because otherwise a signal would not be caught after the change but before the handler was installed. */ @@ -760,7 +751,6 @@ static void init_terminal(void) if(SetConsoleMode(TerminalSettings.hStdOut, (TerminalSettings.dwOutputMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING))) { - tool_term_has_bold = true; atexit(restore_terminal); } else { @@ -791,6 +781,6 @@ CURLcode win32_init(void) return CURLE_OK; } -#endif /* _WIN32 */ +#endif /* WIN32 */ -#endif /* _WIN32 || MSDOS */ +#endif /* MSDOS || WIN32 */ diff --git a/deps/curl/src/tool_doswin.h b/deps/curl/src/tool_doswin.h index e07d89d9..669fdb6e 100644 --- a/deps/curl/src/tool_doswin.h +++ b/deps/curl/src/tool_doswin.h @@ -25,7 +25,7 @@ ***************************************************************************/ #include "tool_setup.h" -#if defined(_WIN32) || defined(MSDOS) +#if defined(MSDOS) || defined(WIN32) #define SANITIZE_ALLOW_COLONS (1<<0) /* Allow colons */ #define SANITIZE_ALLOW_PATH (1<<1) /* Allow path separators and colons */ @@ -57,7 +57,7 @@ char **__crt0_glob_function(char *arg); #endif /* MSDOS && (__DJGPP__ || __GO32__) */ -#ifdef _WIN32 +#ifdef WIN32 CURLcode FindWin32CACert(struct OperationConfig *config, curl_sslbackend backend, @@ -65,8 +65,8 @@ CURLcode FindWin32CACert(struct OperationConfig *config, struct curl_slist *GetLoadedModulePaths(void); CURLcode win32_init(void); -#endif /* _WIN32 */ +#endif /* WIN32 */ -#endif /* _WIN32 || MSDOS */ +#endif /* MSDOS || WIN32 */ #endif /* HEADER_CURL_TOOL_DOSWIN_H */ diff --git a/deps/curl/src/tool_filetime.c b/deps/curl/src/tool_filetime.c index 13113886..9c2e8042 100644 --- a/deps/curl/src/tool_filetime.c +++ b/deps/curl/src/tool_filetime.c @@ -41,7 +41,7 @@ int getfiletime(const char *filename, struct GlobalConfig *global, /* Windows stat() may attempt to adjust the unix GMT file time by a daylight saving time offset and since it's GMT that is bad behavior. When we have access to a 64-bit type we can bypass stat and get the times directly. */ -#if defined(_WIN32) +#if defined(WIN32) HANDLE hfile; TCHAR *tchar_filename = curlx_convert_UTF8_to_tchar((char *)filename); @@ -87,7 +87,7 @@ int getfiletime(const char *filename, struct GlobalConfig *global, return rc; } -#if defined(HAVE_UTIME) || defined(HAVE_UTIMES) || defined(_WIN32) +#if defined(HAVE_UTIME) || defined(HAVE_UTIMES) || defined(WIN32) void setfiletime(curl_off_t filetime, const char *filename, struct GlobalConfig *global) { @@ -95,7 +95,7 @@ void setfiletime(curl_off_t filetime, const char *filename, /* Windows utime() may attempt to adjust the unix GMT file time by a daylight saving time offset and since it's GMT that is bad behavior. When we have access to a 64-bit type we can bypass utime and set the times directly. */ -#if defined(_WIN32) +#if defined(WIN32) HANDLE hfile; TCHAR *tchar_filename = curlx_convert_UTF8_to_tchar((char *)filename); @@ -153,4 +153,4 @@ void setfiletime(curl_off_t filetime, const char *filename, } } #endif /* defined(HAVE_UTIME) || defined(HAVE_UTIMES) || \ - defined(_WIN32) */ + defined(WIN32) */ diff --git a/deps/curl/src/tool_filetime.h b/deps/curl/src/tool_filetime.h index 205e5cee..908b2d72 100644 --- a/deps/curl/src/tool_filetime.h +++ b/deps/curl/src/tool_filetime.h @@ -31,12 +31,12 @@ int getfiletime(const char *filename, struct GlobalConfig *global, curl_off_t *stamp); #if defined(HAVE_UTIME) || defined(HAVE_UTIMES) || \ - (defined(_WIN32) && (SIZEOF_CURL_OFF_T >= 8)) + (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) void setfiletime(curl_off_t filetime, const char *filename, struct GlobalConfig *global); #else #define setfiletime(a,b,c) Curl_nop_stmt #endif /* defined(HAVE_UTIME) || defined(HAVE_UTIMES) || \ - (defined(_WIN32) && (SIZEOF_CURL_OFF_T >= 8)) */ + (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) */ #endif /* HEADER_CURL_TOOL_FILETIME_H */ diff --git a/deps/curl/src/tool_findfile.c b/deps/curl/src/tool_findfile.c index a1544a56..201d8f0a 100644 --- a/deps/curl/src/tool_findfile.c +++ b/deps/curl/src/tool_findfile.c @@ -53,7 +53,7 @@ static const struct finder conf_list[] = { { "CURL_HOME", NULL, FALSE }, { "XDG_CONFIG_HOME", NULL, FALSE }, /* index == 1, used in the code */ { "HOME", NULL, FALSE }, -#ifdef _WIN32 +#ifdef WIN32 { "USERPROFILE", NULL, FALSE }, { "APPDATA", NULL, FALSE }, { "USERPROFILE", "\\Application Data", FALSE}, diff --git a/deps/curl/src/tool_findfile.h b/deps/curl/src/tool_findfile.h index 63d25195..faafd71c 100644 --- a/deps/curl/src/tool_findfile.h +++ b/deps/curl/src/tool_findfile.h @@ -25,7 +25,7 @@ ***************************************************************************/ #include "tool_setup.h" -#ifdef _WIN32 +#ifdef WIN32 #define CURLRC_DOTSCORE 2 /* look for underscore-prefixed name too */ #else #define CURLRC_DOTSCORE 1 /* regular .curlrc check */ diff --git a/deps/curl/src/tool_getparam.c b/deps/curl/src/tool_getparam.c index 5fa1ace1..d9772a30 100644 --- a/deps/curl/src/tool_getparam.c +++ b/deps/curl/src/tool_getparam.c @@ -437,7 +437,7 @@ void parse_cert_parameter(const char *cert_parameter, needs to work. In order not to break compatibility, we still use : as separator, but we try to detect when it is used for a file name! On windows. */ -#ifdef _WIN32 +#ifdef WIN32 if((param_place == &cert_parameter[1]) && (cert_parameter[2] == '\\' || cert_parameter[2] == '/') && (ISALPHA(cert_parameter[0])) ) { @@ -1043,12 +1043,6 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ break; } } - - if(denominator > numerator) { - err = PARAM_NUMBER_TOO_LARGE; - break; - } - global->ms_per_transfer = numerator/denominator; } break; diff --git a/deps/curl/src/tool_getpass.c b/deps/curl/src/tool_getpass.c index 8ccccdfb..f5aa98c6 100644 --- a/deps/curl/src/tool_getpass.c +++ b/deps/curl/src/tool_getpass.c @@ -46,7 +46,7 @@ # include iodef #endif -#ifdef _WIN32 +#ifdef WIN32 # include #endif @@ -94,7 +94,7 @@ char *getpass_r(const char *prompt, char *buffer, size_t buflen) #define DONE #endif /* __VMS */ -#if defined(_WIN32) +#if defined(WIN32) char *getpass_r(const char *prompt, char *buffer, size_t buflen) { @@ -122,7 +122,7 @@ char *getpass_r(const char *prompt, char *buffer, size_t buflen) return buffer; /* we always return success */ } #define DONE -#endif /* _WIN32 */ +#endif /* WIN32 */ #ifndef DONE /* not previously provided */ diff --git a/deps/curl/src/tool_help.c b/deps/curl/src/tool_help.c index c8aea295..8983a4ca 100644 --- a/deps/curl/src/tool_help.c +++ b/deps/curl/src/tool_help.c @@ -73,6 +73,8 @@ static const struct category_descriptors categories[] = { {NULL, NULL, CURLHELP_HIDDEN} }; +extern const struct helptxt helptext[]; + static void print_category(curlhelp_t category) { diff --git a/deps/curl/src/tool_ipfs.c b/deps/curl/src/tool_ipfs.c deleted file mode 100644 index 435d1697..00000000 --- a/deps/curl/src/tool_ipfs.c +++ /dev/null @@ -1,296 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at https://curl.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - * SPDX-License-Identifier: curl - * - ***************************************************************************/ -#include "tool_setup.h" - -#define ENABLE_CURLX_PRINTF -/* use our own printf() functions */ -#include "curlx.h" -#include "dynbuf.h" - -#include "tool_cfgable.h" -#include "tool_msgs.h" -#include "tool_ipfs.h" - -#include "memdebug.h" /* keep this as LAST include */ - -/* ensure input ends in slash */ -static CURLcode ensure_trailing_slash(char **input) -{ - if(*input && **input) { - size_t len = strlen(*input); - if(((*input)[len - 1] != '/')) { - struct curlx_dynbuf dyn; - curlx_dyn_init(&dyn, len + 2); - - if(curlx_dyn_addn(&dyn, *input, len)) { - Curl_safefree(*input); - return CURLE_OUT_OF_MEMORY; - } - - Curl_safefree(*input); - - if(curlx_dyn_addn(&dyn, "/", 1)) - return CURLE_OUT_OF_MEMORY; - - *input = curlx_dyn_ptr(&dyn); - } - } - - return CURLE_OK; -} - -static char *ipfs_gateway(void) -{ - char *ipfs_path = NULL; - char *gateway_composed_file_path = NULL; - FILE *gateway_file = NULL; - char *gateway = curlx_getenv("IPFS_GATEWAY"); - - /* Gateway is found from environment variable. */ - if(gateway) { - if(ensure_trailing_slash(&gateway)) - goto fail; - return gateway; - } - - /* Try to find the gateway in the IPFS data folder. */ - ipfs_path = curlx_getenv("IPFS_PATH"); - - if(!ipfs_path) { - char *home = curlx_getenv("HOME"); - if(home && *home) - ipfs_path = aprintf("%s/.ipfs/", home); - /* fallback to "~/.ipfs", as that's the default location. */ - - Curl_safefree(home); - } - - if(!ipfs_path || ensure_trailing_slash(&ipfs_path)) - goto fail; - - gateway_composed_file_path = aprintf("%sgateway", ipfs_path); - - if(!gateway_composed_file_path) - goto fail; - - gateway_file = fopen(gateway_composed_file_path, FOPEN_READTEXT); - Curl_safefree(gateway_composed_file_path); - - if(gateway_file) { - int c; - struct curlx_dynbuf dyn; - curlx_dyn_init(&dyn, MAX_GATEWAY_URL_LEN); - - /* get the first line of the gateway file, ignore the rest */ - while((c = getc(gateway_file)) != EOF && c != '\n' && c != '\r') { - char c_char = (char)c; - if(curlx_dyn_addn(&dyn, &c_char, 1)) - goto fail; - } - - fclose(gateway_file); - gateway_file = NULL; - - if(curlx_dyn_len(&dyn)) - gateway = curlx_dyn_ptr(&dyn); - - if(gateway) - ensure_trailing_slash(&gateway); - - if(!gateway) - goto fail; - - Curl_safefree(ipfs_path); - - return gateway; - } -fail: - if(gateway_file) - fclose(gateway_file); - Curl_safefree(gateway); - Curl_safefree(ipfs_path); - return NULL; -} - -/* - * Rewrite ipfs:// and ipns:// to a HTTP(S) - * URL that can be handled by an IPFS gateway. - */ -CURLcode ipfs_url_rewrite(CURLU *uh, const char *protocol, char **url, - struct OperationConfig *config) -{ - CURLcode result = CURLE_URL_MALFORMAT; - CURLUcode getResult; - char *gateway = NULL; - char *gwhost = NULL; - char *gwpath = NULL; - char *gwquery = NULL; - char *gwscheme = NULL; - char *gwport = NULL; - char *inputpath = NULL; - char *cid = NULL; - char *pathbuffer = NULL; - char *cloneurl; - CURLU *gatewayurl = curl_url(); - - if(!gatewayurl) { - result = CURLE_FAILED_INIT; - goto clean; - } - - getResult = curl_url_get(uh, CURLUPART_HOST, &cid, CURLU_URLDECODE); - if(getResult || !cid) - goto clean; - - /* We might have a --ipfs-gateway argument. Check it first and use it. Error - * if we do have something but if it's an invalid url. - */ - if(config->ipfs_gateway) { - /* ensure the gateway ends in a trailing / */ - if(ensure_trailing_slash(&config->ipfs_gateway) != CURLE_OK) { - result = CURLE_OUT_OF_MEMORY; - goto clean; - } - - if(!curl_url_set(gatewayurl, CURLUPART_URL, config->ipfs_gateway, - CURLU_GUESS_SCHEME)) { - gateway = strdup(config->ipfs_gateway); - if(!gateway) { - result = CURLE_URL_MALFORMAT; - goto clean; - } - - } - else { - result = CURLE_BAD_FUNCTION_ARGUMENT; - goto clean; - } - } - else { - /* this is ensured to end in a trailing / within ipfs_gateway() */ - gateway = ipfs_gateway(); - if(!gateway) { - result = CURLE_FILE_COULDNT_READ_FILE; - goto clean; - } - - if(curl_url_set(gatewayurl, CURLUPART_URL, gateway, 0)) { - result = CURLE_URL_MALFORMAT; - goto clean; - } - } - - /* check for unsupported gateway parts */ - if(curl_url_get(gatewayurl, CURLUPART_QUERY, &gwquery, 0) - != CURLUE_NO_QUERY) { - result = CURLE_URL_MALFORMAT; - goto clean; - } - - /* get gateway parts */ - if(curl_url_get(gatewayurl, CURLUPART_HOST, - &gwhost, CURLU_URLDECODE)) { - goto clean; - } - - if(curl_url_get(gatewayurl, CURLUPART_SCHEME, - &gwscheme, CURLU_URLDECODE)) { - goto clean; - } - - curl_url_get(gatewayurl, CURLUPART_PORT, &gwport, CURLU_URLDECODE); - curl_url_get(gatewayurl, CURLUPART_PATH, &gwpath, CURLU_URLDECODE); - - /* get the path from user input */ - curl_url_get(uh, CURLUPART_PATH, &inputpath, CURLU_URLDECODE); - /* inputpath might be NULL or a valid pointer now */ - - /* set gateway parts in input url */ - if(curl_url_set(uh, CURLUPART_SCHEME, gwscheme, CURLU_URLENCODE) || - curl_url_set(uh, CURLUPART_HOST, gwhost, CURLU_URLENCODE) || - curl_url_set(uh, CURLUPART_PORT, gwport, CURLU_URLENCODE)) - goto clean; - - /* if the input path is just a slash, clear it */ - if(inputpath && (inputpath[0] == '/') && !inputpath[1]) - *inputpath = '\0'; - - /* ensure the gateway path ends with a trailing slash */ - ensure_trailing_slash(&gwpath); - - pathbuffer = aprintf("%s%s/%s%s", gwpath, protocol, cid, - inputpath ? inputpath : ""); - if(!pathbuffer) { - goto clean; - } - - if(curl_url_set(uh, CURLUPART_PATH, pathbuffer, CURLU_URLENCODE)) { - goto clean; - } - - /* Free whatever it has now, rewriting is next */ - Curl_safefree(*url); - - if(curl_url_get(uh, CURLUPART_URL, &cloneurl, CURLU_URLENCODE)) { - goto clean; - } - /* we need to strdup the URL so that we can call free() on it later */ - *url = strdup(cloneurl); - curl_free(cloneurl); - if(!*url) - goto clean; - - result = CURLE_OK; - -clean: - free(gateway); - curl_free(gwhost); - curl_free(gwpath); - curl_free(gwquery); - curl_free(inputpath); - curl_free(gwscheme); - curl_free(gwport); - curl_free(cid); - curl_free(pathbuffer); - curl_url_cleanup(gatewayurl); - { - const char *msg = NULL; - switch(result) { - case CURLE_URL_MALFORMAT: - msg = "malformed target URL"; - break; - case CURLE_FILE_COULDNT_READ_FILE: - msg = "IPFS automatic gateway detection failed"; - break; - case CURLE_BAD_FUNCTION_ARGUMENT: - msg = "--ipfs-gateway was given a malformed URL"; - break; - default: - break; - } - if(msg) - helpf(tool_stderr, msg); - } - return result; -} diff --git a/deps/curl/src/tool_main.c b/deps/curl/src/tool_main.c index 446806ec..2f132e2d 100644 --- a/deps/curl/src/tool_main.c +++ b/deps/curl/src/tool_main.c @@ -25,7 +25,7 @@ #include -#ifdef _WIN32 +#ifdef WIN32 #include #endif @@ -220,7 +220,6 @@ static void main_free(struct GlobalConfig *config) #ifdef _UNICODE #if defined(__GNUC__) /* GCC doesn't know about wmain() */ -#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-prototypes" #pragma GCC diagnostic ignored "-Wmissing-declarations" #endif @@ -235,7 +234,7 @@ int main(int argc, char *argv[]) tool_init_stderr(); -#ifdef _WIN32 +#ifdef WIN32 /* Undocumented diagnostic option to list the full paths of all loaded modules. This is purposely pre-init. */ if(argc == 2 && !_tcscmp(argv[1], _T("--dump-module-paths"))) { @@ -276,7 +275,7 @@ int main(int argc, char *argv[]) main_free(&global); } -#ifdef _WIN32 +#ifdef WIN32 /* Flush buffers of all streams opened in write or update mode */ fflush(NULL); #endif @@ -288,10 +287,4 @@ int main(int argc, char *argv[]) #endif } -#ifdef _UNICODE -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif -#endif - #endif /* ndef UNITTESTS */ diff --git a/deps/curl/src/tool_operate.c b/deps/curl/src/tool_operate.c index c805b773..4991186e 100644 --- a/deps/curl/src/tool_operate.c +++ b/deps/curl/src/tool_operate.c @@ -81,7 +81,6 @@ #include "tool_help.h" #include "tool_hugehelp.h" #include "tool_progress.h" -#include "tool_ipfs.h" #include "dynbuf.h" #include "memdebug.h" /* keep this as LAST include */ @@ -211,7 +210,7 @@ static curl_off_t all_pers; static CURLcode add_per_transfer(struct per_transfer **per) { struct per_transfer *p; - p = calloc(1, sizeof(struct per_transfer)); + p = calloc(sizeof(struct per_transfer), 1); if(!p) return CURLE_OUT_OF_MEMORY; if(!transfers) @@ -463,7 +462,7 @@ static CURLcode post_per_transfer(struct GlobalConfig *global, } } -#ifdef _WIN32 +#ifdef WIN32 /* Discard incomplete UTF-8 sequence buffered from body */ if(outs->utf8seq[0]) memset(outs->utf8seq, 0, sizeof(outs->utf8seq)); @@ -698,6 +697,197 @@ noretry: return result; } +static char *ipfs_gateway(void) +{ + char *gateway = NULL; + char *ipfs_path = NULL; + char *gateway_composed_file_path = NULL; + FILE *gateway_file = NULL; + + gateway = getenv("IPFS_GATEWAY"); + + /* Gateway is found from environment variable. */ + if(gateway && *gateway) { + char *composed_gateway = NULL; + bool add_slash = (gateway[strlen(gateway) - 1] != '/'); + composed_gateway = aprintf("%s%s", gateway, (add_slash) ? "/" : ""); + if(composed_gateway) { + gateway = aprintf("%s", composed_gateway); + Curl_safefree(composed_gateway); + } + return gateway; + } + else + /* a blank string does not count */ + gateway = NULL; + + /* Try to find the gateway in the IPFS data folder. */ + ipfs_path = getenv("IPFS_PATH"); + + if(!ipfs_path) { + char *home = getenv("HOME"); + if(home && *home) + ipfs_path = aprintf("%s/.ipfs/", home); + /* fallback to "~/.ipfs", as that's the default location. */ + } + + if(!ipfs_path) { + Curl_safefree(gateway); + Curl_safefree(ipfs_path); + return NULL; + } + + gateway_composed_file_path = aprintf("%sgateway", ipfs_path); + + if(!gateway_composed_file_path) { + Curl_safefree(gateway); + Curl_safefree(ipfs_path); + return NULL; + } + + gateway_file = fopen(gateway_composed_file_path, FOPEN_READTEXT); + Curl_safefree(gateway_composed_file_path); + + if(gateway_file) { + char *buf = NULL; + + if((PARAM_OK == file2string(&buf, gateway_file)) && buf && *buf) { + bool add_slash = (buf[strlen(buf) - 1] != '/'); + gateway = aprintf("%s%s", buf, (add_slash) ? "/" : ""); + } + Curl_safefree(buf); + + if(gateway_file) + fclose(gateway_file); + + if(!gateway) { + Curl_safefree(gateway); + Curl_safefree(ipfs_path); + return NULL; + } + + Curl_safefree(ipfs_path); + return gateway; + } + + Curl_safefree(gateway); + Curl_safefree(ipfs_path); + return NULL; +} + +/* + * Rewrite ipfs:// and ipns:// to a HTTP(S) + * URL that can be handled by an IPFS gateway. + */ +static CURLcode ipfs_url_rewrite(CURLU *uh, const char *protocol, char **url, + struct OperationConfig *config) +{ + CURLcode result = CURLE_URL_MALFORMAT; + CURLUcode urlGetResult; + char *gateway = NULL; + char *cid = NULL; + char *pathbuffer = NULL; + CURLU *ipfsurl = curl_url(); + + if(!ipfsurl) { + result = CURLE_FAILED_INIT; + goto clean; + } + + urlGetResult = curl_url_get(uh, CURLUPART_HOST, &cid, CURLU_URLDECODE); + + if(urlGetResult) { + goto clean; + } + + if(!cid) { + goto clean; + } + + /* We might have a --ipfs-gateway argument. Check it first and use it. Error + * if we do have something but if it's an invalid url. + */ + if(config->ipfs_gateway) { + if(curl_url_set(ipfsurl, CURLUPART_URL, config->ipfs_gateway, + CURLU_GUESS_SCHEME) + == CURLUE_OK) { + gateway = strdup(config->ipfs_gateway); + if(!gateway) { + result = CURLE_URL_MALFORMAT; + goto clean; + } + + } + else { + result = CURLE_BAD_FUNCTION_ARGUMENT; + goto clean; + } + } + else { + gateway = ipfs_gateway(); + if(!gateway) { + result = CURLE_FILE_COULDNT_READ_FILE; + goto clean; + } + + if(curl_url_set(ipfsurl, CURLUPART_URL, gateway, CURLU_GUESS_SCHEME + | CURLU_NON_SUPPORT_SCHEME) != CURLUE_OK) { + goto clean; + } + } + + pathbuffer = aprintf("%s/%s", protocol, cid); + if(!pathbuffer) { + goto clean; + } + + if(curl_url_set(ipfsurl, CURLUPART_PATH, pathbuffer, CURLU_URLENCODE) + != CURLUE_OK) { + goto clean; + } + + /* Free whatever it has now, rewriting is next */ + Curl_safefree(*url); + + if(curl_url_get(ipfsurl, CURLUPART_URL, url, CURLU_URLENCODE) + != CURLUE_OK) { + goto clean; + } + + result = CURLE_OK; + +clean: + free(gateway); + curl_free(cid); + curl_free(pathbuffer); + curl_url_cleanup(ipfsurl); + + switch(result) { + case CURLE_URL_MALFORMAT: + helpf(tool_stderr, "malformed URL. Visit https://curl.se/" + "docs/ipfs.html#Gateway-file-and-" + "environment-variable for more " + "information"); + break; + case CURLE_FILE_COULDNT_READ_FILE: + helpf(tool_stderr, "IPFS automatic gateway detection " + "failure. Visit https://curl.se/docs/" + "ipfs.html#Malformed-gateway-URL for " + "more information"); + break; + case CURLE_BAD_FUNCTION_ARGUMENT: + helpf(tool_stderr, "--ipfs-gateway argument results in " + "malformed URL. Visit https://curl.se/" + "docs/ipfs.html#Malformed-gateway-URL " + "for more information"); + break; + default: + break; + } + + return result; +} + /* * Return the protocol token for the scheme used in the given URL */ @@ -721,13 +911,13 @@ static CURLcode url_proto(char **url, if(curl_strequal(schemep, proto_ipfs) || curl_strequal(schemep, proto_ipns)) { result = ipfs_url_rewrite(uh, schemep, url, config); + /* short-circuit proto_token, we know it's ipfs or ipns */ if(curl_strequal(schemep, proto_ipfs)) proto = proto_ipfs; else if(curl_strequal(schemep, proto_ipns)) proto = proto_ipns; - if(result) - config->synthetic_error = TRUE; + } else proto = proto_token(schemep); @@ -1586,8 +1776,7 @@ static CURLcode single_transfer(struct GlobalConfig *global, (config->proxy_capath ? config->proxy_capath : config->capath)); - if((result == CURLE_NOT_BUILT_IN) || - (result == CURLE_UNKNOWN_OPTION)) { + if(result == CURLE_NOT_BUILT_IN) { if(config->proxy_capath) { warnf(global, "ignoring --proxy-capath, not supported by libcurl"); @@ -2636,7 +2825,7 @@ static CURLcode transfer_per_config(struct GlobalConfig *global, if(env) curl_free(env); -#ifdef _WIN32 +#ifdef WIN32 else { result = FindWin32CACert(config, tls_backend_info->backend, TEXT("curl-ca-bundle.crt")); diff --git a/deps/curl/src/tool_operate.h b/deps/curl/src/tool_operate.h index 4993b1c9..21a7f929 100644 --- a/deps/curl/src/tool_operate.h +++ b/deps/curl/src/tool_operate.h @@ -74,7 +74,7 @@ struct per_transfer { /* NULL or malloced */ char *uploadfile; - char *errorbuffer; /* allocated and assigned while this is used for a + char *errorbuffer; /* alloced and assigned while this is used for a transfer */ }; diff --git a/deps/curl/src/tool_operhlp.c b/deps/curl/src/tool_operhlp.c index d1e8352d..a964d796 100644 --- a/deps/curl/src/tool_operhlp.c +++ b/deps/curl/src/tool_operhlp.c @@ -215,7 +215,7 @@ CURLcode get_url_file_name(char **filename, const char *url) if(!*filename) return CURLE_OUT_OF_MEMORY; -#if defined(_WIN32) || defined(MSDOS) +#if defined(MSDOS) || defined(WIN32) { char *sanitized; SANITIZEcode sc = sanitize_file_name(&sanitized, *filename, 0); @@ -227,7 +227,7 @@ CURLcode get_url_file_name(char **filename, const char *url) } *filename = sanitized; } -#endif /* _WIN32 || MSDOS */ +#endif /* MSDOS || WIN32 */ /* in case we built debug enabled, we allow an environment variable * named CURL_TESTDIR to prefix the given file name to put it into a diff --git a/deps/curl/src/tool_parsecfg.c b/deps/curl/src/tool_parsecfg.c index da487006..c15f2104 100644 --- a/deps/curl/src/tool_parsecfg.c +++ b/deps/curl/src/tool_parsecfg.c @@ -46,7 +46,7 @@ static const char *unslashquote(const char *line, char *param); #define MAX_CONFIG_LINE_LENGTH (10*1024*1024) static bool my_get_line(FILE *fp, struct curlx_dynbuf *, bool *error); -#ifdef _WIN32 +#ifdef WIN32 static FILE *execpath(const char *filename, char **pathp) { static char filebuffer[512]; @@ -98,7 +98,7 @@ int parseconfig(const char *filename, struct GlobalConfig *global) } filename = pathalloc = curlrc; } -#ifdef _WIN32 /* Windows */ +#ifdef WIN32 /* Windows */ else { char *fullp; /* check for .curlrc then _curlrc in the dir of the executable */ @@ -210,9 +210,8 @@ int parseconfig(const char *filename, struct GlobalConfig *global) break; default: warnf(operation->global, "%s:%d: warning: '%s' uses unquoted " - "whitespace", filename, lineno, option); - warnf(operation->global, "This may cause side-effects. " - "Consider using double quotes?"); + "whitespace in the line that may cause side-effects", + filename, lineno, option); } } if(!*param) diff --git a/deps/curl/src/tool_sdecls.h b/deps/curl/src/tool_sdecls.h index b93c3246..7b2eb233 100644 --- a/deps/curl/src/tool_sdecls.h +++ b/deps/curl/src/tool_sdecls.h @@ -71,7 +71,7 @@ struct OutStruct { FILE *stream; curl_off_t bytes; curl_off_t init; -#ifdef _WIN32 +#ifdef WIN32 unsigned char utf8seq[5]; #endif }; diff --git a/deps/curl/src/tool_setup.h b/deps/curl/src/tool_setup.h index c69859ea..48b35564 100644 --- a/deps/curl/src/tool_setup.h +++ b/deps/curl/src/tool_setup.h @@ -66,12 +66,10 @@ extern FILE *tool_stderr; # include "tool_strdup.h" #endif -#if defined(_WIN32) +#if defined(WIN32) && !defined(MSDOS) /* set in win32_init() */ extern LARGE_INTEGER tool_freq; extern bool tool_isVistaOrGreater; -/* set in init_terminal() */ -extern bool tool_term_has_bold; #endif #endif /* HEADER_CURL_TOOL_SETUP_H */ diff --git a/deps/curl/src/tool_sleep.c b/deps/curl/src/tool_sleep.c index c24f7372..08d6f902 100644 --- a/deps/curl/src/tool_sleep.c +++ b/deps/curl/src/tool_sleep.c @@ -47,7 +47,7 @@ void tool_go_sleep(long ms) { #if defined(MSDOS) delay(ms); -#elif defined(_WIN32) +#elif defined(WIN32) Sleep(ms); #elif defined(HAVE_POLL_FINE) (void)poll((void *)0, 0, (int)ms); diff --git a/deps/curl/src/tool_urlglob.c b/deps/curl/src/tool_urlglob.c index e45c7d10..69016179 100644 --- a/deps/curl/src/tool_urlglob.c +++ b/deps/curl/src/tool_urlglob.c @@ -66,23 +66,13 @@ static CURLcode glob_fixed(struct URLGlob *glob, char *fixed, size_t len) */ static int multiply(curl_off_t *amount, curl_off_t with) { - curl_off_t sum; - DEBUGASSERT(*amount >= 0); - DEBUGASSERT(with >= 0); - if((with <= 0) || (*amount <= 0)) { - sum = 0; - } - else { -#if defined(__GNUC__) && \ - ((__GNUC__ > 5) || ((__GNUC__ == 5) && (__GNUC_MINOR__ >= 1))) - if(__builtin_mul_overflow(*amount, with, &sum)) - return 1; -#else - sum = *amount * with; - if(sum/with != *amount) - return 1; /* didn't fit, bail out */ -#endif + curl_off_t sum = *amount * with; + if(!with) { + *amount = 0; + return 0; } + if(sum/with != *amount) + return 1; /* didn't fit, bail out */ *amount = sum; return 0; } @@ -702,7 +692,7 @@ CURLcode glob_match_url(char **result, char *filename, struct URLGlob *glob) if(curlx_dyn_addn(&dyn, "", 0)) return CURLE_OUT_OF_MEMORY; -#if defined(_WIN32) || defined(MSDOS) +#if defined(MSDOS) || defined(WIN32) { char *sanitized; SANITIZEcode sc = sanitize_file_name(&sanitized, curlx_dyn_ptr(&dyn), @@ -717,5 +707,5 @@ CURLcode glob_match_url(char **result, char *filename, struct URLGlob *glob) #else *result = curlx_dyn_ptr(&dyn); return CURLE_OK; -#endif /* _WIN32 || MSDOS */ +#endif /* MSDOS || WIN32 */ } diff --git a/deps/curl/src/tool_util.c b/deps/curl/src/tool_util.c index 812a689d..7a1c03b2 100644 --- a/deps/curl/src/tool_util.c +++ b/deps/curl/src/tool_util.c @@ -31,7 +31,7 @@ #include "memdebug.h" /* keep this as LAST include */ -#if defined(_WIN32) +#if defined(WIN32) && !defined(MSDOS) /* In case of bug fix this function has a counterpart in timeval.c */ struct timeval tvnow(void) diff --git a/deps/curl/src/tool_writeout_json.c b/deps/curl/src/tool_writeout_json.c index 4ed6b93f..7bc74a26 100644 --- a/deps/curl/src/tool_writeout_json.c +++ b/deps/curl/src/tool_writeout_json.c @@ -41,8 +41,8 @@ int jsonquoted(const char *in, size_t len, struct curlx_dynbuf *out, bool lowercase) { - const unsigned char *i = (unsigned char *)in; - const unsigned char *in_end = &i[len]; + const char *i = in; + const char *in_end = &in[len]; CURLcode result = CURLE_OK; for(; (i < in_end) && !result; i++) { diff --git a/deps/curl/src/tool_xattr.c b/deps/curl/src/tool_xattr.c index 9472194f..968cf2f7 100644 --- a/deps/curl/src/tool_xattr.c +++ b/deps/curl/src/tool_xattr.c @@ -87,12 +87,11 @@ static int xattr(int fd, int err = 0; if(value) { #ifdef DEBUGBUILD - (void)fd; if(getenv("CURL_FAKE_XATTR")) { printf("%s => %s\n", attr, value); } return 0; -#else +#endif #ifdef HAVE_FSETXATTR_6 err = fsetxattr(fd, attr, value, strlen(value), 0, 0); #elif defined(HAVE_FSETXATTR_5) @@ -105,7 +104,6 @@ static int xattr(int fd, attribute */ err = (rc < 0 ? -1 : 0); } -#endif #endif } return err; diff --git a/deps/curl/src/var.c b/deps/curl/src/var.c index 388d4559..f8f42f66 100644 --- a/deps/curl/src/var.c +++ b/deps/curl/src/var.c @@ -358,7 +358,7 @@ static ParameterError addvariable(struct GlobalConfig *global, if(check) notef(global, "Overwriting variable '%s'", check->name); - p = calloc(1, sizeof(struct var)); + p = calloc(sizeof(struct var), 1); if(!p) return PARAM_NO_MEM; diff --git a/deps/curl/tests/.gitignore b/deps/curl/tests/.gitignore index f08407f5..eae0490d 100644 --- a/deps/curl/tests/.gitignore +++ b/deps/curl/tests/.gitignore @@ -26,4 +26,3 @@ testcurl.html testcurl.pdf *.port config -second-hsts.txt diff --git a/deps/curl/tests/README.md b/deps/curl/tests/README.md index 1464eacd..65af2a0b 100644 --- a/deps/curl/tests/README.md +++ b/deps/curl/tests/README.md @@ -8,41 +8,6 @@ SPDX-License-Identifier: curl # Running - See the "Requires to run" section for prerequisites. - - In the root of the curl repository: - - ./configure && make && make test - - To run a specific set of tests (e.g. 303 and 410): - - make test TFLAGS="303 410" - - To run the tests faster, pass the -j (parallelism) flag: - - make test TFLAGS="-j10" - - "make test" builds the test suite support code and invokes the 'runtests.pl' - perl script to run all the tests. The value of `TFLAGS` is passed - directly to 'runtests.pl'. - - When you run tests via make, the flags `-a` and `-s` are passed, meaning - to continue running tests even after one fails, and to emit short output. - - If you'd like to not use those flags, you can run 'runtests.pl' directly. - You must `chdir` into the tests directory, then you can run it like so: - - ./runtests.pl 303 410 - - You must have run `make test` at least once first to build the support code. - - To see what flags are available for runtests.pl, and what output it emits, run: - - man ./tests/runtests.1 - - After a test fails, examine the tests/log directory for stdout, stderr, and - output from the servers used in the test. - ## Requires to run - perl (and a unix-style shell) @@ -50,7 +15,7 @@ SPDX-License-Identifier: curl - python-impacket (for SMB tests) - diff (when a test fails, a diff is shown) - stunnel (for HTTPS and FTPS tests) - - OpenSSH or SunSSH (for SCP and SFTP tests) + - OpenSSH or SunSSH (for SCP, SFTP and SOCKS4/5 tests) - nghttpx (for HTTP/2 and HTTP/3 tests) - nroff (for --manual tests) - An available `en_US.UTF-8` locale @@ -94,7 +59,9 @@ SPDX-License-Identifier: curl The test suite runs stand-alone servers on random ports to which it makes requests. For SSL tests, it runs stunnel to handle encryption to the regular - servers. For SSH, it runs a standard OpenSSH server. + servers. For SSH, it runs a standard OpenSSH server. For SOCKS4/5 tests SSH + is used to perform the SOCKS functionality and requires a SSH client and + server. The listen port numbers for the test servers are picked randomly to allow users to run multiple test cases concurrently and to not collide with other @@ -108,9 +75,47 @@ SPDX-License-Identifier: curl used, set the environment variable `NGHTTPX`. The default can also be changed by specifying `--with-test-nghttpx=` as argument to `configure`. +### Run + + `./configure && make && make test`. This builds the test suite support code + and invokes the 'runtests.pl' perl script to run all the tests. Edit the top + variables of that script in case you have some specific needs, or run the + script manually (after the support code has been built). + + The script breaks on the first test that doesn't do OK. Use `-a` to prevent + the script from aborting on the first error. Run the script with `-v` for + more verbose output. Use `-d` to run the test servers with debug output + enabled as well. Specifying `-k` keeps all the log files generated by the + test intact. + + Use `-s` for shorter output, or pass test numbers to run specific tests only + (like `./runtests.pl 3 4` to test 3 and 4 only). It also supports test case + ranges with 'to', as in `./runtests.pl 3 to 9` which runs the seven tests + from 3 to 9. Any test numbers starting with ! are disabled, as are any test + numbers found in the files `data/DISABLED` or `data/DISABLED.local` (one per + line). The latter is meant for local temporary disables and will be ignored + by git. + + Test cases mentioned in `DISABLED` can still be run if `-f` is provided. + + When `-s` is not present, each successful test will display on one line the + test number and description and on the next line a set of flags, the test + result, current test sequence, total number of tests to be run and an + estimated amount of time to complete the test run. The flags consist of + these letters describing what is checked in this test: + + s stdout + d data + u upload + p protocol + o output + e exit code + m memory + v valgrind + ### Shell startup scripts - Tests which use the ssh test server, SCP/SFTP tests, might be badly + Tests which use the ssh test server, SCP/SFTP/SOCKS tests, might be badly influenced by the output of system wide or user specific shell startup scripts, .bashrc, .profile, /etc/csh.cshrc, .login, /etc/bashrc, etc. which output text messages or escape sequences on user login. When these shell diff --git a/deps/curl/tests/data/DISABLED b/deps/curl/tests/data/DISABLED index b077c67a..308d27e5 100644 --- a/deps/curl/tests/data/DISABLED +++ b/deps/curl/tests/data/DISABLED @@ -70,6 +70,9 @@ 266 579 587 +722 +724 +727 # 1021 re-added here due to flakiness 1021 1117 diff --git a/deps/curl/tests/data/Makefile.inc b/deps/curl/tests/data/Makefile.inc index de13c525..1472b195 100644 --- a/deps/curl/tests/data/Makefile.inc +++ b/deps/curl/tests/data/Makefile.inc @@ -51,7 +51,7 @@ test226 test227 test228 test229 test230 test231 test232 test233 test234 \ test235 test236 test237 test238 test239 test240 test241 test242 test243 \ test244 test245 test246 test247 test248 test249 test250 test251 test252 \ test253 test254 test255 test256 test257 test258 test259 test260 test261 \ -test262 test263 test264 test265 test266 test267 test268 test269 test270 \ +test262 test263 test264 test265 test266 test267 test269 test270 \ test271 test272 test273 test274 test275 test276 test277 test278 test279 \ test280 test281 test282 test283 test284 test285 test286 test287 test288 \ test289 test290 test291 test292 test293 test294 test295 test296 test297 \ @@ -72,7 +72,7 @@ test417 test418 test419 test420 test421 test422 test423 test424 test425 \ test426 test427 test428 test429 test430 test431 test432 test433 test434 \ test435 test436 test437 test438 test439 test440 test441 test442 test443 \ test444 test445 test446 test447 test448 test449 test450 test451 test452 \ -test453 test454 test455 test456 test457 test458 test459 \ +test453 test454 test455 test456 test457 test458 \ \ test490 test491 test492 test493 test494 test495 test496 test497 test498 \ \ @@ -101,8 +101,7 @@ test681 test682 test683 test684 test685 test686 test687 test688 \ test700 test701 test702 test703 test704 test705 test706 test707 test708 \ test709 test710 test711 test712 test713 test714 test715 test716 test717 \ test718 test719 test720 test721 test722 test723 test724 test725 test726 \ -test727 test728 test729 test730 test731 test732 test733 test734 test735 \ -test736 test737 test738 test739 test740 test741 \ +test727 test728 \ \ test799 test800 test801 test802 test803 test804 test805 test806 test807 \ test808 test809 test810 test811 test812 test813 test814 test815 test816 \ @@ -186,14 +185,14 @@ test1439 test1440 test1441 test1442 test1443 test1444 test1445 test1446 \ test1447 test1448 test1449 test1450 test1451 test1452 test1453 test1454 \ test1455 test1456 test1457 test1458 test1459 test1460 test1461 test1462 \ test1463 test1464 test1465 test1466 test1467 test1468 test1469 test1470 \ -test1471 test1472 test1473 test1474 test1475 test1476 test1477 \ +test1471 test1472 test1473 test1474 \ \ test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \ test1508 test1509 test1510 test1511 test1512 test1513 test1514 test1515 \ test1516 test1517 test1518 test1519 test1520 test1521 test1522 test1523 \ test1524 test1525 test1526 test1527 test1528 test1529 test1530 test1531 \ test1532 test1533 test1534 test1535 test1536 test1537 test1538 test1539 \ -test1540 test1542 test1543 test1544 test1545 \ +test1540 test1542 test1543 test1544 \ \ test1550 test1551 test1552 test1553 test1554 test1555 test1556 test1557 \ test1558 test1559 test1560 test1561 test1562 test1563 test1564 test1565 \ @@ -219,7 +218,7 @@ test1700 test1701 test1702 test1703 \ \ test1800 test1801 \ \ -test1900 test1903 test1904 test1905 test1906 test1907 \ + test1903 test1904 test1905 test1906 test1907 \ test1908 test1909 test1910 test1911 test1912 test1913 test1914 test1915 \ test1916 test1917 test1918 test1919 \ \ diff --git a/deps/curl/tests/data/test1475 b/deps/curl/tests/data/test1475 deleted file mode 100644 index f88ef74e..00000000 --- a/deps/curl/tests/data/test1475 +++ /dev/null @@ -1,83 +0,0 @@ - -# also verified by 1156 in libcurl API terms - - - -HTTP -HTTP GET -Resume - - - -# Server-side - - -HTTP/1.1 416 Invalid range -Connection: close -Content-Length: 0 -Content-Range: */100 - - - -# The file data that exists at the start of the test must be included in -# the verification. - -012345678 -012345678 -012345678 -012345678 -012345678 -012345678 -012345678 -012345678 -012345678 -012345678 -HTTP/1.1 416 Invalid range -Connection: close -Content-Length: 0 -Content-Range: */100 - - - - - -# Client-side - - -http - - -http - - --f and 416 with Content-Range: */size - - -http://%HOSTIP:%HTTPPORT/%TESTNUMBER -C - -f - - -012345678 -012345678 -012345678 -012345678 -012345678 -012345678 -012345678 -012345678 -012345678 -012345678 - - - -# Verify data after the test has been "shot" - - -GET /%TESTNUMBER HTTP/1.1 -Host: %HOSTIP:%HTTPPORT -Range: bytes=100- -User-Agent: curl/%VERSION -Accept: */* - - - - diff --git a/deps/curl/tests/data/test1476 b/deps/curl/tests/data/test1476 deleted file mode 100644 index 101fa95b..00000000 --- a/deps/curl/tests/data/test1476 +++ /dev/null @@ -1,59 +0,0 @@ - - - -HTTP -HTTP GET -cookies - - - -# Server-side - - - -HTTP/1.1 200 OK -Date: Tue, 09 Nov 2010 14:49:00 GMT -Content-Length: 0 -Set-Cookie: super=oops; domain=co.UK; path=/ -Set-Cookie: fine=yesyes; domain=CURL.CO.UK; path=/ - - - - -# Client-side - - -http - - -PSL violating cookie with mixed case domain and cookie domain property - - --x http://%HOSTIP:%HTTPPORT/%TESTNUMBER http://curl.co.UK -c %LOGDIR/cookies%TESTNUMBER.txt - - -proxy -PSL -cookies - - - -# Verify data after the test has been "shot" - - -GET http://curl.co.UK/ HTTP/1.1 -Host: curl.co.UK -User-Agent: curl/%VERSION -Accept: */* -Proxy-Connection: Keep-Alive - - - -# Netscape HTTP Cookie File -# https://curl.se/docs/http-cookies.html -# This file was generated by libcurl! Edit at your own risk. - -.CURL.CO.UK TRUE / FALSE 0 fine yesyes - - - diff --git a/deps/curl/tests/data/test1477 b/deps/curl/tests/data/test1477 deleted file mode 100644 index 2771d7f1..00000000 --- a/deps/curl/tests/data/test1477 +++ /dev/null @@ -1,30 +0,0 @@ - - - -documentation - - - -# -# Client-side - - -none - - - -Verify that error codes in headers and libcurl-errors.3 are in sync - - - -%SRCDIR/errorcodes.pl %SRCDIR/.. - - - - - -Result - - - - diff --git a/deps/curl/tests/data/test1506 b/deps/curl/tests/data/test1506 index 0a62c0c2..9eb38cf6 100644 --- a/deps/curl/tests/data/test1506 +++ b/deps/curl/tests/data/test1506 @@ -86,6 +86,7 @@ Accept: */* * Connection #0 to host server1.example.com left intact * Connection #1 to host server2.example.com left intact * Connection #2 to host server3.example.com left intact +* Closing connection * Connection #3 to host server4.example.com left intact diff --git a/deps/curl/tests/data/test1545 b/deps/curl/tests/data/test1545 deleted file mode 100644 index 477b5bf4..00000000 --- a/deps/curl/tests/data/test1545 +++ /dev/null @@ -1,38 +0,0 @@ - - - -HTTP -HTTP GET - - -# -# Server-side - - - -# Client-side - - -form-api - - -http - -# tool is what to use instead of 'curl' - -lib%TESTNUMBER - - - -use curl_formadd() data twice with unreadable file - - -http://%HOSTIP:%HTTPPORT/%TESTNUMBER - - - -# -# Verify data after the test has been "shot" - - - diff --git a/deps/curl/tests/data/test1683 b/deps/curl/tests/data/test1683 index 581470df..178b4054 100644 --- a/deps/curl/tests/data/test1683 +++ b/deps/curl/tests/data/test1683 @@ -40,9 +40,11 @@ to stay the same perl -e 'for my $i ((1..100)) { my $filename = "%LOGDIR/exist%TESTNUMBER.$i"; open(FH, ">", $filename) or die $!; print FH "to stay the same" ; close(FH) }' +# python3 -c 'for i in range(1, 101): open("%LOGDIR/exist%TESTNUMBER.{}".format(i), mode="w").write("to stay the same")' perl -e 'for my $i ((1..100)) { my $filename = "%LOGDIR/exist%TESTNUMBER.$i"; open(FH, "<", $filename) or die $!; ( eq "to stay the same" and eq "") or die "incorrect $filename" ; close(FH) }' +# python3 -c 'for i in range(1, 101): assert open("%LOGDIR/exist%TESTNUMBER.{}".format(i), mode="r").read(17) == "to stay the same"' diff --git a/deps/curl/tests/data/test1900 b/deps/curl/tests/data/test1900 deleted file mode 100644 index f04e7e2a..00000000 --- a/deps/curl/tests/data/test1900 +++ /dev/null @@ -1,38 +0,0 @@ - - - -HTTP -HSTS - - - -# Server-side - - - -# Client-side - - -HSTS -http - - -none - - - -HSTS curl_easy_duphandle - - -lib%TESTNUMBER - - - -http://%HOSTIP:%NOLISTENPORT/not-there/%TESTNUMBER - - - -# Verify data after the test has been "shot" - - - diff --git a/deps/curl/tests/data/test194 b/deps/curl/tests/data/test194 index 07434895..4de767e3 100644 --- a/deps/curl/tests/data/test194 +++ b/deps/curl/tests/data/test194 @@ -64,8 +64,9 @@ User-Agent: curl/%VERSION Accept: */* +# CURLE_HTTP_RETURNED_ERROR -0 +22 diff --git a/deps/curl/tests/data/test268 b/deps/curl/tests/data/test268 deleted file mode 100644 index 3a1ab6a9..00000000 --- a/deps/curl/tests/data/test268 +++ /dev/null @@ -1,59 +0,0 @@ - - - -HTTP -variables - - - -# -# Server-side - - -HTTP/1.1 200 OK -Date: Tue, 09 Nov 2010 14:49:00 GMT -Server: test-server/fake -Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT -ETag: "21025-dc7-39462498" -Accept-Ranges: bytes -Content-Length: 6 -Connection: close -Content-Type: text/html -Funny-head: yesyes - --foo- - - - -# -# Client-side - - -http - - -JSON encoding of unicode string - - -%hex[%e2%80%9c]hex% - - -http://%HOSTIP:%HTTPPORT/%TESTNUMBER --variable hello@%LOGDIR/junk --expand-data {{hello:json}} - - - -# -# Verify data after the test has been "shot" - - -POST /%TESTNUMBER HTTP/1.1 -Host: %HOSTIP:%HTTPPORT -User-Agent: curl/%VERSION -Accept: */* -Content-Length: 3 -Content-Type: application/x-www-form-urlencoded - -%hex[%e2%80%9c]hex% - - - diff --git a/deps/curl/tests/data/test3103 b/deps/curl/tests/data/test3103 index 423c4ada..23a0fea1 100644 --- a/deps/curl/tests/data/test3103 +++ b/deps/curl/tests/data/test3103 @@ -48,7 +48,7 @@ http://%HOSTIP:%HTTPPORT/%TESTNUMBER # # Verify data after the test has been "shot" - + GET http://localhost/ HTTP/1.1 Host: localhost Accept: */* diff --git a/deps/curl/tests/data/test439 b/deps/curl/tests/data/test439 index c997a397..da126153 100644 --- a/deps/curl/tests/data/test439 +++ b/deps/curl/tests/data/test439 @@ -38,7 +38,7 @@ debug aws-sigv4 with query -"http://fake.fake.fake:8000/%TESTNUMBER/?name=me%&noval&aim=b%aad&&&weirdo=*.//-" -u user:secret --aws-sigv4 "aws:amz:us-east-2:es" --connect-to fake.fake.fake:8000:%HOSTIP:%HTTPPORT +"http://fake.fake.fake:8000/%TESTNUMBER/?name=me%&aim=b%aad&&&weirdo=*.//-" -u user:secret --aws-sigv4 "aws:amz:us-east-2:es" --connect-to fake.fake.fake:8000:%HOSTIP:%HTTPPORT @@ -46,9 +46,9 @@ aws-sigv4 with query # Verify data after the test has been "shot" -GET /439/?name=me%&noval&aim=b%aad&&&weirdo=*.//- HTTP/1.1 +GET /%TESTNUMBER/?name=me%&aim=b%aad&&&weirdo=*.//- HTTP/1.1 Host: fake.fake.fake:8000 -Authorization: AWS4-HMAC-SHA256 Credential=user/19700101/us-east-2/es/aws4_request, SignedHeaders=host;x-amz-date, Signature=cbbf4a72764e27e396730f5e56cea046d4ce862a2d91db4856fb086b92f49270 +Authorization: AWS4-HMAC-SHA256 Credential=user/19700101/us-east-2/es/aws4_request, SignedHeaders=host;x-amz-date, Signature=88884e3b3142133685b2092d29d8b522b785b1a9ec9e4a90cbea83e882f8dcb6 X-Amz-Date: 19700101T000000Z User-Agent: curl/%VERSION Accept: */* diff --git a/deps/curl/tests/data/test457 b/deps/curl/tests/data/test457 index aa391d7f..77eb9c85 100644 --- a/deps/curl/tests/data/test457 +++ b/deps/curl/tests/data/test457 @@ -20,8 +20,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 30 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 21;heresatest=moooo -cccccccccccccccccccccccccccccc -c +cccccccccccccccccccccccccccccccc 0 @@ -32,7 +31,7 @@ Server: fakeit/0.9 fakeitbad/1.0 Transfer-Encoding: chunked Connection: mooo -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccc +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccc diff --git a/deps/curl/tests/data/test459 b/deps/curl/tests/data/test459 deleted file mode 100644 index e46d0297..00000000 --- a/deps/curl/tests/data/test459 +++ /dev/null @@ -1,63 +0,0 @@ - - - -HTTP ---config - - - -# -# Server-side - - -HTTP/1.1 200 OK -Date: Tue, 09 Nov 2010 14:49:00 GMT -Server: test-server/fake -Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT -ETag: "21025-dc7-39462498" -Accept-Ranges: bytes -Content-Length: 6 -Connection: close -Content-Type: text/html -Funny-head: yesyes - --foo- - - - -# -# Client-side - - -http - - -config file with argument using whitespace missing quotes - - -data = arg with space - - -http://%HOSTIP:%HTTPPORT/%TESTNUMBER --config %LOGDIR/config --silent - - - -# -# Verify data after the test has been "shot" - - -POST /%TESTNUMBER HTTP/1.1 -Host: %HOSTIP:%HTTPPORT -User-Agent: curl/%VERSION -Accept: */* -Content-Length: 3 -Content-Type: application/x-www-form-urlencoded - -arg - - -Warning: %LOGDIR/config:1: warning: 'data' uses unquoted whitespace -Warning: This may cause side-effects. Consider using double quotes? - - - diff --git a/deps/curl/tests/data/test722 b/deps/curl/tests/data/test722 index c5b8d861..674efd14 100644 --- a/deps/curl/tests/data/test722 +++ b/deps/curl/tests/data/test722 @@ -8,7 +8,7 @@ IPFS # # Server-side - + HTTP/1.1 200 OK Date: Tue, 09 Nov 2010 14:49:00 GMT Server: test-server/fake @@ -34,7 +34,7 @@ http IPFS ---ipfs-gateway http://%HOSTIP:%HTTPPORT ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u +--ipfs-gateway http://%HOSTIP:%HTTPPORT/%TESTNUMBER ipfs://QmV5JejrpgUxnkZeFZYMxVCqAbKy3KdPXWXyuEDiMNZwUx @@ -42,7 +42,7 @@ IPFS # Verify data after the test has been "shot" -GET /ipfs/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u HTTP/1.1 +GET /ipfs/QmV5JejrpgUxnkZeFZYMxVCqAbKy3KdPXWXyuEDiMNZwUx HTTP/1.1 Host: %HOSTIP:%HTTPPORT User-Agent: curl/%VERSION Accept: */* diff --git a/deps/curl/tests/data/test723 b/deps/curl/tests/data/test723 index dac78fc5..aaf4d27a 100644 --- a/deps/curl/tests/data/test723 +++ b/deps/curl/tests/data/test723 @@ -20,7 +20,7 @@ http IPFS with malformed gateway URL (bad function argument error) ---ipfs-gateway http://nonexisting,local:8080 ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u +--ipfs-gateway http://nonexisting,local:8080/%TESTNUMBER ipfs://QmV5JejrpgUxnkZeFZYMxVCqAbKy3KdPXWXyuEDiMNZwUx diff --git a/deps/curl/tests/data/test724 b/deps/curl/tests/data/test724 index c97354b0..692046b3 100644 --- a/deps/curl/tests/data/test724 +++ b/deps/curl/tests/data/test724 @@ -8,7 +8,7 @@ IPFS # # Server-side - + HTTP/1.1 200 OK Date: Tue, 09 Nov 2010 14:49:00 GMT Server: test-server/fake @@ -37,10 +37,10 @@ HOME=%PWD/%LOGDIR IPFS with gateway URL from gateway file -ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u +ipfs://QmV5JejrpgUxnkZeFZYMxVCqAbKy3KdPXWXyuEDiMNZwUx -http://%HOSTIP:%HTTPPORT +http://%HOSTIP:%HTTPPORT/%TESTNUMBER @@ -48,7 +48,7 @@ http://%HOSTIP:%HTTPPORT # Verify data after the test has been "shot" -GET /ipfs/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u HTTP/1.1 +GET /ipfs/QmV5JejrpgUxnkZeFZYMxVCqAbKy3KdPXWXyuEDiMNZwUx HTTP/1.1 Host: %HOSTIP:%HTTPPORT User-Agent: curl/%VERSION Accept: */* diff --git a/deps/curl/tests/data/test725 b/deps/curl/tests/data/test725 index de7c3949..cf3c1966 100644 --- a/deps/curl/tests/data/test725 +++ b/deps/curl/tests/data/test725 @@ -23,10 +23,10 @@ HOME=%PWD/%LOGDIR IPFS with malformed gateway URL from gateway file -ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u +ipfs://QmV5JejrpgUxnkZeFZYMxVCqAbKy3KdPXWXyuEDiMNZwUx -http://nonexisting,local:8080 +http://nonexisting,local:8080/%TESTNUMBER diff --git a/deps/curl/tests/data/test726 b/deps/curl/tests/data/test726 index f51adf59..c0abbf29 100644 --- a/deps/curl/tests/data/test726 +++ b/deps/curl/tests/data/test726 @@ -26,7 +26,7 @@ HOME=%PWD IPFS with no gateway URL (no environment or home file either) -ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u +ipfs://QmV5JejrpgUxnkZeFZYMxVCqAbKy3KdPXWXyuEDiMNZwUx diff --git a/deps/curl/tests/data/test727 b/deps/curl/tests/data/test727 index aa2c84fb..e71ef5f4 100644 --- a/deps/curl/tests/data/test727 +++ b/deps/curl/tests/data/test727 @@ -8,7 +8,7 @@ IPNS # # Server-side - + HTTP/1.1 200 OK Date: Tue, 09 Nov 2010 14:49:00 GMT Server: test-server/fake @@ -34,7 +34,7 @@ http IPNS ---ipfs-gateway http://%HOSTIP:%HTTPPORT ipns://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u +--ipfs-gateway http://%HOSTIP:%HTTPPORT/%TESTNUMBER ipns://QmV5JejrpgUxnkZeFZYMxVCqAbKy3KdPXWXyuEDiMNZwUx @@ -42,7 +42,7 @@ IPNS # Verify data after the test has been "shot" -GET /ipns/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u HTTP/1.1 +GET /ipns/QmV5JejrpgUxnkZeFZYMxVCqAbKy3KdPXWXyuEDiMNZwUx HTTP/1.1 Host: %HOSTIP:%HTTPPORT User-Agent: curl/%VERSION Accept: */* diff --git a/deps/curl/tests/data/test729 b/deps/curl/tests/data/test729 deleted file mode 100644 index 80575892..00000000 --- a/deps/curl/tests/data/test729 +++ /dev/null @@ -1,41 +0,0 @@ - - - -HTTP -HTTP GET -SOCKS4 - - - -# -# Server-side - - - -# -# Client-side - - -proxy - - -http -socks4 - - -SOCKS4 with very long proxy user name - - -http://fake --limit-rate 1 -x socks4a://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@%HOSTIP:%SOCKSPORT - - - -# -# Verify data after the test has been "shot" - -# CURLE_PROXY - -97 - - - diff --git a/deps/curl/tests/data/test730 b/deps/curl/tests/data/test730 deleted file mode 100644 index 138f8508..00000000 --- a/deps/curl/tests/data/test730 +++ /dev/null @@ -1,52 +0,0 @@ - - - -IPFS - - - -# -# Server-side - - -HTTP/1.1 200 OK -Date: Tue, 09 Nov 2010 14:49:00 GMT -Server: test-server/fake -Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT -ETag: "21025-dc7-39462498" -Accept-Ranges: bytes -Content-Length: 21 -Connection: close -Content-Type: text/plain -Funny-head: yesyes - -Hello curl from IPFS - - - -# -# Client-side - - -http - - -IPFS arg gateway with path - - ---ipfs-gateway http://%HOSTIP:%HTTPPORT/foo/bar ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u - - - -# -# Verify data after the test has been "shot" - - -GET /foo/bar/ipfs/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u HTTP/1.1 -Host: %HOSTIP:%HTTPPORT -User-Agent: curl/%VERSION -Accept: */* - - - - diff --git a/deps/curl/tests/data/test731 b/deps/curl/tests/data/test731 deleted file mode 100644 index 9e135dbe..00000000 --- a/deps/curl/tests/data/test731 +++ /dev/null @@ -1,58 +0,0 @@ - - - -IPFS - - - -# -# Server-side - - -HTTP/1.1 200 OK -Date: Tue, 09 Nov 2010 14:49:00 GMT -Server: test-server/fake -Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT -ETag: "21025-dc7-39462498" -Accept-Ranges: bytes -Content-Length: 21 -Connection: close -Content-Type: text/plain -Funny-head: yesyes - -Hello curl from IPFS - - - -# -# Client-side - - -http - - -HOME=%PWD/%LOGDIR - - -IPFS with gateway URL and path from gateway file - - -ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u - - -http://%HOSTIP:%HTTPPORT/%TESTNUMBER - - - -# -# Verify data after the test has been "shot" - - -GET /%TESTNUMBER/ipfs/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u HTTP/1.1 -Host: %HOSTIP:%HTTPPORT -User-Agent: curl/%VERSION -Accept: */* - - - - diff --git a/deps/curl/tests/data/test732 b/deps/curl/tests/data/test732 deleted file mode 100644 index 9adaedb9..00000000 --- a/deps/curl/tests/data/test732 +++ /dev/null @@ -1,52 +0,0 @@ - - - -IPFS - - - -# -# Server-side - - -HTTP/1.1 200 OK -Date: Tue, 09 Nov 2010 14:49:00 GMT -Server: test-server/fake -Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT -ETag: "21025-dc7-39462498" -Accept-Ranges: bytes -Content-Length: 21 -Connection: close -Content-Type: text/plain -Funny-head: yesyes - -Hello curl from IPFS - - - -# -# Client-side - - -http - - -IPFS with path - - ---ipfs-gateway http://%HOSTIP:%HTTPPORT "ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u/a/b" - - - -# -# Verify data after the test has been "shot" - - -GET /ipfs/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u/a/b HTTP/1.1 -Host: %HOSTIP:%HTTPPORT -User-Agent: curl/%VERSION -Accept: */* - - - - diff --git a/deps/curl/tests/data/test733 b/deps/curl/tests/data/test733 deleted file mode 100644 index ad17cd4b..00000000 --- a/deps/curl/tests/data/test733 +++ /dev/null @@ -1,52 +0,0 @@ - - - -IPFS - - - -# -# Server-side - - -HTTP/1.1 200 OK -Date: Tue, 09 Nov 2010 14:49:00 GMT -Server: test-server/fake -Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT -ETag: "21025-dc7-39462498" -Accept-Ranges: bytes -Content-Length: 21 -Connection: close -Content-Type: text/plain -Funny-head: yesyes - -Hello curl from IPFS - - - -# -# Client-side - - -http - - -IPFS with path and query args - - ---ipfs-gateway http://%HOSTIP:%HTTPPORT "ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u/a/b?foo=bar&aaa=bbb" - - - -# -# Verify data after the test has been "shot" - - -GET /ipfs/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u/a/b?foo=bar&aaa=bbb HTTP/1.1 -Host: %HOSTIP:%HTTPPORT -User-Agent: curl/%VERSION -Accept: */* - - - - diff --git a/deps/curl/tests/data/test734 b/deps/curl/tests/data/test734 deleted file mode 100644 index 03f571cc..00000000 --- a/deps/curl/tests/data/test734 +++ /dev/null @@ -1,52 +0,0 @@ - - - -IPFS - - - -# -# Server-side - - -HTTP/1.1 200 OK -Date: Tue, 09 Nov 2010 14:49:00 GMT -Server: test-server/fake -Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT -ETag: "21025-dc7-39462498" -Accept-Ranges: bytes -Content-Length: 21 -Connection: close -Content-Type: text/plain -Funny-head: yesyes - -Hello curl from IPFS - - - -# -# Client-side - - -http - - -IPFS with path, query args and gateway with path - - ---ipfs-gateway http://%HOSTIP:%HTTPPORT/some/path "ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u/a/b?foo=bar&aaa=bbb" - - - -# -# Verify data after the test has been "shot" - - -GET /some/path/ipfs/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u/a/b?foo=bar&aaa=bbb HTTP/1.1 -Host: %HOSTIP:%HTTPPORT -User-Agent: curl/%VERSION -Accept: */* - - - - diff --git a/deps/curl/tests/data/test735 b/deps/curl/tests/data/test735 deleted file mode 100644 index da1aac4d..00000000 --- a/deps/curl/tests/data/test735 +++ /dev/null @@ -1,52 +0,0 @@ - - - -IPFS - - - -# -# Server-side - - -HTTP/1.1 200 OK -Date: Tue, 09 Nov 2010 14:49:00 GMT -Server: test-server/fake -Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT -ETag: "21025-dc7-39462498" -Accept-Ranges: bytes -Content-Length: 21 -Connection: close -Content-Type: text/plain -Funny-head: yesyes - -Hello curl from IPFS - - - -# -# Client-side - - -http - - -IPNS with path, query args and gateway with path - - ---ipfs-gateway http://%HOSTIP:%HTTPPORT/some/path "ipns://fancy.tld/a/b?foo=bar&aaa=bbb" - - - -# -# Verify data after the test has been "shot" - - -GET /some/path/ipns/fancy.tld/a/b?foo=bar&aaa=bbb HTTP/1.1 -Host: %HOSTIP:%HTTPPORT -User-Agent: curl/%VERSION -Accept: */* - - - - diff --git a/deps/curl/tests/data/test736 b/deps/curl/tests/data/test736 deleted file mode 100644 index 45d9a055..00000000 --- a/deps/curl/tests/data/test736 +++ /dev/null @@ -1,58 +0,0 @@ - - - -IPFS - - - -# -# Server-side - - -HTTP/1.1 200 OK -Date: Tue, 09 Nov 2010 14:49:00 GMT -Server: test-server/fake -Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT -ETag: "21025-dc7-39462498" -Accept-Ranges: bytes -Content-Length: 21 -Connection: close -Content-Type: text/plain -Funny-head: yesyes - -Hello curl from IPFS - - - -# -# Client-side - - -http - - -IPFS_PATH=%LOGDIR/.ipfs - - -IPFS with IPFS_PATH set, no trailing slash - - -ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u - - -http://%HOSTIP:%HTTPPORT - - - -# -# Verify data after the test has been "shot" - - -GET /ipfs/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u HTTP/1.1 -Host: %HOSTIP:%HTTPPORT -User-Agent: curl/%VERSION -Accept: */* - - - - diff --git a/deps/curl/tests/data/test737 b/deps/curl/tests/data/test737 deleted file mode 100644 index bc6e8576..00000000 --- a/deps/curl/tests/data/test737 +++ /dev/null @@ -1,58 +0,0 @@ - - - -IPFS - - - -# -# Server-side - - -HTTP/1.1 200 OK -Date: Tue, 09 Nov 2010 14:49:00 GMT -Server: test-server/fake -Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT -ETag: "21025-dc7-39462498" -Accept-Ranges: bytes -Content-Length: 21 -Connection: close -Content-Type: text/plain -Funny-head: yesyes - -Hello curl from IPFS - - - -# -# Client-side - - -http - - -IPFS_PATH=%LOGDIR/.ipfs/ - - -IPFS with IPFS_PATH set, with trailing slash - - -ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u - - -http://%HOSTIP:%HTTPPORT - - - -# -# Verify data after the test has been "shot" - - -GET /ipfs/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u HTTP/1.1 -Host: %HOSTIP:%HTTPPORT -User-Agent: curl/%VERSION -Accept: */* - - - - diff --git a/deps/curl/tests/data/test738 b/deps/curl/tests/data/test738 deleted file mode 100644 index 5c05137d..00000000 --- a/deps/curl/tests/data/test738 +++ /dev/null @@ -1,37 +0,0 @@ - - - -IPFS - - - -# -# Server-side - - - -# -# Client-side - - -http - - -IPFS_PATH=%LOGDIR/.ipfs/ - - -IPFS with IPFS_PATH, no gateway file - - -ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u - - - -# -# Verify error code with no gateway file (detection fails) - - -37 - - - diff --git a/deps/curl/tests/data/test739 b/deps/curl/tests/data/test739 deleted file mode 100644 index fe78c41b..00000000 --- a/deps/curl/tests/data/test739 +++ /dev/null @@ -1,34 +0,0 @@ - - - -IPFS - - - -# -# Server-side - - - -# -# Client-side - - -http - - -IPNS path and query args for gateway and IPFS url (malformed gateway url) - - ---ipfs-gateway "http://%HOSTIP:%HTTPPORT/some/path?biz=baz" "ipns://fancy.tld/a/b?foo=bar&aaa=bbb" - - - -# -# Verify data after the test has been "shot" - - -3 - - - diff --git a/deps/curl/tests/data/test740 b/deps/curl/tests/data/test740 deleted file mode 100644 index 97258d38..00000000 --- a/deps/curl/tests/data/test740 +++ /dev/null @@ -1,60 +0,0 @@ - - - -IPFS - - - -# -# Server-side - - -HTTP/1.1 200 OK -Date: Tue, 09 Nov 2010 14:49:00 GMT -Server: test-server/fake -Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT -ETag: "21025-dc7-39462498" -Accept-Ranges: bytes -Content-Length: 21 -Connection: close -Content-Type: text/plain -Funny-head: yesyes - -Hello curl from IPFS - - - -# -# Client-side - - -http - - -HOME=%PWD/%LOGDIR - - -IPFS with gateway URL from multiline gateway file - - -ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u - - -http://%HOSTIP:%HTTPPORT -foo -bar - - - -# -# Verify data after the test has been "shot" - - -GET /ipfs/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u HTTP/1.1 -Host: %HOSTIP:%HTTPPORT -User-Agent: curl/%VERSION -Accept: */* - - - - diff --git a/deps/curl/tests/data/test741 b/deps/curl/tests/data/test741 deleted file mode 100644 index e773cd08..00000000 --- a/deps/curl/tests/data/test741 +++ /dev/null @@ -1,42 +0,0 @@ - - - -IPFS - - - -# -# Server-side - - - -# -# Client-side - - -http - - -HOME=%PWD/%LOGDIR - - -IPFS with malformed gateway URL from multiline gateway file, first line no url - - -ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u - - -foo -bar - - - -# -# Verify data after the test has been "shot" - -# malformed gateway URL, first line in file must be a gateway URL - -3 - - - diff --git a/deps/curl/tests/disable-scan.pl b/deps/curl/tests/disable-scan.pl index b6f3179c..99f5436a 100644 --- a/deps/curl/tests/disable-scan.pl +++ b/deps/curl/tests/disable-scan.pl @@ -29,8 +29,6 @@ use warnings; # the DISABLE options that can be set by configure my %disable; -# the DISABLE options that can be set by CMakeLists.txt -my %disable_cmake; # the DISABLE options that are used in C files my %file; # the DISABLE options that are documented @@ -63,24 +61,6 @@ sub scan_configure { } } -sub scanconf_cmake { - my ($f)=@_; - open S, "<$f"; - while() { - if(/(CURL_DISABLE_[A-Z_]+)/g) { - my ($sym)=($1); - if(not $sym =~ /(CURL_DISABLE_INSTALL|CURL_DISABLE_TESTS|CURL_DISABLE_SRP)/) { - $disable_cmake{$sym} = 1; - } - } - } - close S; -} - -sub scan_cmake { - scanconf_cmake("$root/CMakeLists.txt"); -} - sub scan_file { my ($source)=@_; open F, "<$source"; @@ -124,7 +104,6 @@ sub scan_docs { } scan_configure(); -scan_cmake(); scan_sources(); scan_docs(); @@ -142,28 +121,12 @@ for my $s (sort keys %disable) { } } -# Check the CMakeLists.txt symbols for use in code -for my $s (sort keys %disable_cmake) { - if(!$file{$s}) { - printf "Present in CMakeLists.txt, not used by code: %s\n", $s; - $error++; - } - if(!$docs{$s}) { - printf "Present in CMakeLists.txt, not documented in $DOCS: %s\n", $s; - $error++; - } -} - # Check the code symbols for use in configure for my $s (sort keys %file) { if(!$disable{$s}) { printf "Not set by configure: %s (%s)\n", $s, $file{$s}; $error++; } - if(!$disable_cmake{$s}) { - printf "Not set by CMakeLists.txt: %s (%s)\n", $s, $file{$s}; - $error++; - } if(!$docs{$s}) { printf "Used in code, not documented in $DOCS: %s\n", $s; $error++; @@ -176,10 +139,6 @@ for my $s (sort keys %docs) { printf "Documented but not in configure: %s\n", $s; $error++; } - if(!$disable_cmake{$s}) { - printf "Documented but not in CMakeLists.txt: %s\n", $s; - $error++; - } if(!$file{$s}) { printf "Documented, but not used by code: %s\n", $s; $error++; diff --git a/deps/curl/tests/errorcodes.pl b/deps/curl/tests/errorcodes.pl deleted file mode 100644 index 9c8f9e88..00000000 --- a/deps/curl/tests/errorcodes.pl +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env perl -#*************************************************************************** -# _ _ ____ _ -# Project ___| | | | _ \| | -# / __| | | | |_) | | -# | (__| |_| | _ <| |___ -# \___|\___/|_| \_\_____| -# -# Copyright (C) Daniel Stenberg, , et al. -# -# This software is licensed as described in the file COPYING, which -# you should have received as part of this distribution. The terms -# are also available at https://curl.se/docs/copyright.html. -# -# You may opt to use, copy, modify, merge, publish, distribute and/or sell -# copies of the Software, and permit persons to whom the Software is -# furnished to do so, under the terms of the COPYING file. -# -# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -# KIND, either express or implied. -# -# SPDX-License-Identifier: curl -# -########################################################################### - -# Check that libcurl-errors.3 and the public header files have the same set of -# error codes. - -use strict; -use warnings; - -# we may get the dir roots pointed out -my $root=$ARGV[0] || "."; -my $manpge = "$root/docs/libcurl/libcurl-errors.3"; -my $curlh = "$root/include/curl"; -my $errors=0; - -my @hnames; -my %wherefrom; -my @mnames; -my %manfrom; - -sub scanheader { - my ($file)=@_; - open H, "<$file"; - my $line = 0; - while() { - $line++; - if($_ =~ /^ (CURL(E|UE|SHE|HE|M)_[A-Z0-9_]*)/) { - my ($name)=($1); - if(($name !~ /OBSOLETE/) && ($name !~ /_LAST\z/)) { - push @hnames, $name; - if($wherefrom{$name}) { - print STDERR "double: $name\n"; - } - $wherefrom{$name}="$file:$line"; - } - } - } - close(H); -} - -sub scanmanpage { - my ($file)=@_; - open H, "<$file"; - my $line = 0; - while() { - $line++; - if($_ =~ /^\.IP \"(CURL(E|UE|SHE|HE|M)_[A-Z0-9_]*)/) { - my ($name)=($1); - push @mnames, $name; - $manfrom{$name}="$file:$line"; - } - } - close(H); -} - - -opendir(my $dh, $curlh) || die "Can't opendir $curlh: $!"; -my @hfiles = grep { /\.h$/ } readdir($dh); -closedir $dh; - -for(sort @hfiles) { - scanheader("$curlh/$_"); -} -scanmanpage($manpge); - -print "Result\n"; -for my $h (sort @hnames) { - if(!$manfrom{$h}) { - printf "$h from %s, not in man page\n", $wherefrom{$h}; - } -} - -for my $m (sort @mnames) { - if(!$wherefrom{$m}) { - printf "$m from %s, not in any header\n", $manfrom{$m}; - } -} diff --git a/deps/curl/tests/http/clients/h2-download.c b/deps/curl/tests/http/clients/h2-download.c index 53f3ac0d..24ccedbd 100644 --- a/deps/curl/tests/http/clients/h2-download.c +++ b/deps/curl/tests/http/clients/h2-download.c @@ -196,6 +196,7 @@ int main(int argc, char *argv[]) case 'h': usage(NULL); return 2; + break; case 'a': abort_paused = 1; break; diff --git a/deps/curl/tests/http/test_02_download.py b/deps/curl/tests/http/test_02_download.py index 391371c3..22fa32cd 100644 --- a/deps/curl/tests/http/test_02_download.py +++ b/deps/curl/tests/http/test_02_download.py @@ -108,17 +108,16 @@ class TestDownload: # download 500 files sequential @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3']) - def test_02_05_download_many_sequential(self, env: Env, - httpd, nghttpx, repeat, proto): + def test_02_05_download_500_sequential(self, env: Env, + httpd, nghttpx, repeat, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") if proto == 'h3' and env.curl_uses_lib('msh3'): pytest.skip("msh3 shaky here") - count = 200 curl = CurlClient(env=env) - urln = f'https://{env.authority_for(env.domain1, proto)}/data.json?[0-{count-1}]' + urln = f'https://{env.authority_for(env.domain1, proto)}/data.json?[0-499]' r = curl.http_download(urls=[urln], alpn_proto=proto) - r.check_response(http_status=200, count=count) + r.check_response(http_status=200, count=500) if proto == 'http/1.1': # http/1.1 parallel transfers will open multiple connections assert r.total_connects > 1, r.dump_logs() @@ -128,11 +127,11 @@ class TestDownload: # download 500 files parallel @pytest.mark.parametrize("proto", ['h2', 'h3']) - def test_02_06_download_many_parallel(self, env: Env, - httpd, nghttpx, repeat, proto): + def test_02_06_download_500_parallel(self, env: Env, + httpd, nghttpx, repeat, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - count = 200 + count = 500 max_parallel = 50 curl = CurlClient(env=env) urln = f'https://{env.authority_for(env.domain1, proto)}/data.json?[000-{count-1}]' @@ -208,7 +207,7 @@ class TestDownload: httpd, nghttpx, repeat, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - count = 10 + count = 20 urln = f'https://{env.authority_for(env.domain1, proto)}/data-10m?[0-{count-1}]' curl = CurlClient(env=env) r = curl.http_download(urls=[urln], alpn_proto=proto) @@ -223,7 +222,7 @@ class TestDownload: pytest.skip("h3 not supported") if proto == 'h3' and env.curl_uses_lib('msh3'): pytest.skip("msh3 stalls here") - count = 10 + count = 20 urln = f'https://{env.authority_for(env.domain1, proto)}/data-10m?[0-{count-1}]' curl = CurlClient(env=env) r = curl.http_download(urls=[urln], alpn_proto=proto, extra_args=[ @@ -236,7 +235,7 @@ class TestDownload: httpd, nghttpx, repeat, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - count = 50 + count = 100 urln = f'https://{env.authority_for(env.domain1, proto)}/data-10m?[0-{count-1}]' curl = CurlClient(env=env) r = curl.http_download(urls=[urln], alpn_proto=proto, extra_args=[ @@ -249,7 +248,7 @@ class TestDownload: httpd, nghttpx, repeat, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - count = 50 + count = 100 urln = f'http://{env.domain1}:{env.http_port}/data-10m?[0-{count-1}]' curl = CurlClient(env=env) r = curl.http_download(urls=[urln], alpn_proto=proto, extra_args=[ diff --git a/deps/curl/tests/http/test_07_upload.py b/deps/curl/tests/http/test_07_upload.py index 018a56c6..5aee3ea2 100644 --- a/deps/curl/tests/http/test_07_upload.py +++ b/deps/curl/tests/http/test_07_upload.py @@ -124,7 +124,7 @@ class TestUpload: if proto == 'h3' and env.curl_uses_lib('msh3'): pytest.skip("msh3 stalls here") fdata = os.path.join(env.gen_dir, 'data-100k') - count = 20 + count = 50 curl = CurlClient(env=env) url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-{count-1}]' r = curl.http_upload(urls=[url], data=f'@{fdata}', alpn_proto=proto) @@ -161,7 +161,7 @@ class TestUpload: if proto == 'h3' and env.curl_uses_lib('msh3'): pytest.skip("msh3 stalls here") # limit since we use a separate connection in h1 - count = 20 + count = 50 data = '0123456789' curl = CurlClient(env=env) url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-{count-1}]' @@ -181,7 +181,7 @@ class TestUpload: pytest.skip("msh3 stalls here") fdata = os.path.join(env.gen_dir, 'data-100k') # limit since we use a separate connection in h1 - count = 20 + count = 50 curl = CurlClient(env=env) url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-{count-1}]' r = curl.http_upload(urls=[url], data=f'@{fdata}', alpn_proto=proto, @@ -219,7 +219,7 @@ class TestUpload: fdata = os.path.join(env.gen_dir, 'data-10m') count = 1 curl = CurlClient(env=env) - url = f'https://{env.authority_for(env.domain1, proto)}/curltest/put?id=[0-{count-1}]&chunk_delay=2ms' + url = f'https://{env.authority_for(env.domain1, proto)}/curltest/put?id=[0-{count-1}]&chunk_delay=10ms' r = curl.http_put(urls=[url], fdata=fdata, alpn_proto=proto, extra_args=['--parallel']) r.check_stats(count=count, http_status=200, exitcode=0) diff --git a/deps/curl/tests/http/test_10_proxy.py b/deps/curl/tests/http/test_10_proxy.py index 0e4060b6..df234013 100644 --- a/deps/curl/tests/http/test_10_proxy.py +++ b/deps/curl/tests/http/test_10_proxy.py @@ -247,105 +247,3 @@ class TestProxy: assert r.total_connects == 2 else: assert r.total_connects == 2 - - @pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL") - @pytest.mark.parametrize("tunnel", ['http/1.1', 'h2']) - @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available") - def test_10_10_reuse_proxy(self, env: Env, httpd, nghttpx_fwd, tunnel, repeat): - # url twice via https: proxy separated with '--next', will reuse - if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'): - pytest.skip('only supported with nghttp2') - curl = CurlClient(env=env) - url = f'https://localhost:{env.https_port}/data.json' - proxy_args = curl.get_proxy_args(tunnel=True, proto=tunnel) - r1 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True, - extra_args=proxy_args) - r1.check_response(count=1, http_status=200) - assert self.get_tunnel_proto_used(r1) == 'HTTP/2' \ - if tunnel == 'h2' else 'HTTP/1.1' - # get the args, duplicate separated with '--next' - x2_args = r1.args[1:] - x2_args.append('--next') - x2_args.extend(proxy_args) - r2 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True, - extra_args=x2_args) - r2.check_response(count=2, http_status=200) - assert r2.total_connects == 1 - - @pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL") - @pytest.mark.parametrize("tunnel", ['http/1.1', 'h2']) - @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available") - @pytest.mark.skipif(condition=not Env.curl_uses_lib('openssl'), reason="tls13-ciphers not supported") - def test_10_11_noreuse_proxy_https(self, env: Env, httpd, nghttpx_fwd, tunnel, repeat): - # different --proxy-tls13-ciphers, no reuse of connection for https: - curl = CurlClient(env=env) - if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'): - pytest.skip('only supported with nghttp2') - url = f'https://localhost:{env.https_port}/data.json' - proxy_args = curl.get_proxy_args(tunnel=True, proto=tunnel) - r1 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True, - extra_args=proxy_args) - r1.check_response(count=1, http_status=200) - assert self.get_tunnel_proto_used(r1) == 'HTTP/2' \ - if tunnel == 'h2' else 'HTTP/1.1' - # get the args, duplicate separated with '--next' - x2_args = r1.args[1:] - x2_args.append('--next') - x2_args.extend(proxy_args) - x2_args.extend(['--proxy-tls13-ciphers', 'TLS_AES_128_GCM_SHA256']) - r2 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True, - extra_args=x2_args) - r2.check_response(count=2, http_status=200) - assert r2.total_connects == 2 - - @pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL") - @pytest.mark.parametrize("tunnel", ['http/1.1', 'h2']) - @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available") - @pytest.mark.skipif(condition=not Env.curl_uses_lib('openssl'), reason="tls13-ciphers not supported") - def test_10_12_noreuse_proxy_http(self, env: Env, httpd, nghttpx_fwd, tunnel, repeat): - # different --proxy-tls13-ciphers, no reuse of connection for http: - if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'): - pytest.skip('only supported with nghttp2') - curl = CurlClient(env=env) - url = f'http://localhost:{env.http_port}/data.json' - proxy_args = curl.get_proxy_args(tunnel=True, proto=tunnel) - r1 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True, - extra_args=proxy_args) - r1.check_response(count=1, http_status=200) - assert self.get_tunnel_proto_used(r1) == 'HTTP/2' \ - if tunnel == 'h2' else 'HTTP/1.1' - # get the args, duplicate separated with '--next' - x2_args = r1.args[1:] - x2_args.append('--next') - x2_args.extend(proxy_args) - x2_args.extend(['--proxy-tls13-ciphers', 'TLS_AES_128_GCM_SHA256']) - r2 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True, - extra_args=x2_args) - r2.check_response(count=2, http_status=200) - assert r2.total_connects == 2 - - @pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL") - @pytest.mark.parametrize("tunnel", ['http/1.1', 'h2']) - @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available") - @pytest.mark.skipif(condition=not Env.curl_uses_lib('openssl'), reason="tls13-ciphers not supported") - def test_10_13_noreuse_https(self, env: Env, httpd, nghttpx_fwd, tunnel, repeat): - # different --tls13-ciphers on https: same proxy config - if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'): - pytest.skip('only supported with nghttp2') - curl = CurlClient(env=env) - url = f'https://localhost:{env.https_port}/data.json' - proxy_args = curl.get_proxy_args(tunnel=True, proto=tunnel) - r1 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True, - extra_args=proxy_args) - r1.check_response(count=1, http_status=200) - assert self.get_tunnel_proto_used(r1) == 'HTTP/2' \ - if tunnel == 'h2' else 'HTTP/1.1' - # get the args, duplicate separated with '--next' - x2_args = r1.args[1:] - x2_args.append('--next') - x2_args.extend(proxy_args) - x2_args.extend(['--tls13-ciphers', 'TLS_AES_128_GCM_SHA256']) - r2 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True, - extra_args=x2_args) - r2.check_response(count=2, http_status=200) - assert r2.total_connects == 2 diff --git a/deps/curl/tests/http/testenv/curl.py b/deps/curl/tests/http/testenv/curl.py index bc5b4881..9f92f629 100644 --- a/deps/curl/tests/http/testenv/curl.py +++ b/deps/curl/tests/http/testenv/curl.py @@ -504,20 +504,14 @@ class CurlClient: args = [self._curl, "-s", "--path-as-is"] if with_headers: args.extend(["-D", self._headerfile]) - if def_tracing is not False and not self._silent: - args.extend(['-v', '--trace-ids', '--trace-time']) + if def_tracing is not False: + args.extend(['-v', '--trace-config', 'ids,time']) if self.env.verbose > 1: args.extend(['--trace-config', 'http/2,http/3,h2-proxy,h1-proxy']) pass - active_options = options - if options is not None and '--next' in options: - active_options = options[options.index('--next') + 1:] - for url in urls: u = urlparse(urls[0]) - if options: - args.extend(options) if alpn_proto is not None: if alpn_proto not in self.ALPN_ARG: raise Exception(f'unknown ALPN protocol: "{alpn_proto}"') @@ -527,7 +521,7 @@ class CurlClient: pass elif insecure: args.append('--insecure') - elif active_options and "--cacert" in active_options: + elif options and "--cacert" in options: pass elif u.hostname: args.extend(["--cacert", self.env.ca.cert_file]) @@ -538,6 +532,8 @@ class CurlClient: args.extend(["--resolve", f"{u.hostname}:{port}:127.0.0.1"]) if timeout is not None and int(timeout) > 0: args.extend(["--connect-timeout", str(int(timeout))]) + if options: + args.extend(options) args.append(url) return args diff --git a/deps/curl/tests/libtest/CMakeLists.txt b/deps/curl/tests/libtest/CMakeLists.txt index b6450ff3..98f5b9c6 100644 --- a/deps/curl/tests/libtest/CMakeLists.txt +++ b/deps/curl/tests/libtest/CMakeLists.txt @@ -67,7 +67,7 @@ endforeach() # Allows for hostname override to make tests machine independent. # TODO this cmake build assumes a shared build, detect static linking here! if(NOT WIN32) - add_library(hostname MODULE EXCLUDE_FROM_ALL sethostname.c) + add_library(hostname MODULE EXCLUDE_FROM_ALL sethostname.c sethostname.h) add_dependencies(testdeps hostname) # Output to .libs for compatibility with autotools, the test data expects a # library at (tests)/libtest/.libs/libhostname.so diff --git a/deps/curl/tests/libtest/Makefile.am b/deps/curl/tests/libtest/Makefile.am index 8ae972a2..09a13914 100644 --- a/deps/curl/tests/libtest/Makefile.am +++ b/deps/curl/tests/libtest/Makefile.am @@ -103,7 +103,7 @@ libhostname_la_CPPFLAGS = $(AM_CPPFLAGS) $(libhostname_la_CPPFLAGS_EXTRA) libhostname_la_LDFLAGS = $(AM_LDFLAGS) $(libhostname_la_LDFLAGS_EXTRA) libhostname_la_CFLAGS = $(AM_CFLAGS) $(libhostname_la_CFLAGS_EXTRA) -libhostname_la_SOURCES = sethostname.c +libhostname_la_SOURCES = sethostname.c sethostname.h libhostname_la_LIBADD = libhostname_la_DEPENDENCIES = diff --git a/deps/curl/tests/libtest/Makefile.inc b/deps/curl/tests/libtest/Makefile.inc index c4d36a26..85801e00 100644 --- a/deps/curl/tests/libtest/Makefile.inc +++ b/deps/curl/tests/libtest/Makefile.inc @@ -58,14 +58,13 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect libprereq \ lib1518 lib1520 lib1521 lib1522 lib1523 \ lib1525 lib1526 lib1527 lib1528 lib1529 lib1530 lib1531 lib1532 lib1533 \ lib1534 lib1535 lib1536 lib1537 lib1538 lib1539 \ - lib1540 lib1542 lib1543 lib1545 \ + lib1540 lib1542 lib1543 \ lib1550 lib1551 lib1552 lib1553 lib1554 lib1555 lib1556 lib1557 \ lib1558 lib1559 lib1560 lib1564 lib1565 lib1567 lib1568 lib1569 \ lib1591 lib1592 lib1593 lib1594 lib1596 lib1597 \ \ lib1662 \ \ - lib1900 \ lib1903 lib1905 lib1906 lib1907 lib1908 lib1910 lib1911 lib1912 lib1913 \ lib1915 lib1916 lib1917 lib1918 lib1919 \ lib1933 lib1934 lib1935 lib1936 lib1937 lib1938 lib1939 lib1940 \ @@ -467,9 +466,6 @@ lib1542_LDADD = $(TESTUTIL_LIBS) lib1543_SOURCES = lib1518.c $(SUPPORTFILES) lib1543_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1543 -lib1545_SOURCES = lib1545.c $(SUPPORTFILES) -lib1545_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_DISABLE_DEPRECATION - lib1550_SOURCES = lib1550.c $(SUPPORTFILES) lib1551_SOURCES = lib1551.c $(SUPPORTFILES) @@ -534,8 +530,6 @@ lib1597_LDADD = $(TESTUTIL_LIBS) lib1662_SOURCES = lib1662.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) lib1662_LDADD = $(TESTUTIL_LIBS) -lib1900_SOURCES = lib1900.c $(SUPPORTFILES) - lib1903_SOURCES = lib1903.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) lib1903_LDADD = $(TESTUTIL_LIBS) diff --git a/deps/curl/tests/libtest/first.c b/deps/curl/tests/libtest/first.c index 6d138068..7bd129ab 100644 --- a/deps/curl/tests/libtest/first.c +++ b/deps/curl/tests/libtest/first.c @@ -174,7 +174,7 @@ int main(int argc, char **argv) result = test(URL); fprintf(stderr, "Test ended with result %d\n", result); -#ifdef _WIN32 +#ifdef WIN32 /* flush buffers of all streams regardless of mode */ _flushall(); #endif diff --git a/deps/curl/tests/libtest/lib1156.c b/deps/curl/tests/libtest/lib1156.c index b512ef67..aae2893e 100644 --- a/deps/curl/tests/libtest/lib1156.c +++ b/deps/curl/tests/libtest/lib1156.c @@ -68,7 +68,7 @@ static const struct testparams params[] = { { F_RESUME | F_HTTP416 | F_CONTENTRANGE | F_IGNOREBODY, CURLE_OK }, { F_RESUME | F_HTTP416 | F_FAIL | F_IGNOREBODY, CURLE_OK }, { F_RESUME | F_HTTP416 | F_FAIL | F_CONTENTRANGE | F_IGNOREBODY, - CURLE_OK } + CURLE_HTTP_RETURNED_ERROR } }; static int hasbody; diff --git a/deps/curl/tests/libtest/lib1517.c b/deps/curl/tests/libtest/lib1517.c index 12679201..706b5567 100644 --- a/deps/curl/tests/libtest/lib1517.c +++ b/deps/curl/tests/libtest/lib1517.c @@ -61,7 +61,7 @@ int test(char *URL) struct WriteThis pooh; if(!strcmp(URL, "check")) { -#if (defined(_WIN32) || defined(__CYGWIN__)) +#if (defined(WIN32) || defined(__CYGWIN__)) printf("Windows TCP does not deliver response data but reports " "CONNABORTED\n"); return 1; /* skip since test will fail on Windows without workaround */ diff --git a/deps/curl/tests/libtest/lib1531.c b/deps/curl/tests/libtest/lib1531.c index b64e1660..70340017 100644 --- a/deps/curl/tests/libtest/lib1531.c +++ b/deps/curl/tests/libtest/lib1531.c @@ -110,7 +110,7 @@ int test(char *URL) curl_multi_fdset() doc. */ if(maxfd == -1) { -#if defined(_WIN32) +#if defined(WIN32) || defined(_WIN32) Sleep(100); rc = 0; #else diff --git a/deps/curl/tests/libtest/lib1545.c b/deps/curl/tests/libtest/lib1545.c deleted file mode 100644 index 9278b2a5..00000000 --- a/deps/curl/tests/libtest/lib1545.c +++ /dev/null @@ -1,53 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at https://curl.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - * SPDX-License-Identifier: curl - * - ***************************************************************************/ -#include "test.h" - -int test(char *URL) -{ - CURL *eh = NULL; - int res = 0; - struct curl_httppost *lastptr = NULL; - struct curl_httppost *m_formpost = NULL; - - global_init(CURL_GLOBAL_ALL); - - easy_init(eh); - - easy_setopt(eh, CURLOPT_URL, URL); - curl_formadd(&m_formpost, &lastptr, CURLFORM_COPYNAME, "file", - CURLFORM_FILE, "missing-file", CURLFORM_END); - curl_easy_setopt(eh, CURLOPT_HTTPPOST, m_formpost); - - (void)curl_easy_perform(eh); - (void)curl_easy_perform(eh); - -test_cleanup: - - curl_formfree(m_formpost); - - curl_easy_cleanup(eh); - curl_global_cleanup(); - - return res; -} diff --git a/deps/curl/tests/libtest/lib1560.c b/deps/curl/tests/libtest/lib1560.c index 87420a33..765df0a2 100644 --- a/deps/curl/tests/libtest/lib1560.c +++ b/deps/curl/tests/libtest/lib1560.c @@ -151,9 +151,6 @@ struct clearurlcase { }; static const struct testcase get_parts_list[] ={ - {"https://curl.se/# ", - "https | [11] | [12] | [13] | curl.se | [15] | / | [16] | %20%20", - CURLU_URLENCODE|CURLU_ALLOW_SPACE, 0, CURLUE_OK}, {"", "", 0, 0, CURLUE_MALFORMED_INPUT}, {" ", "", 0, 0, CURLUE_MALFORMED_INPUT}, {"1h://example.net", "", 0, 0, CURLUE_BAD_SCHEME}, @@ -319,7 +316,7 @@ static const struct testcase get_parts_list[] ={ "http | ftp.user | moo | [13] | example.com | [15] | /color/ | [16] | " "green?no-red", CURLU_GUESS_SCHEME, 0, CURLUE_OK }, -#ifdef _WIN32 +#ifdef WIN32 {"file:/C:\\programs\\foo", "file | [11] | [12] | [13] | [14] | [15] | C:\\programs\\foo | [16] | [17]", CURLU_DEFAULT_SCHEME, 0, CURLUE_OK}, @@ -788,18 +785,6 @@ static const struct setgetcase setget_parts_list[] = { /* !checksrc! disable SPACEBEFORECOMMA 1 */ static const struct setcase set_parts_list[] = { - {"https://example.com/?param=value", - "query=\"\",", - "https://example.com/", - 0, CURLU_APPENDQUERY | CURLU_URLENCODE, CURLUE_OK, CURLUE_OK}, - {"https://example.com/", - "host=\"\",", - "https://example.com/", - 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_BAD_HOSTNAME}, - {"https://example.com/", - "host=\"\",", - "https://example.com/", - 0, 0, CURLUE_OK, CURLUE_BAD_HOSTNAME}, {"https://example.com", "path=get,", "https://example.com/get", diff --git a/deps/curl/tests/libtest/lib1900.c b/deps/curl/tests/libtest/lib1900.c deleted file mode 100644 index 92f89c4c..00000000 --- a/deps/curl/tests/libtest/lib1900.c +++ /dev/null @@ -1,55 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at https://curl.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - * SPDX-License-Identifier: curl - * - ***************************************************************************/ -#include "test.h" - -#include "testutil.h" -#include "warnless.h" -#include "memdebug.h" - -int test(char *URL) -{ - CURLcode res = CURLE_OK; - CURL *hnd = NULL; - CURL *second = NULL; - - global_init(CURL_GLOBAL_ALL); - - easy_init(hnd); - easy_setopt(hnd, CURLOPT_URL, URL); - easy_setopt(hnd, CURLOPT_HSTS, "first-hsts.txt"); - easy_setopt(hnd, CURLOPT_HSTS, "second-hsts.txt"); - - second = curl_easy_duphandle(hnd); - - curl_easy_cleanup(hnd); - curl_easy_cleanup(second); - curl_global_cleanup(); - return 0; - -test_cleanup: - curl_easy_cleanup(hnd); - curl_easy_cleanup(second); - curl_global_cleanup(); - return (int)res; -} diff --git a/deps/curl/tests/libtest/lib1960.c b/deps/curl/tests/libtest/lib1960.c index b01370e6..fc2f4b0a 100644 --- a/deps/curl/tests/libtest/lib1960.c +++ b/deps/curl/tests/libtest/lib1960.c @@ -25,7 +25,7 @@ #ifdef HAVE_INET_PTON -#ifdef _WIN32 +#ifdef WIN32 #include #include #include diff --git a/deps/curl/tests/libtest/lib2305.c b/deps/curl/tests/libtest/lib2305.c index 374423f0..0778e0b5 100644 --- a/deps/curl/tests/libtest/lib2305.c +++ b/deps/curl/tests/libtest/lib2305.c @@ -71,6 +71,8 @@ static void websocket(CURL *curl) websocket_close(curl); } +extern struct libtest_trace_cfg libtest_debug_config; + int test(char *URL) { CURL *curl; diff --git a/deps/curl/tests/libtest/lib3026.c b/deps/curl/tests/libtest/lib3026.c index 34dcafc5..42b44c89 100644 --- a/deps/curl/tests/libtest/lib3026.c +++ b/deps/curl/tests/libtest/lib3026.c @@ -28,7 +28,7 @@ #define NUM_THREADS 100 -#ifdef _WIN32 +#ifdef WIN32 #ifdef _WIN32_WCE static DWORD WINAPI run_thread(LPVOID ptr) #else diff --git a/deps/curl/tests/libtest/lib518.c b/deps/curl/tests/libtest/lib518.c index e61d80a6..87b6f2d8 100644 --- a/deps/curl/tests/libtest/lib518.c +++ b/deps/curl/tests/libtest/lib518.c @@ -42,7 +42,7 @@ #define NUM_OPEN (FD_SETSIZE + 10) #define NUM_NEEDED (NUM_OPEN + SAFETY_MARGIN) -#if defined(_WIN32) || defined(MSDOS) +#if defined(WIN32) || defined(_WIN32) || defined(MSDOS) #define DEV_NULL "NUL" #else #define DEV_NULL "/dev/null" diff --git a/deps/curl/tests/libtest/lib537.c b/deps/curl/tests/libtest/lib537.c index 8735947c..3782282b 100644 --- a/deps/curl/tests/libtest/lib537.c +++ b/deps/curl/tests/libtest/lib537.c @@ -42,7 +42,7 @@ #define SAFETY_MARGIN (11) -#if defined(_WIN32) || defined(MSDOS) +#if defined(WIN32) || defined(_WIN32) || defined(MSDOS) #define DEV_NULL "NUL" #else #define DEV_NULL "/dev/null" diff --git a/deps/curl/tests/libtest/lib544.c b/deps/curl/tests/libtest/lib544.c index a58fa05e..192bfb2e 100644 --- a/deps/curl/tests/libtest/lib544.c +++ b/deps/curl/tests/libtest/lib544.c @@ -63,6 +63,7 @@ int test(char *URL) /* Update the original data to detect non-copy. */ strcpy(teststring, "FAIL"); +#ifdef LIB545 { CURL *handle2; handle2 = curl_easy_duphandle(curl); @@ -70,6 +71,7 @@ int test(char *URL) curl = handle2; } +#endif /* Now, this is a POST request with binary 0 embedded in POST data. */ res = curl_easy_perform(curl); diff --git a/deps/curl/tests/libtest/lib670.c b/deps/curl/tests/libtest/lib670.c index b348343c..700b908c 100644 --- a/deps/curl/tests/libtest/lib670.c +++ b/deps/curl/tests/libtest/lib670.c @@ -215,7 +215,7 @@ int test(char *URL) mres = curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcept, &maxfd); if(mres) break; -#if defined(_WIN32) +#if defined(WIN32) || defined(_WIN32) if(maxfd == -1) Sleep(100); else diff --git a/deps/curl/tests/libtest/sethostname.c b/deps/curl/tests/libtest/sethostname.c index 1e07d26b..9dcad976 100644 --- a/deps/curl/tests/libtest/sethostname.c +++ b/deps/curl/tests/libtest/sethostname.c @@ -23,6 +23,8 @@ ***************************************************************************/ #include "curl_setup.h" +#include "sethostname.h" + /* * we force our own host name, in order to make some tests machine independent */ diff --git a/deps/curl/src/tool_ipfs.h b/deps/curl/tests/libtest/sethostname.h similarity index 70% rename from deps/curl/src/tool_ipfs.h rename to deps/curl/tests/libtest/sethostname.h index 9c8a83e3..1ffcba11 100644 --- a/deps/curl/src/tool_ipfs.h +++ b/deps/curl/tests/libtest/sethostname.h @@ -1,5 +1,3 @@ -#ifndef HEADER_CURL_TOOL_IPFS_H -#define HEADER_CURL_TOOL_IPFS_H /*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | @@ -23,11 +21,22 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ -#include "tool_setup.h" -#define MAX_GATEWAY_URL_LEN 10000 +#ifdef CURL_STATICLIB +# define LIBHOSTNAME_EXTERN +#elif defined(WIN32) +# define LIBHOSTNAME_EXTERN __declspec(dllexport) +#elif defined(CURL_HIDDEN_SYMBOLS) +# define LIBHOSTNAME_EXTERN CURL_EXTERN_SYMBOL +#else +# define LIBHOSTNAME_EXTERN +#endif -CURLcode ipfs_url_rewrite(CURLU *uh, const char *protocol, char **url, - struct OperationConfig *config); +#ifdef USE_WINSOCK +# define FUNCALLCONV __stdcall +#else +# define FUNCALLCONV +#endif -#endif /* HEADER_CURL_TOOL_IPFS_H */ +LIBHOSTNAME_EXTERN int FUNCALLCONV + gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen); diff --git a/deps/curl/tests/libtest/stub_gssapi.c b/deps/curl/tests/libtest/stub_gssapi.c index 85c760c2..634dddfd 100644 --- a/deps/curl/tests/libtest/stub_gssapi.c +++ b/deps/curl/tests/libtest/stub_gssapi.c @@ -183,7 +183,7 @@ OM_uint32 gss_init_sec_context(OM_uint32 *min, return GSS_S_FAILURE; } - ctx = (gss_ctx_id_t) calloc(1, sizeof(*ctx)); + ctx = (gss_ctx_id_t) calloc(sizeof(*ctx), 1); if(!ctx) { *min = GSS_NO_MEMORY; return GSS_S_FAILURE; diff --git a/deps/curl/tests/libtest/test.h b/deps/curl/tests/libtest/test.h index 7f29db11..7eb7fdaa 100644 --- a/deps/curl/tests/libtest/test.h +++ b/deps/curl/tests/libtest/test.h @@ -42,7 +42,7 @@ #include "curl_printf.h" -#ifdef _WIN32 +#ifdef WIN32 #define sleep(sec) Sleep ((sec)*1000) #endif diff --git a/deps/curl/tests/libtest/test613.pl b/deps/curl/tests/libtest/test613.pl index dee3b175..3ad7805a 100644 --- a/deps/curl/tests/libtest/test613.pl +++ b/deps/curl/tests/libtest/test613.pl @@ -81,7 +81,7 @@ elsif ($ARGV[0] eq "postprocess") rmdir $dirname || die "$!"; - if ($logfile && -s $logfile) { + if ($logfile) { # Process the directory file to remove all information that # could be inconsistent from one test run to the next (e.g. # file date) or may be unsupported on some platforms (e.g. diff --git a/deps/curl/tests/libtest/testutil.c b/deps/curl/tests/libtest/testutil.c index 4a3cd944..1a1e689e 100644 --- a/deps/curl/tests/libtest/testutil.c +++ b/deps/curl/tests/libtest/testutil.c @@ -26,7 +26,7 @@ #include "testutil.h" #include "memdebug.h" -#if defined(_WIN32) +#if defined(WIN32) && !defined(MSDOS) struct timeval tutil_tvnow(void) { @@ -130,7 +130,7 @@ double tutil_tvdiff_secs(struct timeval newer, struct timeval older) return (double)(newer.tv_usec-older.tv_usec)/1000000.0; } -#ifdef _WIN32 +#ifdef WIN32 HMODULE win32_load_system_library(const TCHAR *filename) { size_t filenamelen = _tcslen(filename); diff --git a/deps/curl/tests/libtest/testutil.h b/deps/curl/tests/libtest/testutil.h index 9f063795..36b94483 100644 --- a/deps/curl/tests/libtest/testutil.h +++ b/deps/curl/tests/libtest/testutil.h @@ -42,7 +42,7 @@ long tutil_tvdiff(struct timeval t1, struct timeval t2); */ double tutil_tvdiff_secs(struct timeval t1, struct timeval t2); -#ifdef _WIN32 +#ifdef WIN32 HMODULE win32_load_system_library(const TCHAR *filename); #endif diff --git a/deps/curl/tests/pathhelp.pm b/deps/curl/tests/pathhelp.pm index 3afc5dac..7d924b86 100644 --- a/deps/curl/tests/pathhelp.pm +++ b/deps/curl/tests/pathhelp.pm @@ -789,7 +789,6 @@ sub exe_ext { $^O eq 'dos' || $^O eq 'os2') { return '.exe'; } - return ''; } 1; # End of module diff --git a/deps/curl/tests/runtests.1 b/deps/curl/tests/runtests.1 index 6d895d2b..571e5ce0 100644 --- a/deps/curl/tests/runtests.1 +++ b/deps/curl/tests/runtests.1 @@ -53,35 +53,6 @@ this keyword. Remember that the exclamation marks and spaces will need to be quoted somehow when entered at many command shells. Prefix a keyword with a tilde (~) to still run it, but ignore the results. - -.SH "OUTPUT" - -When running without -s (short output), for instance when running runtests.pl -directly rather than via make, each test will emits a pair of lines like this: - -Test 0045...[simple HTTP Location: without protocol in initial URL] ---pd---e-v- OK (45 out of 1427, remaining: 16:08, took 6.188s, duration: 00:31) - -the first line contains the test number and a description. On the second line, -the characters at the beginning are flags indicating which aspects of curl's -behavior were checked by the test: - - s stdout - r stderr - p protocol - d data - u upload - P proxy - o output - e exit code - m memory - v valgrind - E the test was run event-based - -The remainder of the second line contains the test result, current test sequence, -total number of tests to be run and an estimated amount of time to complete the -test run. - .SH OPTIONS .IP "-a" Continue running the rest of the test cases even if one test fails. By @@ -120,6 +91,9 @@ start. Run the given test(s) with gdb as a windowed application. .IP "-h, --help" Displays a help text about this program's command line options. +.IP "-k" +Keep output and log files in log/ after a test run, even if no error was +detected. Useful for debugging. .IP "-j[num]" Spawn num processes to run tests. This defaults to 0 to run tests serially within a single process. Using a number greater than one allows multiple tests @@ -127,9 +101,6 @@ to run in parallel, speeding up a test run. The optimum number is dependent on the system and set of tests to run, but 7*number of CPU cores is a good figure to start with, or 1.3*number of CPU cores if Valgrind is in use. Enabling parallel tests is not recommended in conjunction with the \-g option. -.IP "-k" -Keep output and log files in log/ after a test run, even if no error was -detected. Useful for debugging. .IP "-L " Load and execute the specified file which should contain perl code. This option allows one to change \fIruntests.pl\fP behaviour by overwriting diff --git a/deps/curl/tests/runtests.pl b/deps/curl/tests/runtests.pl index e7b9f01f..32e06803 100644 --- a/deps/curl/tests/runtests.pl +++ b/deps/curl/tests/runtests.pl @@ -23,8 +23,6 @@ # ########################################################################### -# For documentation, run `man ./runtests.1` and see README.md. - # Experimental hooks are available to run tests remotely on machines that # are able to run curl but are unable to run the test harness. # The following sections need to be modified: @@ -1505,7 +1503,7 @@ sub singletest_check { } else { - $ok .= "-"; # proxy not checked + $ok .= "-"; # protocol not checked } my $outputok; diff --git a/deps/curl/tests/server/getpart.c b/deps/curl/tests/server/getpart.c index 9ab9e88d..7d3bff75 100644 --- a/deps/curl/tests/server/getpart.c +++ b/deps/curl/tests/server/getpart.c @@ -60,7 +60,7 @@ curl_free_callback Curl_cfree = (curl_free_callback)free; curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc; curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)strdup; curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc; -#if defined(_WIN32) && defined(UNICODE) +#if defined(WIN32) && defined(UNICODE) curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; #endif @@ -149,7 +149,7 @@ static int readline(char **buffer, size_t *bufsize, size_t *length, char *newptr; if(!*buffer) { - *buffer = calloc(1, 128); + *buffer = calloc(128, 1); if(!*buffer) return GPE_OUT_OF_MEMORY; *bufsize = 128; diff --git a/deps/curl/tests/server/mqttd.c b/deps/curl/tests/server/mqttd.c index 8a0da3ee..55ef02cd 100644 --- a/deps/curl/tests/server/mqttd.c +++ b/deps/curl/tests/server/mqttd.c @@ -98,6 +98,7 @@ #define MQTT_CONNACK_LEN 4 #define MQTT_SUBACK_LEN 5 #define MQTT_CLIENTID_LEN 12 /* "curl0123abcd" */ +#define MQTT_HEADER_LEN 5 /* max 5 bytes */ struct configurable { unsigned char version; /* initial version byte in the request must match @@ -1016,7 +1017,7 @@ int main(int argc, char *argv[]) msnprintf(loglockfile, sizeof(loglockfile), "%s/%s/mqtt-%s.lock", logdir, SERVERLOGS_LOCKDIR, ipv_inuse); -#ifdef _WIN32 +#ifdef WIN32 win32_init(); atexit(win32_cleanup); diff --git a/deps/curl/tests/server/resolve.c b/deps/curl/tests/server/resolve.c index 8ae31bc5..221df64b 100644 --- a/deps/curl/tests/server/resolve.c +++ b/deps/curl/tests/server/resolve.c @@ -102,7 +102,7 @@ int main(int argc, char *argv[]) return 1; } -#ifdef _WIN32 +#ifdef WIN32 win32_init(); atexit(win32_cleanup); #endif diff --git a/deps/curl/tests/server/rtspd.c b/deps/curl/tests/server/rtspd.c index 9c01ce87..dbe8a48b 100644 --- a/deps/curl/tests/server/rtspd.c +++ b/deps/curl/tests/server/rtspd.c @@ -1150,7 +1150,7 @@ int main(int argc, char *argv[]) msnprintf(loglockfile, sizeof(loglockfile), "%s/%s/rtsp-%s.lock", logdir, SERVERLOGS_LOCKDIR, ipv_inuse); -#ifdef _WIN32 +#ifdef WIN32 win32_init(); atexit(win32_cleanup); #endif diff --git a/deps/curl/tests/server/sockfilt.c b/deps/curl/tests/server/sockfilt.c index f87d1c8f..7e342e33 100644 --- a/deps/curl/tests/server/sockfilt.c +++ b/deps/curl/tests/server/sockfilt.c @@ -152,7 +152,7 @@ enum sockmode { ACTIVE_DISCONNECT /* as a client, disconnected from server */ }; -#ifdef _WIN32 +#ifdef WIN32 /* * read-wrapper to support reading from stdin on Windows. */ @@ -1461,7 +1461,7 @@ int main(int argc, char *argv[]) } } -#ifdef _WIN32 +#ifdef WIN32 win32_init(); atexit(win32_cleanup); diff --git a/deps/curl/tests/server/socksd.c b/deps/curl/tests/server/socksd.c index 490085d4..cf9a14fd 100644 --- a/deps/curl/tests/server/socksd.c +++ b/deps/curl/tests/server/socksd.c @@ -379,10 +379,6 @@ static curl_socket_t sockit(curl_socket_t fd) getconfig(); rc = recv(fd, (char *)buffer, sizeof(buffer), 0); - if(rc <= 0) { - logmsg("SOCKS identifier message missing, recv returned %d", rc); - return CURL_SOCKET_BAD; - } logmsg("READ %d bytes", rc); loghex(buffer, rc); @@ -390,11 +386,6 @@ static curl_socket_t sockit(curl_socket_t fd) if(buffer[SOCKS5_VERSION] == 4) return socks4(fd, buffer, rc); - if(rc < 3) { - logmsg("SOCKS5 identifier message too short: %d", rc); - return CURL_SOCKET_BAD; - } - if(buffer[SOCKS5_VERSION] != config.version) { logmsg("VERSION byte not %d", config.version); return CURL_SOCKET_BAD; @@ -426,10 +417,6 @@ static curl_socket_t sockit(curl_socket_t fd) /* expect the request or auth */ rc = recv(fd, (char *)buffer, sizeof(buffer), 0); - if(rc <= 0) { - logmsg("SOCKS5 request or auth message missing, recv returned %d", rc); - return CURL_SOCKET_BAD; - } logmsg("READ %d bytes", rc); loghex(buffer, rc); @@ -485,10 +472,6 @@ static curl_socket_t sockit(curl_socket_t fd) /* expect the request */ rc = recv(fd, (char *)buffer, sizeof(buffer), 0); - if(rc <= 0) { - logmsg("SOCKS5 request message missing, recv returned %d", rc); - return CURL_SOCKET_BAD; - } logmsg("READ %d bytes", rc); loghex(buffer, rc); @@ -1076,7 +1059,7 @@ int main(int argc, char *argv[]) } } -#ifdef _WIN32 +#ifdef WIN32 win32_init(); atexit(win32_cleanup); diff --git a/deps/curl/tests/server/sws.c b/deps/curl/tests/server/sws.c index fa9b1ac8..bea3191a 100644 --- a/deps/curl/tests/server/sws.c +++ b/deps/curl/tests/server/sws.c @@ -2119,7 +2119,7 @@ int main(int argc, char *argv[]) logdir, SERVERLOGS_LOCKDIR, protocol_type, is_proxy ? "-proxy" : "", socket_type); -#ifdef _WIN32 +#ifdef WIN32 win32_init(); atexit(win32_cleanup); #endif diff --git a/deps/curl/tests/server/tftpd.c b/deps/curl/tests/server/tftpd.c index 9f93f4c6..670897c0 100644 --- a/deps/curl/tests/server/tftpd.c +++ b/deps/curl/tests/server/tftpd.c @@ -453,7 +453,7 @@ static ssize_t write_behind(struct testcase *test, int convert) if(!test->ofile) { char outfile[256]; msnprintf(outfile, sizeof(outfile), "%s/upload.%ld", logdir, test->testno); -#ifdef _WIN32 +#ifdef WIN32 test->ofile = open(outfile, O_CREAT|O_RDWR|O_BINARY, 0777); #else test->ofile = open(outfile, O_CREAT|O_RDWR, 0777); @@ -642,7 +642,7 @@ int main(int argc, char **argv) msnprintf(loglockfile, sizeof(loglockfile), "%s/%s/tftp-%s.lock", logdir, SERVERLOGS_LOCKDIR, ipv_inuse); -#ifdef _WIN32 +#ifdef WIN32 win32_init(); atexit(win32_cleanup); #endif diff --git a/deps/curl/tests/server/util.c b/deps/curl/tests/server/util.c index 5cfdab26..19faa261 100644 --- a/deps/curl/tests/server/util.c +++ b/deps/curl/tests/server/util.c @@ -144,7 +144,7 @@ void logmsg(const char *msg, ...) } } -#ifdef _WIN32 +#ifdef WIN32 /* use instead of strerror() on generic Windows */ static const char *win32_strerror(int err, char *buf, size_t buflen) { @@ -208,7 +208,7 @@ const char *sstrerror(int err) static char buf[512]; return win32_strerror(err, buf, sizeof(buf)); } -#endif /* _WIN32 */ +#endif /* WIN32 */ /* set by the main code to point to where the test dir is */ const char *path = "."; @@ -292,7 +292,7 @@ curl_off_t our_getpid(void) curl_off_t pid; pid = (curl_off_t)getpid(); -#if defined(_WIN32) || defined(_WIN32) +#if defined(WIN32) || defined(_WIN32) /* store pid + 65536 to avoid conflict with Cygwin/msys PIDs, see also: * - https://cygwin.com/git/?p=newlib-cygwin.git;a=commit; ↵ * h=b5e1003722cb14235c4f166be72c09acdffc62ea @@ -378,7 +378,7 @@ void clear_advisor_read_lock(const char *filename) } -#if defined(_WIN32) && !defined(MSDOS) +#if defined(WIN32) && !defined(MSDOS) static struct timeval tvnow(void) { @@ -501,11 +501,11 @@ static SIGHANDLER_T old_sigint_handler = SIG_ERR; static SIGHANDLER_T old_sigterm_handler = SIG_ERR; #endif -#if defined(SIGBREAK) && defined(_WIN32) +#if defined(SIGBREAK) && defined(WIN32) static SIGHANDLER_T old_sigbreak_handler = SIG_ERR; #endif -#ifdef _WIN32 +#ifdef WIN32 #ifdef _WIN32_WCE static DWORD thread_main_id = 0; #else @@ -521,7 +521,7 @@ volatile int got_exit_signal = 0; /* if next is set indicates the first signal handled in exit_signal_handler */ volatile int exit_signal = 0; -#ifdef _WIN32 +#ifdef WIN32 /* event which if set indicates that the program should finish */ HANDLE exit_event = NULL; #endif @@ -538,7 +538,7 @@ static void exit_signal_handler(int signum) if(got_exit_signal == 0) { got_exit_signal = 1; exit_signal = signum; -#ifdef _WIN32 +#ifdef WIN32 if(exit_event) (void)SetEvent(exit_event); #endif @@ -547,7 +547,7 @@ static void exit_signal_handler(int signum) errno = old_errno; } -#ifdef _WIN32 +#ifdef WIN32 /* CTRL event handler for Windows Console applications to simulate * SIGINT, SIGTERM and SIGBREAK on CTRL events and trigger signal handler. * @@ -698,7 +698,7 @@ static SIGHANDLER_T set_signal(int signum, SIGHANDLER_T handler, void install_signal_handlers(bool keep_sigalrm) { -#ifdef _WIN32 +#ifdef WIN32 #ifdef _WIN32_WCE typedef HANDLE curl_win_thread_handle_t; #else @@ -744,13 +744,13 @@ void install_signal_handlers(bool keep_sigalrm) if(old_sigterm_handler == SIG_ERR) logmsg("cannot install SIGTERM handler: %s", strerror(errno)); #endif -#if defined(SIGBREAK) && defined(_WIN32) +#if defined(SIGBREAK) && defined(WIN32) /* handle SIGBREAK signal with our exit_signal_handler */ old_sigbreak_handler = set_signal(SIGBREAK, exit_signal_handler, TRUE); if(old_sigbreak_handler == SIG_ERR) logmsg("cannot install SIGBREAK handler: %s", strerror(errno)); #endif -#ifdef _WIN32 +#ifdef WIN32 if(!SetConsoleCtrlHandler(ctrl_event_handler, TRUE)) logmsg("cannot install CTRL event handler"); #ifdef _WIN32_WCE @@ -792,11 +792,11 @@ void restore_signal_handlers(bool keep_sigalrm) if(SIG_ERR != old_sigterm_handler) (void) set_signal(SIGTERM, old_sigterm_handler, FALSE); #endif -#if defined(SIGBREAK) && defined(_WIN32) +#if defined(SIGBREAK) && defined(WIN32) if(SIG_ERR != old_sigbreak_handler) (void) set_signal(SIGBREAK, old_sigbreak_handler, FALSE); #endif -#ifdef _WIN32 +#ifdef WIN32 (void)SetConsoleCtrlHandler(ctrl_event_handler, FALSE); if(thread_main_window && thread_main_id) { if(PostThreadMessage(thread_main_id, WM_APP, 0, 0)) { @@ -846,7 +846,7 @@ int bind_unix_socket(curl_socket_t sock, const char *unix_socket, return rc; } /* socket server is not alive, now check if it was actually a socket. */ -#ifdef _WIN32 +#ifdef WIN32 /* Windows does not have lstat function. */ rc = curlx_win32_stat(unix_socket, &statbuf); #else diff --git a/deps/curl/tests/server/util.h b/deps/curl/tests/server/util.h index 4dff40e8..a12f4dbf 100644 --- a/deps/curl/tests/server/util.h +++ b/deps/curl/tests/server/util.h @@ -41,7 +41,7 @@ extern const char *serverlogfile; extern const char *cmdfile; -#ifdef _WIN32 +#ifdef WIN32 #include #include @@ -54,10 +54,10 @@ void win32_perror(const char *msg); void win32_init(void); void win32_cleanup(void); const char *sstrerror(int err); -#else /* _WIN32 */ +#else /* WIN32 */ #define sstrerror(e) strerror(e) -#endif /* _WIN32 */ +#endif /* WIN32 */ /* fopens the test case file */ FILE *test2fopen(long testno, const char *logdir); @@ -68,6 +68,7 @@ int write_pidfile(const char *filename); int write_portfile(const char *filename, int port); void set_advisor_read_lock(const char *filename); void clear_advisor_read_lock(const char *filename); +int strncasecompare(const char *first, const char *second, size_t max); /* global variable which if set indicates that the program should finish */ extern volatile int got_exit_signal; @@ -75,7 +76,7 @@ extern volatile int got_exit_signal; /* global variable which if set indicates the first signal handled */ extern volatile int exit_signal; -#ifdef _WIN32 +#ifdef WIN32 /* global event which if set indicates that the program should finish */ extern HANDLE exit_event; #endif diff --git a/deps/curl/tests/servers.pm b/deps/curl/tests/servers.pm index 9416ba75..4f67432c 100644 --- a/deps/curl/tests/servers.pm +++ b/deps/curl/tests/servers.pm @@ -153,15 +153,10 @@ our $stunnel; # path to stunnel command # sub checkcmd { my ($cmd, @extrapaths)=@_; - my $sep = '[:]'; - if ($^O eq 'MSWin32' || $^O eq 'dos' || $^O eq 'os2') { - # PATH separator is different - $sep = '[;]'; - } - my @paths=(split(m/$sep/, $ENV{'PATH'}), "/usr/sbin", "/usr/local/sbin", + my @paths=(split(m/[:]/, $ENV{'PATH'}), "/usr/sbin", "/usr/local/sbin", "/sbin", "/usr/bin", "/usr/local/bin", @extrapaths); for(@paths) { - if( -x "$_/$cmd" . exe_ext('SYS') && ! -d "$_/$cmd" . exe_ext('SYS')) { + if( -x "$_/$cmd" && ! -d "$_/$cmd") { # executable bit but not a directory! return "$_/$cmd"; } @@ -269,22 +264,19 @@ sub clearlocks { if(os_is_win()) { $dir = sys_native_abs_path($dir); $dir =~ s/\//\\\\/g; - my $handle = "handle"; + my $handle = "handle.exe"; if($ENV{"PROCESSOR_ARCHITECTURE"} =~ /64$/) { - $handle = "handle64"; + $handle = "handle64.exe"; } - if(checkcmd($handle)) { - my @handles = `$handle $dir -accepteula -nobanner`; - for my $tryhandle (@handles) { - # Skip the "No matching handles found." warning when returned - if($tryhandle =~ /^(\S+)\s+pid:\s+(\d+)\s+type:\s+(\w+)\s+([0-9A-F]+):\s+(.+)\r\r/) { - logmsg "Found $3 lock of '$5' ($4) by $1 ($2)\n"; - # Ignore stunnel since we cannot do anything about its locks - if("$3" eq "File" && "$1" ne "tstunnel.exe") { - logmsg "Killing IMAGENAME eq $1 and PID eq $2\n"; - system("taskkill.exe -f -fi \"IMAGENAME eq $1\" -fi \"PID eq $2\" >nul 2>&1"); - $done = 1; - } + my @handles = `$handle $dir -accepteula -nobanner`; + for my $tryhandle (@handles) { + if($tryhandle =~ /^(\S+)\s+pid:\s+(\d+)\s+type:\s+(\w+)\s+([0-9A-F]+):\s+(.+)\r\r/) { + logmsg "Found $3 lock of '$5' ($4) by $1 ($2)\n"; + # Ignore stunnel since we cannot do anything about its locks + if("$3" eq "File" && "$1" ne "tstunnel.exe") { + logmsg "Killing IMAGENAME eq $1 and PID eq $2\n"; + system("taskkill.exe -f -fi \"IMAGENAME eq $1\" -fi \"PID eq $2\" >nul 2>&1"); + $done = 1; } } } diff --git a/deps/curl/tests/unit/curlcheck.h b/deps/curl/tests/unit/curlcheck.h index 92896442..756f76e3 100644 --- a/deps/curl/tests/unit/curlcheck.h +++ b/deps/curl/tests/unit/curlcheck.h @@ -93,6 +93,8 @@ } while(0) +extern int unitfail; + #define UNITTEST_START \ int test(char *arg) \ { \ diff --git a/deps/curl/tests/unit/unit1394.c b/deps/curl/tests/unit/unit1394.c index ef398ab2..e4e99818 100644 --- a/deps/curl/tests/unit/unit1394.c +++ b/deps/curl/tests/unit/unit1394.c @@ -61,7 +61,7 @@ UNITTEST_START "pkcs11:foobar", "pkcs11:foobar", NULL, "PKCS11:foobar", "PKCS11:foobar", NULL, "PkCs11:foobar", "PkCs11:foobar", NULL, -#ifdef _WIN32 +#ifdef WIN32 "c:\\foo:bar:baz", "c:\\foo", "bar:baz", "c:\\foo\\:bar:baz", "c:\\foo:bar", "baz", "c:\\foo\\\\:bar:baz", "c:\\foo\\", "bar:baz", diff --git a/deps/curl/tests/unit/unit1395.c b/deps/curl/tests/unit/unit1395.c index 017b45a0..d01403f3 100644 --- a/deps/curl/tests/unit/unit1395.c +++ b/deps/curl/tests/unit/unit1395.c @@ -83,17 +83,15 @@ UNITTEST_START abort_unless(err == 0, "returned error"); abort_if(err && out, "returned error with output"); - if(out && pairs[i].output && strcmp(out, pairs[i].output)) { + if(out && strcmp(out, pairs[i].output)) { fprintf(stderr, "Test %u: '%s' gave '%s' instead of '%s'\n", i, pairs[i].input, out, pairs[i].output); fail("Test case output mismatched"); fails++; } - else if((!out && pairs[i].output) || - (out && !pairs[i].output)) { - fprintf(stderr, "Test %u: '%s' gave '%s' instead of '%s'\n", - i, pairs[i].input, out ? out : "(null)", - pairs[i].output ? pairs[i].output : "(null)"); + else if(!out && pairs[i].output) { + fprintf(stderr, "Test %u: '%s' gave '%s' instead of NULL\n", + i, pairs[i].input, out); fail("Test case output mismatched"); fails++; } diff --git a/deps/curl/tests/unit/unit1604.c b/deps/curl/tests/unit/unit1604.c index cba3dfcf..411b94a0 100644 --- a/deps/curl/tests/unit/unit1604.c +++ b/deps/curl/tests/unit/unit1604.c @@ -42,7 +42,7 @@ static void unit_stop(void) } -#if defined(_WIN32) || defined(MSDOS) +#if defined(MSDOS) || defined(WIN32) static char *getflagstr(int flags) { @@ -353,6 +353,6 @@ UNITTEST_START { fprintf(stderr, "Skipped test not for this platform\n"); } -#endif /* _WIN32 || MSDOS */ +#endif /* MSDOS || WIN32 */ UNITTEST_STOP diff --git a/deps/curl/tests/unit/unit2600.c b/deps/curl/tests/unit/unit2600.c index a2089b27..d7b1efdd 100644 --- a/deps/curl/tests/unit/unit2600.c +++ b/deps/curl/tests/unit/unit2600.c @@ -124,7 +124,7 @@ static void cf_test_destroy(struct Curl_cfilter *cf, struct Curl_easy *data) struct cf_test_ctx *ctx = cf->ctx; #ifndef CURL_DISABLE_VERBOSE_STRINGS infof(data, "%04dms: cf[%s] destroyed", - (int)Curl_timediff(Curl_now(), current_tr->started), ctx->id); + (int)Curl_timediff(Curl_now(), current_tr->started), ctx->id); #else (void)data; #endif @@ -145,7 +145,7 @@ static CURLcode cf_test_connect(struct Curl_cfilter *cf, duration_ms = Curl_timediff(Curl_now(), ctx->started); if(duration_ms >= ctx->fail_delay_ms) { infof(data, "%04dms: cf[%s] fail delay reached", - (int)duration_ms, ctx->id); + (int)duration_ms, ctx->id); return CURLE_COULDNT_CONNECT; } if(duration_ms) @@ -162,7 +162,7 @@ static struct Curl_cftype cft_test = { cf_test_connect, Curl_cf_def_close, Curl_cf_def_get_host, - Curl_cf_def_adjust_pollset, + Curl_cf_def_get_select_socks, Curl_cf_def_data_pending, Curl_cf_def_send, Curl_cf_def_recv, @@ -185,7 +185,7 @@ static CURLcode cf_test_create(struct Curl_cfilter **pcf, (void)data; (void)conn; - ctx = calloc(1, sizeof(*ctx)); + ctx = calloc(sizeof(*ctx), 1); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; diff --git a/deps/curl/tests/unit/unit3200.c b/deps/curl/tests/unit/unit3200.c index 0544bcc9..eff56677 100644 --- a/deps/curl/tests/unit/unit3200.c +++ b/deps/curl/tests/unit/unit3200.c @@ -47,7 +47,6 @@ static CURLcode unit_stop(void) } #ifdef __GNUC__ -#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Woverlength-strings" #endif @@ -162,10 +161,6 @@ UNITTEST_START } UNITTEST_STOP -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - #else static CURLcode unit_setup(void) { diff --git a/deps/libtomcrypt/.github/workflows/main.yml b/deps/libtomcrypt/.github/workflows/main.yml index 9f9df9be..68f444e2 100644 --- a/deps/libtomcrypt/.github/workflows/main.yml +++ b/deps/libtomcrypt/.github/workflows/main.yml @@ -34,24 +34,24 @@ jobs: cc: [ gcc, clang ] os: [ ubuntu-20.04, ubuntu-22.04 ] config: - - { BUILDNAME: 'META_BUILDS', BUILDOPTIONS: '-DGMP_DESC', BUILDSCRIPT: '.ci/meta_builds.sh' } - - { BUILDNAME: 'VALGRIND', BUILDOPTIONS: '', BUILDSCRIPT: '.ci/valgrind.sh' } - - { BUILDNAME: 'STOCK', BUILDOPTIONS: '', BUILDSCRIPT: '.ci/run.sh' } - - { BUILDNAME: 'STOCK-MPI', BUILDOPTIONS: '-ULTM_DESC -UTFM_DESC -UUSE_LTM -UUSE_TFM', BUILDSCRIPT: '.ci/run.sh' } - - { BUILDNAME: 'STOCK+AESNI', BUILDOPTIONS: '-msse4.1 -maes', BUILDSCRIPT: '.ci/run.sh' } - - { BUILDNAME: 'EASY', BUILDOPTIONS: '-DLTC_EASY', BUILDSCRIPT: '.ci/run.sh' } - - { BUILDNAME: 'SMALL', BUILDOPTIONS: '-DLTC_SMALL_CODE', BUILDSCRIPT: '.ci/run.sh' } - - { BUILDNAME: 'NOTABLES', BUILDOPTIONS: '-DLTC_NO_TABLES', BUILDSCRIPT: '.ci/run.sh' } - - { BUILDNAME: 'SMALL+NOTABLES', BUILDOPTIONS: '-DLTC_SMALL_CODE -DLTC_NO_TABLES', BUILDSCRIPT: '.ci/run.sh' } - - { BUILDNAME: 'NO_FAST', BUILDOPTIONS: '-DLTC_NO_FAST', BUILDSCRIPT: '.ci/run.sh' } - - { BUILDNAME: 'NO_FAST+NOTABLES', BUILDOPTIONS: '-DLTC_NO_FAST -DLTC_NO_TABLES', BUILDSCRIPT: '.ci/run.sh' } - - { BUILDNAME: 'NO_ASM', BUILDOPTIONS: '-DLTC_NO_ASM', BUILDSCRIPT: '.ci/run.sh' } - - { BUILDNAME: 'NO_TIMING_RESISTANCE', BUILDOPTIONS: '-DLTC_NO_ECC_TIMING_RESISTANT -DLTC_NO_RSA_BLINDING', BUILDSCRIPT: '.ci/run.sh' } - - { BUILDNAME: 'PTHREAD', BUILDOPTIONS: '-DLTC_PTHREAD', BUILDSCRIPT: '.ci/run.sh' } - - { BUILDNAME: 'STOCK+ARGTYPE=1', BUILDOPTIONS: '-DARGTYPE=1', BUILDSCRIPT: '.ci/run.sh' } - - { BUILDNAME: 'STOCK+ARGTYPE=2', BUILDOPTIONS: '-DARGTYPE=2', BUILDSCRIPT: '.ci/run.sh' } - - { BUILDNAME: 'STOCK+ARGTYPE=3', BUILDOPTIONS: '-DARGTYPE=3', BUILDSCRIPT: '.ci/run.sh' } - - { BUILDNAME: 'STOCK+ARGTYPE=4', BUILDOPTIONS: '-DARGTYPE=4', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'META_BUILDS', BUILDOPTIONS: '-DGMP_DESC', BUILDSCRIPT: '.ci/meta_builds.sh' } + - { BUILDNAME: 'VALGRIND', BUILDOPTIONS: '', BUILDSCRIPT: '.ci/valgrind.sh' } + - { BUILDNAME: 'STOCK', BUILDOPTIONS: '', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'STOCK-MPI', BUILDOPTIONS: '-ULTM_DESC -UTFM_DESC -UUSE_LTM -UUSE_TFM', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'STOCK+AESNI', BUILDOPTIONS: '-msse4.1 -maes', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'EASY', BUILDOPTIONS: '-DLTC_EASY', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'SMALL', BUILDOPTIONS: '-DLTC_SMALL_CODE', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'NO_TABLES', BUILDOPTIONS: '-DLTC_NO_TABLES', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'NO_FAST', BUILDOPTIONS: '-DLTC_NO_FAST', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'NO_FAST+SMALL+NO_TABLES', BUILDOPTIONS: '-DLTC_NO_FAST -DLTC_SMALL_CODE -DLTC_NO_TABLES', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'NO_ASM', BUILDOPTIONS: '-DLTC_NO_ASM', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'NO_TIMING_RESISTANCE', BUILDOPTIONS: '-DLTC_NO_ECC_TIMING_RESISTANT -DLTC_NO_RSA_BLINDING', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'FORTUNA_CUSTOM_OPTIONS', BUILDOPTIONS: '-DLTC_FORTUNA_USE_ENCRYPT_ONLY -DLTC_FORTUNA_RESEED_RATELIMIT_STATIC', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'PTHREAD', BUILDOPTIONS: '-DLTC_PTHREAD', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'STOCK+ARGTYPE=1', BUILDOPTIONS: '-DARGTYPE=1', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'STOCK+ARGTYPE=2', BUILDOPTIONS: '-DARGTYPE=2', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'STOCK+ARGTYPE=3', BUILDOPTIONS: '-DARGTYPE=3', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'STOCK+ARGTYPE=4', BUILDOPTIONS: '-DARGTYPE=4', BUILDSCRIPT: '.ci/run.sh' } steps: - uses: actions/checkout@v2 - name: install dependencies diff --git a/deps/libtomcrypt/doc/crypt.tex b/deps/libtomcrypt/doc/crypt.tex index 87804cc6..eaf8822c 100644 --- a/deps/libtomcrypt/doc/crypt.tex +++ b/deps/libtomcrypt/doc/crypt.tex @@ -2798,6 +2798,7 @@ The following hashes are provided as of this release within the LibTomCrypt libr \hline SHA-224 & sha224\_desc & 28 & 10 \\ \hline BLAKE2S-224 & blake2s\_224\_desc & 28 & 23 \\ \hline TIGER-192 & tiger\_desc & 24 & 1 \\ + \hline TIGER2-192 & tiger2\_desc & 24 & 33 \\ \hline SHA-1 & sha1\_desc & 20 & 2 \\ \hline RIPEMD-160 & rmd160\_desc & 20 & 9 \\ \hline BLAKE2S-160 & blake2s\_160\_desc & 20 & 22 \\ @@ -2876,6 +2877,7 @@ For further information see \url{https://en.wikipedia.org/wiki/SHA-3} Example of using SHAKE256 with an arbitrary length output. +\begin{small} \begin{verbatim} #include int main(void) @@ -2900,14 +2902,76 @@ int main(void) return EXIT_SUCCESS; } \end{verbatim} +\end{small} + +\mysection{Extended Tiger API} + +The Tiger and Tiger2 hash algorithms \url{http://www.cs.technion.ac.il/~biham/Reports/Tiger/} specify the possibility to run the algorithm with +a configurable number of passes. The default and minimum is 3 passes, there is a second more or less widely used version with 4 passes, +which has been introduced by PHP. Its utilization is mostly limited to PHP, so we don't provide descriptors by default. + +An example of how to use the 4-pass version of Tiger in a libtomcrypt-style way is shown below. + +\index{tiger\_init\_ex()} +\begin{small} +\begin{verbatim} +#include + +static const char *tiger_4passes_name = "tiger-4passes"; + +static int tiger_4passes_init(hash_state *md) +{ + return tiger_init_ex(md, 4); +} + +static struct ltc_hash_descriptor tiger_4passes_desc; + +int main(void) +{ + int err = 0; + unsigned char hash[MAXBLOCKSIZE], *p; + unsigned long hashlen = sizeof(hash); + + memcpy(&tiger_4passes_desc, &tiger_desc, sizeof(tiger_4passes_desc)); + tiger_4passes_desc.init = tiger_4passes_init; + /* Make sure to have a different name, ID and OID than standard Tiger */ + tiger_4passes_desc.name = tiger_4passes_name; + tiger_4passes_desc.ID |= 0x80u; + memset(tiger_4passes_desc.OID, 0, sizeof(tiger_4passes_desc.OID)); + tiger_4passes_desc.OIDlen = 0; + + if ((err = register_hash(&tiger_4passes_desc)) == CRYPT_OK) { + err = hash_memory(find_hash(tiger_4passes_name), (unsigned char*)"abc", 3, hash, &hashlen); + } + + if (err != 0) { + fprintf(stderr, "Error %s (%d)", error_to_string(err), err); + } else { + p = hash; + printf("Resulting hash: "); + while(hashlen--) { + printf("%02x", *p++); + } + printf("\n"); + } + return err; +} +\end{verbatim} +\end{small} + +When compiling and running this, the output should be: + +\begin{verbatim} +Resulting hash: 538883c8fc5f28250299018e66bdf4fdb5ef7b65f2e91753 +\end{verbatim} \mysection{Notice} It is highly recommended that you \textbf{not} use the MD2, MD4, MD5, or SHA-1 hashes for the purposes of digital signatures or authentication codes. These hashes are provided for completeness and they still can be used for the purposes of password hashing or one-way accumulators (e.g. Yarrow). -The other hashes such as the SHA-2 (that includes SHA-512, SHA-512/384, SHA-384, SHA-512/256, SHA-256 and SHA-224) and TIGER-192 are still considered secure -for all purposes you would normally use a hash for. +The other hashes such as the SHA-2 (that includes SHA-512, SHA-512/384, SHA-384, SHA-512/256, SHA-256 and SHA-224), TIGER-192 and TIGER2-192 are still +considered secure for all purposes you would normally use a hash for. \chapter{Checksum Functions} diff --git a/deps/libtomcrypt/makefile_include.mk b/deps/libtomcrypt/makefile_include.mk index f76798c4..41430263 100644 --- a/deps/libtomcrypt/makefile_include.mk +++ b/deps/libtomcrypt/makefile_include.mk @@ -446,6 +446,11 @@ bins: $(call print-help,bins,Builds the library and all useful demos) $(USEFUL_D check: test ./test +tvs: sizes constants tv_gen + ./tv_gen + ./.ci/coverage_more.sh + mv *_tv.txt notes/ + #build the doxy files (requires Doxygen, tetex and patience) doxygen: $(call print-help,doxygen,Builds the doxygen html documentation) $(MAKE) -C doc/ $@ V=$(V) diff --git a/deps/libtomcrypt/src/ciphers/aes/aes_desc.c b/deps/libtomcrypt/src/ciphers/aes/aes_desc.c index 5b42d92b..4b930a5e 100644 --- a/deps/libtomcrypt/src/ciphers/aes/aes_desc.c +++ b/deps/libtomcrypt/src/ciphers/aes/aes_desc.c @@ -34,6 +34,7 @@ const struct ltc_cipher_descriptor aes_desc = #define AES_SETUP aes_enc_setup #define AES_ENC aes_enc_ecb_encrypt #define AES_DONE aes_enc_done +#define AES_TEST aes_enc_test #define AES_KS aes_enc_keysize const struct ltc_cipher_descriptor aes_enc_desc = @@ -119,6 +120,7 @@ int AES_ENC(const unsigned char *pt, unsigned char *ct, const symmetric_key *ske } +#ifndef ENCRYPT_ONLY /** Decrypts a block of text with AES @param ct The input ciphertext (16 bytes) @@ -135,6 +137,7 @@ int AES_DEC(const unsigned char *ct, unsigned char *pt, const symmetric_key *ske #endif return rijndael_ecb_decrypt(ct, pt, skey); } +#endif /* ENCRYPT_ONLY */ /** Performs a self-test of the AES block cipher @@ -181,26 +184,33 @@ int AES_TEST(void) symmetric_key key; unsigned char tmp[2][16]; - int i, y; + int i; +#ifndef ENCRYPT_ONLY + int y; +#endif for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { zeromem(&key, sizeof(key)); - if ((err = aes_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { + if ((err = AES_SETUP(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { return err; } - aes_ecb_encrypt(tests[i].pt, tmp[0], &key); - aes_ecb_decrypt(tmp[0], tmp[1], &key); - if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "AES Encrypt", i) || - compare_testvector(tmp[1], 16, tests[i].pt, 16, "AES Decrypt", i)) { + AES_ENC(tests[i].pt, tmp[0], &key); + if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "AES Encrypt", i)) { + return CRYPT_FAIL_TESTVECTOR; + } +#ifndef ENCRYPT_ONLY + AES_DEC(tmp[0], tmp[1], &key); + if (compare_testvector(tmp[1], 16, tests[i].pt, 16, "AES Decrypt", i)) { return CRYPT_FAIL_TESTVECTOR; } /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ for (y = 0; y < 16; y++) tmp[0][y] = 0; - for (y = 0; y < 1000; y++) aes_ecb_encrypt(tmp[0], tmp[0], &key); - for (y = 0; y < 1000; y++) aes_ecb_decrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 1000; y++) AES_ENC(tmp[0], tmp[0], &key); + for (y = 0; y < 1000; y++) AES_DEC(tmp[0], tmp[0], &key); for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; +#endif } return CRYPT_OK; #endif diff --git a/deps/libtomcrypt/src/encauth/ccm/ccm_memory.c b/deps/libtomcrypt/src/encauth/ccm/ccm_memory.c index 45951ff9..c0ffa781 100644 --- a/deps/libtomcrypt/src/encauth/ccm/ccm_memory.c +++ b/deps/libtomcrypt/src/encauth/ccm/ccm_memory.c @@ -162,7 +162,8 @@ int ccm_memory(int cipher, } for (; y < L; y++) { if (x >= sizeof(PAD)) { - return CRYPT_INVALID_ARG; + err = CRYPT_INVALID_ARG; + goto error; } PAD[x++] = (unsigned char)((len >> 24) & 255); len <<= 8; diff --git a/deps/libtomcrypt/src/hashes/tiger.c b/deps/libtomcrypt/src/hashes/tiger.c index 8ca2d54f..145bf28c 100644 --- a/deps/libtomcrypt/src/hashes/tiger.c +++ b/deps/libtomcrypt/src/hashes/tiger.c @@ -28,6 +28,24 @@ const struct ltc_hash_descriptor tiger_desc = NULL }; +const struct ltc_hash_descriptor tiger2_desc = +{ + "tiger2", + 33, + 24, + 64, + + /* OID ... does not exist */ + { 0 }, + 0, + + &tiger2_init, + &tiger_process, + &tiger_done, + &tiger2_test, + NULL +}; + #define t1 (table) #define t2 (table+256) #define t3 (table+256*2) @@ -601,7 +619,7 @@ static int ss_tiger_compress(hash_state *md, const unsigned char *buf) static int s_tiger_compress(hash_state *md, const unsigned char *buf) #endif { - ulong64 a, b, c, x[8]; + ulong64 a, b, c, x[8], t; unsigned long i; /* load words */ @@ -617,6 +635,11 @@ static int s_tiger_compress(hash_state *md, const unsigned char *buf) s_pass(&c,&a,&b,x,7); s_key_schedule(x); s_pass(&b,&c,&a,x,9); + for (i = 3; i < md->tiger.passes; ++i) { + s_key_schedule(x); + s_pass(&a,&b,&c,x,9); + t = a; a = c; c = b; b = t; + } /* store state */ md->tiger.state[0] = a ^ md->tiger.state[0]; @@ -649,6 +672,57 @@ int tiger_init(hash_state *md) md->tiger.state[2] = CONST64(0xF096A5B4C3B2E187); md->tiger.curlen = 0; md->tiger.length = 0; + md->tiger.passes = 3; + md->tiger.pad = 0x01u; + return CRYPT_OK; +} + +/** + Initialize the hash state (extended version) + @param md The hash state you wish to initialize + @param passes The number of passes that should be executed + when the compress function is called. + @return CRYPT_OK if successful +*/ +int tiger_init_ex(hash_state *md, unsigned long passes) +{ + int err; + if ((err = tiger_init(md) != CRYPT_OK)) { + return err; + } + md->tiger.passes = passes; + return CRYPT_OK; +} + +/** + Initialize the hash state (extended version) + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int tiger2_init(hash_state *md) +{ + int err; + if ((err = tiger_init(md) != CRYPT_OK)) { + return err; + } + md->tiger.pad = 0x80u; + return CRYPT_OK; +} + +/** + Initialize the hash state (extended version) + @param md The hash state you wish to initialize + @param passes The number of passes that should be executed + when the compress function is called. + @return CRYPT_OK if successful +*/ +int tiger2_init_ex(hash_state *md, unsigned long passes) +{ + int err; + if ((err = tiger2_init(md) != CRYPT_OK)) { + return err; + } + md->tiger.passes = passes; return CRYPT_OK; } @@ -679,8 +753,8 @@ int tiger_done(hash_state * md, unsigned char *out) /* increase the length of the message */ md->tiger.length += md->tiger.curlen * 8; - /* append the '1' bit */ - md->tiger.buf[md->tiger.curlen++] = (unsigned char)0x01; + /* append the padding bit */ + md->tiger.buf[md->tiger.curlen++] = md->tiger.pad; /* if the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length @@ -717,51 +791,77 @@ int tiger_done(hash_state * md, unsigned char *out) Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ -int tiger_test(void) +int s_tiger_test(unsigned int idx) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; - unsigned char hash[24]; + unsigned char hash[2][24]; } tests[] = { { "", - { 0x32, 0x93, 0xac, 0x63, 0x0c, 0x13, 0xf0, 0x24, - 0x5f, 0x92, 0xbb, 0xb1, 0x76, 0x6e, 0x16, 0x16, - 0x7a, 0x4e, 0x58, 0x49, 0x2d, 0xde, 0x73, 0xf3 } + { + { 0x32, 0x93, 0xac, 0x63, 0x0c, 0x13, 0xf0, 0x24, + 0x5f, 0x92, 0xbb, 0xb1, 0x76, 0x6e, 0x16, 0x16, + 0x7a, 0x4e, 0x58, 0x49, 0x2d, 0xde, 0x73, 0xf3 }, + { 0x44, 0x41, 0xbe, 0x75, 0xf6, 0x01, 0x87, 0x73, + 0xc2, 0x06, 0xc2, 0x27, 0x45, 0x37, 0x4b, 0x92, + 0x4a, 0xa8, 0x31, 0x3f, 0xef, 0x91, 0x9f, 0x41 }, + }, }, { "abc", - { 0x2a, 0xab, 0x14, 0x84, 0xe8, 0xc1, 0x58, 0xf2, - 0xbf, 0xb8, 0xc5, 0xff, 0x41, 0xb5, 0x7a, 0x52, - 0x51, 0x29, 0x13, 0x1c, 0x95, 0x7b, 0x5f, 0x93 } + { + { 0x2a, 0xab, 0x14, 0x84, 0xe8, 0xc1, 0x58, 0xf2, + 0xbf, 0xb8, 0xc5, 0xff, 0x41, 0xb5, 0x7a, 0x52, + 0x51, 0x29, 0x13, 0x1c, 0x95, 0x7b, 0x5f, 0x93 }, + { 0xf6, 0x8d, 0x7b, 0xc5, 0xaf, 0x4b, 0x43, 0xa0, + 0x6e, 0x04, 0x8d, 0x78, 0x29, 0x56, 0x0d, 0x4a, + 0x94, 0x15, 0x65, 0x8b, 0xb0, 0xb1, 0xf3, 0xbf }, + }, }, { "Tiger", - { 0xdd, 0x00, 0x23, 0x07, 0x99, 0xf5, 0x00, 0x9f, - 0xec, 0x6d, 0xeb, 0xc8, 0x38, 0xbb, 0x6a, 0x27, - 0xdf, 0x2b, 0x9d, 0x6f, 0x11, 0x0c, 0x79, 0x37 } + { + { 0xdd, 0x00, 0x23, 0x07, 0x99, 0xf5, 0x00, 0x9f, + 0xec, 0x6d, 0xeb, 0xc8, 0x38, 0xbb, 0x6a, 0x27, + 0xdf, 0x2b, 0x9d, 0x6f, 0x11, 0x0c, 0x79, 0x37 }, + { 0xfe, 0x40, 0x79, 0x8b, 0x8e, 0xb9, 0x37, 0xfd, + 0x97, 0x76, 0x08, 0x93, 0x05, 0x48, 0xd6, 0xa8, + 0x94, 0xc2, 0x0b, 0x04, 0xcb, 0xef, 0x7a, 0x42 }, + }, }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", - { 0xf7, 0x1c, 0x85, 0x83, 0x90, 0x2a, 0xfb, 0x87, - 0x9e, 0xdf, 0xe6, 0x10, 0xf8, 0x2c, 0x0d, 0x47, - 0x86, 0xa3, 0xa5, 0x34, 0x50, 0x44, 0x86, 0xb5 } + { + { 0xf7, 0x1c, 0x85, 0x83, 0x90, 0x2a, 0xfb, 0x87, + 0x9e, 0xdf, 0xe6, 0x10, 0xf8, 0x2c, 0x0d, 0x47, + 0x86, 0xa3, 0xa5, 0x34, 0x50, 0x44, 0x86, 0xb5 }, + { 0x15, 0x9b, 0x38, 0x0a, 0xb7, 0x92, 0x94, 0xe0, + 0xda, 0x19, 0xf1, 0x62, 0x82, 0xce, 0x6d, 0xce, + 0x0f, 0x84, 0xd3, 0x4f, 0x72, 0x9d, 0xbe, 0xa3 }, + }, }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", - { 0xc5, 0x40, 0x34, 0xe5, 0xb4, 0x3e, 0xb8, 0x00, - 0x58, 0x48, 0xa7, 0xe0, 0xae, 0x6a, 0xac, 0x76, - 0xe4, 0xff, 0x59, 0x0a, 0xe7, 0x15, 0xfd, 0x25 } + { + { 0xc5, 0x40, 0x34, 0xe5, 0xb4, 0x3e, 0xb8, 0x00, + 0x58, 0x48, 0xa7, 0xe0, 0xae, 0x6a, 0xac, 0x76, + 0xe4, 0xff, 0x59, 0x0a, 0xe7, 0x15, 0xfd, 0x25 }, + { 0x01, 0xef, 0x91, 0x0b, 0x9b, 0xb2, 0xcb, 0x4c, + 0x6c, 0x47, 0x49, 0x5c, 0x86, 0xb3, 0x64, 0x1a, + 0xff, 0x14, 0xfb, 0xf7, 0x79, 0x40, 0x9c, 0x0e }, + }, }, }; + int (*init[2])(hash_state *hash) = { tiger_init, tiger2_init }; int i; unsigned char tmp[24]; hash_state md; for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { - tiger_init(&md); + init[idx](&md); tiger_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); tiger_done(&md, tmp); - if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "TIGER", i)) { + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash[idx], sizeof(tests[i].hash[idx]), !idx ? "TIGER": "TIGER2", i)) { return CRYPT_FAIL_TESTVECTOR; } } @@ -769,6 +869,24 @@ int tiger_test(void) #endif } +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int tiger_test(void) +{ + return s_tiger_test(0); +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int tiger2_test(void) +{ + return s_tiger_test(1); +} + #endif /* diff --git a/deps/libtomcrypt/src/headers/tomcrypt.h b/deps/libtomcrypt/src/headers/tomcrypt.h index c310a8ce..8efdc8a9 100644 --- a/deps/libtomcrypt/src/headers/tomcrypt.h +++ b/deps/libtomcrypt/src/headers/tomcrypt.h @@ -28,7 +28,7 @@ extern "C" { #ifndef TAB_SIZE /* descriptor table size */ -#define TAB_SIZE 34 +#define TAB_SIZE 48 #endif /* error codes [will be expanded in future releases] */ diff --git a/deps/libtomcrypt/src/headers/tomcrypt_cipher.h b/deps/libtomcrypt/src/headers/tomcrypt_cipher.h index 8b6f8781..aeee3435 100644 --- a/deps/libtomcrypt/src/headers/tomcrypt_cipher.h +++ b/deps/libtomcrypt/src/headers/tomcrypt_cipher.h @@ -699,6 +699,7 @@ void aes_done(symmetric_key *skey); int aes_keysize(int *keysize); int aes_enc_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int aes_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int aes_enc_test(void); void aes_enc_done(symmetric_key *skey); int aes_enc_keysize(int *keysize); extern const struct ltc_cipher_descriptor aes_desc; diff --git a/deps/libtomcrypt/src/headers/tomcrypt_custom.h b/deps/libtomcrypt/src/headers/tomcrypt_custom.h index 129f0245..e1077928 100644 --- a/deps/libtomcrypt/src/headers/tomcrypt_custom.h +++ b/deps/libtomcrypt/src/headers/tomcrypt_custom.h @@ -375,9 +375,9 @@ /* with non-glibc or glibc 2.17+ prefer clock_gettime over gettimeofday */ #if defined(__GLIBC__) && defined(__GLIBC_PREREQ) -#if __GLIBC_PREREQ(2, 17) - #define LTC_CLOCK_GETTIME -#endif + #if __GLIBC_PREREQ(2, 17) + #define LTC_CLOCK_GETTIME + #endif #elif defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L #define LTC_CLOCK_GETTIME #endif @@ -407,6 +407,11 @@ #define LTC_FORTUNA_POOLS 32 #endif +/* at compile time you can decide whether fortuna uses the regular AES APIs + * or whether it will use the 'encrypt_only' variants. + * This is useful for custom builds of libtomcrypt for size-constrained targets. */ +/* #define LTC_FORTUNA_USE_ENCRYPT_ONLY */ + #endif /* LTC_FORTUNA */ diff --git a/deps/libtomcrypt/src/headers/tomcrypt_hash.h b/deps/libtomcrypt/src/headers/tomcrypt_hash.h index 3c4bcf5a..384ee2a6 100644 --- a/deps/libtomcrypt/src/headers/tomcrypt_hash.h +++ b/deps/libtomcrypt/src/headers/tomcrypt_hash.h @@ -57,8 +57,8 @@ struct md4_state { #ifdef LTC_TIGER struct tiger_state { ulong64 state[3], length; - unsigned long curlen; - unsigned char buf[64]; + unsigned long curlen, passes; + unsigned char buf[64], pad; }; #endif @@ -440,10 +440,16 @@ extern const struct ltc_hash_descriptor md2_desc; #ifdef LTC_TIGER int tiger_init(hash_state * md); +int tiger_init_ex(hash_state *md, unsigned long passes); int tiger_process(hash_state * md, const unsigned char *in, unsigned long inlen); int tiger_done(hash_state * md, unsigned char *out); int tiger_test(void); -extern const struct ltc_hash_descriptor tiger_desc; +int tiger2_init(hash_state *md); +int tiger2_init_ex(hash_state *md, unsigned long passes); +#define tiger2_process(m, i, l) tiger_process(m, i, l) +#define tiger2_done(m, o) tiger_done(m, o) +int tiger2_test(void); +extern const struct ltc_hash_descriptor tiger_desc, tiger2_desc; #endif #ifdef LTC_RIPEMD128 diff --git a/deps/libtomcrypt/src/misc/crypt/crypt.c b/deps/libtomcrypt/src/misc/crypt/crypt.c index f91ae06f..81f00dbf 100644 --- a/deps/libtomcrypt/src/misc/crypt/crypt.c +++ b/deps/libtomcrypt/src/misc/crypt/crypt.c @@ -315,9 +315,12 @@ const char *crypt_build_settings = #if defined(LTC_FORTUNA) " Fortuna (" NAME_VALUE(LTC_FORTUNA_POOLS) ", " #if defined(LTC_FORTUNA_RESEED_RATELIMIT_TIMED) - "LTC_FORTUNA_RESEED_RATELIMIT_TIMED, " + "LTC_FORTUNA_RESEED_RATELIMIT_TIMED" #else "LTC_FORTUNA_RESEED_RATELIMIT_STATIC, " NAME_VALUE(LTC_FORTUNA_WD) +#endif +#if defined(LTC_FORTUNA_USE_ENCRYPT_ONLY) + ", LTC_FORTUNA_USE_ENCRYPT_ONLY" #endif ")\n" #endif diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_register_all_hashes.c b/deps/libtomcrypt/src/misc/crypt/crypt_register_all_hashes.c index 68a64aed..328e84a6 100644 --- a/deps/libtomcrypt/src/misc/crypt/crypt_register_all_hashes.c +++ b/deps/libtomcrypt/src/misc/crypt/crypt_register_all_hashes.c @@ -17,6 +17,7 @@ int register_all_hashes(void) { #ifdef LTC_TIGER REGISTER_HASH(&tiger_desc); + REGISTER_HASH(&tiger2_desc); #endif #ifdef LTC_MD2 REGISTER_HASH(&md2_desc); diff --git a/deps/libtomcrypt/src/prngs/fortuna.c b/deps/libtomcrypt/src/prngs/fortuna.c index 6f500986..9c92595e 100644 --- a/deps/libtomcrypt/src/prngs/fortuna.c +++ b/deps/libtomcrypt/src/prngs/fortuna.c @@ -39,6 +39,18 @@ we reseed automatically when len(pool0) >= 64 or every LTC_FORTUNA_WD calls to t #error LTC_FORTUNA_POOLS must be in [4..32] #endif +#ifdef LTC_FORTUNA_USE_ENCRYPT_ONLY +#define AES_SETUP aes_enc_setup +#define AES_ENC aes_enc_ecb_encrypt +#define AES_DONE aes_enc_done +#define AES_TEST aes_enc_test +#else +#define AES_SETUP aes_setup +#define AES_ENC aes_ecb_encrypt +#define AES_DONE aes_done +#define AES_TEST aes_test +#endif + const struct ltc_prng_descriptor fortuna_desc = { "fortuna", 64, @@ -146,7 +158,7 @@ static int s_fortuna_reseed(prng_state *prng) if ((err = sha256_done(&md, prng->u.fortuna.K)) != CRYPT_OK) { return err; } - if ((err = rijndael_setup(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey)) != CRYPT_OK) { + if ((err = AES_SETUP(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey)) != CRYPT_OK) { return err; } s_fortuna_update_iv(prng); @@ -236,7 +248,7 @@ int fortuna_start(prng_state *prng) /* reset bufs */ zeromem(prng->u.fortuna.K, 32); - if ((err = rijndael_setup(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey)) != CRYPT_OK) { + if ((err = AES_SETUP(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey)) != CRYPT_OK) { for (x = 0; x < LTC_FORTUNA_POOLS; x++) { sha256_done(&prng->u.fortuna.pool[x], tmp); } @@ -395,7 +407,7 @@ unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state /* handle whole blocks without the extra XMEMCPY */ while (outlen >= 16) { /* encrypt the IV and store it */ - rijndael_ecb_encrypt(prng->u.fortuna.IV, out, &prng->u.fortuna.skey); + AES_ENC(prng->u.fortuna.IV, out, &prng->u.fortuna.skey); out += 16; outlen -= 16; s_fortuna_update_iv(prng); @@ -403,19 +415,19 @@ unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state /* left over bytes? */ if (outlen > 0) { - rijndael_ecb_encrypt(prng->u.fortuna.IV, tmp, &prng->u.fortuna.skey); + AES_ENC(prng->u.fortuna.IV, tmp, &prng->u.fortuna.skey); XMEMCPY(out, tmp, outlen); s_fortuna_update_iv(prng); } /* generate new key */ - rijndael_ecb_encrypt(prng->u.fortuna.IV, prng->u.fortuna.K , &prng->u.fortuna.skey); + AES_ENC(prng->u.fortuna.IV, prng->u.fortuna.K , &prng->u.fortuna.skey); s_fortuna_update_iv(prng); - rijndael_ecb_encrypt(prng->u.fortuna.IV, prng->u.fortuna.K+16, &prng->u.fortuna.skey); + AES_ENC(prng->u.fortuna.IV, prng->u.fortuna.K+16, &prng->u.fortuna.skey); s_fortuna_update_iv(prng); - if (rijndael_setup(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey) != CRYPT_OK) { + if (AES_SETUP(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey) != CRYPT_OK) { tlen = 0; } @@ -512,7 +524,7 @@ int fortuna_test(void) if ((err = sha256_test()) != CRYPT_OK) { return err; } - return rijndael_test(); + return AES_TEST(); #endif } diff --git a/deps/libtomcrypt/tests/cipher_hash_test.c b/deps/libtomcrypt/tests/cipher_hash_test.c index 4ddc0755..431a7648 100644 --- a/deps/libtomcrypt/tests/cipher_hash_test.c +++ b/deps/libtomcrypt/tests/cipher_hash_test.c @@ -20,6 +20,7 @@ int cipher_hash_test(void) } DO(rijndael_test()); #endif + DO(aes_enc_test()); /* test stream ciphers */ #ifdef LTC_CHACHA diff --git a/deps/libtomcrypt/tests/test.c b/deps/libtomcrypt/tests/test.c index 22848a96..ccd6051b 100644 --- a/deps/libtomcrypt/tests/test.c +++ b/deps/libtomcrypt/tests/test.c @@ -185,6 +185,7 @@ static void s_unregister_all(void) #endif #ifdef LTC_TIGER + unregister_hash(&tiger2_desc); unregister_hash(&tiger_desc); #endif #ifdef LTC_MD2 diff --git a/deps/libtommath/.github/workflows/main.yml b/deps/libtommath/.github/workflows/main.yml index 2f0ef4e7..18a832bb 100644 --- a/deps/libtommath/.github/workflows/main.yml +++ b/deps/libtommath/.github/workflows/main.yml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-20.04 container: texlive/texlive:latest-full steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: generate PDF run: | make docs V=1 @@ -70,6 +70,12 @@ jobs: # RSA superclass with tests (no sanitizer, but debug info) - { BUILDOPTIONS: '--with-cc=gcc --with-m64 --cflags=-DLTM_NOTHING --cflags=-DSC_RSA_1_WITH_TESTS --limit-valgrind', SANITIZER: '', COMPILE_DEBUG: '1', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: '' } + # Build with small stack-size + - { BUILDOPTIONS: '--with-cc=gcc --with-m32 --with-m64 --cflags=-DMP_SMALL_STACK_SIZE', SANITIZER: '', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'gcc-multilib' } + - { BUILDOPTIONS: '--with-cc=clang-10 --with-m32 --with-m64 --cflags=-DMP_SMALL_STACK_SIZE --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'clang-10 llvm-10 libc6-dev-i386 gcc-multilib' } + - { BUILDOPTIONS: '--with-cc=gcc --with-m32 --with-m64 --cflags=-DMP_SMALL_STACK_SIZE --multithread --limit-valgrind', SANITIZER: '', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'libc6-dev-i386 gcc-multilib' } + - { BUILDOPTIONS: '--with-cc=clang-10 --with-m32 --with-m64 --cflags=-DMP_SMALL_STACK_SIZE --multithread', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'clang-10 llvm-10 gcc-multilib' } + # Test "autotuning", the automatic evaluation and setting of the Toom-Cook cut-offs. #- env: SANITIZER=1 BUILDOPTIONS='--with-cc=gcc-5 --cflags=-DMP_16BIT --limit-valgrind --make-option=tune' #- env: SANITIZER=1 BUILDOPTIONS='--with-cc=gcc-5 --cflags=-DMP_32BIT --limit-valgrind --make-option=tune' @@ -129,7 +135,7 @@ jobs: - { BUILDOPTIONS: '--with-cc=clang --cflags=-DMP_16BIT --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'clang llvm' } - { BUILDOPTIONS: '--with-cc=clang --cflags=-DMP_32BIT --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'clang llvm' } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: install dependencies run: | sudo apt-get update -qq @@ -172,7 +178,7 @@ jobs: amalgam: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: install dependencies run: | make amalgamated_timing @@ -190,7 +196,7 @@ jobs: # Shared library build - { CMAKEOPTIONS: '-DBUILD_SHARED_LIBS=On' } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: install dependencies run: | sudo apt-get update -qq diff --git a/deps/libtommath/.gitignore b/deps/libtommath/.gitignore index d2f01329..51f3eee2 100644 --- a/deps/libtommath/.gitignore +++ b/deps/libtommath/.gitignore @@ -29,6 +29,17 @@ mtest.exe mtest_opponent mtest_opponent.exe +2kprime +2kprime.exe +drprime +drprime.exe +mersenne +mersenne.exe +mont +mont.exe +pprime +pprime.exe + # ignore eclipse project files .cproject .project @@ -66,9 +77,11 @@ perf.data.old # ignore tommath_amalgam.c generated by make tommath_amalgam.c -# ignore file generated by make tune +# ignore file generated by make 'tune and friends' tuning_list etc/tune +2kprime.1 +drprimes.txt # ignore stuff generated by "make manual" and "make poster" *.aux diff --git a/deps/libtommath/CMakeLists.txt b/deps/libtommath/CMakeLists.txt index dfbcb0f2..014fb188 100644 --- a/deps/libtommath/CMakeLists.txt +++ b/deps/libtommath/CMakeLists.txt @@ -7,7 +7,7 @@ cmake_minimum_required(VERSION 3.10) project(libtommath - VERSION 1.2.0 + VERSION 1.3.0 DESCRIPTION "A free open source portable number theoretic multiple-precision integer (MPI) library written entirely in C." HOMEPAGE_URL "https://www.libtom.net/LibTomMath" LANGUAGES C) @@ -28,7 +28,9 @@ option(BUILD_TESTING "" OFF) include(CTest) include(sources.cmake) -# The only direct cmake argument for now +#----------------------------------------------------------------------------- +# Options +#----------------------------------------------------------------------------- option(BUILD_SHARED_LIBS "Build shared library and only the shared library if \"ON\", default is static" OFF) #----------------------------------------------------------------------------- @@ -122,7 +124,7 @@ if(COMPILE_LTO) if(COMPILER_SUPPORTS_LTO) set_property(TARGET ${PROJECT_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) else() - message(SEND_ERROR "This compiler does not support LTO. Reconfigure ${PROJECT_NAME} with -DCOMPILE_LTO=OFF.") + message(FATAL_ERROR "This compiler does not support LTO. Reconfigure ${PROJECT_NAME} with -DCOMPILE_LTO=OFF.") endif() endif() diff --git a/deps/libtommath/README.md b/deps/libtommath/README.md index 29e077f2..8ebdab70 100644 --- a/deps/libtommath/README.md +++ b/deps/libtommath/README.md @@ -30,8 +30,14 @@ Use those packages with caution and at your own discretion. The `develop` branch contains the in-development version. Stable releases are tagged. -Documentation is built from the LaTeX file `bn.tex`. There is also limited documentation in `tommath.h`. -There is also a document, `tommath.pdf`, which describes the goals of the project and many of the algorithms used. +Documentation is built from the LaTeX file `doc/bn.tex` and available as PDF for each release. +This PDF is also created as build artifact on each CI run. + +There is also limited documentation in `tommath.h`. + +Originally the library contained a document, `tommath.pdf`, which describes the goals of the project and many of the algorithms used at the time. +This document has been removed since it can't be built anymore and nobody spent the time to fix and update it. +The latest valid update to that document was done in version [`0.39`](https://github.com/libtom/libtommath/releases/tag/0.39) of the library and it is contained within that tarball. The project can be build by using `make`. Along with the usual `make`, `make clean` and `make install`, there are several other build targets, see the makefile for details. diff --git a/deps/libtommath/appveyor.yml b/deps/libtommath/appveyor.yml index 5accc261..d483d0e9 100644 --- a/deps/libtommath/appveyor.yml +++ b/deps/libtommath/appveyor.yml @@ -1,4 +1,4 @@ -version: 1.2.1-{build} +version: 1.3.0-{build} branches: only: - master @@ -11,6 +11,10 @@ image: - Visual Studio 2019 - Visual Studio 2017 - Visual Studio 2015 +environment: + matrix: + - CFLAGS_VAR: "" + CFLAGS_VAR_DLL: "CFLAGS=\"/Ox /MD /DLTM_TEST_DYNAMIC\"" build_script: - cmd: >- if "Visual Studio 2022"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" @@ -18,9 +22,9 @@ build_script: if "Visual Studio 2017"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" if "Visual Studio 2015"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 if "Visual Studio 2015"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86_amd64 - nmake -f makefile.msvc test.exe + nmake -f makefile.msvc test.exe %CFLAGS_VAR% nmake -f makefile.msvc clean-obj - nmake -f makefile.msvc test_dll.exe CFLAGS="/Ox /MD /DLTM_TEST_DYNAMIC" + nmake -f makefile.msvc test_dll.exe %CFLAGS_VAR_DLL% test_script: - cmd: test.exe - cmd: test_dll.exe diff --git a/deps/libtommath/changes.txt b/deps/libtommath/changes.txt index 2d8ff9f8..df2735da 100644 --- a/deps/libtommath/changes.txt +++ b/deps/libtommath/changes.txt @@ -1,3 +1,9 @@ +Mar 27th, 2024 +v1.3.0 + -- Deprecate more APIs which are replaced in develop (PR #572) + -- Add support for CMake (PR #573) + -- Add support for GitHub Actions (PR #573) + Sep 04th, 2023 v1.2.1 -- Bugfix release because of potential integer overflow diff --git a/deps/libtommath/demo/test.c b/deps/libtommath/demo/test.c index c5141ef7..2fa6e08d 100644 --- a/deps/libtommath/demo/test.c +++ b/deps/libtommath/demo/test.c @@ -1229,11 +1229,20 @@ LBL_ERR: static int test_mp_reduce_2k(void) { int ix, cnt; + bool is2k; mp_int a, b, c, d; DOR(mp_init_multi(&a, &b, &c, &d, NULL)); /* test mp_reduce_2k */ + + /* Algorithm as implemented does not work if the least significant digit is zero */ + DO(mp_2expt(&a, 100)); + DO(mp_sub_d(&a, 1, &a)); + DO(mp_sub_d(&a, MP_MASK, &a)); + is2k = mp_reduce_is_2k(&a); + EXPECT(!is2k); + for (cnt = 3; cnt <= 128; ++cnt) { mp_digit tmp; @@ -2446,12 +2455,101 @@ LBL_ERR: #define ONLY_PUBLIC_API_C #endif +#if !defined(LTM_TEST_MULTITHREAD) +#define SINGLE_THREADED_C +typedef uintptr_t thread_id_t; +#else +#define MULTI_THREADED_C +#if !defined(_WIN32) +#define MULTI_THREADED_PTHREAD_C +#include +typedef pthread_t thread_id_t; +#else +#define MULTI_THREADED_MSVC_C + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#endif +#ifndef WINVER +#define WINVER 0x0501 +#endif + +#define WIN32_LEAN_AND_MEAN +#include +typedef HANDLE thread_id_t; +#endif +#endif + +#if !defined(MULTI_THREADED_PTHREAD_C) +extern int pthread_create(thread_id_t *, const void *, void *(*)(void *), void *); +extern int pthread_join(thread_id_t, void **); +#endif + +#if !defined(MULTI_THREADED_MSVC_C) +extern thread_id_t CreateThread(void *, size_t, unsigned long (*)(void *), void *, unsigned long, void *); +extern unsigned long WaitForSingleObject(thread_id_t hHandle, unsigned long dwMilliseconds); +#define INFINITE ((unsigned long)-1) +#endif + +struct test_fn { + const char *name; + int (*fn)(void); +}; + +struct thread_info { + thread_id_t thread_id; + const struct test_fn *t; + int ret; +}; + +static void run(struct thread_info *tinfo) +{ + tinfo->ret = tinfo->t->fn(); + + if (mp_warray_free() == -2) + tinfo->ret = EXIT_FAILURE; +} + +static void *run_pthread(void *arg) +{ + run(arg); + + return arg; +} + +static unsigned long run_msvc(void *arg) +{ + run(arg); + + return 0; +} + +static int thread_start(struct thread_info *info) +{ + if (MP_HAS(MULTI_THREADED_PTHREAD)) + return pthread_create(&info->thread_id, NULL, run_pthread, info); + if (MP_HAS(MULTI_THREADED_MSVC)) { + info->thread_id = CreateThread(NULL, 0, run_msvc, info, 0, NULL); + return info->thread_id == (thread_id_t)NULL ? -1 : 0; + } + return -1; +} + +static int thread_join(struct thread_info *info, struct thread_info **res) +{ + if (MP_HAS(MULTI_THREADED_PTHREAD)) + return pthread_join(info->thread_id, (void **)res); + if (MP_HAS(MULTI_THREADED_MSVC)) { + WaitForSingleObject(info->thread_id, INFINITE); + *res = info; + return 0; + } + return -1; +} + static int unit_tests(int argc, char **argv) { - static const struct { - const char *name; - int (*fn)(void); - } test[] = { + static const struct test_fn test[] = { #define T0(n) { #n, test_##n } #define T1(n, o) { #n, MP_HAS(o) ? test_##n : NULL } #define T2(n, o1, o2) { #n, (MP_HAS(o1) && MP_HAS(o2)) ? test_##n : NULL } @@ -2513,10 +2611,10 @@ static int unit_tests(int argc, char **argv) #undef T2 #undef T1 }; + struct thread_info test_threads[sizeof(test)/sizeof(test[0])], *res; unsigned long i, ok, fail, nop; uint64_t t; int j; - ok = fail = nop = 0; t = (uint64_t)time(NULL); @@ -2524,20 +2622,43 @@ static int unit_tests(int argc, char **argv) s_mp_rand_jenkins_init(t); mp_rand_source(s_mp_rand_jenkins); + if (MP_HAS(MP_SMALL_STACK_SIZE)) { + printf("Small-stack enabled\n\n"); + } + + if (MP_HAS(MULTI_THREADED)) { + printf("Multi-threading enabled\n\n"); + /* we ignore the fact that jenkins is not thread safe */ + for (i = 0; i < (sizeof(test) / sizeof(test[0])); ++i) { + test_threads[i].t = &test[i]; + EXPECT(thread_start(&test_threads[i]) == 0); + } + } + for (i = 0; i < (sizeof(test) / sizeof(test[0])); ++i) { - if (argc > 1) { - for (j = 1; j < argc; ++j) { - if (strstr(test[i].name, argv[j]) != NULL) { - break; + j = -1; + if (MP_HAS(SINGLE_THREADED)) { + if (argc > 1) { + for (j = 1; j < argc; ++j) { + if (strstr(test[i].name, argv[j]) != NULL) { + break; + } } + if (j == argc) continue; } - if (j == argc) continue; + + if (test[i].fn) + j = test[i].fn(); + } else if (MP_HAS(MULTI_THREADED)) { + EXPECT(thread_join(&test_threads[i], &res) == 0); + j = res->ret; } printf("TEST %s\n", test[i].name); + if (test[i].fn == NULL) { nop++; printf("NOP %s\n\n", test[i].name); - } else if (test[i].fn() == EXIT_SUCCESS) { + } else if (j == EXIT_SUCCESS) { ok++; printf("\n"); } else { @@ -2547,8 +2668,12 @@ static int unit_tests(int argc, char **argv) } fprintf(fail?stderr:stdout, "Tests OK/NOP/FAIL: %lu/%lu/%lu\n", ok, nop, fail); - if (fail != 0) return EXIT_FAILURE; - else return EXIT_SUCCESS; + EXPECT(mp_warray_free() != -2); + + if (fail == 0) + return EXIT_SUCCESS; +LBL_ERR: + return EXIT_FAILURE; } int main(int argc, char **argv) diff --git a/deps/libtommath/doc/bn.tex b/deps/libtommath/doc/bn.tex index 118a4700..63e71633 100644 --- a/deps/libtommath/doc/bn.tex +++ b/deps/libtommath/doc/bn.tex @@ -51,7 +51,7 @@ \begin{document} \frontmatter \pagestyle{empty} -\title{LibTomMath User Manual \\ v1.2.1} +\title{LibTomMath User Manual \\ v1.3.0} \author{LibTom Projects \\ www.libtom.net} \maketitle This text, the library and the accompanying textbook are all hereby placed in the public domain. @@ -352,6 +352,16 @@ which means they are to be defined only if \texttt{LTM\_LAST} has been defined. \end{center} \end{small} +\subsection{Small-Stack option} +\label{ch:SMALL_STACK_INTRO} +The library can be compiled with the symbol \texttt{MP\_SMALL\_STACK\_SIZE} defined, which results in +the temporary \texttt{MP\_WARRAY}-sized stack buffers being put on the heap. +This comes with one problem, namely: formerly promised thread-safety isn't given anymore. +Therefore if the Small-Stack option is enabled while doing multi threading, one shall always initialize +the library by calling \texttt{mp\_warray\_init()} once with the correct number of threads. + +C.f. \ref{ch:SMALL_STACK_API} for the API description and further details. + \section{Purpose of LibTomMath} Unlike GNU MP (GMP) Library, LIP, OpenSSL or various other commercial kits (Miracl), LibTomMath was not written with bleeding edge performance in mind. First and foremost LibTomMath was written @@ -428,7 +438,11 @@ environments. Fast RSA for example can be performed with as little as 8 Kibibyt \section{Building Programs} In order to use LibTomMath you must include ``tommath.h'' and link against the appropriate library file (typically -libtommath.a). There is no library initialization required and the entire library is thread safe. +libtommath.a). There is no library initialization required and the entire library is thread safe +if it is used in its default configuration. The small-stack option makes use of atomic operations +to maintain its internal state and therefore does not require locking, but it MUST be initialized +if used from multiple threads. For further information see \ref{ch:SMALL_STACK_INTRO} resp. +\ref{ch:SMALL_STACK_API}. \section{Return Codes} There are five possible return codes a function may return. @@ -813,6 +827,37 @@ int main(void) \end{alltt} \end{small} +\section{Small-Stack option} +\label{ch:SMALL_STACK_API} + +In case the \texttt{MP\_SMALL\_STACK\_SIZE} symbol is defined the following functions +can be useful. + +To initialize the internal structure the following function shall be called. + +\index{mp\_warray\_init} +\begin{alltt} +mp_err mp_warray_init(size_t n_alloc, bool preallocate); +\end{alltt} + +The flag \texttt{preallocate} controls whether the internal buffers -- +\texttt{n\_alloc} buffers of size \texttt{MP\_WARRAY} -- will be allocated when +\texttt{mp\_warray\_init()} is called, or whether they will be allocated when required. + +To free the internally allocated memory the following function shall be called. + +\index{mp\_warray\_free} +\begin{alltt} +int mp_warray_free(void); +\end{alltt} + + +Those two API functions are always available, even if the \texttt{MP\_SMALL\_STACK\_SIZE} option +has been disabled at compile time. +In that case \texttt{mp\_warray\_init()} will return \texttt{MP\_ERR} and \texttt{mp\_warray\_free()} +will return $-1$. + + \chapter{Basic Operations} \section{Copying} diff --git a/deps/libtommath/etc/2kprime.1 b/deps/libtommath/etc/2kprime.1 deleted file mode 100644 index c41ded1f..00000000 --- a/deps/libtommath/etc/2kprime.1 +++ /dev/null @@ -1,2 +0,0 @@ -256-bits (k = 36113) = 115792089237316195423570985008687907853269984665640564039457584007913129603823 -512-bits (k = 38117) = 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006045979 diff --git a/deps/libtommath/etc/2kprime.c b/deps/libtommath/etc/2kprime.c index 3a3e2830..5aa83abd 100644 --- a/deps/libtommath/etc/2kprime.c +++ b/deps/libtommath/etc/2kprime.c @@ -10,23 +10,24 @@ int main(void) size_t x; bool y; mp_int q, p; + mp_err err; FILE *out; clock_t t1; mp_digit z; - mp_init_multi(&q, &p, NULL); + if ((err = mp_init_multi(&q, &p, NULL)) != MP_OKAY) goto LTM_ERR; out = fopen("2kprime.1", "w"); if (out != NULL) { for (x = 0; x < (sizeof(sizes) / sizeof(sizes[0])); x++) { top: - mp_2expt(&q, sizes[x]); - mp_add_d(&q, 3uL, &q); + if ((err = mp_2expt(&q, sizes[x])) != MP_OKAY) goto LTM_ERR; + if ((err = mp_add_d(&q, 3uL, &q)) != MP_OKAY) goto LTM_ERR; z = -3; t1 = clock(); for (;;) { - mp_sub_d(&q, 4uL, &q); + if ((err = mp_sub_d(&q, 4uL, &q)) != MP_OKAY) goto LTM_ERR; z += 4uL; if (z > MP_MASK) { @@ -42,21 +43,21 @@ top: } /* quick test on q */ - mp_prime_is_prime(&q, 1, &y); + if ((err = mp_prime_is_prime(&q, 1, &y)) != MP_OKAY) goto LTM_ERR; if (!y) { continue; } /* find (q-1)/2 */ - mp_sub_d(&q, 1uL, &p); - mp_div_2(&p, &p); - mp_prime_is_prime(&p, 3, &y); + if ((err = mp_sub_d(&q, 1uL, &p)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_div_2(&p, &p)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_prime_is_prime(&p, 3, &y)) != MP_OKAY) goto LTM_ERR; if (!y) { continue; } /* test on q */ - mp_prime_is_prime(&q, 3, &y); + if ((err = mp_prime_is_prime(&q, 3, &y)) != MP_OKAY) goto LTM_ERR; if (!y) { continue; } @@ -69,13 +70,13 @@ top: goto top; } - mp_to_decimal(&q, buf, sizeof(buf)); + if ((err = mp_to_decimal(&q, buf, sizeof(buf))) != MP_OKAY) goto LTM_ERR; printf("\n\n%d-bits (k = %lu) = %s\n", sizes[x], z, buf); fprintf(out, "%d-bits (k = %lu) = %s\n", sizes[x], z, buf); fflush(out); } fclose(out); } - +LTM_ERR: return 0; } diff --git a/deps/libtommath/etc/drprime.c b/deps/libtommath/etc/drprime.c index 31dff4e9..e2e709b9 100644 --- a/deps/libtommath/etc/drprime.c +++ b/deps/libtommath/etc/drprime.c @@ -10,16 +10,17 @@ int main(void) char buf[4096]; FILE *out; mp_int a, b; + mp_err err; - mp_init(&a); - mp_init(&b); + if ((err = mp_init(&a)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_init(&b)) != MP_OKAY) goto LTM_ERR; out = fopen("drprimes.txt", "w"); if (out != NULL) { for (x = 0; x < (int)(sizeof(sizes)/sizeof(sizes[0])); x++) { top: printf("Seeking a %d-bit safe prime\n", sizes[x] * MP_DIGIT_BIT); - mp_grow(&a, sizes[x]); + if ((err = mp_grow(&a, sizes[x])) != MP_OKAY) goto LTM_ERR; mp_zero(&a); for (y = 1; y < sizes[x]; y++) { a.dp[y] = MP_MASK; @@ -34,15 +35,15 @@ top: for (;;) { a.dp[0] += 4uL; if (a.dp[0] >= MP_MASK) break; - mp_prime_is_prime(&a, 1, &res); + if ((err = mp_prime_is_prime(&a, 1, &res)) != MP_OKAY) goto LTM_ERR; if (!res) continue; printf("."); fflush(stdout); - mp_sub_d(&a, 1uL, &b); - mp_div_2(&b, &b); - mp_prime_is_prime(&b, 3, &res); + if ((err = mp_sub_d(&a, 1uL, &b)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_div_2(&b, &b)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_prime_is_prime(&b, 3, &res)) != MP_OKAY) goto LTM_ERR; if (!res) continue; - mp_prime_is_prime(&a, 3, &res); + if ((err = mp_prime_is_prime(&a, 3, &res)) != MP_OKAY) goto LTM_ERR; if (res) break; } @@ -51,7 +52,7 @@ top: sizes[x] += 1; goto top; } else { - mp_to_decimal(&a, buf, sizeof(buf)); + if ((err = mp_to_decimal(&a, buf, sizeof(buf))) != MP_OKAY) goto LTM_ERR; printf("\n\np == %s\n\n", buf); fprintf(out, "%d-bit prime:\np == %s\n\n", mp_count_bits(&a), buf); fflush(out); @@ -60,6 +61,7 @@ top: fclose(out); } +LTM_ERR: mp_clear(&a); mp_clear(&b); diff --git a/deps/libtommath/etc/drprimes.txt b/deps/libtommath/etc/drprimes.txt deleted file mode 100644 index 7c97f67b..00000000 --- a/deps/libtommath/etc/drprimes.txt +++ /dev/null @@ -1,9 +0,0 @@ -300-bit prime: -p == 2037035976334486086268445688409378161051468393665936250636140449354381298610415201576637819 - -540-bit prime: -p == 3599131035634557106248430806148785487095757694641533306480604458089470064537190296255232548883112685719936728506816716098566612844395439751206810991770626477344739 - -780-bit prime: -p == 6359114106063703798370219984742410466332205126109989319225557147754704702203399726411277962562135973685197744935448875852478791860694279747355800678568677946181447581781401213133886609947027230004277244697462656003655947791725966271167 - diff --git a/deps/libtommath/etc/makefile b/deps/libtommath/etc/makefile index 52ad4753..0e178396 100644 --- a/deps/libtommath/etc/makefile +++ b/deps/libtommath/etc/makefile @@ -6,6 +6,8 @@ LTM_TUNE_CFLAGS = $(CFLAGS) $(LTM_CFLAGS) -Wall -W -Wextra -Wshadow -O3 -I../ # libname when you can't install the lib with install LIBNAME=../libtommath.a +all: pprime tune test_standalone mersenne drprime 2kprime mont + #provable primes pprime: pprime.o $(CC) $(LTM_TUNE_CFLAGS) pprime.o $(LIBNAME) -o pprime diff --git a/deps/libtommath/etc/mersenne.c b/deps/libtommath/etc/mersenne.c index 4d3939e3..f7487ecd 100644 --- a/deps/libtommath/etc/mersenne.c +++ b/deps/libtommath/etc/mersenne.c @@ -57,7 +57,9 @@ static mp_err is_mersenne(long s, bool *pp) /* if u == 0 then its prime */ if (mp_iszero(&u)) { - mp_prime_is_prime(&n, 8, pp); + if ((res = mp_prime_is_prime(&n, 8, pp)) != MP_OKAY) { + goto LBL_MU; + } if (!*pp) printf("FAILURE\n"); } diff --git a/deps/libtommath/etc/mont.c b/deps/libtommath/etc/mont.c index 4652410d..3d844496 100644 --- a/deps/libtommath/etc/mont.c +++ b/deps/libtommath/etc/mont.c @@ -7,10 +7,11 @@ int main(void) { mp_int modulus, R, p, pp; mp_digit mp; + mp_err err; int x, y; srand(time(NULL)); - mp_init_multi(&modulus, &R, &p, &pp, NULL); + if ((err = mp_init_multi(&modulus, &R, &p, &pp, NULL)) != MP_OKAY) goto LTM_ERR; /* loop through various sizes */ for (x = 4; x < 256; x++) { @@ -18,18 +19,20 @@ int main(void) fflush(stdout); /* make up the odd modulus */ - mp_rand(&modulus, x); + if ((err = mp_rand(&modulus, x)) != MP_OKAY) goto LTM_ERR; modulus.dp[0] |= 1uL; /* now find the R value */ - mp_montgomery_calc_normalization(&R, &modulus); - mp_montgomery_setup(&modulus, &mp); + if ((err = mp_montgomery_calc_normalization(&R, &modulus)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_montgomery_setup(&modulus, &mp)) != MP_OKAY) goto LTM_ERR; /* now run through a bunch tests */ for (y = 0; y < 1000; y++) { - mp_rand(&p, x/2); /* p = random */ - mp_mul(&p, &R, &pp); /* pp = R * p */ - mp_montgomery_reduce(&pp, &modulus, mp); + /* p = random */ + if ((err = mp_rand(&p, x/2)) != MP_OKAY) goto LTM_ERR; + /* pp = R * p */ + if ((err = mp_mul(&p, &R, &pp)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_montgomery_reduce(&pp, &modulus, mp)) != MP_OKAY) goto LTM_ERR; /* should be equal to p */ if (mp_cmp(&pp, &p) != MP_EQ) { @@ -40,5 +43,6 @@ int main(void) printf("PASSED\n"); } +LTM_ERR: return 0; } diff --git a/deps/libtommath/etc/pprime.c b/deps/libtommath/etc/pprime.c index 1d59cab7..7533a609 100644 --- a/deps/libtommath/etc/pprime.c +++ b/deps/libtommath/etc/pprime.c @@ -1,179 +1,40 @@ -/* Generates provable primes - * - * See http://gmail.com:8080/papers/pp.pdf for more info. +/* + * Generates provable primes * * Tom St Denis, tomstdenis@gmail.com, http://tom.gmail.com + * */ #include #include -#include "tommath_private.h" +#include "../tommath_private.h" -static int n_prime; -static FILE *primes; - -/* fast square root */ -static mp_digit i_sqrt(mp_word x) +static void mp_print(const char *s, const mp_int *a, int radix, FILE *stream) { - mp_word x1, x2; - - x2 = x; - do { - x1 = x2; - x2 = x1 - ((x1 * x1) - x) / (2u * x1); - } while (x1 != x2); - - if ((x1 * x1) > x) { - --x1; + mp_err err; + fputs(s, stream); + err = mp_fwrite(a, radix, stream); + if (err != MP_OKAY) { + fprintf(stderr,"mp_fwrite in mp_print failed. error = %s\n", mp_error_to_string(err)); + exit(EXIT_FAILURE); } - - return x1; + fputc('\n',stream); } - -/* generates a prime digit */ -static void gen_prime(void) +static mp_digit prime_digit(int bits) { - mp_digit r, x, y, next; - FILE *out; + mp_digit d = 0; + mp_int a; + mp_err err; - out = fopen("pprime.dat", "wb"); - if (out != NULL) { - - /* write first set of primes */ - /* *INDENT-OFF* */ - r = 3uL; fwrite(&r, 1uL, sizeof(mp_digit), out); - r = 5uL; fwrite(&r, 1uL, sizeof(mp_digit), out); - r = 7uL; fwrite(&r, 1uL, sizeof(mp_digit), out); - r = 11uL; fwrite(&r, 1uL, sizeof(mp_digit), out); - r = 13uL; fwrite(&r, 1uL, sizeof(mp_digit), out); - r = 17uL; fwrite(&r, 1uL, sizeof(mp_digit), out); - r = 19uL; fwrite(&r, 1uL, sizeof(mp_digit), out); - r = 23uL; fwrite(&r, 1uL, sizeof(mp_digit), out); - r = 29uL; fwrite(&r, 1uL, sizeof(mp_digit), out); - r = 31uL; fwrite(&r, 1uL, sizeof(mp_digit), out); - /* *INDENT-ON* */ - - /* get square root, since if 'r' is composite its factors must be < than this */ - y = i_sqrt(r); - next = (y + 1uL) * (y + 1uL); - - for (;;) { - do { - r += 2uL; /* next candidate */ - r &= MP_MASK; - if (r < 31uL) break; - - /* update sqrt ? */ - if (next <= r) { - ++y; - next = (y + 1uL) * (y + 1uL); - } - - /* loop if divisible by 3,5,7,11,13,17,19,23,29 */ - if ((r % 3uL) == 0uL) { - x = 0uL; - continue; - } - if ((r % 5uL) == 0uL) { - x = 0uL; - continue; - } - if ((r % 7uL) == 0uL) { - x = 0uL; - continue; - } - if ((r % 11uL) == 0uL) { - x = 0uL; - continue; - } - if ((r % 13uL) == 0uL) { - x = 0uL; - continue; - } - if ((r % 17uL) == 0uL) { - x = 0uL; - continue; - } - if ((r % 19uL) == 0uL) { - x = 0uL; - continue; - } - if ((r % 23uL) == 0uL) { - x = 0uL; - continue; - } - if ((r % 29uL) == 0uL) { - x = 0uL; - continue; - } - - /* now check if r is divisible by x + k={1,7,11,13,17,19,23,29} */ - for (x = 30uL; x <= y; x += 30uL) { - if ((r % (x + 1uL)) == 0uL) { - x = 0uL; - break; - } - if ((r % (x + 7uL)) == 0uL) { - x = 0uL; - break; - } - if ((r % (x + 11uL)) == 0uL) { - x = 0uL; - break; - } - if ((r % (x + 13uL)) == 0uL) { - x = 0uL; - break; - } - if ((r % (x + 17uL)) == 0uL) { - x = 0uL; - break; - } - if ((r % (x + 19uL)) == 0uL) { - x = 0uL; - break; - } - if ((r % (x + 23uL)) == 0uL) { - x = 0uL; - break; - } - if ((r % (x + 29uL)) == 0uL) { - x = 0uL; - break; - } - } - } while (x == 0uL); - if (r > 31uL) { - fwrite(&r, 1uL, sizeof(mp_digit), out); - printf("%9lu\r", r); - fflush(stdout); - } - if (r < 31uL) break; - } - - fclose(out); + if ((err = mp_init(&a)) != MP_OKAY) { + return 0; } -} -static void load_tab(void) -{ - primes = fopen("pprime.dat", "rb"); - if (primes == NULL) { - gen_prime(); - primes = fopen("pprime.dat", "rb"); - } - fseek(primes, 0L, SEEK_END); - n_prime = ftell(primes) / sizeof(mp_digit); -} + if ((err = mp_prime_rand(&a, 1, bits, false)) != MP_OKAY) goto LTM_ERR; + d = a.dp[0]; -static mp_digit prime_digit(void) -{ - int n; - mp_digit d; - - n = abs(rand()) % n_prime; - fseek(primes, n * sizeof(mp_digit), SEEK_SET); - fread(&d, 1uL, sizeof(mp_digit), primes); +LTM_ERR: + mp_clear(&a); return d; } @@ -182,230 +43,177 @@ static mp_digit prime_digit(void) static mp_err pprime(int k, int li, mp_int *p, mp_int *q) { mp_int a, b, c, n, x, y, z, v; - mp_err res; - int ii; - static const mp_digit bases[] = { 2, 3, 5, 7, 11, 13, 17, 19 }; + mp_err err = MP_OKAY; + int ii, bits; /* single digit ? */ - if (k <= (int) MP_DIGIT_BIT) { - mp_set(p, prime_digit()); + if (k < (int) MP_DIGIT_BIT) { + mp_set(p, prime_digit(k)); + if (mp_iszero(p)) { + return MP_VAL; + } return MP_OKAY; } - if ((res = mp_init(&c)) != MP_OKAY) { - return res; - } - - if ((res = mp_init(&v)) != MP_OKAY) { - goto LBL_C; + if ((err = mp_init_multi(&a, &b, &c, &n, &x, &y, &z, &v, NULL)) != MP_OKAY) { + return err; } /* product of first 50 primes */ - if ((res = - mp_read_radix(&v, - "19078266889580195013601891820992757757219839668357012055907516904309700014933909014729740190", - 10)) != MP_OKAY) { - goto LBL_V; - } - - if ((res = mp_init(&a)) != MP_OKAY) { - goto LBL_V; + if ((err = mp_read_radix(&v, "9NPvy2By/eZ0N6s68ky5K/8UTD0Q7fInhDK9BHnueH92HfzU4+U", 64)) != MP_OKAY) { + goto LTM_ERR; } /* set the prime */ - mp_set(&a, prime_digit()); - - if ((res = mp_init(&b)) != MP_OKAY) { - goto LBL_A; - } - - if ((res = mp_init(&n)) != MP_OKAY) { - goto LBL_B; - } - - if ((res = mp_init(&x)) != MP_OKAY) { - goto LBL_N; - } - - if ((res = mp_init(&y)) != MP_OKAY) { - goto LBL_X; - } - - if ((res = mp_init(&z)) != MP_OKAY) { - goto LBL_Y; + mp_set(&a, prime_digit(MP_DIGIT_BIT)); + if (mp_iszero(&a)) { + err = MP_VAL; + goto LTM_ERR; } /* now loop making the single digit */ while (mp_count_bits(&a) < k) { - fprintf(stderr, "prime has %4d bits left\r", k - mp_count_bits(&a)); + bits = k - mp_count_bits(&a); + fprintf(stderr, "prime has %4d bits left\r", bits); fflush(stderr); top: - mp_set(&b, prime_digit()); + if (bits < MP_DIGIT_BIT) { + mp_set(&b, prime_digit(bits)); + } else { + mp_set(&b, prime_digit(MP_DIGIT_BIT)); + } + if (mp_iszero(&b)) { + err = MP_VAL; + goto LTM_ERR; + } /* now compute z = a * b * 2 */ - if ((res = mp_mul(&a, &b, &z)) != MP_OKAY) { /* z = a * b */ - goto LBL_Z; - } - - if ((res = mp_copy(&z, &c)) != MP_OKAY) { /* c = a * b */ - goto LBL_Z; - } - - if ((res = mp_mul_2(&z, &z)) != MP_OKAY) { /* z = 2 * a * b */ - goto LBL_Z; - } - + /* z = a * b */ + if ((err = mp_mul(&a, &b, &z)) != MP_OKAY) goto LTM_ERR; + /* c = a * b */ + if ((err = mp_copy(&z, &c)) != MP_OKAY) goto LTM_ERR; + /* z = 2 * a * b */ + if ((err = mp_mul_2(&z, &z)) != MP_OKAY) goto LTM_ERR; /* n = z + 1 */ - if ((res = mp_add_d(&z, 1uL, &n)) != MP_OKAY) { /* n = z + 1 */ - goto LBL_Z; - } + if ((err = mp_add_d(&z, 1uL, &n)) != MP_OKAY) goto LTM_ERR; + /* check (n, v) == 1; y = (n, v) */ + if ((err = mp_gcd(&n, &v, &y)) != MP_OKAY) goto LTM_ERR; - /* check (n, v) == 1 */ - if ((res = mp_gcd(&n, &v, &y)) != MP_OKAY) { /* y = (n, v) */ - goto LBL_Z; - } - - if (mp_cmp_d(&y, 1uL) != MP_EQ) + if (mp_cmp_d(&y, 1uL) != MP_EQ) { goto top; - + } + mp_set(&x, 2u); /* now try base x=bases[ii] */ for (ii = 0; ii < li; ii++) { - mp_set(&x, bases[ii]); + if ((err = mp_prime_next_prime(&x, -1, false)) != MP_OKAY) goto LTM_ERR; - /* compute x^a mod n */ - if ((res = mp_exptmod(&x, &a, &n, &y)) != MP_OKAY) { /* y = x^a mod n */ - goto LBL_Z; + /* compute x^a mod n; y = x^a mod n */ + if ((err = mp_exptmod(&x, &a, &n, &y)) != MP_OKAY) goto LTM_ERR; + /* if y == 1 loop */ + if (mp_cmp_d(&y, 1uL) == MP_EQ) { + continue; } + /* now x^2a mod n ; y = x^2a mod n*/ + if ((err = mp_sqrmod(&y, &n, &y)) != MP_OKAY) goto LTM_ERR; + + if (mp_cmp_d(&y, 1uL) == MP_EQ) { + continue; + } + + /* compute x^b mod n ; y = x^b mod n*/ + if ((err = mp_exptmod(&x, &b, &n, &y)) != MP_OKAY) goto LTM_ERR; /* if y == 1 loop */ - if (mp_cmp_d(&y, 1uL) == MP_EQ) + if (mp_cmp_d(&y, 1uL) == MP_EQ) { continue; - - /* now x^2a mod n */ - if ((res = mp_sqrmod(&y, &n, &y)) != MP_OKAY) { /* y = x^2a mod n */ - goto LBL_Z; } - if (mp_cmp_d(&y, 1uL) == MP_EQ) - continue; + /* now x^2b mod n; y = x^2b mod n */ + if ((err = mp_sqrmod(&y, &n, &y)) != MP_OKAY) goto LTM_ERR; - /* compute x^b mod n */ - if ((res = mp_exptmod(&x, &b, &n, &y)) != MP_OKAY) { /* y = x^b mod n */ - goto LBL_Z; + if (mp_cmp_d(&y, 1uL) == MP_EQ) { + continue; } + /* compute x^c mod n == x^ab mod n ; y = x^ab mod n */ + if ((err = mp_exptmod(&x, &c, &n, &y)) != MP_OKAY) goto LTM_ERR; /* if y == 1 loop */ - if (mp_cmp_d(&y, 1uL) == MP_EQ) + if (mp_cmp_d(&y, 1uL) == MP_EQ) { continue; - - /* now x^2b mod n */ - if ((res = mp_sqrmod(&y, &n, &y)) != MP_OKAY) { /* y = x^2b mod n */ - goto LBL_Z; - } - - if (mp_cmp_d(&y, 1uL) == MP_EQ) - continue; - - /* compute x^c mod n == x^ab mod n */ - if ((res = mp_exptmod(&x, &c, &n, &y)) != MP_OKAY) { /* y = x^ab mod n */ - goto LBL_Z; - } - - /* if y == 1 loop */ - if (mp_cmp_d(&y, 1uL) == MP_EQ) - continue; - - /* now compute (x^c mod n)^2 */ - if ((res = mp_sqrmod(&y, &n, &y)) != MP_OKAY) { /* y = x^2ab mod n */ - goto LBL_Z; } + /* now compute (x^c mod n)^2 ; y = x^2ab mod n */ + if ((err = mp_sqrmod(&y, &n, &y)) != MP_OKAY) goto LTM_ERR; /* y should be 1 */ - if (mp_cmp_d(&y, 1uL) != MP_EQ) + if (mp_cmp_d(&y, 1uL) != MP_EQ) { continue; + } break; } /* no bases worked? */ - if (ii == li) + if (ii == li) { goto top; - - { - char buf[4096]; - - mp_to_decimal(&n, buf, sizeof(buf)); - printf("Certificate of primality for:\n%s\n\n", buf); - mp_to_decimal(&a, buf, sizeof(buf)); - printf("A == \n%s\n\n", buf); - mp_to_decimal(&b, buf, sizeof(buf)); - printf("B == \n%s\n\nG == %lu\n", buf, bases[ii]); - printf("----------------------------------------------------------------\n"); } + mp_print("Certificate of primality for:\n ", &n, 10, stdout); + mp_print("A == ", &a, 10, stdout); + mp_print("B == ", &b, 10, stdout); + mp_print("G == ", &x, 10, stdout); + printf("----------------------------------------------------------------\n"); + /* a = n */ - mp_copy(&n, &a); + if ((err = mp_copy(&n, &a)) != MP_OKAY) goto LTM_ERR; } /* get q to be the order of the large prime subgroup */ - mp_sub_d(&n, 1uL, q); - mp_div_2(q, q); - mp_div(q, &b, q, NULL); + if ((err = mp_sub_d(&n, 1uL, q)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_div_2(q, q)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_div(q, &b, q, NULL)) != MP_OKAY) goto LTM_ERR; mp_exch(&n, p); - res = MP_OKAY; -LBL_Z: - mp_clear(&z); -LBL_Y: - mp_clear(&y); -LBL_X: - mp_clear(&x); -LBL_N: - mp_clear(&n); -LBL_B: - mp_clear(&b); -LBL_A: - mp_clear(&a); -LBL_V: - mp_clear(&v); -LBL_C: - mp_clear(&c); - return res; + err = MP_OKAY; +LTM_ERR: + mp_clear_multi(&a, &b, &c, &n, &x, &y, &z, &v, NULL); + return err; } int main(void) { mp_int p, q; + mp_err err; char buf[4096]; int k, li; clock_t t1; - srand(time(NULL)); - load_tab(); - printf("Enter # of bits: \n"); fgets(buf, sizeof(buf), stdin); sscanf(buf, "%d", &k); - printf("Enter number of bases to try (1 to 8):\n"); + printf("Enter number of bases to try\n"); fgets(buf, sizeof(buf), stdin); sscanf(buf, "%d", &li); - mp_init(&p); - mp_init(&q); + if ((err = mp_init_multi(&p, &q, NULL)) != MP_OKAY) goto LTM_ERR; t1 = clock(); - pprime(k, li, &p, &q); + if ((err = pprime(k, li, &p, &q)) != MP_OKAY) { + fprintf(stderr, "Something went wrong in function pprime: %s\n", mp_error_to_string(err)); + goto LTM_ERR; + } t1 = clock() - t1; printf("\n\nTook %lu ticks, %d bits\n", t1, mp_count_bits(&p)); - mp_to_decimal(&p, buf, sizeof(buf)); - printf("P == %s\n", buf); - mp_to_decimal(&q, buf, sizeof(buf)); - printf("Q == %s\n", buf); + mp_print("P == ", &p, 10, stdout); + mp_print("Q == ", &q, 10, stdout); - return 0; + mp_clear_multi(&p, &q, NULL); + exit(EXIT_SUCCESS); +LTM_ERR: + mp_clear_multi(&p, &q, NULL); + exit(EXIT_FAILURE); } diff --git a/deps/libtommath/helper.pl b/deps/libtommath/helper.pl index 53658614..ffc592a7 100644 --- a/deps/libtommath/helper.pl +++ b/deps/libtommath/helper.pl @@ -394,7 +394,7 @@ EOS foreach my $filename (glob '*mp_*.c') { my $content; my $cc = $ENV{'CC'} || 'gcc'; - $content = `$cc -E -x c -DLTM_ALL $filename`; + $content = `$cc -E -x c -DLTM_ALL -DMP_SMALL_STACK_SIZE $filename`; $content =~ s/^# 1 "$filename".*?^# 2 "$filename"//ms; # convert filename to upper case so we can use it as a define diff --git a/deps/libtommath/libtommath_VS2008.vcproj b/deps/libtommath/libtommath_VS2008.vcproj index 50a2dd68..b819477e 100644 --- a/deps/libtommath/libtommath_VS2008.vcproj +++ b/deps/libtommath/libtommath_VS2008.vcproj @@ -792,6 +792,10 @@ RelativePath="mp_unpack.c" > + + @@ -928,6 +932,18 @@ RelativePath="s_mp_sub.c" > + + + + + + diff --git a/deps/libtommath/makefile b/deps/libtommath/makefile index f8feff7c..8f211f5f 100644 --- a/deps/libtommath/makefile +++ b/deps/libtommath/makefile @@ -43,13 +43,14 @@ mp_reduce_2k_l.o mp_reduce_2k_setup.o mp_reduce_2k_setup_l.o mp_reduce_is_2k.o m mp_reduce_setup.o mp_root_n.o mp_rshd.o mp_sbin_size.o mp_set.o mp_set_double.o mp_set_i32.o mp_set_i64.o \ mp_set_l.o mp_set_u32.o mp_set_u64.o mp_set_ul.o mp_shrink.o mp_signed_rsh.o mp_sqrmod.o mp_sqrt.o \ mp_sqrtmod_prime.o mp_sub.o mp_sub_d.o mp_submod.o mp_to_radix.o mp_to_sbin.o mp_to_ubin.o mp_ubin_size.o \ -mp_unpack.o mp_xor.o mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o s_mp_div_recursive.o \ -s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_fp_log.o s_mp_fp_log_d.o \ -s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.o s_mp_montgomery_reduce_comba.o s_mp_mul.o \ -s_mp_mul_balance.o s_mp_mul_comba.o s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o \ -s_mp_mul_toom.o s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o \ -s_mp_radix_size_overestimate.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o s_mp_sqr_karatsuba.o \ -s_mp_sqr_toom.o s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o +mp_unpack.o mp_warray_free.o mp_xor.o mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o \ +s_mp_div_recursive.o s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_fp_log.o \ +s_mp_fp_log_d.o s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.o \ +s_mp_montgomery_reduce_comba.o s_mp_mul.o s_mp_mul_balance.o s_mp_mul_comba.o s_mp_mul_high.o \ +s_mp_mul_high_comba.o s_mp_mul_karatsuba.o s_mp_mul_toom.o s_mp_prime_is_divisible.o s_mp_prime_tab.o \ +s_mp_radix_map.o s_mp_radix_size_overestimate.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o \ +s_mp_sqr_karatsuba.o s_mp_sqr_toom.o s_mp_sub.o s_mp_warray.o s_mp_warray_get.o s_mp_warray_put.o \ +s_mp_zero_buf.o s_mp_zero_digs.o #END_INS @@ -107,6 +108,10 @@ tune: $(LIBNAME) $(MAKE) -C etc tune CFLAGS="$(LTM_CFLAGS) -I../" $(MAKE) +etc-all: $(LIBNAME) + $(MAKE) -C etc all CFLAGS="$(LTM_CFLAGS) -I../" + $(MAKE) + # You have to create a file .coveralls.yml with the content "repo_token: " # in the base folder to be able to submit to coveralls coveralls: lcov @@ -122,8 +127,12 @@ cmp: profiled_single ./timing $(MAKE) -C logs/ cmp +zipup: + $(MAKE) clean + $(MAKE) .zipup + TODAY=$(shell date -I) -zipup: clean astyle new_file docs +.zipup: astyle new_file docs @# Update the index, so diff-index won't fail in case the pdf has been created. @# As the pdf creation modifies the tex files, git sometimes detects the @# modified files, but misses that it's put back to its original version. @@ -164,9 +173,10 @@ c89: -e 's/UINT32_MAX/0xFFFFFFFFu/g' \ -e 's/UINT64_MAX/(mp_u64)-1/g' \ -e 's/INT32_MAX/0x7FFFFFFF/g' \ - -e 's/INT32_MIN/(-2147483647-1)/g' \ + -e 's/INT32_MIN/(-2147483647-1)/g' \ -e 's/INT64_MAX/(mp_i64)(((mp_u64)1<<63)-1)/g' \ -e 's/INT64_MIN/(mp_i64)((mp_u64)1<<63)/g' \ + -e 's/uintptr_t/mp_uintptr/g' \ -e 's/SIZE_MAX/((size_t)-1)/g' \ -e 's/\(PRI[ioux]64\)/MP_\1/g' \ -e 's/uint\([0-9][0-9]*\)_t/mp_u\1/g' \ @@ -187,10 +197,11 @@ c99: -e 's/false_/MP_NO_/g' \ -e 's/0xFFFFFFFFu/UINT32_MAX/g' \ -e 's/(mp_u64)-1/UINT64_MAX/g' \ - -e 's/(-2147483647-1)/INT32_MIN/g' \ + -e 's/(-2147483647-1)/INT32_MIN/g' \ -e 's/0x7FFFFFFF/INT32_MAX/g' \ -e 's/(mp_i64)((mp_u64)1<<63)/INT64_MIN/g' \ -e 's/(mp_i64)(((mp_u64)1<<63)-1)/INT64_MAX/g' \ + -e 's/mp_uintptr/uintptr_t/g' \ -e 's/((size_t)-1)/SIZE_MAX/g' \ -e 's/MP_\(PRI[ioux]64\)/\1/g' \ -e 's/mp_u\([0-9][0-9]*\)/uint\1_t/g' \ diff --git a/deps/libtommath/makefile.mingw b/deps/libtommath/makefile.mingw index 532747be..e2445e8a 100644 --- a/deps/libtommath/makefile.mingw +++ b/deps/libtommath/makefile.mingw @@ -45,13 +45,14 @@ mp_reduce_2k_l.o mp_reduce_2k_setup.o mp_reduce_2k_setup_l.o mp_reduce_is_2k.o m mp_reduce_setup.o mp_root_n.o mp_rshd.o mp_sbin_size.o mp_set.o mp_set_double.o mp_set_i32.o mp_set_i64.o \ mp_set_l.o mp_set_u32.o mp_set_u64.o mp_set_ul.o mp_shrink.o mp_signed_rsh.o mp_sqrmod.o mp_sqrt.o \ mp_sqrtmod_prime.o mp_sub.o mp_sub_d.o mp_submod.o mp_to_radix.o mp_to_sbin.o mp_to_ubin.o mp_ubin_size.o \ -mp_unpack.o mp_xor.o mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o s_mp_div_recursive.o \ -s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_fp_log.o s_mp_fp_log_d.o \ -s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.o s_mp_montgomery_reduce_comba.o s_mp_mul.o \ -s_mp_mul_balance.o s_mp_mul_comba.o s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o \ -s_mp_mul_toom.o s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o \ -s_mp_radix_size_overestimate.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o s_mp_sqr_karatsuba.o \ -s_mp_sqr_toom.o s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o +mp_unpack.o mp_warray_free.o mp_xor.o mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o \ +s_mp_div_recursive.o s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_fp_log.o \ +s_mp_fp_log_d.o s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.o \ +s_mp_montgomery_reduce_comba.o s_mp_mul.o s_mp_mul_balance.o s_mp_mul_comba.o s_mp_mul_high.o \ +s_mp_mul_high_comba.o s_mp_mul_karatsuba.o s_mp_mul_toom.o s_mp_prime_is_divisible.o s_mp_prime_tab.o \ +s_mp_radix_map.o s_mp_radix_size_overestimate.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o \ +s_mp_sqr_karatsuba.o s_mp_sqr_toom.o s_mp_sub.o s_mp_warray.o s_mp_warray_get.o s_mp_warray_put.o \ +s_mp_zero_buf.o s_mp_zero_digs.o HEADERS_PUB=tommath.h HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB) diff --git a/deps/libtommath/makefile.msvc b/deps/libtommath/makefile.msvc index 5d128549..8feb425c 100644 --- a/deps/libtommath/makefile.msvc +++ b/deps/libtommath/makefile.msvc @@ -41,13 +41,14 @@ mp_reduce_2k_l.obj mp_reduce_2k_setup.obj mp_reduce_2k_setup_l.obj mp_reduce_is_ mp_reduce_setup.obj mp_root_n.obj mp_rshd.obj mp_sbin_size.obj mp_set.obj mp_set_double.obj mp_set_i32.obj mp_set_i64.obj \ mp_set_l.obj mp_set_u32.obj mp_set_u64.obj mp_set_ul.obj mp_shrink.obj mp_signed_rsh.obj mp_sqrmod.obj mp_sqrt.obj \ mp_sqrtmod_prime.obj mp_sub.obj mp_sub_d.obj mp_submod.obj mp_to_radix.obj mp_to_sbin.obj mp_to_ubin.obj mp_ubin_size.obj \ -mp_unpack.obj mp_xor.obj mp_zero.obj s_mp_add.obj s_mp_copy_digs.obj s_mp_div_3.obj s_mp_div_recursive.obj \ -s_mp_div_school.obj s_mp_div_small.obj s_mp_exptmod.obj s_mp_exptmod_fast.obj s_mp_fp_log.obj s_mp_fp_log_d.obj \ -s_mp_get_bit.obj s_mp_invmod.obj s_mp_invmod_odd.obj s_mp_log_2expt.obj s_mp_montgomery_reduce_comba.obj s_mp_mul.obj \ -s_mp_mul_balance.obj s_mp_mul_comba.obj s_mp_mul_high.obj s_mp_mul_high_comba.obj s_mp_mul_karatsuba.obj \ -s_mp_mul_toom.obj s_mp_prime_is_divisible.obj s_mp_prime_tab.obj s_mp_radix_map.obj \ -s_mp_radix_size_overestimate.obj s_mp_rand_platform.obj s_mp_sqr.obj s_mp_sqr_comba.obj s_mp_sqr_karatsuba.obj \ -s_mp_sqr_toom.obj s_mp_sub.obj s_mp_zero_buf.obj s_mp_zero_digs.obj +mp_unpack.obj mp_warray_free.obj mp_xor.obj mp_zero.obj s_mp_add.obj s_mp_copy_digs.obj s_mp_div_3.obj \ +s_mp_div_recursive.obj s_mp_div_school.obj s_mp_div_small.obj s_mp_exptmod.obj s_mp_exptmod_fast.obj s_mp_fp_log.obj \ +s_mp_fp_log_d.obj s_mp_get_bit.obj s_mp_invmod.obj s_mp_invmod_odd.obj s_mp_log_2expt.obj \ +s_mp_montgomery_reduce_comba.obj s_mp_mul.obj s_mp_mul_balance.obj s_mp_mul_comba.obj s_mp_mul_high.obj \ +s_mp_mul_high_comba.obj s_mp_mul_karatsuba.obj s_mp_mul_toom.obj s_mp_prime_is_divisible.obj s_mp_prime_tab.obj \ +s_mp_radix_map.obj s_mp_radix_size_overestimate.obj s_mp_rand_platform.obj s_mp_sqr.obj s_mp_sqr_comba.obj \ +s_mp_sqr_karatsuba.obj s_mp_sqr_toom.obj s_mp_sub.obj s_mp_warray.obj s_mp_warray_get.obj s_mp_warray_put.obj \ +s_mp_zero_buf.obj s_mp_zero_digs.obj HEADERS_PUB=tommath.h HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB) diff --git a/deps/libtommath/makefile.shared b/deps/libtommath/makefile.shared index c9b93351..50c33526 100644 --- a/deps/libtommath/makefile.shared +++ b/deps/libtommath/makefile.shared @@ -40,13 +40,14 @@ mp_reduce_2k_l.o mp_reduce_2k_setup.o mp_reduce_2k_setup_l.o mp_reduce_is_2k.o m mp_reduce_setup.o mp_root_n.o mp_rshd.o mp_sbin_size.o mp_set.o mp_set_double.o mp_set_i32.o mp_set_i64.o \ mp_set_l.o mp_set_u32.o mp_set_u64.o mp_set_ul.o mp_shrink.o mp_signed_rsh.o mp_sqrmod.o mp_sqrt.o \ mp_sqrtmod_prime.o mp_sub.o mp_sub_d.o mp_submod.o mp_to_radix.o mp_to_sbin.o mp_to_ubin.o mp_ubin_size.o \ -mp_unpack.o mp_xor.o mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o s_mp_div_recursive.o \ -s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_fp_log.o s_mp_fp_log_d.o \ -s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.o s_mp_montgomery_reduce_comba.o s_mp_mul.o \ -s_mp_mul_balance.o s_mp_mul_comba.o s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o \ -s_mp_mul_toom.o s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o \ -s_mp_radix_size_overestimate.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o s_mp_sqr_karatsuba.o \ -s_mp_sqr_toom.o s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o +mp_unpack.o mp_warray_free.o mp_xor.o mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o \ +s_mp_div_recursive.o s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_fp_log.o \ +s_mp_fp_log_d.o s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.o \ +s_mp_montgomery_reduce_comba.o s_mp_mul.o s_mp_mul_balance.o s_mp_mul_comba.o s_mp_mul_high.o \ +s_mp_mul_high_comba.o s_mp_mul_karatsuba.o s_mp_mul_toom.o s_mp_prime_is_divisible.o s_mp_prime_tab.o \ +s_mp_radix_map.o s_mp_radix_size_overestimate.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o \ +s_mp_sqr_karatsuba.o s_mp_sqr_toom.o s_mp_sub.o s_mp_warray.o s_mp_warray_get.o s_mp_warray_put.o \ +s_mp_zero_buf.o s_mp_zero_digs.o #END_INS diff --git a/deps/libtommath/makefile.unix b/deps/libtommath/makefile.unix index ccf8f021..58642098 100644 --- a/deps/libtommath/makefile.unix +++ b/deps/libtommath/makefile.unix @@ -20,7 +20,7 @@ ARFLAGS = rcs CFLAGS = -O2 LDFLAGS = -VERSION = 1.2.1 +VERSION = 1.3.0 #Compilation flags LTM_CFLAGS = -I. $(CFLAGS) @@ -46,13 +46,14 @@ mp_reduce_2k_l.o mp_reduce_2k_setup.o mp_reduce_2k_setup_l.o mp_reduce_is_2k.o m mp_reduce_setup.o mp_root_n.o mp_rshd.o mp_sbin_size.o mp_set.o mp_set_double.o mp_set_i32.o mp_set_i64.o \ mp_set_l.o mp_set_u32.o mp_set_u64.o mp_set_ul.o mp_shrink.o mp_signed_rsh.o mp_sqrmod.o mp_sqrt.o \ mp_sqrtmod_prime.o mp_sub.o mp_sub_d.o mp_submod.o mp_to_radix.o mp_to_sbin.o mp_to_ubin.o mp_ubin_size.o \ -mp_unpack.o mp_xor.o mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o s_mp_div_recursive.o \ -s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_fp_log.o s_mp_fp_log_d.o \ -s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.o s_mp_montgomery_reduce_comba.o s_mp_mul.o \ -s_mp_mul_balance.o s_mp_mul_comba.o s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o \ -s_mp_mul_toom.o s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o \ -s_mp_radix_size_overestimate.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o s_mp_sqr_karatsuba.o \ -s_mp_sqr_toom.o s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o +mp_unpack.o mp_warray_free.o mp_xor.o mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o \ +s_mp_div_recursive.o s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_fp_log.o \ +s_mp_fp_log_d.o s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.o \ +s_mp_montgomery_reduce_comba.o s_mp_mul.o s_mp_mul_balance.o s_mp_mul_comba.o s_mp_mul_high.o \ +s_mp_mul_high_comba.o s_mp_mul_karatsuba.o s_mp_mul_toom.o s_mp_prime_is_divisible.o s_mp_prime_tab.o \ +s_mp_radix_map.o s_mp_radix_size_overestimate.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o \ +s_mp_sqr_karatsuba.o s_mp_sqr_toom.o s_mp_sub.o s_mp_warray.o s_mp_warray_get.o s_mp_warray_put.o \ +s_mp_zero_buf.o s_mp_zero_digs.o HEADERS_PUB=tommath.h diff --git a/deps/libtommath/makefile_include.mk b/deps/libtommath/makefile_include.mk index 77708305..d47ea2ba 100644 --- a/deps/libtommath/makefile_include.mk +++ b/deps/libtommath/makefile_include.mk @@ -3,9 +3,9 @@ # #version of library -VERSION=1.2.1-develop -VERSION_PC=1.2.1 -VERSION_SO=3:1:2 +VERSION=1.3.0-develop +VERSION_PC=1.3.0 +VERSION_SO=4:0:3 PLATFORM := $(shell uname | sed -e 's/_.*//') @@ -97,7 +97,7 @@ endif endif # COMPILE_SIZE ifneq ($(findstring clang,$(CC)),) -LTM_CFLAGS += -Wno-typedef-redefinition -Wno-tautological-compare -Wno-builtin-requires-header +LTM_CFLAGS += -Wno-unknown-warning-option -Wno-typedef-redefinition -Wno-tautological-compare -Wno-builtin-requires-header -Wno-incomplete-setjmp-declaration ifdef IGNORE_SPEED #for dead code eliminiation LTM_CFLAGS += -O1 diff --git a/deps/libtommath/mp_prime_rand.c b/deps/libtommath/mp_prime_rand.c index c5cebbda..5351aefe 100644 --- a/deps/libtommath/mp_prime_rand.c +++ b/deps/libtommath/mp_prime_rand.c @@ -26,7 +26,7 @@ mp_err mp_prime_rand(mp_int *a, int t, int size, int flags) mp_err err; /* sanity check the input */ - if ((size <= 1) || (t <= 0)) { + if (size <= 1) { return MP_VAL; } diff --git a/deps/libtommath/mp_prime_strong_lucas_selfridge.c b/deps/libtommath/mp_prime_strong_lucas_selfridge.c index ffbd9d34..23486e3a 100644 --- a/deps/libtommath/mp_prime_strong_lucas_selfridge.c +++ b/deps/libtommath/mp_prime_strong_lucas_selfridge.c @@ -52,7 +52,8 @@ mp_err mp_prime_strong_lucas_selfridge(const mp_int *a, bool *result) { /* CZ TODO: choose better variable names! */ mp_int Dz, gcd, Np1, Uz, Vz, U2mz, V2mz, Qmz, Q2mz, Qkdz, T1z, T2z, T3z, T4z, Q2kdz; - int32_t D, Ds, J, sign, P, Q, r, s, u, Nbits; + int J; + int32_t D, Ds, sign, P, Q, r, s, u, Nbits; mp_err err; bool oddness; diff --git a/deps/libtommath/mp_reduce_is_2k.c b/deps/libtommath/mp_reduce_is_2k.c index 9774f96e..d5496338 100644 --- a/deps/libtommath/mp_reduce_is_2k.c +++ b/deps/libtommath/mp_reduce_is_2k.c @@ -11,9 +11,16 @@ bool mp_reduce_is_2k(const mp_int *a) } else if (a->used == 1) { return true; } else if (a->used > 1) { - int ix, iy = mp_count_bits(a), iw = 1; - mp_digit iz = 1; + int ix, iy, iw = 1; + mp_digit iz; + /* Algorithm as implemented does not work if the least significant digit is zero */ + iz = a->dp[0] & MP_MASK; + if (iz == 0u) { + return false; + } + iy = mp_count_bits(a); + iz = 1; /* Test every bit from the second digit up, must be 1 */ for (ix = MP_DIGIT_BIT; ix < iy; ix++) { if ((a->dp[iw] & iz) == 0u) { diff --git a/deps/libtommath/mp_warray_free.c b/deps/libtommath/mp_warray_free.c new file mode 100644 index 00000000..f7470f81 --- /dev/null +++ b/deps/libtommath/mp_warray_free.c @@ -0,0 +1,28 @@ +#include "tommath_private.h" +#ifdef MP_WARRAY_FREE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* static check that the multiplication won't overflow */ +MP_STATIC_ASSERT(warray_free_sz_does_not_overflow, (sizeof(mp_word) * MP_WARRAY) >= MP_WARRAY) + +static int s_warray_free(void) +{ + int ret = 0; + if (s_mp_warray.w_used) + return -2; + if (s_mp_warray.w_free) { + s_mp_zero_buf(s_mp_warray.w_free, sizeof(mp_word) * MP_WARRAY); + MP_FREE(s_mp_warray.w_free, sizeof(mp_word) * MP_WARRAY); + s_mp_warray.w_free = NULL; + } + return ret; +} + +int mp_warray_free(void) +{ + if (MP_HAS(MP_SMALL_STACK_SIZE)) return s_warray_free(); + return -1; +} + +#endif diff --git a/deps/libtommath/s_mp_montgomery_reduce_comba.c b/deps/libtommath/s_mp_montgomery_reduce_comba.c index 7472caf3..3858f75a 100644 --- a/deps/libtommath/s_mp_montgomery_reduce_comba.c +++ b/deps/libtommath/s_mp_montgomery_reduce_comba.c @@ -15,9 +15,12 @@ mp_err s_mp_montgomery_reduce_comba(mp_int *x, const mp_int *n, mp_digit rho) { int ix, oldused; mp_err err; - mp_word W[MP_WARRAY]; + mp_word MP_ALLOC_WARRAY(W); + + MP_CHECK_WARRAY(W); if (x->used > MP_WARRAY) { + MP_FREE_WARRAY(W); return MP_VAL; } @@ -26,6 +29,7 @@ mp_err s_mp_montgomery_reduce_comba(mp_int *x, const mp_int *n, mp_digit rho) /* grow a as required */ if ((err = mp_grow(x, n->used + 1)) != MP_OKAY) { + MP_FREE_WARRAY(W); return err; } @@ -110,6 +114,7 @@ mp_err s_mp_montgomery_reduce_comba(mp_int *x, const mp_int *n, mp_digit rho) mp_clamp(x); + MP_FREE_WARRAY(W); /* if A >= m then A = A - m */ if (mp_cmp_mag(x, n) != MP_LT) { return s_mp_sub(x, n, x); diff --git a/deps/libtommath/s_mp_mul_comba.c b/deps/libtommath/s_mp_mul_comba.c index ca89ff9d..5b37035e 100644 --- a/deps/libtommath/s_mp_mul_comba.c +++ b/deps/libtommath/s_mp_mul_comba.c @@ -23,15 +23,19 @@ mp_err s_mp_mul_comba(const mp_int *a, const mp_int *b, mp_int *c, int digs) { int oldused, pa, ix; mp_err err; - mp_digit W[MP_WARRAY]; + mp_digit MP_ALLOC_WARRAY(W); mp_word _W; + MP_CHECK_WARRAY(W); + if (digs < 0) { + MP_FREE_WARRAY(W); return MP_VAL; } /* grow the destination as required */ if ((err = mp_grow(c, digs)) != MP_OKAY) { + MP_FREE_WARRAY(W); return err; } @@ -77,6 +81,7 @@ mp_err s_mp_mul_comba(const mp_int *a, const mp_int *b, mp_int *c, int digs) s_mp_zero_digs(c->dp + c->used, oldused - c->used); mp_clamp(c); + MP_FREE_WARRAY(W); return MP_OKAY; } #endif diff --git a/deps/libtommath/s_mp_mul_high_comba.c b/deps/libtommath/s_mp_mul_high_comba.c index b5ac06d7..b0096d4e 100644 --- a/deps/libtommath/s_mp_mul_high_comba.c +++ b/deps/libtommath/s_mp_mul_high_comba.c @@ -16,16 +16,20 @@ mp_err s_mp_mul_high_comba(const mp_int *a, const mp_int *b, mp_int *c, int digs { int oldused, pa, ix; mp_err err; - mp_digit W[MP_WARRAY]; + mp_digit MP_ALLOC_WARRAY(W); mp_word _W; + MP_CHECK_WARRAY(W); + if (digs < 0) { + MP_FREE_WARRAY(W); return MP_VAL; } /* grow the destination as required */ pa = a->used + b->used; if ((err = mp_grow(c, pa)) != MP_OKAY) { + MP_FREE_WARRAY(W); return err; } @@ -69,6 +73,7 @@ mp_err s_mp_mul_high_comba(const mp_int *a, const mp_int *b, mp_int *c, int digs s_mp_zero_digs(c->dp + c->used, oldused - c->used); mp_clamp(c); + MP_FREE_WARRAY(W); return MP_OKAY; } #endif diff --git a/deps/libtommath/s_mp_sqr_comba.c b/deps/libtommath/s_mp_sqr_comba.c index 1bcc1f93..336a0a08 100644 --- a/deps/libtommath/s_mp_sqr_comba.c +++ b/deps/libtommath/s_mp_sqr_comba.c @@ -16,13 +16,16 @@ After that loop you do the squares and add them in. mp_err s_mp_sqr_comba(const mp_int *a, mp_int *b) { int oldused, pa, ix; - mp_digit W[MP_WARRAY]; + mp_digit MP_ALLOC_WARRAY(W); mp_word W1; mp_err err; + MP_CHECK_WARRAY(W); + /* grow the destination as required */ pa = a->used + a->used; if ((err = mp_grow(b, pa)) != MP_OKAY) { + MP_FREE_WARRAY(W); return err; } @@ -82,6 +85,7 @@ mp_err s_mp_sqr_comba(const mp_int *a, mp_int *b) s_mp_zero_digs(b->dp + b->used, oldused - b->used); mp_clamp(b); + MP_FREE_WARRAY(W); return MP_OKAY; } #endif diff --git a/deps/libtommath/s_mp_warray.c b/deps/libtommath/s_mp_warray.c new file mode 100644 index 00000000..1b8b068b --- /dev/null +++ b/deps/libtommath/s_mp_warray.c @@ -0,0 +1,8 @@ +#include "tommath_private.h" +#ifdef S_MP_WARRAY_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +mp_thread st_warray s_mp_warray = { 0 }; + +#endif diff --git a/deps/libtommath/s_mp_warray_get.c b/deps/libtommath/s_mp_warray_get.c new file mode 100644 index 00000000..26b0d7c1 --- /dev/null +++ b/deps/libtommath/s_mp_warray_get.c @@ -0,0 +1,18 @@ +#include "tommath_private.h" +#ifdef S_MP_WARRAY_GET_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +void *s_mp_warray_get(void) +{ + if (s_mp_warray.w_used) + return NULL; + if (s_mp_warray.w_free == NULL) { + s_mp_warray.w_free = MP_CALLOC(MP_WARRAY, sizeof(mp_word)); + } + s_mp_warray.w_used = s_mp_warray.w_free; + s_mp_warray.w_free = NULL; + return s_mp_warray.w_used; +} + +#endif diff --git a/deps/libtommath/s_mp_warray_put.c b/deps/libtommath/s_mp_warray_put.c new file mode 100644 index 00000000..79e014ac --- /dev/null +++ b/deps/libtommath/s_mp_warray_put.c @@ -0,0 +1,14 @@ +#include "tommath_private.h" +#ifdef S_MP_WARRAY_PUT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +void s_mp_warray_put(void *w) +{ + if (s_mp_warray.w_free || s_mp_warray.w_used != w) + return; + s_mp_warray.w_free = w; + s_mp_warray.w_used = NULL; +} + +#endif diff --git a/deps/libtommath/sources.cmake b/deps/libtommath/sources.cmake index bbb2aeab..103e9c09 100644 --- a/deps/libtommath/sources.cmake +++ b/deps/libtommath/sources.cmake @@ -122,6 +122,7 @@ mp_to_sbin.c mp_to_ubin.c mp_ubin_size.c mp_unpack.c +mp_warray_free.c mp_xor.c mp_zero.c s_mp_add.c @@ -156,6 +157,9 @@ s_mp_sqr_comba.c s_mp_sqr_karatsuba.c s_mp_sqr_toom.c s_mp_sub.c +s_mp_warray.c +s_mp_warray_get.c +s_mp_warray_put.c s_mp_zero_buf.c s_mp_zero_digs.c ) diff --git a/deps/libtommath/testme.sh b/deps/libtommath/testme.sh index 089e42a7..92997a04 100644 --- a/deps/libtommath/testme.sh +++ b/deps/libtommath/testme.sh @@ -70,6 +70,8 @@ All other options will be tested with all MP_xBIT configurations. runtime and may trigger the 30 minutes timeout. + --multithread Run tests in multi-threaded mode (via pthread). + Godmode: --all Choose all architectures and gcc and clang @@ -128,7 +130,7 @@ _make() echo -ne " Compile $1 $2" suffix=$(echo ${1}${2} | tr ' ' '_') _fixup_cflags "$1" - CC="$1" CFLAGS="$2 $TEST_CFLAGS" make -j$MAKE_JOBS $3 $MAKE_OPTIONS 2>gcc_errors_${suffix}.log + CC="$1" CFLAGS="$2 $TEST_CFLAGS" LFLAGS="$4" LDFLAGS="$5" make -j$MAKE_JOBS $3 $MAKE_OPTIONS 2>gcc_errors_${suffix}.log errcnt=$(wc -l < gcc_errors_${suffix}.log) if [[ ${errcnt} -gt 1 ]]; then echo " failed" @@ -148,10 +150,10 @@ _runtest() # "make tune" will run "tune_it.sh" automatically, hence "autotune", but it cannot # get switched off without some effort, so we just let it run twice for testing purposes echo -e "\rRun autotune $1 $2" - _make "$1" "$2" "" + _make "$1" "$2" "" "$3" "$4" $_timeout $TUNE_CMD > test_${suffix}.log || _die "running autotune" $? else - _make "$1" "$2" "test" + _make "$1" "$2" "test" "$3" "$4" echo -e "\rRun test $1 $2" $_timeout ./test > test_${suffix}.log || _die "running tests" $? fi @@ -171,13 +173,13 @@ echo "MAKE_OPTIONS = \"$MAKE_OPTIONS\"" if [[ "$MAKE_OPTIONS" =~ "tune" ]] then echo "autotune branch" - _make "$1" "$2" "" + _make "$1" "$2" "" "$3" "$4" # The shell used for /bin/sh is DASH 0.5.7-4ubuntu1 on the author's machine which fails valgrind, so # we just run on instance of etc/tune with the same options as in etc/tune_it.sh echo -e "\rRun etc/tune $1 $2 once inside valgrind" $_timeout $VALGRIND_BIN $VALGRIND_OPTS $TUNE_CMD > test_${suffix}.log || _die "running etc/tune" $? else - _make "$1" "$2" "test" + _make "$1" "$2" "test" "$3" "$4" echo -e "\rRun test $1 $2 inside valgrind" $_timeout $VALGRIND_BIN $VALGRIND_OPTS ./test > test_${suffix}.log || _die "running tests" $? fi @@ -301,6 +303,11 @@ do --symbols) CHECK_SYMBOLS="1" ;; + --multithread) + CFLAGS="$CFLAGS -DLTM_TEST_MULTITHREAD" + LFLAGS="$LFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" + ;; --all) COMPILERS="gcc clang" ARCHFLAGS="-m64 -m32 -mx32" @@ -376,9 +383,9 @@ then _banner "$CC" if [[ "$VALGRIND_BIN" != "" ]] then - _runvalgrind "$CC" "" + _runvalgrind "$CC" "" "$LFLAGS" "$LDFLAGS" else - _runtest "$CC" "" + _runtest "$CC" "" "$LFLAGS" "$LDFLAGS" fi _exit fi @@ -398,9 +405,9 @@ _banner if [[ "$TEST_VS_MTEST" != "" ]] then make clean > /dev/null - _make "${compilers[0]}" "${archflags[0]} $CFLAGS" "mtest_opponent" + _make "${compilers[0]}" "${archflags[0]} $CFLAGS" "mtest_opponent" "$LFLAGS" "$LDFLAGS" echo - _make "gcc" "$MTEST_RAND" "mtest" + _make "gcc" "$MTEST_RAND" "mtest" "$LFLAGS" "$LDFLAGS" echo echo "Run test vs. mtest for $TEST_VS_MTEST iterations" _timeout="" @@ -429,15 +436,15 @@ do fi if [[ "$VALGRIND_BIN" != "" ]] then - _runvalgrind "$i" "$a $CFLAGS" + _runvalgrind "$i" "$a $CFLAGS" "$LFLAGS" "$LDFLAGS" [ "$WITH_LOW_MP" != "1" ] && continue - _runvalgrind "$i" "$a -DMP_16BIT $CFLAGS" - _runvalgrind "$i" "$a -DMP_32BIT $CFLAGS" + _runvalgrind "$i" "$a -DMP_16BIT $CFLAGS" "$LFLAGS" "$LDFLAGS" + _runvalgrind "$i" "$a -DMP_32BIT $CFLAGS" "$LFLAGS" "$LDFLAGS" else - _runtest "$i" "$a $CFLAGS" + _runtest "$i" "$a $CFLAGS" "$LFLAGS" "$LDFLAGS" [ "$WITH_LOW_MP" != "1" ] && continue - _runtest "$i" "$a -DMP_16BIT $CFLAGS" - _runtest "$i" "$a -DMP_32BIT $CFLAGS" + _runtest "$i" "$a -DMP_16BIT $CFLAGS" "$LFLAGS" "$LDFLAGS" + _runtest "$i" "$a -DMP_32BIT $CFLAGS" "$LFLAGS" "$LDFLAGS" fi done done diff --git a/deps/libtommath/tommath.def b/deps/libtommath/tommath.def index 86f34872..ed5aa8b0 100644 --- a/deps/libtommath/tommath.def +++ b/deps/libtommath/tommath.def @@ -125,6 +125,7 @@ EXPORTS mp_to_ubin mp_ubin_size mp_unpack + mp_warray_free mp_xor mp_zero MP_MUL_KARATSUBA_CUTOFF diff --git a/deps/libtommath/tommath.h b/deps/libtommath/tommath.h index 84bb0909..1820d243 100644 --- a/deps/libtommath/tommath.h +++ b/deps/libtommath/tommath.h @@ -588,6 +588,8 @@ mp_err mp_fread(mp_int *a, int radix, FILE *stream) MP_WUR; mp_err mp_fwrite(const mp_int *a, int radix, FILE *stream) MP_WUR; #endif +int mp_warray_free(void); + #define mp_to_binary(M, S, N) mp_to_radix((M), (S), (N), NULL, 2) #define mp_to_octal(M, S, N) mp_to_radix((M), (S), (N), NULL, 8) #define mp_to_decimal(M, S, N) mp_to_radix((M), (S), (N), NULL, 10) diff --git a/deps/libtommath/tommath_c89.h b/deps/libtommath/tommath_c89.h index 49400a13..22436366 100644 --- a/deps/libtommath/tommath_c89.h +++ b/deps/libtommath/tommath_c89.h @@ -26,6 +26,11 @@ typedef __UINT8_TYPE__ mp_u8; typedef __UINT16_TYPE__ mp_u16; typedef __UINT32_TYPE__ mp_u32; typedef __UINT64_TYPE__ mp_u64; +# if __WORDSIZE == 64 +typedef __UINT64_TYPE__ mp_uintptr; +# else +typedef __UINT32_TYPE__ mp_uintptr; +# endif /* inttypes.h replacement, printf format specifier */ # if __WORDSIZE == 64 diff --git a/deps/libtommath/tommath_class.h b/deps/libtommath/tommath_class.h index e08bc5f3..09bb3ea6 100644 --- a/deps/libtommath/tommath_class.h +++ b/deps/libtommath/tommath_class.h @@ -131,6 +131,7 @@ # define MP_TO_UBIN_C # define MP_UBIN_SIZE_C # define MP_UNPACK_C +# define MP_WARRAY_FREE_C # define MP_XOR_C # define MP_ZERO_C # define S_MP_ADD_C @@ -165,6 +166,9 @@ # define S_MP_SQR_KARATSUBA_C # define S_MP_SQR_TOOM_C # define S_MP_SUB_C +# define S_MP_WARRAY_C +# define S_MP_WARRAY_GET_C +# define S_MP_WARRAY_PUT_C # define S_MP_ZERO_BUF_C # define S_MP_ZERO_DIGS_C #endif @@ -957,6 +961,10 @@ # define MP_ZERO_C #endif +#if defined(MP_WARRAY_FREE_C) +# define S_MP_ZERO_BUF_C +#endif + #if defined(MP_XOR_C) # define MP_CLAMP_C # define MP_GROW_C @@ -1137,6 +1145,8 @@ # define MP_CMP_MAG_C # define MP_GROW_C # define S_MP_SUB_C +# define S_MP_WARRAY_GET_C +# define S_MP_WARRAY_PUT_C # define S_MP_ZERO_BUF_C # define S_MP_ZERO_DIGS_C #endif @@ -1165,6 +1175,8 @@ #if defined(S_MP_MUL_COMBA_C) # define MP_CLAMP_C # define MP_GROW_C +# define S_MP_WARRAY_GET_C +# define S_MP_WARRAY_PUT_C # define S_MP_ZERO_DIGS_C #endif @@ -1179,6 +1191,8 @@ #if defined(S_MP_MUL_HIGH_COMBA_C) # define MP_CLAMP_C # define MP_GROW_C +# define S_MP_WARRAY_GET_C +# define S_MP_WARRAY_PUT_C # define S_MP_ZERO_DIGS_C #endif @@ -1244,6 +1258,8 @@ #if defined(S_MP_SQR_COMBA_C) # define MP_CLAMP_C # define MP_GROW_C +# define S_MP_WARRAY_GET_C +# define S_MP_WARRAY_PUT_C # define S_MP_ZERO_DIGS_C #endif @@ -1279,6 +1295,15 @@ # define S_MP_ZERO_DIGS_C #endif +#if defined(S_MP_WARRAY_C) +#endif + +#if defined(S_MP_WARRAY_GET_C) +#endif + +#if defined(S_MP_WARRAY_PUT_C) +#endif + #if defined(S_MP_ZERO_BUF_C) #endif diff --git a/deps/libtommath/tommath_private.h b/deps/libtommath/tommath_private.h index d319a1db..be620dbc 100644 --- a/deps/libtommath/tommath_private.h +++ b/deps/libtommath/tommath_private.h @@ -160,8 +160,13 @@ MP_STATIC_ASSERT(correct_word_size, sizeof(mp_word) == (2u * sizeof(mp_digit))) * - Must be large enough such that the mp_set_u64 setter can * store uint64_t in the mp_int without growing */ -#define MP_MIN_DIGIT_COUNT MP_MAX(3, (((int)MP_SIZEOF_BITS(uint64_t) + MP_DIGIT_BIT) - 1) / MP_DIGIT_BIT) +#ifndef MP_MIN_DIGIT_COUNT +# define MP_MIN_DIGIT_COUNT MP_MAX(3, (((int)MP_SIZEOF_BITS(uint64_t) + MP_DIGIT_BIT) - 1) / MP_DIGIT_BIT) +#endif MP_STATIC_ASSERT(prec_geq_min_prec, MP_DEFAULT_DIGIT_COUNT >= MP_MIN_DIGIT_COUNT) +MP_STATIC_ASSERT(min_prec_geq_3, MP_MIN_DIGIT_COUNT >= 3) +MP_STATIC_ASSERT(min_prec_geq_uint64size, + MP_MIN_DIGIT_COUNT >= ((((int)MP_SIZEOF_BITS(uint64_t) + MP_DIGIT_BIT) - 1) / MP_DIGIT_BIT)) /* Maximum number of digits. * - Must be small enough such that mp_bit_count does not overflow. @@ -229,6 +234,47 @@ MP_PRIVATE mp_err s_mp_radix_size_overestimate(const mp_int *a, const int radix, MP_PRIVATE mp_err s_mp_fp_log(const mp_int *a, mp_int *c) MP_WUR; MP_PRIVATE mp_err s_mp_fp_log_d(const mp_int *a, mp_word *c) MP_WUR; +#ifdef MP_SMALL_STACK_SIZE + +#if defined(__GNUC__) +/* We use TLS (Thread Local Storage) to manage the instance of the WARRAY + * per thread. + * The compilers we're usually looking at are GCC, Clang and MSVC. + * Both GCC and Clang are straight-forward with TLS, so it's enabled there. + * Using MSVC the tests were OK with the static library, but failed when + * the library was built as a DLL. As a result we completely disable + * support for MSVC. + * If your compiler can handle TLS properly without too much hocus pocus, + * feel free to open a PR to add support for it. + */ +#define mp_thread __thread +#else +#error "MP_SMALL_STACK_SIZE not supported with your compiler" +#endif + +#define MP_SMALL_STACK_SIZE_C +#define MP_ALLOC_WARRAY(name) *name = s_mp_warray_get() +#define MP_FREE_WARRAY(name) s_mp_warray_put(name) +#define MP_CHECK_WARRAY(name) do { if ((name) == NULL) { return MP_MEM; } } while(0) +#else +#define MP_ALLOC_WARRAY(name) name[MP_WARRAY] +#define MP_FREE_WARRAY(name) +#define MP_CHECK_WARRAY(name) +#endif + +#ifndef mp_thread +#define mp_thread +#endif + +typedef struct { + void *w_free, *w_used; +} st_warray; + +extern MP_PRIVATE mp_thread st_warray s_mp_warray; + +MP_PRIVATE void *s_mp_warray_get(void); +MP_PRIVATE void s_mp_warray_put(void *w); + #define MP_RADIX_MAP_REVERSE_SIZE 80u extern MP_PRIVATE const char s_mp_radix_map[]; extern MP_PRIVATE const uint8_t s_mp_radix_map_reverse[]; diff --git a/deps/libtommath/tommath_superclass.h b/deps/libtommath/tommath_superclass.h index 9245e002..10c7f12a 100644 --- a/deps/libtommath/tommath_superclass.h +++ b/deps/libtommath/tommath_superclass.h @@ -42,6 +42,8 @@ # define MP_SBIN_SIZE_C # define MP_TO_RADIX_C # define MP_TO_SBIN_C +# define MP_WARRAY_FREE_C +# define MP_WARRAY_INIT_C # define S_MP_RAND_JENKINS_C # define S_MP_RAND_PLATFORM_C #endif diff --git a/deps/minhook/src/hook.c b/deps/minhook/src/hook.c index b2dd2af3..e387f21e 100644 --- a/deps/minhook/src/hook.c +++ b/deps/minhook/src/hook.c @@ -262,6 +262,7 @@ static VOID ProcessThreadIPs(HANDLE hThread, UINT pos, UINT action) //------------------------------------------------------------------------- static BOOL EnumerateThreads(PFROZEN_THREADS pThreads) { + LPDWORD p; BOOL succeeded = FALSE; HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); @@ -292,7 +293,7 @@ static BOOL EnumerateThreads(PFROZEN_THREADS pThreads) else if (pThreads->size >= pThreads->capacity) { pThreads->capacity *= 2; - LPDWORD p = (LPDWORD)HeapReAlloc( + p = (LPDWORD)HeapReAlloc( g_hHeap, 0, pThreads->pItems, pThreads->capacity * sizeof(DWORD)); if (p == NULL) { diff --git a/deps/rapidjson/.travis.yml b/deps/rapidjson/.travis.yml index 17d8f03d..ac918bed 100644 --- a/deps/rapidjson/.travis.yml +++ b/deps/rapidjson/.travis.yml @@ -28,69 +28,69 @@ env: matrix: include: # gcc - - env: CONF=release ARCH=x86 CXX11=ON CXX17=OFF MEMBERSMAP=OFF + - env: CONF=release ARCH=x86 CXX11=ON CXX17=OFF CXX20=OFF MEMBERSMAP=OFF compiler: gcc arch: amd64 - - env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF MEMBERSMAP=OFF + - env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF CXX20=OFF MEMBERSMAP=OFF compiler: gcc arch: amd64 - - env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF MEMBERSMAP=ON + - env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF CXX20=OFF MEMBERSMAP=ON compiler: gcc arch: amd64 - - env: CONF=debug ARCH=x86 CXX11=OFF CXX17=OFF MEMBERSMAP=OFF + - env: CONF=debug ARCH=x86 CXX11=OFF CXX17=OFF CXX20=OFF MEMBERSMAP=OFF compiler: gcc arch: amd64 - - env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=OFF MEMBERSMAP=OFF + - env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=OFF CXX20=OFF MEMBERSMAP=OFF compiler: gcc arch: amd64 - - env: CONF=debug ARCH=x86 CXX11=OFF CXX17=ON MEMBERSMAP=ON CXX_FLAGS='-D_GLIBCXX_DEBUG' + - env: CONF=debug ARCH=x86 CXX11=OFF CXX17=ON CXX20=OFF MEMBERSMAP=ON CXX_FLAGS='-D_GLIBCXX_DEBUG' compiler: gcc arch: amd64 - - env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=ON MEMBERSMAP=ON CXX_FLAGS='-D_GLIBCXX_DEBUG' + - env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=ON CXX20=OFF MEMBERSMAP=ON CXX_FLAGS='-D_GLIBCXX_DEBUG' compiler: gcc arch: amd64 - - env: CONF=release ARCH=aarch64 CXX11=ON CXX17=OFF MEMBERSMAP=OFF + - env: CONF=release ARCH=aarch64 CXX11=ON CXX17=OFF CXX20=OFF MEMBERSMAP=OFF compiler: gcc arch: arm64 - - env: CONF=release ARCH=aarch64 CXX11=OFF CXX17=OFF MEMBERSMAP=OFF + - env: CONF=release ARCH=aarch64 CXX11=OFF CXX17=OFF CXX20=OFF MEMBERSMAP=OFF compiler: gcc arch: arm64 - - env: CONF=release ARCH=aarch64 CXX11=OFF CXX17=ON MEMBERSMAP=ON + - env: CONF=release ARCH=aarch64 CXX11=OFF CXX17=ON CXX20=OFF MEMBERSMAP=ON compiler: gcc arch: arm64 # clang - - env: CONF=release ARCH=x86 CXX11=ON CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes + - env: CONF=release ARCH=x86 CXX11=ON CXX17=OFF CXX20=OFF MEMBERSMAP=ON CCACHE_CPP2=yes compiler: clang arch: amd64 - - env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes + - env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF CXX20=OFF MEMBERSMAP=ON CCACHE_CPP2=yes compiler: clang arch: amd64 - - env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF MEMBERSMAP=OFF CCACHE_CPP2=yes + - env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF CXX20=OFF MEMBERSMAP=OFF CCACHE_CPP2=yes compiler: clang arch: amd64 - - env: CONF=debug ARCH=x86 CXX11=OFF CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes + - env: CONF=debug ARCH=x86 CXX11=OFF CXX17=OFF CXX20=OFF MEMBERSMAP=ON CCACHE_CPP2=yes compiler: clang arch: amd64 - - env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes + - env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=OFF CXX20=OFF MEMBERSMAP=ON CCACHE_CPP2=yes compiler: clang arch: amd64 - - env: CONF=debug ARCH=x86 CXX11=OFF CXX17=ON MEMBERSMAP=OFF CCACHE_CPP2=yes + - env: CONF=debug ARCH=x86 CXX11=OFF CXX17=ON CXX20=OFF MEMBERSMAP=OFF CCACHE_CPP2=yes compiler: clang arch: amd64 - - env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=ON MEMBERSMAP=OFF CCACHE_CPP2=yes + - env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=ON CXX20=OFF MEMBERSMAP=OFF CCACHE_CPP2=yes compiler: clang arch: amd64 - - env: CONF=debug ARCH=aarch64 CXX11=ON CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes + - env: CONF=debug ARCH=aarch64 CXX11=ON CXX17=OFF CXX20=OFF MEMBERSMAP=ON CCACHE_CPP2=yes compiler: clang arch: arm64 - - env: CONF=debug ARCH=aarch64 CXX11=OFF CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes + - env: CONF=debug ARCH=aarch64 CXX11=OFF CXX17=OFF CXX20=OFF MEMBERSMAP=ON CCACHE_CPP2=yes compiler: clang arch: arm64 - - env: CONF=debug ARCH=aarch64 CXX11=OFF CXX17=ON MEMBERSMAP=OFF CCACHE_CPP2=yes + - env: CONF=debug ARCH=aarch64 CXX11=OFF CXX17=ON CXX20=OFF MEMBERSMAP=OFF CCACHE_CPP2=yes compiler: clang arch: arm64 # coverage report - - env: CONF=debug ARCH=x86 GCOV_FLAGS='--coverage' CXX_FLAGS='-O0' CXX11=OFF CXX17=OFF + - env: CONF=debug ARCH=x86 GCOV_FLAGS='--coverage' CXX_FLAGS='-O0' CXX11=OFF CXX17=OFF CXX20=OFF compiler: gcc arch: amd64 cache: @@ -99,7 +99,7 @@ matrix: after_success: - pip install --user cpp-coveralls - coveralls -r .. --gcov-options '\-lp' -e thirdparty -e example -e test -e build/CMakeFiles -e include/rapidjson/msinttypes -e include/rapidjson/internal/meta.h -e include/rapidjson/error/en.h - - env: CONF=debug ARCH=x86_64 GCOV_FLAGS='--coverage' CXX_FLAGS='-O0' CXX11=ON CXX17=OFF MEMBERSMAP=ON + - env: CONF=debug ARCH=x86_64 GCOV_FLAGS='--coverage' CXX_FLAGS='-O0' CXX11=ON CXX17=OFF CXX20=OFF MEMBERSMAP=ON compiler: gcc arch: amd64 cache: @@ -108,7 +108,7 @@ matrix: after_success: - pip install --user cpp-coveralls - coveralls -r .. --gcov-options '\-lp' -e thirdparty -e example -e test -e build/CMakeFiles -e include/rapidjson/msinttypes -e include/rapidjson/internal/meta.h -e include/rapidjson/error/en.h - - env: CONF=debug ARCH=aarch64 GCOV_FLAGS='--coverage' CXX_FLAGS='-O0' CXX11=OFF CXX17=ON + - env: CONF=debug ARCH=aarch64 GCOV_FLAGS='--coverage' CXX_FLAGS='-O0' CXX11=OFF CXX17=ON CXX20=OFF compiler: gcc arch: arm64 cache: @@ -155,6 +155,7 @@ script: -DRAPIDJSON_USE_MEMBERSMAP=$MEMBERSMAP -DRAPIDJSON_BUILD_CXX11=$CXX11 -DRAPIDJSON_BUILD_CXX17=$CXX17 + -DRAPIDJSON_BUILD_CXX20=$CXX20 -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_BUILD_TYPE=$CONF -DCMAKE_CXX_FLAGS="$ARCH_FLAGS $GCOV_FLAGS $CXX_FLAGS" diff --git a/deps/rapidjson/CMakeLists.txt b/deps/rapidjson/CMakeLists.txt index 60334151..1b3a79de 100644 --- a/deps/rapidjson/CMakeLists.txt +++ b/deps/rapidjson/CMakeLists.txt @@ -37,6 +37,7 @@ option(RAPIDJSON_BUILD_THIRDPARTY_GTEST option(RAPIDJSON_BUILD_CXX11 "Build rapidjson with C++11" ON) option(RAPIDJSON_BUILD_CXX17 "Build rapidjson with C++17" OFF) +option(RAPIDJSON_BUILD_CXX20 "Build rapidjson with C++20" OFF) if(RAPIDJSON_BUILD_CXX11) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED TRUE) @@ -66,6 +67,8 @@ if(CCACHE_FOUND) endif() endif(CCACHE_FOUND) +find_program(VALGRIND_FOUND valgrind) + if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") if(RAPIDJSON_ENABLE_INSTRUMENTATION_OPT AND NOT CMAKE_CROSSCOMPILING) if(CMAKE_SYSTEM_PROCESSOR STREQUAL "powerpc" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64le") @@ -85,6 +88,8 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") endif() elseif (RAPIDJSON_BUILD_CXX17 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.0") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") + elseif (RAPIDJSON_BUILD_CXX20 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "8.0") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20") endif() if (RAPIDJSON_BUILD_ASAN) if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.8.0") @@ -115,6 +120,8 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") elseif (RAPIDJSON_BUILD_CXX17 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.0") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") + elseif (RAPIDJSON_BUILD_CXX20 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "10.0") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20") endif() if (RAPIDJSON_BUILD_ASAN) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") @@ -135,6 +142,8 @@ elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++11") elseif (RAPIDJSON_BUILD_CXX17 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.14") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17") + elseif (RAPIDJSON_BUILD_CXX20 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.29") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++20") endif() # Always compile with /WX if(CMAKE_CXX_FLAGS MATCHES "/WX-") diff --git a/deps/rapidjson/appveyor.yml b/deps/rapidjson/appveyor.yml index 4044ba66..0623dce5 100644 --- a/deps/rapidjson/appveyor.yml +++ b/deps/rapidjson/appveyor.yml @@ -15,83 +15,96 @@ environment: VS_PLATFORM: win32 CXX11: OFF CXX17: OFF + CXX20: OFF MEMBERSMAP: OFF - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 VS_VERSION: 10 2010 VS_PLATFORM: x64 CXX11: OFF CXX17: OFF + CXX20: OFF MEMBERSMAP: ON - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 VS_VERSION: 11 2012 VS_PLATFORM: win32 CXX11: OFF CXX17: OFF + CXX20: OFF MEMBERSMAP: ON - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 VS_VERSION: 11 2012 VS_PLATFORM: x64 CXX11: OFF CXX17: OFF + CXX20: OFF MEMBERSMAP: OFF - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 VS_VERSION: 12 2013 VS_PLATFORM: win32 CXX11: OFF CXX17: OFF + CXX20: OFF MEMBERSMAP: OFF - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 VS_VERSION: 12 2013 VS_PLATFORM: x64 CXX11: OFF CXX17: OFF + CXX20: OFF MEMBERSMAP: ON - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 VS_VERSION: 14 2015 VS_PLATFORM: win32 CXX11: OFF CXX17: OFF + CXX20: OFF MEMBERSMAP: ON - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 VS_VERSION: 14 2015 VS_PLATFORM: x64 CXX11: OFF CXX17: OFF + CXX20: OFF MEMBERSMAP: OFF - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 VS_VERSION: 15 2017 VS_PLATFORM: win32 CXX11: OFF CXX17: OFF + CXX20: OFF MEMBERSMAP: OFF - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 VS_VERSION: 15 2017 VS_PLATFORM: x64 CXX11: OFF CXX17: OFF + CXX20: OFF MEMBERSMAP: ON - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 VS_VERSION: 15 2017 VS_PLATFORM: x64 CXX11: ON CXX17: OFF + CXX20: OFF MEMBERSMAP: OFF - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 VS_VERSION: 15 2017 VS_PLATFORM: x64 CXX11: OFF CXX17: ON + CXX20: OFF MEMBERSMAP: OFF - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 VS_VERSION: 16 2019 VS_PLATFORM: x64 CXX11: OFF CXX17: ON + CXX20: OFF MEMBERSMAP: ON before_build: - git submodule update --init --recursive -- cmake -H. -BBuild/VS -G "Visual Studio %VS_VERSION%" -DCMAKE_GENERATOR_PLATFORM=%VS_PLATFORM% -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=true -DRAPIDJSON_BUILD_CXX11=%CXX11% -DRAPIDJSON_BUILD_CXX17=%CXX17% -DRAPIDJSON_USE_MEMBERSMAP=%MEMBERSMAP% -Wno-dev +- cmake -H. -BBuild/VS -G "Visual Studio %VS_VERSION%" -DCMAKE_GENERATOR_PLATFORM=%VS_PLATFORM% -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=true -DRAPIDJSON_BUILD_CXX11=%CXX11% -DRAPIDJSON_BUILD_CXX17=%CXX17% -DRAPIDJSON_BUILD_CXX20=%CXX20% -DRAPIDJSON_USE_MEMBERSMAP=%MEMBERSMAP% -Wno-dev build: project: Build\VS\RapidJSON.sln diff --git a/deps/rapidjson/include/rapidjson/document.h b/deps/rapidjson/include/rapidjson/document.h index 2cd9a70a..f183749a 100644 --- a/deps/rapidjson/include/rapidjson/document.h +++ b/deps/rapidjson/include/rapidjson/document.h @@ -1033,7 +1033,7 @@ public: return false; for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) { typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name); - if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value) + if (rhsMemberItr == rhs.MemberEnd() || (!(lhsMemberItr->value == rhsMemberItr->value))) return false; } return true; @@ -1042,7 +1042,7 @@ public: if (data_.a.size != rhs.data_.a.size) return false; for (SizeType i = 0; i < data_.a.size; i++) - if ((*this)[i] != rhs[i]) + if (!((*this)[i] == rhs[i])) return false; return true; diff --git a/deps/rapidjson/include/rapidjson/internal/regex.h b/deps/rapidjson/include/rapidjson/internal/regex.h index 6446c403..7740dcd5 100644 --- a/deps/rapidjson/include/rapidjson/internal/regex.h +++ b/deps/rapidjson/include/rapidjson/internal/regex.h @@ -615,7 +615,7 @@ public: RAPIDJSON_ASSERT(regex_.IsValid()); if (!allocator_) ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); - stateSet_ = static_cast(allocator_->Malloc(GetStateSetSize())); + stateSet_ = static_cast(allocator_->Malloc(GetStateSetSize())); state0_.template Reserve(regex_.stateCount_); state1_.template Reserve(regex_.stateCount_); } diff --git a/deps/rapidjson/include/rapidjson/rapidjson.h b/deps/rapidjson/include/rapidjson/rapidjson.h index 5ea69479..247b8e68 100644 --- a/deps/rapidjson/include/rapidjson/rapidjson.h +++ b/deps/rapidjson/include/rapidjson/rapidjson.h @@ -268,7 +268,7 @@ # elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) # define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN // Detect with architecture macros -# elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__) +# elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__) # define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN # elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__) # define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN diff --git a/deps/rapidjson/include/rapidjson/schema.h b/deps/rapidjson/include/rapidjson/schema.h index 973e935f..02a6d0f9 100644 --- a/deps/rapidjson/include/rapidjson/schema.h +++ b/deps/rapidjson/include/rapidjson/schema.h @@ -24,13 +24,9 @@ #if !defined(RAPIDJSON_SCHEMA_USE_INTERNALREGEX) #define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1 -#else -#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0 #endif -#if !RAPIDJSON_SCHEMA_USE_INTERNALREGEX && defined(RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)) -#define RAPIDJSON_SCHEMA_USE_STDREGEX 1 -#else +#if !defined(RAPIDJSON_SCHEMA_USE_STDREGEX) || !(__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)) #define RAPIDJSON_SCHEMA_USE_STDREGEX 0 #endif @@ -1645,9 +1641,13 @@ private: bool CheckDoubleMultipleOf(Context& context, double d) const { double a = std::abs(d), b = std::abs(multipleOf_.GetDouble()); - double q = std::floor(a / b); - double r = a - q * b; - if (r > 0.0) { + double q = a / b; + double qRounded = std::floor(q + 0.5); + double scaledEpsilon = (q + qRounded) * std::numeric_limits::epsilon(); + double difference = std::abs(qRounded - q); + bool isMultiple = (difference <= scaledEpsilon) + || (difference < std::numeric_limits::min()); + if (!isMultiple) { context.error_handler.NotMultipleOf(d, multipleOf_); RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMultipleOf); } diff --git a/deps/rapidjson/test/unittest/CMakeLists.txt b/deps/rapidjson/test/unittest/CMakeLists.txt index 565ed982..87c04683 100644 --- a/deps/rapidjson/test/unittest/CMakeLists.txt +++ b/deps/rapidjson/test/unittest/CMakeLists.txt @@ -80,7 +80,7 @@ add_test(NAME unittest COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) -if(NOT MSVC) +if(NOT MSVC AND VALGRIND_FOUND) # Not running SIMD.* unit test cases for Valgrind add_test(NAME valgrind_unittest COMMAND valgrind --suppressions=${CMAKE_SOURCE_DIR}/test/valgrind.supp --leak-check=full --error-exitcode=1 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest --gtest_filter=-SIMD.* diff --git a/deps/rapidjson/test/unittest/schematest.cpp b/deps/rapidjson/test/unittest/schematest.cpp index dbc467ea..9d95cd40 100644 --- a/deps/rapidjson/test/unittest/schematest.cpp +++ b/deps/rapidjson/test/unittest/schematest.cpp @@ -2285,7 +2285,7 @@ TEST(SchemaValidator, TestSuite) { MemoryPoolAllocator<>::Free(json); jsonAllocator.Clear(); } - printf("%d / %d passed (%2d%%)\n", passCount, testCount, passCount * 100 / testCount); + printf("%u / %u passed (%2u%%)\n", passCount, testCount, passCount * 100 / testCount); if (passCount != testCount) ADD_FAILURE(); } diff --git a/deps/stb/.gitignore b/deps/stb/.gitignore new file mode 100644 index 00000000..8cc774f0 --- /dev/null +++ b/deps/stb/.gitignore @@ -0,0 +1,3 @@ +*.o +*.obj +*.exe diff --git a/deps/stb/README.md b/deps/stb/README.md index f228dac1..cba7a52e 100644 --- a/deps/stb/README.md +++ b/deps/stb/README.md @@ -5,16 +5,18 @@ stb single-file public domain (or MIT licensed) libraries for C/C++ +# This project discusses security-relevant bugs in public in Github Issues and Pull Requests, and it may take significant time for security fixes to be implemented or merged. If this poses an unreasonable risk to your project, do not use stb libraries. + Noteworthy: * image loader: [stb_image.h](stb_image.h) * image writer: [stb_image_write.h](stb_image_write.h) -* image resizer: [stb_image_resize.h](stb_image_resize.h) +* image resizer: [stb_image_resize2.h](stb_image_resize2.h) * font text rasterizer: [stb_truetype.h](stb_truetype.h) * typesafe containers: [stb_ds.h](stb_ds.h) -Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, stb_image_resize -by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts. +Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, original stb_image_resize +by Jorge L. "VinoBS" Rodriguez, and stb_image_resize2 and stb_sprintf by Jeff Roberts. @@ -22,10 +24,10 @@ library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- **[stb_vorbis.c](stb_vorbis.c)** | 1.22 | audio | 5584 | decode ogg vorbis files from file/memory to float/16-bit signed output **[stb_hexwave.h](stb_hexwave.h)** | 0.5 | audio | 680 | audio waveform synthesizer -**[stb_image.h](stb_image.h)** | 2.28 | graphics | 7987 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**[stb_image.h](stb_image.h)** | 2.29 | graphics | 7985 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC **[stb_truetype.h](stb_truetype.h)** | 1.26 | graphics | 5077 | parse, decode, and rasterize characters from truetype fonts **[stb_image_write.h](stb_image_write.h)** | 1.16 | graphics | 1724 | image writing to disk: PNG, TGA, BMP -**[stb_image_resize.h](stb_image_resize.h)** | 0.97 | graphics | 2634 | resize images larger/smaller with good quality +**[stb_image_resize2.h](stb_image_resize2.h)** | 2.07 | graphics | 10366 | resize images larger/smaller with good quality **[stb_rect_pack.h](stb_rect_pack.h)** | 1.01 | graphics | 623 | simple 2D rectangle packer with decent quality **[stb_perlin.h](stb_perlin.h)** | 0.5 | graphics | 428 | perlin's revised simplex noise w/ different seeds **[stb_ds.h](stb_ds.h)** | 0.67 | utility | 1895 | typesafe dynamic array and hash tables for C, will compile in C++ @@ -43,7 +45,7 @@ library | lastest version | category | LoC | description **[stb_include.h](stb_include.h)** | 0.02 | misc | 295 | implement recursive #include support, particularly for GLSL Total libraries: 21 -Total lines of C code: 43117 +Total lines of C code: 50847 FAQ diff --git a/deps/stb/stb_image_resize.h b/deps/stb/deprecated/stb_image_resize.h similarity index 100% rename from deps/stb/stb_image_resize.h rename to deps/stb/deprecated/stb_image_resize.h diff --git a/deps/stb/stb_image.h b/deps/stb/stb_image.h index 5e807a0a..a632d543 100644 --- a/deps/stb/stb_image.h +++ b/deps/stb/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.28 - public domain image loader - http://nothings.org/stb +/* stb_image - v2.29 - public domain image loader - http://nothings.org/stb no warranty implied; use at your own risk Do this: @@ -48,6 +48,7 @@ LICENSE RECENT REVISION HISTORY: + 2.29 (2023-05-xx) optimizations 2.28 (2023-01-29) many error fixes, security errors, just tons of stuff 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes 2.26 (2020-07-13) many minor fixes @@ -1072,8 +1073,8 @@ static int stbi__addints_valid(int a, int b) return a <= INT_MAX - b; } -// returns 1 if the product of two signed shorts is valid, 0 on overflow. -static int stbi__mul2shorts_valid(short a, short b) +// returns 1 if the product of two ints fits in a signed short, 0 on overflow. +static int stbi__mul2shorts_valid(int a, int b) { if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid @@ -3384,13 +3385,13 @@ static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) return 1; } -static int stbi__skip_jpeg_junk_at_end(stbi__jpeg *j) +static stbi_uc stbi__skip_jpeg_junk_at_end(stbi__jpeg *j) { // some JPEGs have junk at end, skip over it but if we find what looks // like a valid marker, resume there while (!stbi__at_eof(j->s)) { - int x = stbi__get8(j->s); - while (x == 255) { // might be a marker + stbi_uc x = stbi__get8(j->s); + while (x == 0xff) { // might be a marker if (stbi__at_eof(j->s)) return STBI__MARKER_none; x = stbi__get8(j->s); if (x != 0x00 && x != 0xff) { @@ -4176,6 +4177,7 @@ typedef struct { stbi_uc *zbuffer, *zbuffer_end; int num_bits; + int hit_zeof_once; stbi__uint32 code_buffer; char *zout; @@ -4242,9 +4244,20 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) int b,s; if (a->num_bits < 16) { if (stbi__zeof(a)) { - return -1; /* report error for unexpected end of data. */ + if (!a->hit_zeof_once) { + // This is the first time we hit eof, insert 16 extra padding btis + // to allow us to keep going; if we actually consume any of them + // though, that is invalid data. This is caught later. + a->hit_zeof_once = 1; + a->num_bits += 16; // add 16 implicit zero bits + } else { + // We already inserted our extra 16 padding bits and are again + // out, this stream is actually prematurely terminated. + return -1; + } + } else { + stbi__fill_bits(a); } - stbi__fill_bits(a); } b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; if (b) { @@ -4309,6 +4322,13 @@ static int stbi__parse_huffman_block(stbi__zbuf *a) int len,dist; if (z == 256) { a->zout = zout; + if (a->hit_zeof_once && a->num_bits < 16) { + // The first time we hit zeof, we inserted 16 extra zero bits into our bit + // buffer so the decoder can just do its speculative decoding. But if we + // actually consumed any of those bits (which is the case when num_bits < 16), + // the stream actually read past the end so it is malformed. + return stbi__err("unexpected end","Corrupt PNG"); + } return 1; } if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data @@ -4320,7 +4340,7 @@ static int stbi__parse_huffman_block(stbi__zbuf *a) dist = stbi__zdist_base[z]; if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); - if (zout + len > a->zout_end) { + if (len > a->zout_end - zout) { if (!stbi__zexpand(a, zout, len)) return 0; zout = a->zout; } @@ -4464,6 +4484,7 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) if (!stbi__parse_zlib_header(a)) return 0; a->num_bits = 0; a->code_buffer = 0; + a->hit_zeof_once = 0; do { final = stbi__zreceive(a,1); type = stbi__zreceive(a,2); @@ -4619,9 +4640,8 @@ enum { STBI__F_up=2, STBI__F_avg=3, STBI__F_paeth=4, - // synthetic filters used for first scanline to avoid needing a dummy row of 0s - STBI__F_avg_first, - STBI__F_paeth_first + // synthetic filter used for first scanline to avoid needing a dummy row of 0s + STBI__F_avg_first }; static stbi_uc first_row_filter[5] = @@ -4630,29 +4650,56 @@ static stbi_uc first_row_filter[5] = STBI__F_sub, STBI__F_none, STBI__F_avg_first, - STBI__F_paeth_first + STBI__F_sub // Paeth with b=c=0 turns out to be equivalent to sub }; static int stbi__paeth(int a, int b, int c) { - int p = a + b - c; - int pa = abs(p-a); - int pb = abs(p-b); - int pc = abs(p-c); - if (pa <= pb && pa <= pc) return a; - if (pb <= pc) return b; - return c; + // This formulation looks very different from the reference in the PNG spec, but is + // actually equivalent and has favorable data dependencies and admits straightforward + // generation of branch-free code, which helps performance significantly. + int thresh = c*3 - (a + b); + int lo = a < b ? a : b; + int hi = a < b ? b : a; + int t0 = (hi <= thresh) ? lo : c; + int t1 = (thresh <= lo) ? hi : t0; + return t1; } static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; +// adds an extra all-255 alpha channel +// dest == src is legal +// img_n must be 1 or 3 +static void stbi__create_png_alpha_expand8(stbi_uc *dest, stbi_uc *src, stbi__uint32 x, int img_n) +{ + int i; + // must process data backwards since we allow dest==src + if (img_n == 1) { + for (i=x-1; i >= 0; --i) { + dest[i*2+1] = 255; + dest[i*2+0] = src[i]; + } + } else { + STBI_ASSERT(img_n == 3); + for (i=x-1; i >= 0; --i) { + dest[i*4+3] = 255; + dest[i*4+2] = src[i*3+2]; + dest[i*4+1] = src[i*3+1]; + dest[i*4+0] = src[i*3+0]; + } + } +} + // create the png data from post-deflated data static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) { - int bytes = (depth == 16? 2 : 1); + int bytes = (depth == 16 ? 2 : 1); stbi__context *s = a->s; stbi__uint32 i,j,stride = x*out_n*bytes; stbi__uint32 img_len, img_width_bytes; + stbi_uc *filter_buf; + int all_ok = 1; int k; int img_n = s->img_n; // copy it into a local for later @@ -4664,8 +4711,11 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into if (!a->out) return stbi__err("outofmem", "Out of memory"); + // note: error exits here don't need to clean up a->out individually, + // stbi__do_png always does on error. if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); img_width_bytes = (((img_n * x * depth) + 7) >> 3); + if (!stbi__mad2sizes_valid(img_width_bytes, y, img_width_bytes)) return stbi__err("too large", "Corrupt PNG"); img_len = (img_width_bytes + 1) * y; // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, @@ -4673,189 +4723,137 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r // so just check for raw_len < img_len always. if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + // Allocate two scan lines worth of filter workspace buffer. + filter_buf = (stbi_uc *) stbi__malloc_mad2(img_width_bytes, 2, 0); + if (!filter_buf) return stbi__err("outofmem", "Out of memory"); + + // Filtering for low-bit-depth images + if (depth < 8) { + filter_bytes = 1; + width = img_width_bytes; + } + for (j=0; j < y; ++j) { - stbi_uc *cur = a->out + stride*j; - stbi_uc *prior; + // cur/prior filter buffers alternate + stbi_uc *cur = filter_buf + (j & 1)*img_width_bytes; + stbi_uc *prior = filter_buf + (~j & 1)*img_width_bytes; + stbi_uc *dest = a->out + stride*j; + int nk = width * filter_bytes; int filter = *raw++; - if (filter > 4) - return stbi__err("invalid filter","Corrupt PNG"); - - if (depth < 8) { - if (img_width_bytes > x) return stbi__err("invalid width","Corrupt PNG"); - cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place - filter_bytes = 1; - width = img_width_bytes; + // check filter type + if (filter > 4) { + all_ok = stbi__err("invalid filter","Corrupt PNG"); + break; } - prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above // if first row, use special filter that doesn't sample previous row if (j == 0) filter = first_row_filter[filter]; - // handle first byte explicitly - for (k=0; k < filter_bytes; ++k) { - switch (filter) { - case STBI__F_none : cur[k] = raw[k]; break; - case STBI__F_sub : cur[k] = raw[k]; break; - case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; - case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break; - case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break; - case STBI__F_avg_first : cur[k] = raw[k]; break; - case STBI__F_paeth_first: cur[k] = raw[k]; break; - } + // perform actual filtering + switch (filter) { + case STBI__F_none: + memcpy(cur, raw, nk); + break; + case STBI__F_sub: + memcpy(cur, raw, filter_bytes); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); + break; + case STBI__F_up: + for (k = 0; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + prior[k]); + break; + case STBI__F_avg: + for (k = 0; k < filter_bytes; ++k) + cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); + break; + case STBI__F_paeth: + for (k = 0; k < filter_bytes; ++k) + cur[k] = STBI__BYTECAST(raw[k] + prior[k]); // prior[k] == stbi__paeth(0,prior[k],0) + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes], prior[k], prior[k-filter_bytes])); + break; + case STBI__F_avg_first: + memcpy(cur, raw, filter_bytes); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); + break; } - if (depth == 8) { - if (img_n != out_n) - cur[img_n] = 255; // first pixel - raw += img_n; - cur += out_n; - prior += out_n; - } else if (depth == 16) { - if (img_n != out_n) { - cur[filter_bytes] = 255; // first pixel top byte - cur[filter_bytes+1] = 255; // first pixel bottom byte - } - raw += filter_bytes; - cur += output_bytes; - prior += output_bytes; - } else { - raw += 1; - cur += 1; - prior += 1; - } + raw += nk; - // this is a little gross, so that we don't switch per-pixel or per-component - if (depth < 8 || img_n == out_n) { - int nk = (width - 1)*filter_bytes; - #define STBI__CASE(f) \ - case f: \ - for (k=0; k < nk; ++k) - switch (filter) { - // "none" filter turns into a memcpy here; make that explicit. - case STBI__F_none: memcpy(cur, raw, nk); break; - STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break; - STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; - STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break; - STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break; - STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break; - STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break; - } - #undef STBI__CASE - raw += nk; - } else { - STBI_ASSERT(img_n+1 == out_n); - #define STBI__CASE(f) \ - case f: \ - for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \ - for (k=0; k < filter_bytes; ++k) - switch (filter) { - STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break; - STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break; - STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; - STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break; - STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break; - STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break; - STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break; - } - #undef STBI__CASE - - // the loop above sets the high byte of the pixels' alpha, but for - // 16 bit png files we also need the low byte set. we'll do that here. - if (depth == 16) { - cur = a->out + stride*j; // start at the beginning of the row again - for (i=0; i < x; ++i,cur+=output_bytes) { - cur[filter_bytes+1] = 255; - } - } - } - } - - // we make a separate pass to expand bits to pixels; for performance, - // this could run two scanlines behind the above code, so it won't - // intefere with filtering but will still be in the cache. - if (depth < 8) { - for (j=0; j < y; ++j) { - stbi_uc *cur = a->out + stride*j; - stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes; - // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit - // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop + // expand decoded bits in cur to dest, also adding an extra alpha channel if desired + if (depth < 8) { stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range + stbi_uc *in = cur; + stbi_uc *out = dest; + stbi_uc inb = 0; + stbi__uint32 nsmp = x*img_n; - // note that the final byte might overshoot and write more data than desired. - // we can allocate enough data that this never writes out of memory, but it - // could also overwrite the next scanline. can it overwrite non-empty data - // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel. - // so we need to explicitly clamp the final ones - + // expand bits to bytes first if (depth == 4) { - for (k=x*img_n; k >= 2; k-=2, ++in) { - *cur++ = scale * ((*in >> 4) ); - *cur++ = scale * ((*in ) & 0x0f); + for (i=0; i < nsmp; ++i) { + if ((i & 1) == 0) inb = *in++; + *out++ = scale * (inb >> 4); + inb <<= 4; } - if (k > 0) *cur++ = scale * ((*in >> 4) ); } else if (depth == 2) { - for (k=x*img_n; k >= 4; k-=4, ++in) { - *cur++ = scale * ((*in >> 6) ); - *cur++ = scale * ((*in >> 4) & 0x03); - *cur++ = scale * ((*in >> 2) & 0x03); - *cur++ = scale * ((*in ) & 0x03); + for (i=0; i < nsmp; ++i) { + if ((i & 3) == 0) inb = *in++; + *out++ = scale * (inb >> 6); + inb <<= 2; } - if (k > 0) *cur++ = scale * ((*in >> 6) ); - if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03); - if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03); - } else if (depth == 1) { - for (k=x*img_n; k >= 8; k-=8, ++in) { - *cur++ = scale * ((*in >> 7) ); - *cur++ = scale * ((*in >> 6) & 0x01); - *cur++ = scale * ((*in >> 5) & 0x01); - *cur++ = scale * ((*in >> 4) & 0x01); - *cur++ = scale * ((*in >> 3) & 0x01); - *cur++ = scale * ((*in >> 2) & 0x01); - *cur++ = scale * ((*in >> 1) & 0x01); - *cur++ = scale * ((*in ) & 0x01); + } else { + STBI_ASSERT(depth == 1); + for (i=0; i < nsmp; ++i) { + if ((i & 7) == 0) inb = *in++; + *out++ = scale * (inb >> 7); + inb <<= 1; } - if (k > 0) *cur++ = scale * ((*in >> 7) ); - if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01); - if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01); - if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01); - if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01); - if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01); - if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01); } - if (img_n != out_n) { - int q; - // insert alpha = 255 - cur = a->out + stride*j; + + // insert alpha=255 values if desired + if (img_n != out_n) + stbi__create_png_alpha_expand8(dest, dest, x, img_n); + } else if (depth == 8) { + if (img_n == out_n) + memcpy(dest, cur, x*img_n); + else + stbi__create_png_alpha_expand8(dest, cur, x, img_n); + } else if (depth == 16) { + // convert the image data from big-endian to platform-native + stbi__uint16 *dest16 = (stbi__uint16*)dest; + stbi__uint32 nsmp = x*img_n; + + if (img_n == out_n) { + for (i = 0; i < nsmp; ++i, ++dest16, cur += 2) + *dest16 = (cur[0] << 8) | cur[1]; + } else { + STBI_ASSERT(img_n+1 == out_n); if (img_n == 1) { - for (q=x-1; q >= 0; --q) { - cur[q*2+1] = 255; - cur[q*2+0] = cur[q]; + for (i = 0; i < x; ++i, dest16 += 2, cur += 2) { + dest16[0] = (cur[0] << 8) | cur[1]; + dest16[1] = 0xffff; } } else { STBI_ASSERT(img_n == 3); - for (q=x-1; q >= 0; --q) { - cur[q*4+3] = 255; - cur[q*4+2] = cur[q*3+2]; - cur[q*4+1] = cur[q*3+1]; - cur[q*4+0] = cur[q*3+0]; + for (i = 0; i < x; ++i, dest16 += 4, cur += 6) { + dest16[0] = (cur[0] << 8) | cur[1]; + dest16[1] = (cur[2] << 8) | cur[3]; + dest16[2] = (cur[4] << 8) | cur[5]; + dest16[3] = 0xffff; } } } } - } else if (depth == 16) { - // force the image data from big-endian to platform-native. - // this is done in a separate pass due to the decoding relying - // on the data being untouched, but could probably be done - // per-line during decode if care is taken. - stbi_uc *cur = a->out; - stbi__uint16 *cur16 = (stbi__uint16*)cur; - - for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) { - *cur16 = (cur[0] << 8) | cur[1]; - } } + STBI_FREE(filter_buf); + if (!all_ok) return 0; + return 1; } diff --git a/deps/stb/stb_image_resize2.h b/deps/stb/stb_image_resize2.h new file mode 100644 index 00000000..f48c509d --- /dev/null +++ b/deps/stb/stb_image_resize2.h @@ -0,0 +1,10366 @@ +/* stb_image_resize2 - v2.07 - public domain image resizing + + by Jeff Roberts (v2) and Jorge L Rodriguez + http://github.com/nothings/stb + + Can be threaded with the extended API. SSE2, AVX, Neon and WASM SIMD support. Only + scaling and translation is supported, no rotations or shears. + + COMPILING & LINKING + In one C/C++ file that #includes this file, do this: + #define STB_IMAGE_RESIZE_IMPLEMENTATION + before the #include. That will create the implementation in that file. + + PORTING FROM VERSION 1 + + The API has changed. You can continue to use the old version of stb_image_resize.h, + which is available in the "deprecated/" directory. + + If you're using the old simple-to-use API, porting is straightforward. + (For more advanced APIs, read the documentation.) + + stbir_resize_uint8(): + - call `stbir_resize_uint8_linear`, cast channel count to `stbir_pixel_layout` + + stbir_resize_float(): + - call `stbir_resize_float_linear`, cast channel count to `stbir_pixel_layout` + + stbir_resize_uint8_srgb(): + - function name is unchanged + - cast channel count to `stbir_pixel_layout` + - above is sufficient unless your image has alpha and it's not RGBA/BGRA + - in that case, follow the below instructions for stbir_resize_uint8_srgb_edgemode + + stbir_resize_uint8_srgb_edgemode() + - switch to the "medium complexity" API + - stbir_resize(), very similar API but a few more parameters: + - pixel_layout: cast channel count to `stbir_pixel_layout` + - data_type: STBIR_TYPE_UINT8_SRGB + - edge: unchanged (STBIR_EDGE_WRAP, etc.) + - filter: STBIR_FILTER_DEFAULT + - which channel is alpha is specified in stbir_pixel_layout, see enum for details + + EASY API CALLS: + Easy API downsamples w/Mitchell filter, upsamples w/cubic interpolation, clamps to edge. + + stbir_resize_uint8_srgb( input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + pixel_layout_enum ) + + stbir_resize_uint8_linear( input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + pixel_layout_enum ) + + stbir_resize_float_linear( input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + pixel_layout_enum ) + + If you pass NULL or zero for the output_pixels, we will allocate the output buffer + for you and return it from the function (free with free() or STBIR_FREE). + As a special case, XX_stride_in_bytes of 0 means packed continuously in memory. + + API LEVELS + There are three levels of API - easy-to-use, medium-complexity and extended-complexity. + + See the "header file" section of the source for API documentation. + + ADDITIONAL DOCUMENTATION + + MEMORY ALLOCATION + By default, we use malloc and free for memory allocation. To override the + memory allocation, before the implementation #include, add a: + + #define STBIR_MALLOC(size,user_data) ... + #define STBIR_FREE(ptr,user_data) ... + + Each resize makes exactly one call to malloc/free (unless you use the + extended API where you can do one allocation for many resizes). Under + address sanitizer, we do separate allocations to find overread/writes. + + PERFORMANCE + This library was written with an emphasis on performance. When testing + stb_image_resize with RGBA, the fastest mode is STBIR_4CHANNEL with + STBIR_TYPE_UINT8 pixels and CLAMPed edges (which is what many other resize + libs do by default). Also, make sure SIMD is turned on of course (default + for 64-bit targets). Avoid WRAP edge mode if you want the fastest speed. + + This library also comes with profiling built-in. If you define STBIR_PROFILE, + you can use the advanced API and get low-level profiling information by + calling stbir_resize_extended_profile_info() or stbir_resize_split_profile_info() + after a resize. + + SIMD + Most of the routines have optimized SSE2, AVX, NEON and WASM versions. + + On Microsoft compilers, we automatically turn on SIMD for 64-bit x64 and + ARM; for 32-bit x86 and ARM, you select SIMD mode by defining STBIR_SSE2 or + STBIR_NEON. For AVX and AVX2, we auto-select it by detecting the /arch:AVX + or /arch:AVX2 switches. You can also always manually turn SSE2, AVX or AVX2 + support on by defining STBIR_SSE2, STBIR_AVX or STBIR_AVX2. + + On Linux, SSE2 and Neon is on by default for 64-bit x64 or ARM64. For 32-bit, + we select x86 SIMD mode by whether you have -msse2, -mavx or -mavx2 enabled + on the command line. For 32-bit ARM, you must pass -mfpu=neon-vfpv4 for both + clang and GCC, but GCC also requires an additional -mfp16-format=ieee to + automatically enable NEON. + + On x86 platforms, you can also define STBIR_FP16C to turn on FP16C instructions + for converting back and forth to half-floats. This is autoselected when we + are using AVX2. Clang and GCC also require the -mf16c switch. ARM always uses + the built-in half float hardware NEON instructions. + + You can also tell us to use multiply-add instructions with STBIR_USE_FMA. + Because x86 doesn't always have fma, we turn it off by default to maintain + determinism across all platforms. If you don't care about non-FMA determinism + and are willing to restrict yourself to more recent x86 CPUs (around the AVX + timeframe), then fma will give you around a 15% speedup. + + You can force off SIMD in all cases by defining STBIR_NO_SIMD. You can turn + off AVX or AVX2 specifically with STBIR_NO_AVX or STBIR_NO_AVX2. AVX is 10% + to 40% faster, and AVX2 is generally another 12%. + + ALPHA CHANNEL + Most of the resizing functions provide the ability to control how the alpha + channel of an image is processed. + + When alpha represents transparency, it is important that when combining + colors with filtering, the pixels should not be treated equally; they + should use a weighted average based on their alpha values. For example, + if a pixel is 1% opaque bright green and another pixel is 99% opaque + black and you average them, the average will be 50% opaque, but the + unweighted average and will be a middling green color, while the weighted + average will be nearly black. This means the unweighted version introduced + green energy that didn't exist in the source image. + + (If you want to know why this makes sense, you can work out the math for + the following: consider what happens if you alpha composite a source image + over a fixed color and then average the output, vs. if you average the + source image pixels and then composite that over the same fixed color. + Only the weighted average produces the same result as the ground truth + composite-then-average result.) + + Therefore, it is in general best to "alpha weight" the pixels when applying + filters to them. This essentially means multiplying the colors by the alpha + values before combining them, and then dividing by the alpha value at the + end. + + The computer graphics industry introduced a technique called "premultiplied + alpha" or "associated alpha" in which image colors are stored in image files + already multiplied by their alpha. This saves some math when compositing, + and also avoids the need to divide by the alpha at the end (which is quite + inefficient). However, while premultiplied alpha is common in the movie CGI + industry, it is not commonplace in other industries like videogames, and most + consumer file formats are generally expected to contain not-premultiplied + colors. For example, Photoshop saves PNG files "unpremultiplied", and web + browsers like Chrome and Firefox expect PNG images to be unpremultiplied. + + Note that there are three possibilities that might describe your image + and resize expectation: + + 1. images are not premultiplied, alpha weighting is desired + 2. images are not premultiplied, alpha weighting is not desired + 3. images are premultiplied + + Both case #2 and case #3 require the exact same math: no alpha weighting + should be applied or removed. Only case 1 requires extra math operations; + the other two cases can be handled identically. + + stb_image_resize expects case #1 by default, applying alpha weighting to + images, expecting the input images to be unpremultiplied. This is what the + COLOR+ALPHA buffer types tell the resizer to do. + + When you use the pixel layouts STBIR_RGBA, STBIR_BGRA, STBIR_ARGB, + STBIR_ABGR, STBIR_RX, or STBIR_XR you are telling us that the pixels are + non-premultiplied. In these cases, the resizer will alpha weight the colors + (effectively creating the premultiplied image), do the filtering, and then + convert back to non-premult on exit. + + When you use the pixel layouts STBIR_RGBA_PM, STBIR_RGBA_PM, STBIR_RGBA_PM, + STBIR_RGBA_PM, STBIR_RX_PM or STBIR_XR_PM, you are telling that the pixels + ARE premultiplied. In this case, the resizer doesn't have to do the + premultipling - it can filter directly on the input. This about twice as + fast as the non-premultiplied case, so it's the right option if your data is + already setup correctly. + + When you use the pixel layout STBIR_4CHANNEL or STBIR_2CHANNEL, you are + telling us that there is no channel that represents transparency; it may be + RGB and some unrelated fourth channel that has been stored in the alpha + channel, but it is actually not alpha. No special processing will be + performed. + + The difference between the generic 4 or 2 channel layouts, and the + specialized _PM versions is with the _PM versions you are telling us that + the data *is* alpha, just don't premultiply it. That's important when + using SRGB pixel formats, we need to know where the alpha is, because + it is converted linearly (rather than with the SRGB converters). + + Because alpha weighting produces the same effect as premultiplying, you + even have the option with non-premultiplied inputs to let the resizer + produce a premultiplied output. Because the intially computed alpha-weighted + output image is effectively premultiplied, this is actually more performant + than the normal path which un-premultiplies the output image as a final step. + + Finally, when converting both in and out of non-premulitplied space (for + example, when using STBIR_RGBA), we go to somewhat heroic measures to + ensure that areas with zero alpha value pixels get something reasonable + in the RGB values. If you don't care about the RGB values of zero alpha + pixels, you can call the stbir_set_non_pm_alpha_speed_over_quality() + function - this runs a premultiplied resize about 25% faster. That said, + when you really care about speed, using premultiplied pixels for both in + and out (STBIR_RGBA_PM, etc) much faster than both of these premultiplied + options. + + PIXEL LAYOUT CONVERSION + The resizer can convert from some pixel layouts to others. When using the + stbir_set_pixel_layouts(), you can, for example, specify STBIR_RGBA + on input, and STBIR_ARGB on output, and it will re-organize the channels + during the resize. Currently, you can only convert between two pixel + layouts with the same number of channels. + + DETERMINISM + We commit to being deterministic (from x64 to ARM to scalar to SIMD, etc). + This requires compiling with fast-math off (using at least /fp:precise). + Also, you must turn off fp-contracting (which turns mult+adds into fmas)! + We attempt to do this with pragmas, but with Clang, you usually want to add + -ffp-contract=off to the command line as well. + + For 32-bit x86, you must use SSE and SSE2 codegen for determinism. That is, + if the scalar x87 unit gets used at all, we immediately lose determinism. + On Microsoft Visual Studio 2008 and earlier, from what we can tell there is + no way to be deterministic in 32-bit x86 (some x87 always leaks in, even + with fp:strict). On 32-bit x86 GCC, determinism requires both -msse2 and + -fpmath=sse. + + Note that we will not be deterministic with float data containing NaNs - + the NaNs will propagate differently on different SIMD and platforms. + + If you turn on STBIR_USE_FMA, then we will be deterministic with other + fma targets, but we will differ from non-fma targets (this is unavoidable, + because a fma isn't simply an add with a mult - it also introduces a + rounding difference compared to non-fma instruction sequences. + + FLOAT PIXEL FORMAT RANGE + Any range of values can be used for the non-alpha float data that you pass + in (0 to 1, -1 to 1, whatever). However, if you are inputting float values + but *outputting* bytes or shorts, you must use a range of 0 to 1 so that we + scale back properly. The alpha channel must also be 0 to 1 for any format + that does premultiplication prior to resizing. + + Note also that with float output, using filters with negative lobes, the + output filtered values might go slightly out of range. You can define + STBIR_FLOAT_LOW_CLAMP and/or STBIR_FLOAT_HIGH_CLAMP to specify the range + to clamp to on output, if that's important. + + MAX/MIN SCALE FACTORS + The input pixel resolutions are in integers, and we do the internal pointer + resolution in size_t sized integers. However, the scale ratio from input + resolution to output resolution is calculated in float form. This means + the effective possible scale ratio is limited to 24 bits (or 16 million + to 1). As you get close to the size of the float resolution (again, 16 + million pixels wide or high), you might start seeing float inaccuracy + issues in general in the pipeline. If you have to do extreme resizes, + you can usually do this is multiple stages (using float intermediate + buffers). + + FLIPPED IMAGES + Stride is just the delta from one scanline to the next. This means you can + use a negative stride to handle inverted images (point to the final + scanline and use a negative stride). You can invert the input or output, + using negative strides. + + DEFAULT FILTERS + For functions which don't provide explicit control over what filters to + use, you can change the compile-time defaults with: + + #define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_something + #define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_something + + See stbir_filter in the header-file section for the list of filters. + + NEW FILTERS + A number of 1D filter kernels are supplied. For a list of supported + filters, see the stbir_filter enum. You can install your own filters by + using the stbir_set_filter_callbacks function. + + PROGRESS + For interactive use with slow resize operations, you can use the the + scanline callbacks in the extended API. It would have to be a *very* large + image resample to need progress though - we're very fast. + + CEIL and FLOOR + In scalar mode, the only functions we use from math.h are ceilf and floorf, + but if you have your own versions, you can define the STBIR_CEILF(v) and + STBIR_FLOORF(v) macros and we'll use them instead. In SIMD, we just use + our own versions. + + ASSERT + Define STBIR_ASSERT(boolval) to override assert() and not use assert.h + + FUTURE TODOS + * For polyphase integral filters, we just memcpy the coeffs to dupe + them, but we should indirect and use the same coeff memory. + * Add pixel layout conversions for sensible different channel counts + (maybe, 1->3/4, 3->4, 4->1, 3->1). + * For SIMD encode and decode scanline routines, do any pre-aligning + for bad input/output buffer alignments and pitch? + * For very wide scanlines, we should we do vertical strips to stay within + L2 cache. Maybe do chunks of 1K pixels at a time. There would be + some pixel reconversion, but probably dwarfed by things falling out + of cache. Probably also something possible with alternating between + scattering and gathering at high resize scales? + * Rewrite the coefficient generator to do many at once. + * AVX-512 vertical kernels - worried about downclocking here. + * Convert the reincludes to macros when we know they aren't changing. + * Experiment with pivoting the horizontal and always using the + vertical filters (which are faster, but perhaps not enough to overcome + the pivot cost and the extra memory touches). Need to buffer the whole + image so have to balance memory use. + * Most of our code is internally function pointers, should we compile + all the SIMD stuff always and dynamically dispatch? + + CONTRIBUTORS + Jeff Roberts: 2.0 implementation, optimizations, SIMD + Martins Mozeiko: NEON simd, WASM simd, clang and GCC whisperer. + Fabian Giesen: half float and srgb converters + Sean Barrett: API design, optimizations + Jorge L Rodriguez: Original 1.0 implementation + Aras Pranckevicius: bugfixes + Nathan Reed: warning fixes for 1.0 + + REVISIONS + 2.07 (2024-05-24) fix for slow final split during threaded conversions of very + wide scanlines when downsampling (caused by extra input + converting), fix for wide scanline resamples with many + splits (int overflow), fix GCC warning. + 2.06 (2024-02-10) fix for identical width/height 3x or more down-scaling + undersampling a single row on rare resize ratios (about 1%) + 2.05 (2024-02-07) fix for 2 pixel to 1 pixel resizes with wrap (thanks Aras) + fix for output callback (thanks Julien Koenen) + 2.04 (2023-11-17) fix for rare AVX bug, shadowed symbol (thanks Nikola Smiljanic). + 2.03 (2023-11-01) ASAN and TSAN warnings fixed, minor tweaks. + 2.00 (2023-10-10) mostly new source: new api, optimizations, simd, vertical-first, etc + (2x-5x faster without simd, 4x-12x faster with simd) + (in some cases, 20x to 40x faster - resizing to very small for example) + 0.96 (2019-03-04) fixed warnings + 0.95 (2017-07-23) fixed warnings + 0.94 (2017-03-18) fixed warnings + 0.93 (2017-03-03) fixed bug with certain combinations of heights + 0.92 (2017-01-02) fix integer overflow on large (>2GB) images + 0.91 (2016-04-02) fix warnings; fix handling of subpixel regions + 0.90 (2014-09-17) first released version + + LICENSE + See end of file for license information. +*/ + +#if !defined(STB_IMAGE_RESIZE_DO_HORIZONTALS) && !defined(STB_IMAGE_RESIZE_DO_VERTICALS) && !defined(STB_IMAGE_RESIZE_DO_CODERS) // for internal re-includes + +#ifndef STBIR_INCLUDE_STB_IMAGE_RESIZE2_H +#define STBIR_INCLUDE_STB_IMAGE_RESIZE2_H + +#include +#ifdef _MSC_VER +typedef unsigned char stbir_uint8; +typedef unsigned short stbir_uint16; +typedef unsigned int stbir_uint32; +typedef unsigned __int64 stbir_uint64; +#else +#include +typedef uint8_t stbir_uint8; +typedef uint16_t stbir_uint16; +typedef uint32_t stbir_uint32; +typedef uint64_t stbir_uint64; +#endif + +#ifdef _M_IX86_FP +#if ( _M_IX86_FP >= 1 ) +#ifndef STBIR_SSE +#define STBIR_SSE +#endif +#endif +#endif + +#if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(_M_AMD64) || defined(__SSE2__) || defined(STBIR_SSE) || defined(STBIR_SSE2) + #ifndef STBIR_SSE2 + #define STBIR_SSE2 + #endif + #if defined(__AVX__) || defined(STBIR_AVX2) + #ifndef STBIR_AVX + #ifndef STBIR_NO_AVX + #define STBIR_AVX + #endif + #endif + #endif + #if defined(__AVX2__) || defined(STBIR_AVX2) + #ifndef STBIR_NO_AVX2 + #ifndef STBIR_AVX2 + #define STBIR_AVX2 + #endif + #if defined( _MSC_VER ) && !defined(__clang__) + #ifndef STBIR_FP16C // FP16C instructions are on all AVX2 cpus, so we can autoselect it here on microsoft - clang needs -m16c + #define STBIR_FP16C + #endif + #endif + #endif + #endif + #ifdef __F16C__ + #ifndef STBIR_FP16C // turn on FP16C instructions if the define is set (for clang and gcc) + #define STBIR_FP16C + #endif + #endif +#endif + +#if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || defined(_M_ARM) || (__ARM_NEON_FP & 4) != 0 && __ARM_FP16_FORMAT_IEEE != 0 +#ifndef STBIR_NEON +#define STBIR_NEON +#endif +#endif + +#if defined(_M_ARM) +#ifdef STBIR_USE_FMA +#undef STBIR_USE_FMA // no FMA for 32-bit arm on MSVC +#endif +#endif + +#if defined(__wasm__) && defined(__wasm_simd128__) +#ifndef STBIR_WASM +#define STBIR_WASM +#endif +#endif + +#ifndef STBIRDEF +#ifdef STB_IMAGE_RESIZE_STATIC +#define STBIRDEF static +#else +#ifdef __cplusplus +#define STBIRDEF extern "C" +#else +#define STBIRDEF extern +#endif +#endif +#endif + +////////////////////////////////////////////////////////////////////////////// +//// start "header file" /////////////////////////////////////////////////// +// +// Easy-to-use API: +// +// * stride is the offset between successive rows of image data +// in memory, in bytes. specify 0 for packed continuously in memory +// * colorspace is linear or sRGB as specified by function name +// * Uses the default filters +// * Uses edge mode clamped +// * returned result is 1 for success or 0 in case of an error. + + +// stbir_pixel_layout specifies: +// number of channels +// order of channels +// whether color is premultiplied by alpha +// for back compatibility, you can cast the old channel count to an stbir_pixel_layout +typedef enum +{ + STBIR_1CHANNEL = 1, + STBIR_2CHANNEL = 2, + STBIR_RGB = 3, // 3-chan, with order specified (for channel flipping) + STBIR_BGR = 0, // 3-chan, with order specified (for channel flipping) + STBIR_4CHANNEL = 5, + + STBIR_RGBA = 4, // alpha formats, where alpha is NOT premultiplied into color channels + STBIR_BGRA = 6, + STBIR_ARGB = 7, + STBIR_ABGR = 8, + STBIR_RA = 9, + STBIR_AR = 10, + + STBIR_RGBA_PM = 11, // alpha formats, where alpha is premultiplied into color channels + STBIR_BGRA_PM = 12, + STBIR_ARGB_PM = 13, + STBIR_ABGR_PM = 14, + STBIR_RA_PM = 15, + STBIR_AR_PM = 16, + + STBIR_RGBA_NO_AW = 11, // alpha formats, where NO alpha weighting is applied at all! + STBIR_BGRA_NO_AW = 12, // these are just synonyms for the _PM flags (which also do + STBIR_ARGB_NO_AW = 13, // no alpha weighting). These names just make it more clear + STBIR_ABGR_NO_AW = 14, // for some folks). + STBIR_RA_NO_AW = 15, + STBIR_AR_NO_AW = 16, + +} stbir_pixel_layout; + +//=============================================================== +// Simple-complexity API +// +// If output_pixels is NULL (0), then we will allocate the buffer and return it to you. +//-------------------------------- + +STBIRDEF unsigned char * stbir_resize_uint8_srgb( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_type ); + +STBIRDEF unsigned char * stbir_resize_uint8_linear( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_type ); + +STBIRDEF float * stbir_resize_float_linear( const float *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_type ); +//=============================================================== + +//=============================================================== +// Medium-complexity API +// +// This extends the easy-to-use API as follows: +// +// * Can specify the datatype - U8, U8_SRGB, U16, FLOAT, HALF_FLOAT +// * Edge wrap can selected explicitly +// * Filter can be selected explicitly +//-------------------------------- + +typedef enum +{ + STBIR_EDGE_CLAMP = 0, + STBIR_EDGE_REFLECT = 1, + STBIR_EDGE_WRAP = 2, // this edge mode is slower and uses more memory + STBIR_EDGE_ZERO = 3, +} stbir_edge; + +typedef enum +{ + STBIR_FILTER_DEFAULT = 0, // use same filter type that easy-to-use API chooses + STBIR_FILTER_BOX = 1, // A trapezoid w/1-pixel wide ramps, same result as box for integer scale ratios + STBIR_FILTER_TRIANGLE = 2, // On upsampling, produces same results as bilinear texture filtering + STBIR_FILTER_CUBICBSPLINE = 3, // The cubic b-spline (aka Mitchell-Netrevalli with B=1,C=0), gaussian-esque + STBIR_FILTER_CATMULLROM = 4, // An interpolating cubic spline + STBIR_FILTER_MITCHELL = 5, // Mitchell-Netrevalli filter with B=1/3, C=1/3 + STBIR_FILTER_POINT_SAMPLE = 6, // Simple point sampling + STBIR_FILTER_OTHER = 7, // User callback specified +} stbir_filter; + +typedef enum +{ + STBIR_TYPE_UINT8 = 0, + STBIR_TYPE_UINT8_SRGB = 1, + STBIR_TYPE_UINT8_SRGB_ALPHA = 2, // alpha channel, when present, should also be SRGB (this is very unusual) + STBIR_TYPE_UINT16 = 3, + STBIR_TYPE_FLOAT = 4, + STBIR_TYPE_HALF_FLOAT = 5 +} stbir_datatype; + +// medium api +STBIRDEF void * stbir_resize( const void *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_layout, stbir_datatype data_type, + stbir_edge edge, stbir_filter filter ); +//=============================================================== + + + +//=============================================================== +// Extended-complexity API +// +// This API exposes all resize functionality. +// +// * Separate filter types for each axis +// * Separate edge modes for each axis +// * Separate input and output data types +// * Can specify regions with subpixel correctness +// * Can specify alpha flags +// * Can specify a memory callback +// * Can specify a callback data type for pixel input and output +// * Can be threaded for a single resize +// * Can be used to resize many frames without recalculating the sampler info +// +// Use this API as follows: +// 1) Call the stbir_resize_init function on a local STBIR_RESIZE structure +// 2) Call any of the stbir_set functions +// 3) Optionally call stbir_build_samplers() if you are going to resample multiple times +// with the same input and output dimensions (like resizing video frames) +// 4) Resample by calling stbir_resize_extended(). +// 5) Call stbir_free_samplers() if you called stbir_build_samplers() +//-------------------------------- + + +// Types: + +// INPUT CALLBACK: this callback is used for input scanlines +typedef void const * stbir_input_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context ); + +// OUTPUT CALLBACK: this callback is used for output scanlines +typedef void stbir_output_callback( void const * output_ptr, int num_pixels, int y, void * context ); + +// callbacks for user installed filters +typedef float stbir__kernel_callback( float x, float scale, void * user_data ); // centered at zero +typedef float stbir__support_callback( float scale, void * user_data ); + +// internal structure with precomputed scaling +typedef struct stbir__info stbir__info; + +typedef struct STBIR_RESIZE // use the stbir_resize_init and stbir_override functions to set these values for future compatibility +{ + void * user_data; + void const * input_pixels; + int input_w, input_h; + double input_s0, input_t0, input_s1, input_t1; + stbir_input_callback * input_cb; + void * output_pixels; + int output_w, output_h; + int output_subx, output_suby, output_subw, output_subh; + stbir_output_callback * output_cb; + int input_stride_in_bytes; + int output_stride_in_bytes; + int splits; + int fast_alpha; + int needs_rebuild; + int called_alloc; + stbir_pixel_layout input_pixel_layout_public; + stbir_pixel_layout output_pixel_layout_public; + stbir_datatype input_data_type; + stbir_datatype output_data_type; + stbir_filter horizontal_filter, vertical_filter; + stbir_edge horizontal_edge, vertical_edge; + stbir__kernel_callback * horizontal_filter_kernel; stbir__support_callback * horizontal_filter_support; + stbir__kernel_callback * vertical_filter_kernel; stbir__support_callback * vertical_filter_support; + stbir__info * samplers; +} STBIR_RESIZE; + +// extended complexity api + + +// First off, you must ALWAYS call stbir_resize_init on your resize structure before any of the other calls! +STBIRDEF void stbir_resize_init( STBIR_RESIZE * resize, + const void *input_pixels, int input_w, int input_h, int input_stride_in_bytes, // stride can be zero + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, // stride can be zero + stbir_pixel_layout pixel_layout, stbir_datatype data_type ); + +//=============================================================== +// You can update these parameters any time after resize_init and there is no cost +//-------------------------------- + +STBIRDEF void stbir_set_datatypes( STBIR_RESIZE * resize, stbir_datatype input_type, stbir_datatype output_type ); +STBIRDEF void stbir_set_pixel_callbacks( STBIR_RESIZE * resize, stbir_input_callback * input_cb, stbir_output_callback * output_cb ); // no callbacks by default +STBIRDEF void stbir_set_user_data( STBIR_RESIZE * resize, void * user_data ); // pass back STBIR_RESIZE* by default +STBIRDEF void stbir_set_buffer_ptrs( STBIR_RESIZE * resize, const void * input_pixels, int input_stride_in_bytes, void * output_pixels, int output_stride_in_bytes ); + +//=============================================================== + + +//=============================================================== +// If you call any of these functions, you will trigger a sampler rebuild! +//-------------------------------- + +STBIRDEF int stbir_set_pixel_layouts( STBIR_RESIZE * resize, stbir_pixel_layout input_pixel_layout, stbir_pixel_layout output_pixel_layout ); // sets new buffer layouts +STBIRDEF int stbir_set_edgemodes( STBIR_RESIZE * resize, stbir_edge horizontal_edge, stbir_edge vertical_edge ); // CLAMP by default + +STBIRDEF int stbir_set_filters( STBIR_RESIZE * resize, stbir_filter horizontal_filter, stbir_filter vertical_filter ); // STBIR_DEFAULT_FILTER_UPSAMPLE/DOWNSAMPLE by default +STBIRDEF int stbir_set_filter_callbacks( STBIR_RESIZE * resize, stbir__kernel_callback * horizontal_filter, stbir__support_callback * horizontal_support, stbir__kernel_callback * vertical_filter, stbir__support_callback * vertical_support ); + +STBIRDEF int stbir_set_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, int subw, int subh ); // sets both sub-regions (full regions by default) +STBIRDEF int stbir_set_input_subrect( STBIR_RESIZE * resize, double s0, double t0, double s1, double t1 ); // sets input sub-region (full region by default) +STBIRDEF int stbir_set_output_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, int subw, int subh ); // sets output sub-region (full region by default) + +// when inputting AND outputting non-premultiplied alpha pixels, we use a slower but higher quality technique +// that fills the zero alpha pixel's RGB values with something plausible. If you don't care about areas of +// zero alpha, you can call this function to get about a 25% speed improvement for STBIR_RGBA to STBIR_RGBA +// types of resizes. +STBIRDEF int stbir_set_non_pm_alpha_speed_over_quality( STBIR_RESIZE * resize, int non_pma_alpha_speed_over_quality ); +//=============================================================== + + +//=============================================================== +// You can call build_samplers to prebuild all the internal data we need to resample. +// Then, if you call resize_extended many times with the same resize, you only pay the +// cost once. +// If you do call build_samplers, you MUST call free_samplers eventually. +//-------------------------------- + +// This builds the samplers and does one allocation +STBIRDEF int stbir_build_samplers( STBIR_RESIZE * resize ); + +// You MUST call this, if you call stbir_build_samplers or stbir_build_samplers_with_splits +STBIRDEF void stbir_free_samplers( STBIR_RESIZE * resize ); +//=============================================================== + + +// And this is the main function to perform the resize synchronously on one thread. +STBIRDEF int stbir_resize_extended( STBIR_RESIZE * resize ); + + +//=============================================================== +// Use these functions for multithreading. +// 1) You call stbir_build_samplers_with_splits first on the main thread +// 2) Then stbir_resize_with_split on each thread +// 3) stbir_free_samplers when done on the main thread +//-------------------------------- + +// This will build samplers for threading. +// You can pass in the number of threads you'd like to use (try_splits). +// It returns the number of splits (threads) that you can call it with. +/// It might be less if the image resize can't be split up that many ways. + +STBIRDEF int stbir_build_samplers_with_splits( STBIR_RESIZE * resize, int try_splits ); + +// This function does a split of the resizing (you call this fuction for each +// split, on multiple threads). A split is a piece of the output resize pixel space. + +// Note that you MUST call stbir_build_samplers_with_splits before stbir_resize_extended_split! + +// Usually, you will always call stbir_resize_split with split_start as the thread_index +// and "1" for the split_count. +// But, if you have a weird situation where you MIGHT want 8 threads, but sometimes +// only 4 threads, you can use 0,2,4,6 for the split_start's and use "2" for the +// split_count each time to turn in into a 4 thread resize. (This is unusual). + +STBIRDEF int stbir_resize_extended_split( STBIR_RESIZE * resize, int split_start, int split_count ); +//=============================================================== + + +//=============================================================== +// Pixel Callbacks info: +//-------------------------------- + +// The input callback is super flexible - it calls you with the input address +// (based on the stride and base pointer), it gives you an optional_output +// pointer that you can fill, or you can just return your own pointer into +// your own data. +// +// You can also do conversion from non-supported data types if necessary - in +// this case, you ignore the input_ptr and just use the x and y parameters to +// calculate your own input_ptr based on the size of each non-supported pixel. +// (Something like the third example below.) +// +// You can also install just an input or just an output callback by setting the +// callback that you don't want to zero. +// +// First example, progress: (getting a callback that you can monitor the progress): +// void const * my_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context ) +// { +// percentage_done = y / input_height; +// return input_ptr; // use buffer from call +// } +// +// Next example, copying: (copy from some other buffer or stream): +// void const * my_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context ) +// { +// CopyOrStreamData( optional_output, other_data_src, num_pixels * pixel_width_in_bytes ); +// return optional_output; // return the optional buffer that we filled +// } +// +// Third example, input another buffer without copying: (zero-copy from other buffer): +// void const * my_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context ) +// { +// void * pixels = ( (char*) other_image_base ) + ( y * other_image_stride ) + ( x * other_pixel_width_in_bytes ); +// return pixels; // return pointer to your data without copying +// } +// +// +// The output callback is considerably simpler - it just calls you so that you can dump +// out each scanline. You could even directly copy out to disk if you have a simple format +// like TGA or BMP. You can also convert to other output types here if you want. +// +// Simple example: +// void const * my_output( void * output_ptr, int num_pixels, int y, void * context ) +// { +// percentage_done = y / output_height; +// fwrite( output_ptr, pixel_width_in_bytes, num_pixels, output_file ); +// } +//=============================================================== + + + + +//=============================================================== +// optional built-in profiling API +//-------------------------------- + +#ifdef STBIR_PROFILE + +typedef struct STBIR_PROFILE_INFO +{ + stbir_uint64 total_clocks; + + // how many clocks spent (of total_clocks) in the various resize routines, along with a string description + // there are "resize_count" number of zones + stbir_uint64 clocks[ 8 ]; + char const ** descriptions; + + // count of clocks and descriptions + stbir_uint32 count; +} STBIR_PROFILE_INFO; + +// use after calling stbir_resize_extended (or stbir_build_samplers or stbir_build_samplers_with_splits) +STBIRDEF void stbir_resize_build_profile_info( STBIR_PROFILE_INFO * out_info, STBIR_RESIZE const * resize ); + +// use after calling stbir_resize_extended +STBIRDEF void stbir_resize_extended_profile_info( STBIR_PROFILE_INFO * out_info, STBIR_RESIZE const * resize ); + +// use after calling stbir_resize_extended_split +STBIRDEF void stbir_resize_split_profile_info( STBIR_PROFILE_INFO * out_info, STBIR_RESIZE const * resize, int split_start, int split_num ); + +//=============================================================== + +#endif + + +//// end header file ///////////////////////////////////////////////////// +#endif // STBIR_INCLUDE_STB_IMAGE_RESIZE2_H + +#if defined(STB_IMAGE_RESIZE_IMPLEMENTATION) || defined(STB_IMAGE_RESIZE2_IMPLEMENTATION) + +#ifndef STBIR_ASSERT +#include +#define STBIR_ASSERT(x) assert(x) +#endif + +#ifndef STBIR_MALLOC +#include +#define STBIR_MALLOC(size,user_data) ((void)(user_data), malloc(size)) +#define STBIR_FREE(ptr,user_data) ((void)(user_data), free(ptr)) +// (we used the comma operator to evaluate user_data, to avoid "unused parameter" warnings) +#endif + +#ifdef _MSC_VER + +#define stbir__inline __forceinline + +#else + +#define stbir__inline __inline__ + +// Clang address sanitizer +#if defined(__has_feature) + #if __has_feature(address_sanitizer) || __has_feature(memory_sanitizer) + #ifndef STBIR__SEPARATE_ALLOCATIONS + #define STBIR__SEPARATE_ALLOCATIONS + #endif + #endif +#endif + +#endif + +// GCC and MSVC +#if defined(__SANITIZE_ADDRESS__) + #ifndef STBIR__SEPARATE_ALLOCATIONS + #define STBIR__SEPARATE_ALLOCATIONS + #endif +#endif + +// Always turn off automatic FMA use - use STBIR_USE_FMA if you want. +// Otherwise, this is a determinism disaster. +#ifndef STBIR_DONT_CHANGE_FP_CONTRACT // override in case you don't want this behavior +#if defined(_MSC_VER) && !defined(__clang__) +#if _MSC_VER > 1200 +#pragma fp_contract(off) +#endif +#elif defined(__GNUC__) && !defined(__clang__) +#pragma GCC optimize("fp-contract=off") +#else +#pragma STDC FP_CONTRACT OFF +#endif +#endif + +#ifdef _MSC_VER +#define STBIR__UNUSED(v) (void)(v) +#else +#define STBIR__UNUSED(v) (void)sizeof(v) +#endif + +#define STBIR__ARRAY_SIZE(a) (sizeof((a))/sizeof((a)[0])) + + +#ifndef STBIR_DEFAULT_FILTER_UPSAMPLE +#define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_CATMULLROM +#endif + +#ifndef STBIR_DEFAULT_FILTER_DOWNSAMPLE +#define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_MITCHELL +#endif + + +#ifndef STBIR__HEADER_FILENAME +#define STBIR__HEADER_FILENAME "stb_image_resize2.h" +#endif + +// the internal pixel layout enums are in a different order, so we can easily do range comparisons of types +// the public pixel layout is ordered in a way that if you cast num_channels (1-4) to the enum, you get something sensible +typedef enum +{ + STBIRI_1CHANNEL = 0, + STBIRI_2CHANNEL = 1, + STBIRI_RGB = 2, + STBIRI_BGR = 3, + STBIRI_4CHANNEL = 4, + + STBIRI_RGBA = 5, + STBIRI_BGRA = 6, + STBIRI_ARGB = 7, + STBIRI_ABGR = 8, + STBIRI_RA = 9, + STBIRI_AR = 10, + + STBIRI_RGBA_PM = 11, + STBIRI_BGRA_PM = 12, + STBIRI_ARGB_PM = 13, + STBIRI_ABGR_PM = 14, + STBIRI_RA_PM = 15, + STBIRI_AR_PM = 16, +} stbir_internal_pixel_layout; + +// define the public pixel layouts to not compile inside the implementation (to avoid accidental use) +#define STBIR_BGR bad_dont_use_in_implementation +#define STBIR_1CHANNEL STBIR_BGR +#define STBIR_2CHANNEL STBIR_BGR +#define STBIR_RGB STBIR_BGR +#define STBIR_RGBA STBIR_BGR +#define STBIR_4CHANNEL STBIR_BGR +#define STBIR_BGRA STBIR_BGR +#define STBIR_ARGB STBIR_BGR +#define STBIR_ABGR STBIR_BGR +#define STBIR_RA STBIR_BGR +#define STBIR_AR STBIR_BGR +#define STBIR_RGBA_PM STBIR_BGR +#define STBIR_BGRA_PM STBIR_BGR +#define STBIR_ARGB_PM STBIR_BGR +#define STBIR_ABGR_PM STBIR_BGR +#define STBIR_RA_PM STBIR_BGR +#define STBIR_AR_PM STBIR_BGR + +// must match stbir_datatype +static unsigned char stbir__type_size[] = { + 1,1,1,2,4,2 // STBIR_TYPE_UINT8,STBIR_TYPE_UINT8_SRGB,STBIR_TYPE_UINT8_SRGB_ALPHA,STBIR_TYPE_UINT16,STBIR_TYPE_FLOAT,STBIR_TYPE_HALF_FLOAT +}; + +// When gathering, the contributors are which source pixels contribute. +// When scattering, the contributors are which destination pixels are contributed to. +typedef struct +{ + int n0; // First contributing pixel + int n1; // Last contributing pixel +} stbir__contributors; + +typedef struct +{ + int lowest; // First sample index for whole filter + int highest; // Last sample index for whole filter + int widest; // widest single set of samples for an output +} stbir__filter_extent_info; + +typedef struct +{ + int n0; // First pixel of decode buffer to write to + int n1; // Last pixel of decode that will be written to + int pixel_offset_for_input; // Pixel offset into input_scanline +} stbir__span; + +typedef struct stbir__scale_info +{ + int input_full_size; + int output_sub_size; + float scale; + float inv_scale; + float pixel_shift; // starting shift in output pixel space (in pixels) + int scale_is_rational; + stbir_uint32 scale_numerator, scale_denominator; +} stbir__scale_info; + +typedef struct +{ + stbir__contributors * contributors; + float* coefficients; + stbir__contributors * gather_prescatter_contributors; + float * gather_prescatter_coefficients; + stbir__scale_info scale_info; + float support; + stbir_filter filter_enum; + stbir__kernel_callback * filter_kernel; + stbir__support_callback * filter_support; + stbir_edge edge; + int coefficient_width; + int filter_pixel_width; + int filter_pixel_margin; + int num_contributors; + int contributors_size; + int coefficients_size; + stbir__filter_extent_info extent_info; + int is_gather; // 0 = scatter, 1 = gather with scale >= 1, 2 = gather with scale < 1 + int gather_prescatter_num_contributors; + int gather_prescatter_coefficient_width; + int gather_prescatter_contributors_size; + int gather_prescatter_coefficients_size; +} stbir__sampler; + +typedef struct +{ + stbir__contributors conservative; + int edge_sizes[2]; // this can be less than filter_pixel_margin, if the filter and scaling falls off + stbir__span spans[2]; // can be two spans, if doing input subrect with clamp mode WRAP +} stbir__extents; + +typedef struct +{ +#ifdef STBIR_PROFILE + union + { + struct { stbir_uint64 total, looping, vertical, horizontal, decode, encode, alpha, unalpha; } named; + stbir_uint64 array[8]; + } profile; + stbir_uint64 * current_zone_excluded_ptr; +#endif + float* decode_buffer; + + int ring_buffer_first_scanline; + int ring_buffer_last_scanline; + int ring_buffer_begin_index; // first_scanline is at this index in the ring buffer + int start_output_y, end_output_y; + int start_input_y, end_input_y; // used in scatter only + + #ifdef STBIR__SEPARATE_ALLOCATIONS + float** ring_buffers; // one pointer for each ring buffer + #else + float* ring_buffer; // one big buffer that we index into + #endif + + float* vertical_buffer; + + char no_cache_straddle[64]; +} stbir__per_split_info; + +typedef void stbir__decode_pixels_func( float * decode, int width_times_channels, void const * input ); +typedef void stbir__alpha_weight_func( float * decode_buffer, int width_times_channels ); +typedef void stbir__horizontal_gather_channels_func( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, + stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ); +typedef void stbir__alpha_unweight_func(float * encode_buffer, int width_times_channels ); +typedef void stbir__encode_pixels_func( void * output, int width_times_channels, float const * encode ); + +struct stbir__info +{ +#ifdef STBIR_PROFILE + union + { + struct { stbir_uint64 total, build, alloc, horizontal, vertical, cleanup, pivot; } named; + stbir_uint64 array[7]; + } profile; + stbir_uint64 * current_zone_excluded_ptr; +#endif + stbir__sampler horizontal; + stbir__sampler vertical; + + void const * input_data; + void * output_data; + + int input_stride_bytes; + int output_stride_bytes; + int ring_buffer_length_bytes; // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter) + int ring_buffer_num_entries; // Total number of entries in the ring buffer. + + stbir_datatype input_type; + stbir_datatype output_type; + + stbir_input_callback * in_pixels_cb; + void * user_data; + stbir_output_callback * out_pixels_cb; + + stbir__extents scanline_extents; + + void * alloced_mem; + stbir__per_split_info * split_info; // by default 1, but there will be N of these allocated based on the thread init you did + + stbir__decode_pixels_func * decode_pixels; + stbir__alpha_weight_func * alpha_weight; + stbir__horizontal_gather_channels_func * horizontal_gather_channels; + stbir__alpha_unweight_func * alpha_unweight; + stbir__encode_pixels_func * encode_pixels; + + int alloc_ring_buffer_num_entries; // Number of entries in the ring buffer that will be allocated + int splits; // count of splits + + stbir_internal_pixel_layout input_pixel_layout_internal; + stbir_internal_pixel_layout output_pixel_layout_internal; + + int input_color_and_type; + int offset_x, offset_y; // offset within output_data + int vertical_first; + int channels; + int effective_channels; // same as channels, except on RGBA/ARGB (7), or XA/AX (3) + size_t alloced_total; +}; + + +#define stbir__max_uint8_as_float 255.0f +#define stbir__max_uint16_as_float 65535.0f +#define stbir__max_uint8_as_float_inverted (1.0f/255.0f) +#define stbir__max_uint16_as_float_inverted (1.0f/65535.0f) +#define stbir__small_float ((float)1 / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20)) + +// min/max friendly +#define STBIR_CLAMP(x, xmin, xmax) do { \ + if ( (x) < (xmin) ) (x) = (xmin); \ + if ( (x) > (xmax) ) (x) = (xmax); \ +} while (0) + +static stbir__inline int stbir__min(int a, int b) +{ + return a < b ? a : b; +} + +static stbir__inline int stbir__max(int a, int b) +{ + return a > b ? a : b; +} + +static float stbir__srgb_uchar_to_linear_float[256] = { + 0.000000f, 0.000304f, 0.000607f, 0.000911f, 0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f, + 0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f, 0.006049f, 0.006512f, 0.006995f, 0.007499f, + 0.008023f, 0.008568f, 0.009134f, 0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f, 0.014444f, + 0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f, 0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f, + 0.025187f, 0.026241f, 0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f, 0.035601f, 0.036889f, + 0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f, 0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f, + 0.054480f, 0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f, 0.068478f, 0.070360f, 0.072272f, + 0.074214f, 0.076185f, 0.078187f, 0.080220f, 0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f, + 0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f, 0.114435f, 0.116971f, 0.119538f, 0.122139f, + 0.124772f, 0.127438f, 0.130136f, 0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f, 0.152926f, + 0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f, 0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f, + 0.191202f, 0.194618f, 0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f, 0.223228f, 0.226966f, + 0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f, 0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f, + 0.274677f, 0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f, 0.309469f, 0.313989f, 0.318547f, + 0.323143f, 0.327778f, 0.332452f, 0.337164f, 0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f, + 0.376262f, 0.381326f, 0.386430f, 0.391573f, 0.396755f, 0.401978f, 0.407240f, 0.412543f, 0.417885f, 0.423268f, 0.428691f, + 0.434154f, 0.439657f, 0.445201f, 0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473532f, 0.479320f, 0.485150f, 0.491021f, + 0.496933f, 0.502887f, 0.508881f, 0.514918f, 0.520996f, 0.527115f, 0.533276f, 0.539480f, 0.545725f, 0.552011f, 0.558340f, + 0.564712f, 0.571125f, 0.577581f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f, 0.623960f, 0.630757f, + 0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f, 0.672443f, 0.679543f, 0.686685f, 0.693872f, 0.701102f, 0.708376f, + 0.715694f, 0.723055f, 0.730461f, 0.737911f, 0.745404f, 0.752942f, 0.760525f, 0.768151f, 0.775822f, 0.783538f, 0.791298f, + 0.799103f, 0.806952f, 0.814847f, 0.822786f, 0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f, + 0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f, 0.947307f, 0.955974f, 0.964686f, 0.973445f, + 0.982251f, 0.991102f, 1.0f +}; + +typedef union +{ + unsigned int u; + float f; +} stbir__FP32; + +// From https://gist.github.com/rygorous/2203834 + +static const stbir_uint32 fp32_to_srgb8_tab4[104] = { + 0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d, 0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d, + 0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a, 0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a, + 0x010e0033, 0x01280033, 0x01410033, 0x015b0033, 0x01750033, 0x018f0033, 0x01a80033, 0x01c20033, + 0x01dc0067, 0x020f0067, 0x02430067, 0x02760067, 0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067, + 0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce, 0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5, + 0x06970158, 0x07420142, 0x07e30130, 0x087b0120, 0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2, + 0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180, 0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143, + 0x11070264, 0x1238023e, 0x1357021d, 0x14660201, 0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af, + 0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad, 0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240, + 0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392, 0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300, + 0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5, 0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401, + 0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d, 0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559, + 0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f, 0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723, +}; + +static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) +{ + static const stbir__FP32 almostone = { 0x3f7fffff }; // 1-eps + static const stbir__FP32 minval = { (127-13) << 23 }; + stbir_uint32 tab,bias,scale,t; + stbir__FP32 f; + + // Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively. + // The tests are carefully written so that NaNs map to 0, same as in the reference + // implementation. + if (!(in > minval.f)) // written this way to catch NaNs + return 0; + if (in > almostone.f) + return 255; + + // Do the table lookup and unpack bias, scale + f.f = in; + tab = fp32_to_srgb8_tab4[(f.u - minval.u) >> 20]; + bias = (tab >> 16) << 9; + scale = tab & 0xffff; + + // Grab next-highest mantissa bits and perform linear interpolation + t = (f.u >> 12) & 0xff; + return (unsigned char) ((bias + scale*t) >> 16); +} + +#ifndef STBIR_FORCE_GATHER_FILTER_SCANLINES_AMOUNT +#define STBIR_FORCE_GATHER_FILTER_SCANLINES_AMOUNT 32 // when downsampling and <= 32 scanlines of buffering, use gather. gather used down to 1/8th scaling for 25% win. +#endif + +#ifndef STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS +#define STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS 4 // when threading, what is the minimum number of scanlines for a split? +#endif + +// restrict pointers for the output pointers +#if defined( _MSC_VER ) && !defined(__clang__) + #define STBIR_STREAMOUT_PTR( star ) star __restrict + #define STBIR_NO_UNROLL( ptr ) __assume(ptr) // this oddly keeps msvc from unrolling a loop +#elif defined( __clang__ ) + #define STBIR_STREAMOUT_PTR( star ) star __restrict__ + #define STBIR_NO_UNROLL( ptr ) __asm__ (""::"r"(ptr)) +#elif defined( __GNUC__ ) + #define STBIR_STREAMOUT_PTR( star ) star __restrict__ + #define STBIR_NO_UNROLL( ptr ) __asm__ (""::"r"(ptr)) +#else + #define STBIR_STREAMOUT_PTR( star ) star + #define STBIR_NO_UNROLL( ptr ) +#endif + +#ifdef STBIR_NO_SIMD // force simd off for whatever reason + +// force simd off overrides everything else, so clear it all + +#ifdef STBIR_SSE2 +#undef STBIR_SSE2 +#endif + +#ifdef STBIR_AVX +#undef STBIR_AVX +#endif + +#ifdef STBIR_NEON +#undef STBIR_NEON +#endif + +#ifdef STBIR_AVX2 +#undef STBIR_AVX2 +#endif + +#ifdef STBIR_FP16C +#undef STBIR_FP16C +#endif + +#ifdef STBIR_WASM +#undef STBIR_WASM +#endif + +#ifdef STBIR_SIMD +#undef STBIR_SIMD +#endif + +#else // STBIR_SIMD + +#ifdef STBIR_SSE2 + #include + + #define stbir__simdf __m128 + #define stbir__simdi __m128i + + #define stbir_simdi_castf( reg ) _mm_castps_si128(reg) + #define stbir_simdf_casti( reg ) _mm_castsi128_ps(reg) + + #define stbir__simdf_load( reg, ptr ) (reg) = _mm_loadu_ps( (float const*)(ptr) ) + #define stbir__simdi_load( reg, ptr ) (reg) = _mm_loadu_si128 ( (stbir__simdi const*)(ptr) ) + #define stbir__simdf_load1( out, ptr ) (out) = _mm_load_ss( (float const*)(ptr) ) // top values can be random (not denormal or nan for perf) + #define stbir__simdi_load1( out, ptr ) (out) = _mm_castps_si128( _mm_load_ss( (float const*)(ptr) )) + #define stbir__simdf_load1z( out, ptr ) (out) = _mm_load_ss( (float const*)(ptr) ) // top values must be zero + #define stbir__simdf_frep4( fvar ) _mm_set_ps1( fvar ) + #define stbir__simdf_load1frep4( out, fvar ) (out) = _mm_set_ps1( fvar ) + #define stbir__simdf_load2( out, ptr ) (out) = _mm_castsi128_ps( _mm_loadl_epi64( (__m128i*)(ptr)) ) // top values can be random (not denormal or nan for perf) + #define stbir__simdf_load2z( out, ptr ) (out) = _mm_castsi128_ps( _mm_loadl_epi64( (__m128i*)(ptr)) ) // top values must be zero + #define stbir__simdf_load2hmerge( out, reg, ptr ) (out) = _mm_castpd_ps(_mm_loadh_pd( _mm_castps_pd(reg), (double*)(ptr) )) + + #define stbir__simdf_zeroP() _mm_setzero_ps() + #define stbir__simdf_zero( reg ) (reg) = _mm_setzero_ps() + + #define stbir__simdf_store( ptr, reg ) _mm_storeu_ps( (float*)(ptr), reg ) + #define stbir__simdf_store1( ptr, reg ) _mm_store_ss( (float*)(ptr), reg ) + #define stbir__simdf_store2( ptr, reg ) _mm_storel_epi64( (__m128i*)(ptr), _mm_castps_si128(reg) ) + #define stbir__simdf_store2h( ptr, reg ) _mm_storeh_pd( (double*)(ptr), _mm_castps_pd(reg) ) + + #define stbir__simdi_store( ptr, reg ) _mm_storeu_si128( (__m128i*)(ptr), reg ) + #define stbir__simdi_store1( ptr, reg ) _mm_store_ss( (float*)(ptr), _mm_castsi128_ps(reg) ) + #define stbir__simdi_store2( ptr, reg ) _mm_storel_epi64( (__m128i*)(ptr), (reg) ) + + #define stbir__prefetch( ptr ) _mm_prefetch((char*)(ptr), _MM_HINT_T0 ) + + #define stbir__simdi_expand_u8_to_u32(out0,out1,out2,out3,ireg) \ + { \ + stbir__simdi zero = _mm_setzero_si128(); \ + out2 = _mm_unpacklo_epi8( ireg, zero ); \ + out3 = _mm_unpackhi_epi8( ireg, zero ); \ + out0 = _mm_unpacklo_epi16( out2, zero ); \ + out1 = _mm_unpackhi_epi16( out2, zero ); \ + out2 = _mm_unpacklo_epi16( out3, zero ); \ + out3 = _mm_unpackhi_epi16( out3, zero ); \ + } + +#define stbir__simdi_expand_u8_to_1u32(out,ireg) \ + { \ + stbir__simdi zero = _mm_setzero_si128(); \ + out = _mm_unpacklo_epi8( ireg, zero ); \ + out = _mm_unpacklo_epi16( out, zero ); \ + } + + #define stbir__simdi_expand_u16_to_u32(out0,out1,ireg) \ + { \ + stbir__simdi zero = _mm_setzero_si128(); \ + out0 = _mm_unpacklo_epi16( ireg, zero ); \ + out1 = _mm_unpackhi_epi16( ireg, zero ); \ + } + + #define stbir__simdf_convert_float_to_i32( i, f ) (i) = _mm_cvttps_epi32(f) + #define stbir__simdf_convert_float_to_int( f ) _mm_cvtt_ss2si(f) + #define stbir__simdf_convert_float_to_uint8( f ) ((unsigned char)_mm_cvtsi128_si32(_mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(f,STBIR__CONSTF(STBIR_max_uint8_as_float)),_mm_setzero_ps())))) + #define stbir__simdf_convert_float_to_short( f ) ((unsigned short)_mm_cvtsi128_si32(_mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(f,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())))) + + #define stbir__simdi_to_int( i ) _mm_cvtsi128_si32(i) + #define stbir__simdi_convert_i32_to_float(out, ireg) (out) = _mm_cvtepi32_ps( ireg ) + #define stbir__simdf_add( out, reg0, reg1 ) (out) = _mm_add_ps( reg0, reg1 ) + #define stbir__simdf_mult( out, reg0, reg1 ) (out) = _mm_mul_ps( reg0, reg1 ) + #define stbir__simdf_mult_mem( out, reg, ptr ) (out) = _mm_mul_ps( reg, _mm_loadu_ps( (float const*)(ptr) ) ) + #define stbir__simdf_mult1_mem( out, reg, ptr ) (out) = _mm_mul_ss( reg, _mm_load_ss( (float const*)(ptr) ) ) + #define stbir__simdf_add_mem( out, reg, ptr ) (out) = _mm_add_ps( reg, _mm_loadu_ps( (float const*)(ptr) ) ) + #define stbir__simdf_add1_mem( out, reg, ptr ) (out) = _mm_add_ss( reg, _mm_load_ss( (float const*)(ptr) ) ) + + #ifdef STBIR_USE_FMA // not on by default to maintain bit identical simd to non-simd + #include + #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = _mm_fmadd_ps( mul1, mul2, add ) + #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = _mm_fmadd_ss( mul1, mul2, add ) + #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = _mm_fmadd_ps( mul, _mm_loadu_ps( (float const*)(ptr) ), add ) + #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = _mm_fmadd_ss( mul, _mm_load_ss( (float const*)(ptr) ), add ) + #else + #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = _mm_add_ps( add, _mm_mul_ps( mul1, mul2 ) ) + #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = _mm_add_ss( add, _mm_mul_ss( mul1, mul2 ) ) + #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = _mm_add_ps( add, _mm_mul_ps( mul, _mm_loadu_ps( (float const*)(ptr) ) ) ) + #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = _mm_add_ss( add, _mm_mul_ss( mul, _mm_load_ss( (float const*)(ptr) ) ) ) + #endif + + #define stbir__simdf_add1( out, reg0, reg1 ) (out) = _mm_add_ss( reg0, reg1 ) + #define stbir__simdf_mult1( out, reg0, reg1 ) (out) = _mm_mul_ss( reg0, reg1 ) + + #define stbir__simdf_and( out, reg0, reg1 ) (out) = _mm_and_ps( reg0, reg1 ) + #define stbir__simdf_or( out, reg0, reg1 ) (out) = _mm_or_ps( reg0, reg1 ) + + #define stbir__simdf_min( out, reg0, reg1 ) (out) = _mm_min_ps( reg0, reg1 ) + #define stbir__simdf_max( out, reg0, reg1 ) (out) = _mm_max_ps( reg0, reg1 ) + #define stbir__simdf_min1( out, reg0, reg1 ) (out) = _mm_min_ss( reg0, reg1 ) + #define stbir__simdf_max1( out, reg0, reg1 ) (out) = _mm_max_ss( reg0, reg1 ) + + #define stbir__simdf_0123ABCDto3ABx( out, reg0, reg1 ) (out)=_mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( _mm_shuffle_ps( reg1,reg0, (0<<0) + (1<<2) + (2<<4) + (3<<6) )), (3<<0) + (0<<2) + (1<<4) + (2<<6) ) ) + #define stbir__simdf_0123ABCDto23Ax( out, reg0, reg1 ) (out)=_mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( _mm_shuffle_ps( reg1,reg0, (0<<0) + (1<<2) + (2<<4) + (3<<6) )), (2<<0) + (3<<2) + (0<<4) + (1<<6) ) ) + + static const stbir__simdf STBIR_zeroones = { 0.0f,1.0f,0.0f,1.0f }; + static const stbir__simdf STBIR_onezeros = { 1.0f,0.0f,1.0f,0.0f }; + #define stbir__simdf_aaa1( out, alp, ones ) (out)=_mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( _mm_movehl_ps( ones, alp ) ), (1<<0) + (1<<2) + (1<<4) + (2<<6) ) ) + #define stbir__simdf_1aaa( out, alp, ones ) (out)=_mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( _mm_movelh_ps( ones, alp ) ), (0<<0) + (2<<2) + (2<<4) + (2<<6) ) ) + #define stbir__simdf_a1a1( out, alp, ones) (out) = _mm_or_ps( _mm_castsi128_ps( _mm_srli_epi64( _mm_castps_si128(alp), 32 ) ), STBIR_zeroones ) + #define stbir__simdf_1a1a( out, alp, ones) (out) = _mm_or_ps( _mm_castsi128_ps( _mm_slli_epi64( _mm_castps_si128(alp), 32 ) ), STBIR_onezeros ) + + #define stbir__simdf_swiz( reg, one, two, three, four ) _mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( reg ), (one<<0) + (two<<2) + (three<<4) + (four<<6) ) ) + + #define stbir__simdi_and( out, reg0, reg1 ) (out) = _mm_and_si128( reg0, reg1 ) + #define stbir__simdi_or( out, reg0, reg1 ) (out) = _mm_or_si128( reg0, reg1 ) + #define stbir__simdi_16madd( out, reg0, reg1 ) (out) = _mm_madd_epi16( reg0, reg1 ) + + #define stbir__simdf_pack_to_8bytes(out,aa,bb) \ + { \ + stbir__simdf af,bf; \ + stbir__simdi a,b; \ + af = _mm_min_ps( aa, STBIR_max_uint8_as_float ); \ + bf = _mm_min_ps( bb, STBIR_max_uint8_as_float ); \ + af = _mm_max_ps( af, _mm_setzero_ps() ); \ + bf = _mm_max_ps( bf, _mm_setzero_ps() ); \ + a = _mm_cvttps_epi32( af ); \ + b = _mm_cvttps_epi32( bf ); \ + a = _mm_packs_epi32( a, b ); \ + out = _mm_packus_epi16( a, a ); \ + } + + #define stbir__simdf_load4_transposed( o0, o1, o2, o3, ptr ) \ + stbir__simdf_load( o0, (ptr) ); \ + stbir__simdf_load( o1, (ptr)+4 ); \ + stbir__simdf_load( o2, (ptr)+8 ); \ + stbir__simdf_load( o3, (ptr)+12 ); \ + { \ + __m128 tmp0, tmp1, tmp2, tmp3; \ + tmp0 = _mm_unpacklo_ps(o0, o1); \ + tmp2 = _mm_unpacklo_ps(o2, o3); \ + tmp1 = _mm_unpackhi_ps(o0, o1); \ + tmp3 = _mm_unpackhi_ps(o2, o3); \ + o0 = _mm_movelh_ps(tmp0, tmp2); \ + o1 = _mm_movehl_ps(tmp2, tmp0); \ + o2 = _mm_movelh_ps(tmp1, tmp3); \ + o3 = _mm_movehl_ps(tmp3, tmp1); \ + } + + #define stbir__interleave_pack_and_store_16_u8( ptr, r0, r1, r2, r3 ) \ + r0 = _mm_packs_epi32( r0, r1 ); \ + r2 = _mm_packs_epi32( r2, r3 ); \ + r1 = _mm_unpacklo_epi16( r0, r2 ); \ + r3 = _mm_unpackhi_epi16( r0, r2 ); \ + r0 = _mm_unpacklo_epi16( r1, r3 ); \ + r2 = _mm_unpackhi_epi16( r1, r3 ); \ + r0 = _mm_packus_epi16( r0, r2 ); \ + stbir__simdi_store( ptr, r0 ); \ + + #define stbir__simdi_32shr( out, reg, imm ) out = _mm_srli_epi32( reg, imm ) + + #if defined(_MSC_VER) && !defined(__clang__) + // msvc inits with 8 bytes + #define STBIR__CONST_32_TO_8( v ) (char)(unsigned char)((v)&255),(char)(unsigned char)(((v)>>8)&255),(char)(unsigned char)(((v)>>16)&255),(char)(unsigned char)(((v)>>24)&255) + #define STBIR__CONST_4_32i( v ) STBIR__CONST_32_TO_8( v ), STBIR__CONST_32_TO_8( v ), STBIR__CONST_32_TO_8( v ), STBIR__CONST_32_TO_8( v ) + #define STBIR__CONST_4d_32i( v0, v1, v2, v3 ) STBIR__CONST_32_TO_8( v0 ), STBIR__CONST_32_TO_8( v1 ), STBIR__CONST_32_TO_8( v2 ), STBIR__CONST_32_TO_8( v3 ) + #else + // everything else inits with long long's + #define STBIR__CONST_4_32i( v ) (long long)((((stbir_uint64)(stbir_uint32)(v))<<32)|((stbir_uint64)(stbir_uint32)(v))),(long long)((((stbir_uint64)(stbir_uint32)(v))<<32)|((stbir_uint64)(stbir_uint32)(v))) + #define STBIR__CONST_4d_32i( v0, v1, v2, v3 ) (long long)((((stbir_uint64)(stbir_uint32)(v1))<<32)|((stbir_uint64)(stbir_uint32)(v0))),(long long)((((stbir_uint64)(stbir_uint32)(v3))<<32)|((stbir_uint64)(stbir_uint32)(v2))) + #endif + + #define STBIR__SIMDF_CONST(var, x) stbir__simdf var = { x, x, x, x } + #define STBIR__SIMDI_CONST(var, x) stbir__simdi var = { STBIR__CONST_4_32i(x) } + #define STBIR__CONSTF(var) (var) + #define STBIR__CONSTI(var) (var) + + #if defined(STBIR_AVX) || defined(__SSE4_1__) + #include + #define stbir__simdf_pack_to_8words(out,reg0,reg1) out = _mm_packus_epi32(_mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg0,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())), _mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg1,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps()))) + #else + STBIR__SIMDI_CONST(stbir__s32_32768, 32768); + STBIR__SIMDI_CONST(stbir__s16_32768, ((32768<<16)|32768)); + + #define stbir__simdf_pack_to_8words(out,reg0,reg1) \ + { \ + stbir__simdi tmp0,tmp1; \ + tmp0 = _mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg0,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())); \ + tmp1 = _mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg1,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())); \ + tmp0 = _mm_sub_epi32( tmp0, stbir__s32_32768 ); \ + tmp1 = _mm_sub_epi32( tmp1, stbir__s32_32768 ); \ + out = _mm_packs_epi32( tmp0, tmp1 ); \ + out = _mm_sub_epi16( out, stbir__s16_32768 ); \ + } + + #endif + + #define STBIR_SIMD + + // if we detect AVX, set the simd8 defines + #ifdef STBIR_AVX + #include + #define STBIR_SIMD8 + #define stbir__simdf8 __m256 + #define stbir__simdi8 __m256i + #define stbir__simdf8_load( out, ptr ) (out) = _mm256_loadu_ps( (float const *)(ptr) ) + #define stbir__simdi8_load( out, ptr ) (out) = _mm256_loadu_si256( (__m256i const *)(ptr) ) + #define stbir__simdf8_mult( out, a, b ) (out) = _mm256_mul_ps( (a), (b) ) + #define stbir__simdf8_store( ptr, out ) _mm256_storeu_ps( (float*)(ptr), out ) + #define stbir__simdi8_store( ptr, reg ) _mm256_storeu_si256( (__m256i*)(ptr), reg ) + #define stbir__simdf8_frep8( fval ) _mm256_set1_ps( fval ) + + #define stbir__simdf8_min( out, reg0, reg1 ) (out) = _mm256_min_ps( reg0, reg1 ) + #define stbir__simdf8_max( out, reg0, reg1 ) (out) = _mm256_max_ps( reg0, reg1 ) + + #define stbir__simdf8_add4halves( out, bot4, top8 ) (out) = _mm_add_ps( bot4, _mm256_extractf128_ps( top8, 1 ) ) + #define stbir__simdf8_mult_mem( out, reg, ptr ) (out) = _mm256_mul_ps( reg, _mm256_loadu_ps( (float const*)(ptr) ) ) + #define stbir__simdf8_add_mem( out, reg, ptr ) (out) = _mm256_add_ps( reg, _mm256_loadu_ps( (float const*)(ptr) ) ) + #define stbir__simdf8_add( out, a, b ) (out) = _mm256_add_ps( a, b ) + #define stbir__simdf8_load1b( out, ptr ) (out) = _mm256_broadcast_ss( ptr ) + #define stbir__simdf_load1rep4( out, ptr ) (out) = _mm_broadcast_ss( ptr ) // avx load instruction + + #define stbir__simdi8_convert_i32_to_float(out, ireg) (out) = _mm256_cvtepi32_ps( ireg ) + #define stbir__simdf8_convert_float_to_i32( i, f ) (i) = _mm256_cvttps_epi32(f) + + #define stbir__simdf8_bot4s( out, a, b ) (out) = _mm256_permute2f128_ps(a,b, (0<<0)+(2<<4) ) + #define stbir__simdf8_top4s( out, a, b ) (out) = _mm256_permute2f128_ps(a,b, (1<<0)+(3<<4) ) + + #define stbir__simdf8_gettop4( reg ) _mm256_extractf128_ps(reg,1) + + #ifdef STBIR_AVX2 + + #define stbir__simdi8_expand_u8_to_u32(out0,out1,ireg) \ + { \ + stbir__simdi8 a, zero =_mm256_setzero_si256();\ + a = _mm256_permute4x64_epi64( _mm256_unpacklo_epi8( _mm256_permute4x64_epi64(_mm256_castsi128_si256(ireg),(0<<0)+(2<<2)+(1<<4)+(3<<6)), zero ),(0<<0)+(2<<2)+(1<<4)+(3<<6)); \ + out0 = _mm256_unpacklo_epi16( a, zero ); \ + out1 = _mm256_unpackhi_epi16( a, zero ); \ + } + + #define stbir__simdf8_pack_to_16bytes(out,aa,bb) \ + { \ + stbir__simdi8 t; \ + stbir__simdf8 af,bf; \ + stbir__simdi8 a,b; \ + af = _mm256_min_ps( aa, STBIR_max_uint8_as_floatX ); \ + bf = _mm256_min_ps( bb, STBIR_max_uint8_as_floatX ); \ + af = _mm256_max_ps( af, _mm256_setzero_ps() ); \ + bf = _mm256_max_ps( bf, _mm256_setzero_ps() ); \ + a = _mm256_cvttps_epi32( af ); \ + b = _mm256_cvttps_epi32( bf ); \ + t = _mm256_permute4x64_epi64( _mm256_packs_epi32( a, b ), (0<<0)+(2<<2)+(1<<4)+(3<<6) ); \ + out = _mm256_castsi256_si128( _mm256_permute4x64_epi64( _mm256_packus_epi16( t, t ), (0<<0)+(2<<2)+(1<<4)+(3<<6) ) ); \ + } + + #define stbir__simdi8_expand_u16_to_u32(out,ireg) out = _mm256_unpacklo_epi16( _mm256_permute4x64_epi64(_mm256_castsi128_si256(ireg),(0<<0)+(2<<2)+(1<<4)+(3<<6)), _mm256_setzero_si256() ); + + #define stbir__simdf8_pack_to_16words(out,aa,bb) \ + { \ + stbir__simdf8 af,bf; \ + stbir__simdi8 a,b; \ + af = _mm256_min_ps( aa, STBIR_max_uint16_as_floatX ); \ + bf = _mm256_min_ps( bb, STBIR_max_uint16_as_floatX ); \ + af = _mm256_max_ps( af, _mm256_setzero_ps() ); \ + bf = _mm256_max_ps( bf, _mm256_setzero_ps() ); \ + a = _mm256_cvttps_epi32( af ); \ + b = _mm256_cvttps_epi32( bf ); \ + (out) = _mm256_permute4x64_epi64( _mm256_packus_epi32(a, b), (0<<0)+(2<<2)+(1<<4)+(3<<6) ); \ + } + + #else + + #define stbir__simdi8_expand_u8_to_u32(out0,out1,ireg) \ + { \ + stbir__simdi a,zero = _mm_setzero_si128(); \ + a = _mm_unpacklo_epi8( ireg, zero ); \ + out0 = _mm256_setr_m128i( _mm_unpacklo_epi16( a, zero ), _mm_unpackhi_epi16( a, zero ) ); \ + a = _mm_unpackhi_epi8( ireg, zero ); \ + out1 = _mm256_setr_m128i( _mm_unpacklo_epi16( a, zero ), _mm_unpackhi_epi16( a, zero ) ); \ + } + + #define stbir__simdf8_pack_to_16bytes(out,aa,bb) \ + { \ + stbir__simdi t; \ + stbir__simdf8 af,bf; \ + stbir__simdi8 a,b; \ + af = _mm256_min_ps( aa, STBIR_max_uint8_as_floatX ); \ + bf = _mm256_min_ps( bb, STBIR_max_uint8_as_floatX ); \ + af = _mm256_max_ps( af, _mm256_setzero_ps() ); \ + bf = _mm256_max_ps( bf, _mm256_setzero_ps() ); \ + a = _mm256_cvttps_epi32( af ); \ + b = _mm256_cvttps_epi32( bf ); \ + out = _mm_packs_epi32( _mm256_castsi256_si128(a), _mm256_extractf128_si256( a, 1 ) ); \ + out = _mm_packus_epi16( out, out ); \ + t = _mm_packs_epi32( _mm256_castsi256_si128(b), _mm256_extractf128_si256( b, 1 ) ); \ + t = _mm_packus_epi16( t, t ); \ + out = _mm_castps_si128( _mm_shuffle_ps( _mm_castsi128_ps(out), _mm_castsi128_ps(t), (0<<0)+(1<<2)+(0<<4)+(1<<6) ) ); \ + } + + #define stbir__simdi8_expand_u16_to_u32(out,ireg) \ + { \ + stbir__simdi a,b,zero = _mm_setzero_si128(); \ + a = _mm_unpacklo_epi16( ireg, zero ); \ + b = _mm_unpackhi_epi16( ireg, zero ); \ + out = _mm256_insertf128_si256( _mm256_castsi128_si256( a ), b, 1 ); \ + } + + #define stbir__simdf8_pack_to_16words(out,aa,bb) \ + { \ + stbir__simdi t0,t1; \ + stbir__simdf8 af,bf; \ + stbir__simdi8 a,b; \ + af = _mm256_min_ps( aa, STBIR_max_uint16_as_floatX ); \ + bf = _mm256_min_ps( bb, STBIR_max_uint16_as_floatX ); \ + af = _mm256_max_ps( af, _mm256_setzero_ps() ); \ + bf = _mm256_max_ps( bf, _mm256_setzero_ps() ); \ + a = _mm256_cvttps_epi32( af ); \ + b = _mm256_cvttps_epi32( bf ); \ + t0 = _mm_packus_epi32( _mm256_castsi256_si128(a), _mm256_extractf128_si256( a, 1 ) ); \ + t1 = _mm_packus_epi32( _mm256_castsi256_si128(b), _mm256_extractf128_si256( b, 1 ) ); \ + out = _mm256_setr_m128i( t0, t1 ); \ + } + + #endif + + static __m256i stbir_00001111 = { STBIR__CONST_4d_32i( 0, 0, 0, 0 ), STBIR__CONST_4d_32i( 1, 1, 1, 1 ) }; + #define stbir__simdf8_0123to00001111( out, in ) (out) = _mm256_permutevar_ps ( in, stbir_00001111 ) + + static __m256i stbir_22223333 = { STBIR__CONST_4d_32i( 2, 2, 2, 2 ), STBIR__CONST_4d_32i( 3, 3, 3, 3 ) }; + #define stbir__simdf8_0123to22223333( out, in ) (out) = _mm256_permutevar_ps ( in, stbir_22223333 ) + + #define stbir__simdf8_0123to2222( out, in ) (out) = stbir__simdf_swiz(_mm256_castps256_ps128(in), 2,2,2,2 ) + + #define stbir__simdf8_load4b( out, ptr ) (out) = _mm256_broadcast_ps( (__m128 const *)(ptr) ) + + static __m256i stbir_00112233 = { STBIR__CONST_4d_32i( 0, 0, 1, 1 ), STBIR__CONST_4d_32i( 2, 2, 3, 3 ) }; + #define stbir__simdf8_0123to00112233( out, in ) (out) = _mm256_permutevar_ps ( in, stbir_00112233 ) + #define stbir__simdf8_add4( out, a8, b ) (out) = _mm256_add_ps( a8, _mm256_castps128_ps256( b ) ) + + static __m256i stbir_load6 = { STBIR__CONST_4_32i( 0x80000000 ), STBIR__CONST_4d_32i( 0x80000000, 0x80000000, 0, 0 ) }; + #define stbir__simdf8_load6z( out, ptr ) (out) = _mm256_maskload_ps( ptr, stbir_load6 ) + + #define stbir__simdf8_0123to00000000( out, in ) (out) = _mm256_shuffle_ps ( in, in, (0<<0)+(0<<2)+(0<<4)+(0<<6) ) + #define stbir__simdf8_0123to11111111( out, in ) (out) = _mm256_shuffle_ps ( in, in, (1<<0)+(1<<2)+(1<<4)+(1<<6) ) + #define stbir__simdf8_0123to22222222( out, in ) (out) = _mm256_shuffle_ps ( in, in, (2<<0)+(2<<2)+(2<<4)+(2<<6) ) + #define stbir__simdf8_0123to33333333( out, in ) (out) = _mm256_shuffle_ps ( in, in, (3<<0)+(3<<2)+(3<<4)+(3<<6) ) + #define stbir__simdf8_0123to21032103( out, in ) (out) = _mm256_shuffle_ps ( in, in, (2<<0)+(1<<2)+(0<<4)+(3<<6) ) + #define stbir__simdf8_0123to32103210( out, in ) (out) = _mm256_shuffle_ps ( in, in, (3<<0)+(2<<2)+(1<<4)+(0<<6) ) + #define stbir__simdf8_0123to12301230( out, in ) (out) = _mm256_shuffle_ps ( in, in, (1<<0)+(2<<2)+(3<<4)+(0<<6) ) + #define stbir__simdf8_0123to10321032( out, in ) (out) = _mm256_shuffle_ps ( in, in, (1<<0)+(0<<2)+(3<<4)+(2<<6) ) + #define stbir__simdf8_0123to30123012( out, in ) (out) = _mm256_shuffle_ps ( in, in, (3<<0)+(0<<2)+(1<<4)+(2<<6) ) + + #define stbir__simdf8_0123to11331133( out, in ) (out) = _mm256_shuffle_ps ( in, in, (1<<0)+(1<<2)+(3<<4)+(3<<6) ) + #define stbir__simdf8_0123to00220022( out, in ) (out) = _mm256_shuffle_ps ( in, in, (0<<0)+(0<<2)+(2<<4)+(2<<6) ) + + #define stbir__simdf8_aaa1( out, alp, ones ) (out) = _mm256_blend_ps( alp, ones, (1<<0)+(1<<1)+(1<<2)+(0<<3)+(1<<4)+(1<<5)+(1<<6)+(0<<7)); (out)=_mm256_shuffle_ps( out,out, (3<<0) + (3<<2) + (3<<4) + (0<<6) ) + #define stbir__simdf8_1aaa( out, alp, ones ) (out) = _mm256_blend_ps( alp, ones, (0<<0)+(1<<1)+(1<<2)+(1<<3)+(0<<4)+(1<<5)+(1<<6)+(1<<7)); (out)=_mm256_shuffle_ps( out,out, (1<<0) + (0<<2) + (0<<4) + (0<<6) ) + #define stbir__simdf8_a1a1( out, alp, ones) (out) = _mm256_blend_ps( alp, ones, (1<<0)+(0<<1)+(1<<2)+(0<<3)+(1<<4)+(0<<5)+(1<<6)+(0<<7)); (out)=_mm256_shuffle_ps( out,out, (1<<0) + (0<<2) + (3<<4) + (2<<6) ) + #define stbir__simdf8_1a1a( out, alp, ones) (out) = _mm256_blend_ps( alp, ones, (0<<0)+(1<<1)+(0<<2)+(1<<3)+(0<<4)+(1<<5)+(0<<6)+(1<<7)); (out)=_mm256_shuffle_ps( out,out, (1<<0) + (0<<2) + (3<<4) + (2<<6) ) + + #define stbir__simdf8_zero( reg ) (reg) = _mm256_setzero_ps() + + #ifdef STBIR_USE_FMA // not on by default to maintain bit identical simd to non-simd + #define stbir__simdf8_madd( out, add, mul1, mul2 ) (out) = _mm256_fmadd_ps( mul1, mul2, add ) + #define stbir__simdf8_madd_mem( out, add, mul, ptr ) (out) = _mm256_fmadd_ps( mul, _mm256_loadu_ps( (float const*)(ptr) ), add ) + #define stbir__simdf8_madd_mem4( out, add, mul, ptr )(out) = _mm256_fmadd_ps( _mm256_setr_m128( mul, _mm_setzero_ps() ), _mm256_setr_m128( _mm_loadu_ps( (float const*)(ptr) ), _mm_setzero_ps() ), add ) + #else + #define stbir__simdf8_madd( out, add, mul1, mul2 ) (out) = _mm256_add_ps( add, _mm256_mul_ps( mul1, mul2 ) ) + #define stbir__simdf8_madd_mem( out, add, mul, ptr ) (out) = _mm256_add_ps( add, _mm256_mul_ps( mul, _mm256_loadu_ps( (float const*)(ptr) ) ) ) + #define stbir__simdf8_madd_mem4( out, add, mul, ptr ) (out) = _mm256_add_ps( add, _mm256_setr_m128( _mm_mul_ps( mul, _mm_loadu_ps( (float const*)(ptr) ) ), _mm_setzero_ps() ) ) + #endif + #define stbir__if_simdf8_cast_to_simdf4( val ) _mm256_castps256_ps128( val ) + + #endif + + #ifdef STBIR_FLOORF + #undef STBIR_FLOORF + #endif + #define STBIR_FLOORF stbir_simd_floorf + static stbir__inline float stbir_simd_floorf(float x) // martins floorf + { + #if defined(STBIR_AVX) || defined(__SSE4_1__) || defined(STBIR_SSE41) + __m128 t = _mm_set_ss(x); + return _mm_cvtss_f32( _mm_floor_ss(t, t) ); + #else + __m128 f = _mm_set_ss(x); + __m128 t = _mm_cvtepi32_ps(_mm_cvttps_epi32(f)); + __m128 r = _mm_add_ss(t, _mm_and_ps(_mm_cmplt_ss(f, t), _mm_set_ss(-1.0f))); + return _mm_cvtss_f32(r); + #endif + } + + #ifdef STBIR_CEILF + #undef STBIR_CEILF + #endif + #define STBIR_CEILF stbir_simd_ceilf + static stbir__inline float stbir_simd_ceilf(float x) // martins ceilf + { + #if defined(STBIR_AVX) || defined(__SSE4_1__) || defined(STBIR_SSE41) + __m128 t = _mm_set_ss(x); + return _mm_cvtss_f32( _mm_ceil_ss(t, t) ); + #else + __m128 f = _mm_set_ss(x); + __m128 t = _mm_cvtepi32_ps(_mm_cvttps_epi32(f)); + __m128 r = _mm_add_ss(t, _mm_and_ps(_mm_cmplt_ss(t, f), _mm_set_ss(1.0f))); + return _mm_cvtss_f32(r); + #endif + } + +#elif defined(STBIR_NEON) + + #include + + #define stbir__simdf float32x4_t + #define stbir__simdi uint32x4_t + + #define stbir_simdi_castf( reg ) vreinterpretq_u32_f32(reg) + #define stbir_simdf_casti( reg ) vreinterpretq_f32_u32(reg) + + #define stbir__simdf_load( reg, ptr ) (reg) = vld1q_f32( (float const*)(ptr) ) + #define stbir__simdi_load( reg, ptr ) (reg) = vld1q_u32( (uint32_t const*)(ptr) ) + #define stbir__simdf_load1( out, ptr ) (out) = vld1q_dup_f32( (float const*)(ptr) ) // top values can be random (not denormal or nan for perf) + #define stbir__simdi_load1( out, ptr ) (out) = vld1q_dup_u32( (uint32_t const*)(ptr) ) + #define stbir__simdf_load1z( out, ptr ) (out) = vld1q_lane_f32( (float const*)(ptr), vdupq_n_f32(0), 0 ) // top values must be zero + #define stbir__simdf_frep4( fvar ) vdupq_n_f32( fvar ) + #define stbir__simdf_load1frep4( out, fvar ) (out) = vdupq_n_f32( fvar ) + #define stbir__simdf_load2( out, ptr ) (out) = vcombine_f32( vld1_f32( (float const*)(ptr) ), vcreate_f32(0) ) // top values can be random (not denormal or nan for perf) + #define stbir__simdf_load2z( out, ptr ) (out) = vcombine_f32( vld1_f32( (float const*)(ptr) ), vcreate_f32(0) ) // top values must be zero + #define stbir__simdf_load2hmerge( out, reg, ptr ) (out) = vcombine_f32( vget_low_f32(reg), vld1_f32( (float const*)(ptr) ) ) + + #define stbir__simdf_zeroP() vdupq_n_f32(0) + #define stbir__simdf_zero( reg ) (reg) = vdupq_n_f32(0) + + #define stbir__simdf_store( ptr, reg ) vst1q_f32( (float*)(ptr), reg ) + #define stbir__simdf_store1( ptr, reg ) vst1q_lane_f32( (float*)(ptr), reg, 0) + #define stbir__simdf_store2( ptr, reg ) vst1_f32( (float*)(ptr), vget_low_f32(reg) ) + #define stbir__simdf_store2h( ptr, reg ) vst1_f32( (float*)(ptr), vget_high_f32(reg) ) + + #define stbir__simdi_store( ptr, reg ) vst1q_u32( (uint32_t*)(ptr), reg ) + #define stbir__simdi_store1( ptr, reg ) vst1q_lane_u32( (uint32_t*)(ptr), reg, 0 ) + #define stbir__simdi_store2( ptr, reg ) vst1_u32( (uint32_t*)(ptr), vget_low_u32(reg) ) + + #define stbir__prefetch( ptr ) + + #define stbir__simdi_expand_u8_to_u32(out0,out1,out2,out3,ireg) \ + { \ + uint16x8_t l = vmovl_u8( vget_low_u8 ( vreinterpretq_u8_u32(ireg) ) ); \ + uint16x8_t h = vmovl_u8( vget_high_u8( vreinterpretq_u8_u32(ireg) ) ); \ + out0 = vmovl_u16( vget_low_u16 ( l ) ); \ + out1 = vmovl_u16( vget_high_u16( l ) ); \ + out2 = vmovl_u16( vget_low_u16 ( h ) ); \ + out3 = vmovl_u16( vget_high_u16( h ) ); \ + } + + #define stbir__simdi_expand_u8_to_1u32(out,ireg) \ + { \ + uint16x8_t tmp = vmovl_u8( vget_low_u8( vreinterpretq_u8_u32(ireg) ) ); \ + out = vmovl_u16( vget_low_u16( tmp ) ); \ + } + + #define stbir__simdi_expand_u16_to_u32(out0,out1,ireg) \ + { \ + uint16x8_t tmp = vreinterpretq_u16_u32(ireg); \ + out0 = vmovl_u16( vget_low_u16 ( tmp ) ); \ + out1 = vmovl_u16( vget_high_u16( tmp ) ); \ + } + + #define stbir__simdf_convert_float_to_i32( i, f ) (i) = vreinterpretq_u32_s32( vcvtq_s32_f32(f) ) + #define stbir__simdf_convert_float_to_int( f ) vgetq_lane_s32(vcvtq_s32_f32(f), 0) + #define stbir__simdi_to_int( i ) (int)vgetq_lane_u32(i, 0) + #define stbir__simdf_convert_float_to_uint8( f ) ((unsigned char)vgetq_lane_s32(vcvtq_s32_f32(vmaxq_f32(vminq_f32(f,STBIR__CONSTF(STBIR_max_uint8_as_float)),vdupq_n_f32(0))), 0)) + #define stbir__simdf_convert_float_to_short( f ) ((unsigned short)vgetq_lane_s32(vcvtq_s32_f32(vmaxq_f32(vminq_f32(f,STBIR__CONSTF(STBIR_max_uint16_as_float)),vdupq_n_f32(0))), 0)) + #define stbir__simdi_convert_i32_to_float(out, ireg) (out) = vcvtq_f32_s32( vreinterpretq_s32_u32(ireg) ) + #define stbir__simdf_add( out, reg0, reg1 ) (out) = vaddq_f32( reg0, reg1 ) + #define stbir__simdf_mult( out, reg0, reg1 ) (out) = vmulq_f32( reg0, reg1 ) + #define stbir__simdf_mult_mem( out, reg, ptr ) (out) = vmulq_f32( reg, vld1q_f32( (float const*)(ptr) ) ) + #define stbir__simdf_mult1_mem( out, reg, ptr ) (out) = vmulq_f32( reg, vld1q_dup_f32( (float const*)(ptr) ) ) + #define stbir__simdf_add_mem( out, reg, ptr ) (out) = vaddq_f32( reg, vld1q_f32( (float const*)(ptr) ) ) + #define stbir__simdf_add1_mem( out, reg, ptr ) (out) = vaddq_f32( reg, vld1q_dup_f32( (float const*)(ptr) ) ) + + #ifdef STBIR_USE_FMA // not on by default to maintain bit identical simd to non-simd (and also x64 no madd to arm madd) + #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = vfmaq_f32( add, mul1, mul2 ) + #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = vfmaq_f32( add, mul1, mul2 ) + #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = vfmaq_f32( add, mul, vld1q_f32( (float const*)(ptr) ) ) + #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = vfmaq_f32( add, mul, vld1q_dup_f32( (float const*)(ptr) ) ) + #else + #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = vaddq_f32( add, vmulq_f32( mul1, mul2 ) ) + #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = vaddq_f32( add, vmulq_f32( mul1, mul2 ) ) + #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = vaddq_f32( add, vmulq_f32( mul, vld1q_f32( (float const*)(ptr) ) ) ) + #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = vaddq_f32( add, vmulq_f32( mul, vld1q_dup_f32( (float const*)(ptr) ) ) ) + #endif + + #define stbir__simdf_add1( out, reg0, reg1 ) (out) = vaddq_f32( reg0, reg1 ) + #define stbir__simdf_mult1( out, reg0, reg1 ) (out) = vmulq_f32( reg0, reg1 ) + + #define stbir__simdf_and( out, reg0, reg1 ) (out) = vreinterpretq_f32_u32( vandq_u32( vreinterpretq_u32_f32(reg0), vreinterpretq_u32_f32(reg1) ) ) + #define stbir__simdf_or( out, reg0, reg1 ) (out) = vreinterpretq_f32_u32( vorrq_u32( vreinterpretq_u32_f32(reg0), vreinterpretq_u32_f32(reg1) ) ) + + #define stbir__simdf_min( out, reg0, reg1 ) (out) = vminq_f32( reg0, reg1 ) + #define stbir__simdf_max( out, reg0, reg1 ) (out) = vmaxq_f32( reg0, reg1 ) + #define stbir__simdf_min1( out, reg0, reg1 ) (out) = vminq_f32( reg0, reg1 ) + #define stbir__simdf_max1( out, reg0, reg1 ) (out) = vmaxq_f32( reg0, reg1 ) + + #define stbir__simdf_0123ABCDto3ABx( out, reg0, reg1 ) (out) = vextq_f32( reg0, reg1, 3 ) + #define stbir__simdf_0123ABCDto23Ax( out, reg0, reg1 ) (out) = vextq_f32( reg0, reg1, 2 ) + + #define stbir__simdf_a1a1( out, alp, ones ) (out) = vzipq_f32(vuzpq_f32(alp, alp).val[1], ones).val[0] + #define stbir__simdf_1a1a( out, alp, ones ) (out) = vzipq_f32(ones, vuzpq_f32(alp, alp).val[0]).val[0] + + #if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) + + #define stbir__simdf_aaa1( out, alp, ones ) (out) = vcopyq_laneq_f32(vdupq_n_f32(vgetq_lane_f32(alp, 3)), 3, ones, 3) + #define stbir__simdf_1aaa( out, alp, ones ) (out) = vcopyq_laneq_f32(vdupq_n_f32(vgetq_lane_f32(alp, 0)), 0, ones, 0) + + #if defined( _MSC_VER ) && !defined(__clang__) + #define stbir_make16(a,b,c,d) vcombine_u8( \ + vcreate_u8( (4*a+0) | ((4*a+1)<<8) | ((4*a+2)<<16) | ((4*a+3)<<24) | \ + ((stbir_uint64)(4*b+0)<<32) | ((stbir_uint64)(4*b+1)<<40) | ((stbir_uint64)(4*b+2)<<48) | ((stbir_uint64)(4*b+3)<<56)), \ + vcreate_u8( (4*c+0) | ((4*c+1)<<8) | ((4*c+2)<<16) | ((4*c+3)<<24) | \ + ((stbir_uint64)(4*d+0)<<32) | ((stbir_uint64)(4*d+1)<<40) | ((stbir_uint64)(4*d+2)<<48) | ((stbir_uint64)(4*d+3)<<56) ) ) + #else + #define stbir_make16(a,b,c,d) (uint8x16_t){4*a+0,4*a+1,4*a+2,4*a+3,4*b+0,4*b+1,4*b+2,4*b+3,4*c+0,4*c+1,4*c+2,4*c+3,4*d+0,4*d+1,4*d+2,4*d+3} + #endif + + #define stbir__simdf_swiz( reg, one, two, three, four ) vreinterpretq_f32_u8( vqtbl1q_u8( vreinterpretq_u8_f32(reg), stbir_make16(one, two, three, four) ) ) + + #define stbir__simdi_16madd( out, reg0, reg1 ) \ + { \ + int16x8_t r0 = vreinterpretq_s16_u32(reg0); \ + int16x8_t r1 = vreinterpretq_s16_u32(reg1); \ + int32x4_t tmp0 = vmull_s16( vget_low_s16(r0), vget_low_s16(r1) ); \ + int32x4_t tmp1 = vmull_s16( vget_high_s16(r0), vget_high_s16(r1) ); \ + (out) = vreinterpretq_u32_s32( vpaddq_s32(tmp0, tmp1) ); \ + } + + #else + + #define stbir__simdf_aaa1( out, alp, ones ) (out) = vsetq_lane_f32(1.0f, vdupq_n_f32(vgetq_lane_f32(alp, 3)), 3) + #define stbir__simdf_1aaa( out, alp, ones ) (out) = vsetq_lane_f32(1.0f, vdupq_n_f32(vgetq_lane_f32(alp, 0)), 0) + + #if defined( _MSC_VER ) && !defined(__clang__) + static stbir__inline uint8x8x2_t stbir_make8x2(float32x4_t reg) + { + uint8x8x2_t r = { { vget_low_u8(vreinterpretq_u8_f32(reg)), vget_high_u8(vreinterpretq_u8_f32(reg)) } }; + return r; + } + #define stbir_make8(a,b) vcreate_u8( \ + (4*a+0) | ((4*a+1)<<8) | ((4*a+2)<<16) | ((4*a+3)<<24) | \ + ((stbir_uint64)(4*b+0)<<32) | ((stbir_uint64)(4*b+1)<<40) | ((stbir_uint64)(4*b+2)<<48) | ((stbir_uint64)(4*b+3)<<56) ) + #else + #define stbir_make8x2(reg) (uint8x8x2_t){ { vget_low_u8(vreinterpretq_u8_f32(reg)), vget_high_u8(vreinterpretq_u8_f32(reg)) } } + #define stbir_make8(a,b) (uint8x8_t){4*a+0,4*a+1,4*a+2,4*a+3,4*b+0,4*b+1,4*b+2,4*b+3} + #endif + + #define stbir__simdf_swiz( reg, one, two, three, four ) vreinterpretq_f32_u8( vcombine_u8( \ + vtbl2_u8( stbir_make8x2( reg ), stbir_make8( one, two ) ), \ + vtbl2_u8( stbir_make8x2( reg ), stbir_make8( three, four ) ) ) ) + + #define stbir__simdi_16madd( out, reg0, reg1 ) \ + { \ + int16x8_t r0 = vreinterpretq_s16_u32(reg0); \ + int16x8_t r1 = vreinterpretq_s16_u32(reg1); \ + int32x4_t tmp0 = vmull_s16( vget_low_s16(r0), vget_low_s16(r1) ); \ + int32x4_t tmp1 = vmull_s16( vget_high_s16(r0), vget_high_s16(r1) ); \ + int32x2_t out0 = vpadd_s32( vget_low_s32(tmp0), vget_high_s32(tmp0) ); \ + int32x2_t out1 = vpadd_s32( vget_low_s32(tmp1), vget_high_s32(tmp1) ); \ + (out) = vreinterpretq_u32_s32( vcombine_s32(out0, out1) ); \ + } + + #endif + + #define stbir__simdi_and( out, reg0, reg1 ) (out) = vandq_u32( reg0, reg1 ) + #define stbir__simdi_or( out, reg0, reg1 ) (out) = vorrq_u32( reg0, reg1 ) + + #define stbir__simdf_pack_to_8bytes(out,aa,bb) \ + { \ + float32x4_t af = vmaxq_f32( vminq_f32(aa,STBIR__CONSTF(STBIR_max_uint8_as_float) ), vdupq_n_f32(0) ); \ + float32x4_t bf = vmaxq_f32( vminq_f32(bb,STBIR__CONSTF(STBIR_max_uint8_as_float) ), vdupq_n_f32(0) ); \ + int16x4_t ai = vqmovn_s32( vcvtq_s32_f32( af ) ); \ + int16x4_t bi = vqmovn_s32( vcvtq_s32_f32( bf ) ); \ + uint8x8_t out8 = vqmovun_s16( vcombine_s16(ai, bi) ); \ + out = vreinterpretq_u32_u8( vcombine_u8(out8, out8) ); \ + } + + #define stbir__simdf_pack_to_8words(out,aa,bb) \ + { \ + float32x4_t af = vmaxq_f32( vminq_f32(aa,STBIR__CONSTF(STBIR_max_uint16_as_float) ), vdupq_n_f32(0) ); \ + float32x4_t bf = vmaxq_f32( vminq_f32(bb,STBIR__CONSTF(STBIR_max_uint16_as_float) ), vdupq_n_f32(0) ); \ + int32x4_t ai = vcvtq_s32_f32( af ); \ + int32x4_t bi = vcvtq_s32_f32( bf ); \ + out = vreinterpretq_u32_u16( vcombine_u16(vqmovun_s32(ai), vqmovun_s32(bi)) ); \ + } + + #define stbir__interleave_pack_and_store_16_u8( ptr, r0, r1, r2, r3 ) \ + { \ + int16x4x2_t tmp0 = vzip_s16( vqmovn_s32(vreinterpretq_s32_u32(r0)), vqmovn_s32(vreinterpretq_s32_u32(r2)) ); \ + int16x4x2_t tmp1 = vzip_s16( vqmovn_s32(vreinterpretq_s32_u32(r1)), vqmovn_s32(vreinterpretq_s32_u32(r3)) ); \ + uint8x8x2_t out = \ + { { \ + vqmovun_s16( vcombine_s16(tmp0.val[0], tmp0.val[1]) ), \ + vqmovun_s16( vcombine_s16(tmp1.val[0], tmp1.val[1]) ), \ + } }; \ + vst2_u8(ptr, out); \ + } + + #define stbir__simdf_load4_transposed( o0, o1, o2, o3, ptr ) \ + { \ + float32x4x4_t tmp = vld4q_f32(ptr); \ + o0 = tmp.val[0]; \ + o1 = tmp.val[1]; \ + o2 = tmp.val[2]; \ + o3 = tmp.val[3]; \ + } + + #define stbir__simdi_32shr( out, reg, imm ) out = vshrq_n_u32( reg, imm ) + + #if defined( _MSC_VER ) && !defined(__clang__) + #define STBIR__SIMDF_CONST(var, x) __declspec(align(8)) float var[] = { x, x, x, x } + #define STBIR__SIMDI_CONST(var, x) __declspec(align(8)) uint32_t var[] = { x, x, x, x } + #define STBIR__CONSTF(var) (*(const float32x4_t*)var) + #define STBIR__CONSTI(var) (*(const uint32x4_t*)var) + #else + #define STBIR__SIMDF_CONST(var, x) stbir__simdf var = { x, x, x, x } + #define STBIR__SIMDI_CONST(var, x) stbir__simdi var = { x, x, x, x } + #define STBIR__CONSTF(var) (var) + #define STBIR__CONSTI(var) (var) + #endif + + #ifdef STBIR_FLOORF + #undef STBIR_FLOORF + #endif + #define STBIR_FLOORF stbir_simd_floorf + static stbir__inline float stbir_simd_floorf(float x) + { + #if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) + return vget_lane_f32( vrndm_f32( vdup_n_f32(x) ), 0); + #else + float32x2_t f = vdup_n_f32(x); + float32x2_t t = vcvt_f32_s32(vcvt_s32_f32(f)); + uint32x2_t a = vclt_f32(f, t); + uint32x2_t b = vreinterpret_u32_f32(vdup_n_f32(-1.0f)); + float32x2_t r = vadd_f32(t, vreinterpret_f32_u32(vand_u32(a, b))); + return vget_lane_f32(r, 0); + #endif + } + + #ifdef STBIR_CEILF + #undef STBIR_CEILF + #endif + #define STBIR_CEILF stbir_simd_ceilf + static stbir__inline float stbir_simd_ceilf(float x) + { + #if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) + return vget_lane_f32( vrndp_f32( vdup_n_f32(x) ), 0); + #else + float32x2_t f = vdup_n_f32(x); + float32x2_t t = vcvt_f32_s32(vcvt_s32_f32(f)); + uint32x2_t a = vclt_f32(t, f); + uint32x2_t b = vreinterpret_u32_f32(vdup_n_f32(1.0f)); + float32x2_t r = vadd_f32(t, vreinterpret_f32_u32(vand_u32(a, b))); + return vget_lane_f32(r, 0); + #endif + } + + #define STBIR_SIMD + +#elif defined(STBIR_WASM) + + #include + + #define stbir__simdf v128_t + #define stbir__simdi v128_t + + #define stbir_simdi_castf( reg ) (reg) + #define stbir_simdf_casti( reg ) (reg) + + #define stbir__simdf_load( reg, ptr ) (reg) = wasm_v128_load( (void const*)(ptr) ) + #define stbir__simdi_load( reg, ptr ) (reg) = wasm_v128_load( (void const*)(ptr) ) + #define stbir__simdf_load1( out, ptr ) (out) = wasm_v128_load32_splat( (void const*)(ptr) ) // top values can be random (not denormal or nan for perf) + #define stbir__simdi_load1( out, ptr ) (out) = wasm_v128_load32_splat( (void const*)(ptr) ) + #define stbir__simdf_load1z( out, ptr ) (out) = wasm_v128_load32_zero( (void const*)(ptr) ) // top values must be zero + #define stbir__simdf_frep4( fvar ) wasm_f32x4_splat( fvar ) + #define stbir__simdf_load1frep4( out, fvar ) (out) = wasm_f32x4_splat( fvar ) + #define stbir__simdf_load2( out, ptr ) (out) = wasm_v128_load64_splat( (void const*)(ptr) ) // top values can be random (not denormal or nan for perf) + #define stbir__simdf_load2z( out, ptr ) (out) = wasm_v128_load64_zero( (void const*)(ptr) ) // top values must be zero + #define stbir__simdf_load2hmerge( out, reg, ptr ) (out) = wasm_v128_load64_lane( (void const*)(ptr), reg, 1 ) + + #define stbir__simdf_zeroP() wasm_f32x4_const_splat(0) + #define stbir__simdf_zero( reg ) (reg) = wasm_f32x4_const_splat(0) + + #define stbir__simdf_store( ptr, reg ) wasm_v128_store( (void*)(ptr), reg ) + #define stbir__simdf_store1( ptr, reg ) wasm_v128_store32_lane( (void*)(ptr), reg, 0 ) + #define stbir__simdf_store2( ptr, reg ) wasm_v128_store64_lane( (void*)(ptr), reg, 0 ) + #define stbir__simdf_store2h( ptr, reg ) wasm_v128_store64_lane( (void*)(ptr), reg, 1 ) + + #define stbir__simdi_store( ptr, reg ) wasm_v128_store( (void*)(ptr), reg ) + #define stbir__simdi_store1( ptr, reg ) wasm_v128_store32_lane( (void*)(ptr), reg, 0 ) + #define stbir__simdi_store2( ptr, reg ) wasm_v128_store64_lane( (void*)(ptr), reg, 0 ) + + #define stbir__prefetch( ptr ) + + #define stbir__simdi_expand_u8_to_u32(out0,out1,out2,out3,ireg) \ + { \ + v128_t l = wasm_u16x8_extend_low_u8x16 ( ireg ); \ + v128_t h = wasm_u16x8_extend_high_u8x16( ireg ); \ + out0 = wasm_u32x4_extend_low_u16x8 ( l ); \ + out1 = wasm_u32x4_extend_high_u16x8( l ); \ + out2 = wasm_u32x4_extend_low_u16x8 ( h ); \ + out3 = wasm_u32x4_extend_high_u16x8( h ); \ + } + + #define stbir__simdi_expand_u8_to_1u32(out,ireg) \ + { \ + v128_t tmp = wasm_u16x8_extend_low_u8x16(ireg); \ + out = wasm_u32x4_extend_low_u16x8(tmp); \ + } + + #define stbir__simdi_expand_u16_to_u32(out0,out1,ireg) \ + { \ + out0 = wasm_u32x4_extend_low_u16x8 ( ireg ); \ + out1 = wasm_u32x4_extend_high_u16x8( ireg ); \ + } + + #define stbir__simdf_convert_float_to_i32( i, f ) (i) = wasm_i32x4_trunc_sat_f32x4(f) + #define stbir__simdf_convert_float_to_int( f ) wasm_i32x4_extract_lane(wasm_i32x4_trunc_sat_f32x4(f), 0) + #define stbir__simdi_to_int( i ) wasm_i32x4_extract_lane(i, 0) + #define stbir__simdf_convert_float_to_uint8( f ) ((unsigned char)wasm_i32x4_extract_lane(wasm_i32x4_trunc_sat_f32x4(wasm_f32x4_max(wasm_f32x4_min(f,STBIR_max_uint8_as_float),wasm_f32x4_const_splat(0))), 0)) + #define stbir__simdf_convert_float_to_short( f ) ((unsigned short)wasm_i32x4_extract_lane(wasm_i32x4_trunc_sat_f32x4(wasm_f32x4_max(wasm_f32x4_min(f,STBIR_max_uint16_as_float),wasm_f32x4_const_splat(0))), 0)) + #define stbir__simdi_convert_i32_to_float(out, ireg) (out) = wasm_f32x4_convert_i32x4(ireg) + #define stbir__simdf_add( out, reg0, reg1 ) (out) = wasm_f32x4_add( reg0, reg1 ) + #define stbir__simdf_mult( out, reg0, reg1 ) (out) = wasm_f32x4_mul( reg0, reg1 ) + #define stbir__simdf_mult_mem( out, reg, ptr ) (out) = wasm_f32x4_mul( reg, wasm_v128_load( (void const*)(ptr) ) ) + #define stbir__simdf_mult1_mem( out, reg, ptr ) (out) = wasm_f32x4_mul( reg, wasm_v128_load32_splat( (void const*)(ptr) ) ) + #define stbir__simdf_add_mem( out, reg, ptr ) (out) = wasm_f32x4_add( reg, wasm_v128_load( (void const*)(ptr) ) ) + #define stbir__simdf_add1_mem( out, reg, ptr ) (out) = wasm_f32x4_add( reg, wasm_v128_load32_splat( (void const*)(ptr) ) ) + + #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = wasm_f32x4_add( add, wasm_f32x4_mul( mul1, mul2 ) ) + #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = wasm_f32x4_add( add, wasm_f32x4_mul( mul1, mul2 ) ) + #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = wasm_f32x4_add( add, wasm_f32x4_mul( mul, wasm_v128_load( (void const*)(ptr) ) ) ) + #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = wasm_f32x4_add( add, wasm_f32x4_mul( mul, wasm_v128_load32_splat( (void const*)(ptr) ) ) ) + + #define stbir__simdf_add1( out, reg0, reg1 ) (out) = wasm_f32x4_add( reg0, reg1 ) + #define stbir__simdf_mult1( out, reg0, reg1 ) (out) = wasm_f32x4_mul( reg0, reg1 ) + + #define stbir__simdf_and( out, reg0, reg1 ) (out) = wasm_v128_and( reg0, reg1 ) + #define stbir__simdf_or( out, reg0, reg1 ) (out) = wasm_v128_or( reg0, reg1 ) + + #define stbir__simdf_min( out, reg0, reg1 ) (out) = wasm_f32x4_min( reg0, reg1 ) + #define stbir__simdf_max( out, reg0, reg1 ) (out) = wasm_f32x4_max( reg0, reg1 ) + #define stbir__simdf_min1( out, reg0, reg1 ) (out) = wasm_f32x4_min( reg0, reg1 ) + #define stbir__simdf_max1( out, reg0, reg1 ) (out) = wasm_f32x4_max( reg0, reg1 ) + + #define stbir__simdf_0123ABCDto3ABx( out, reg0, reg1 ) (out) = wasm_i32x4_shuffle( reg0, reg1, 3, 4, 5, -1 ) + #define stbir__simdf_0123ABCDto23Ax( out, reg0, reg1 ) (out) = wasm_i32x4_shuffle( reg0, reg1, 2, 3, 4, -1 ) + + #define stbir__simdf_aaa1(out,alp,ones) (out) = wasm_i32x4_shuffle(alp, ones, 3, 3, 3, 4) + #define stbir__simdf_1aaa(out,alp,ones) (out) = wasm_i32x4_shuffle(alp, ones, 4, 0, 0, 0) + #define stbir__simdf_a1a1(out,alp,ones) (out) = wasm_i32x4_shuffle(alp, ones, 1, 4, 3, 4) + #define stbir__simdf_1a1a(out,alp,ones) (out) = wasm_i32x4_shuffle(alp, ones, 4, 0, 4, 2) + + #define stbir__simdf_swiz( reg, one, two, three, four ) wasm_i32x4_shuffle(reg, reg, one, two, three, four) + + #define stbir__simdi_and( out, reg0, reg1 ) (out) = wasm_v128_and( reg0, reg1 ) + #define stbir__simdi_or( out, reg0, reg1 ) (out) = wasm_v128_or( reg0, reg1 ) + #define stbir__simdi_16madd( out, reg0, reg1 ) (out) = wasm_i32x4_dot_i16x8( reg0, reg1 ) + + #define stbir__simdf_pack_to_8bytes(out,aa,bb) \ + { \ + v128_t af = wasm_f32x4_max( wasm_f32x4_min(aa, STBIR_max_uint8_as_float), wasm_f32x4_const_splat(0) ); \ + v128_t bf = wasm_f32x4_max( wasm_f32x4_min(bb, STBIR_max_uint8_as_float), wasm_f32x4_const_splat(0) ); \ + v128_t ai = wasm_i32x4_trunc_sat_f32x4( af ); \ + v128_t bi = wasm_i32x4_trunc_sat_f32x4( bf ); \ + v128_t out16 = wasm_i16x8_narrow_i32x4( ai, bi ); \ + out = wasm_u8x16_narrow_i16x8( out16, out16 ); \ + } + + #define stbir__simdf_pack_to_8words(out,aa,bb) \ + { \ + v128_t af = wasm_f32x4_max( wasm_f32x4_min(aa, STBIR_max_uint16_as_float), wasm_f32x4_const_splat(0)); \ + v128_t bf = wasm_f32x4_max( wasm_f32x4_min(bb, STBIR_max_uint16_as_float), wasm_f32x4_const_splat(0)); \ + v128_t ai = wasm_i32x4_trunc_sat_f32x4( af ); \ + v128_t bi = wasm_i32x4_trunc_sat_f32x4( bf ); \ + out = wasm_u16x8_narrow_i32x4( ai, bi ); \ + } + + #define stbir__interleave_pack_and_store_16_u8( ptr, r0, r1, r2, r3 ) \ + { \ + v128_t tmp0 = wasm_i16x8_narrow_i32x4(r0, r1); \ + v128_t tmp1 = wasm_i16x8_narrow_i32x4(r2, r3); \ + v128_t tmp = wasm_u8x16_narrow_i16x8(tmp0, tmp1); \ + tmp = wasm_i8x16_shuffle(tmp, tmp, 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15); \ + wasm_v128_store( (void*)(ptr), tmp); \ + } + + #define stbir__simdf_load4_transposed( o0, o1, o2, o3, ptr ) \ + { \ + v128_t t0 = wasm_v128_load( ptr ); \ + v128_t t1 = wasm_v128_load( ptr+4 ); \ + v128_t t2 = wasm_v128_load( ptr+8 ); \ + v128_t t3 = wasm_v128_load( ptr+12 ); \ + v128_t s0 = wasm_i32x4_shuffle(t0, t1, 0, 4, 2, 6); \ + v128_t s1 = wasm_i32x4_shuffle(t0, t1, 1, 5, 3, 7); \ + v128_t s2 = wasm_i32x4_shuffle(t2, t3, 0, 4, 2, 6); \ + v128_t s3 = wasm_i32x4_shuffle(t2, t3, 1, 5, 3, 7); \ + o0 = wasm_i32x4_shuffle(s0, s2, 0, 1, 4, 5); \ + o1 = wasm_i32x4_shuffle(s1, s3, 0, 1, 4, 5); \ + o2 = wasm_i32x4_shuffle(s0, s2, 2, 3, 6, 7); \ + o3 = wasm_i32x4_shuffle(s1, s3, 2, 3, 6, 7); \ + } + + #define stbir__simdi_32shr( out, reg, imm ) out = wasm_u32x4_shr( reg, imm ) + + typedef float stbir__f32x4 __attribute__((__vector_size__(16), __aligned__(16))); + #define STBIR__SIMDF_CONST(var, x) stbir__simdf var = (v128_t)(stbir__f32x4){ x, x, x, x } + #define STBIR__SIMDI_CONST(var, x) stbir__simdi var = { x, x, x, x } + #define STBIR__CONSTF(var) (var) + #define STBIR__CONSTI(var) (var) + + #ifdef STBIR_FLOORF + #undef STBIR_FLOORF + #endif + #define STBIR_FLOORF stbir_simd_floorf + static stbir__inline float stbir_simd_floorf(float x) + { + return wasm_f32x4_extract_lane( wasm_f32x4_floor( wasm_f32x4_splat(x) ), 0); + } + + #ifdef STBIR_CEILF + #undef STBIR_CEILF + #endif + #define STBIR_CEILF stbir_simd_ceilf + static stbir__inline float stbir_simd_ceilf(float x) + { + return wasm_f32x4_extract_lane( wasm_f32x4_ceil( wasm_f32x4_splat(x) ), 0); + } + + #define STBIR_SIMD + +#endif // SSE2/NEON/WASM + +#endif // NO SIMD + +#ifdef STBIR_SIMD8 + #define stbir__simdfX stbir__simdf8 + #define stbir__simdiX stbir__simdi8 + #define stbir__simdfX_load stbir__simdf8_load + #define stbir__simdiX_load stbir__simdi8_load + #define stbir__simdfX_mult stbir__simdf8_mult + #define stbir__simdfX_add_mem stbir__simdf8_add_mem + #define stbir__simdfX_madd_mem stbir__simdf8_madd_mem + #define stbir__simdfX_store stbir__simdf8_store + #define stbir__simdiX_store stbir__simdi8_store + #define stbir__simdf_frepX stbir__simdf8_frep8 + #define stbir__simdfX_madd stbir__simdf8_madd + #define stbir__simdfX_min stbir__simdf8_min + #define stbir__simdfX_max stbir__simdf8_max + #define stbir__simdfX_aaa1 stbir__simdf8_aaa1 + #define stbir__simdfX_1aaa stbir__simdf8_1aaa + #define stbir__simdfX_a1a1 stbir__simdf8_a1a1 + #define stbir__simdfX_1a1a stbir__simdf8_1a1a + #define stbir__simdfX_convert_float_to_i32 stbir__simdf8_convert_float_to_i32 + #define stbir__simdfX_pack_to_words stbir__simdf8_pack_to_16words + #define stbir__simdfX_zero stbir__simdf8_zero + #define STBIR_onesX STBIR_ones8 + #define STBIR_max_uint8_as_floatX STBIR_max_uint8_as_float8 + #define STBIR_max_uint16_as_floatX STBIR_max_uint16_as_float8 + #define STBIR_simd_point5X STBIR_simd_point58 + #define stbir__simdfX_float_count 8 + #define stbir__simdfX_0123to1230 stbir__simdf8_0123to12301230 + #define stbir__simdfX_0123to2103 stbir__simdf8_0123to21032103 + static const stbir__simdf8 STBIR_max_uint16_as_float_inverted8 = { stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted }; + static const stbir__simdf8 STBIR_max_uint8_as_float_inverted8 = { stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted }; + static const stbir__simdf8 STBIR_ones8 = { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }; + static const stbir__simdf8 STBIR_simd_point58 = { 0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5 }; + static const stbir__simdf8 STBIR_max_uint8_as_float8 = { stbir__max_uint8_as_float,stbir__max_uint8_as_float,stbir__max_uint8_as_float,stbir__max_uint8_as_float, stbir__max_uint8_as_float,stbir__max_uint8_as_float,stbir__max_uint8_as_float,stbir__max_uint8_as_float }; + static const stbir__simdf8 STBIR_max_uint16_as_float8 = { stbir__max_uint16_as_float,stbir__max_uint16_as_float,stbir__max_uint16_as_float,stbir__max_uint16_as_float, stbir__max_uint16_as_float,stbir__max_uint16_as_float,stbir__max_uint16_as_float,stbir__max_uint16_as_float }; +#else + #define stbir__simdfX stbir__simdf + #define stbir__simdiX stbir__simdi + #define stbir__simdfX_load stbir__simdf_load + #define stbir__simdiX_load stbir__simdi_load + #define stbir__simdfX_mult stbir__simdf_mult + #define stbir__simdfX_add_mem stbir__simdf_add_mem + #define stbir__simdfX_madd_mem stbir__simdf_madd_mem + #define stbir__simdfX_store stbir__simdf_store + #define stbir__simdiX_store stbir__simdi_store + #define stbir__simdf_frepX stbir__simdf_frep4 + #define stbir__simdfX_madd stbir__simdf_madd + #define stbir__simdfX_min stbir__simdf_min + #define stbir__simdfX_max stbir__simdf_max + #define stbir__simdfX_aaa1 stbir__simdf_aaa1 + #define stbir__simdfX_1aaa stbir__simdf_1aaa + #define stbir__simdfX_a1a1 stbir__simdf_a1a1 + #define stbir__simdfX_1a1a stbir__simdf_1a1a + #define stbir__simdfX_convert_float_to_i32 stbir__simdf_convert_float_to_i32 + #define stbir__simdfX_pack_to_words stbir__simdf_pack_to_8words + #define stbir__simdfX_zero stbir__simdf_zero + #define STBIR_onesX STBIR__CONSTF(STBIR_ones) + #define STBIR_simd_point5X STBIR__CONSTF(STBIR_simd_point5) + #define STBIR_max_uint8_as_floatX STBIR__CONSTF(STBIR_max_uint8_as_float) + #define STBIR_max_uint16_as_floatX STBIR__CONSTF(STBIR_max_uint16_as_float) + #define stbir__simdfX_float_count 4 + #define stbir__if_simdf8_cast_to_simdf4( val ) ( val ) + #define stbir__simdfX_0123to1230 stbir__simdf_0123to1230 + #define stbir__simdfX_0123to2103 stbir__simdf_0123to2103 +#endif + + +#if defined(STBIR_NEON) && !defined(_M_ARM) + + #if defined( _MSC_VER ) && !defined(__clang__) + typedef __int16 stbir__FP16; + #else + typedef float16_t stbir__FP16; + #endif + +#else // no NEON, or 32-bit ARM for MSVC + + typedef union stbir__FP16 + { + unsigned short u; + } stbir__FP16; + +#endif + +#if !defined(STBIR_NEON) && !defined(STBIR_FP16C) || defined(STBIR_NEON) && defined(_M_ARM) + + // Fabian's half float routines, see: https://gist.github.com/rygorous/2156668 + + static stbir__inline float stbir__half_to_float( stbir__FP16 h ) + { + static const stbir__FP32 magic = { (254 - 15) << 23 }; + static const stbir__FP32 was_infnan = { (127 + 16) << 23 }; + stbir__FP32 o; + + o.u = (h.u & 0x7fff) << 13; // exponent/mantissa bits + o.f *= magic.f; // exponent adjust + if (o.f >= was_infnan.f) // make sure Inf/NaN survive + o.u |= 255 << 23; + o.u |= (h.u & 0x8000) << 16; // sign bit + return o.f; + } + + static stbir__inline stbir__FP16 stbir__float_to_half(float val) + { + stbir__FP32 f32infty = { 255 << 23 }; + stbir__FP32 f16max = { (127 + 16) << 23 }; + stbir__FP32 denorm_magic = { ((127 - 15) + (23 - 10) + 1) << 23 }; + unsigned int sign_mask = 0x80000000u; + stbir__FP16 o = { 0 }; + stbir__FP32 f; + unsigned int sign; + + f.f = val; + sign = f.u & sign_mask; + f.u ^= sign; + + if (f.u >= f16max.u) // result is Inf or NaN (all exponent bits set) + o.u = (f.u > f32infty.u) ? 0x7e00 : 0x7c00; // NaN->qNaN and Inf->Inf + else // (De)normalized number or zero + { + if (f.u < (113 << 23)) // resulting FP16 is subnormal or zero + { + // use a magic value to align our 10 mantissa bits at the bottom of + // the float. as long as FP addition is round-to-nearest-even this + // just works. + f.f += denorm_magic.f; + // and one integer subtract of the bias later, we have our final float! + o.u = (unsigned short) ( f.u - denorm_magic.u ); + } + else + { + unsigned int mant_odd = (f.u >> 13) & 1; // resulting mantissa is odd + // update exponent, rounding bias part 1 + f.u = f.u + ((15u - 127) << 23) + 0xfff; + // rounding bias part 2 + f.u += mant_odd; + // take the bits! + o.u = (unsigned short) ( f.u >> 13 ); + } + } + + o.u |= sign >> 16; + return o; + } + +#endif + + +#if defined(STBIR_FP16C) + + #include + + static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input) + { + _mm256_storeu_ps( (float*)output, _mm256_cvtph_ps( _mm_loadu_si128( (__m128i const* )input ) ) ); + } + + static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input) + { + _mm_storeu_si128( (__m128i*)output, _mm256_cvtps_ph( _mm256_loadu_ps( input ), 0 ) ); + } + + static stbir__inline float stbir__half_to_float( stbir__FP16 h ) + { + return _mm_cvtss_f32( _mm_cvtph_ps( _mm_cvtsi32_si128( (int)h.u ) ) ); + } + + static stbir__inline stbir__FP16 stbir__float_to_half( float f ) + { + stbir__FP16 h; + h.u = (unsigned short) _mm_cvtsi128_si32( _mm_cvtps_ph( _mm_set_ss( f ), 0 ) ); + return h; + } + +#elif defined(STBIR_SSE2) + + // Fabian's half float routines, see: https://gist.github.com/rygorous/2156668 + stbir__inline static void stbir__half_to_float_SIMD(float * output, void const * input) + { + static const STBIR__SIMDI_CONST(mask_nosign, 0x7fff); + static const STBIR__SIMDI_CONST(smallest_normal, 0x0400); + static const STBIR__SIMDI_CONST(infinity, 0x7c00); + static const STBIR__SIMDI_CONST(expadjust_normal, (127 - 15) << 23); + static const STBIR__SIMDI_CONST(magic_denorm, 113 << 23); + + __m128i i = _mm_loadu_si128 ( (__m128i const*)(input) ); + __m128i h = _mm_unpacklo_epi16 ( i, _mm_setzero_si128() ); + __m128i mnosign = STBIR__CONSTI(mask_nosign); + __m128i eadjust = STBIR__CONSTI(expadjust_normal); + __m128i smallest = STBIR__CONSTI(smallest_normal); + __m128i infty = STBIR__CONSTI(infinity); + __m128i expmant = _mm_and_si128(mnosign, h); + __m128i justsign = _mm_xor_si128(h, expmant); + __m128i b_notinfnan = _mm_cmpgt_epi32(infty, expmant); + __m128i b_isdenorm = _mm_cmpgt_epi32(smallest, expmant); + __m128i shifted = _mm_slli_epi32(expmant, 13); + __m128i adj_infnan = _mm_andnot_si128(b_notinfnan, eadjust); + __m128i adjusted = _mm_add_epi32(eadjust, shifted); + __m128i den1 = _mm_add_epi32(shifted, STBIR__CONSTI(magic_denorm)); + __m128i adjusted2 = _mm_add_epi32(adjusted, adj_infnan); + __m128 den2 = _mm_sub_ps(_mm_castsi128_ps(den1), *(const __m128 *)&magic_denorm); + __m128 adjusted3 = _mm_and_ps(den2, _mm_castsi128_ps(b_isdenorm)); + __m128 adjusted4 = _mm_andnot_ps(_mm_castsi128_ps(b_isdenorm), _mm_castsi128_ps(adjusted2)); + __m128 adjusted5 = _mm_or_ps(adjusted3, adjusted4); + __m128i sign = _mm_slli_epi32(justsign, 16); + __m128 final = _mm_or_ps(adjusted5, _mm_castsi128_ps(sign)); + stbir__simdf_store( output + 0, final ); + + h = _mm_unpackhi_epi16 ( i, _mm_setzero_si128() ); + expmant = _mm_and_si128(mnosign, h); + justsign = _mm_xor_si128(h, expmant); + b_notinfnan = _mm_cmpgt_epi32(infty, expmant); + b_isdenorm = _mm_cmpgt_epi32(smallest, expmant); + shifted = _mm_slli_epi32(expmant, 13); + adj_infnan = _mm_andnot_si128(b_notinfnan, eadjust); + adjusted = _mm_add_epi32(eadjust, shifted); + den1 = _mm_add_epi32(shifted, STBIR__CONSTI(magic_denorm)); + adjusted2 = _mm_add_epi32(adjusted, adj_infnan); + den2 = _mm_sub_ps(_mm_castsi128_ps(den1), *(const __m128 *)&magic_denorm); + adjusted3 = _mm_and_ps(den2, _mm_castsi128_ps(b_isdenorm)); + adjusted4 = _mm_andnot_ps(_mm_castsi128_ps(b_isdenorm), _mm_castsi128_ps(adjusted2)); + adjusted5 = _mm_or_ps(adjusted3, adjusted4); + sign = _mm_slli_epi32(justsign, 16); + final = _mm_or_ps(adjusted5, _mm_castsi128_ps(sign)); + stbir__simdf_store( output + 4, final ); + + // ~38 SSE2 ops for 8 values + } + + // Fabian's round-to-nearest-even float to half + // ~48 SSE2 ops for 8 output + stbir__inline static void stbir__float_to_half_SIMD(void * output, float const * input) + { + static const STBIR__SIMDI_CONST(mask_sign, 0x80000000u); + static const STBIR__SIMDI_CONST(c_f16max, (127 + 16) << 23); // all FP32 values >=this round to +inf + static const STBIR__SIMDI_CONST(c_nanbit, 0x200); + static const STBIR__SIMDI_CONST(c_infty_as_fp16, 0x7c00); + static const STBIR__SIMDI_CONST(c_min_normal, (127 - 14) << 23); // smallest FP32 that yields a normalized FP16 + static const STBIR__SIMDI_CONST(c_subnorm_magic, ((127 - 15) + (23 - 10) + 1) << 23); + static const STBIR__SIMDI_CONST(c_normal_bias, 0xfff - ((127 - 15) << 23)); // adjust exponent and add mantissa rounding + + __m128 f = _mm_loadu_ps(input); + __m128 msign = _mm_castsi128_ps(STBIR__CONSTI(mask_sign)); + __m128 justsign = _mm_and_ps(msign, f); + __m128 absf = _mm_xor_ps(f, justsign); + __m128i absf_int = _mm_castps_si128(absf); // the cast is "free" (extra bypass latency, but no thruput hit) + __m128i f16max = STBIR__CONSTI(c_f16max); + __m128 b_isnan = _mm_cmpunord_ps(absf, absf); // is this a NaN? + __m128i b_isregular = _mm_cmpgt_epi32(f16max, absf_int); // (sub)normalized or special? + __m128i nanbit = _mm_and_si128(_mm_castps_si128(b_isnan), STBIR__CONSTI(c_nanbit)); + __m128i inf_or_nan = _mm_or_si128(nanbit, STBIR__CONSTI(c_infty_as_fp16)); // output for specials + + __m128i min_normal = STBIR__CONSTI(c_min_normal); + __m128i b_issub = _mm_cmpgt_epi32(min_normal, absf_int); + + // "result is subnormal" path + __m128 subnorm1 = _mm_add_ps(absf, _mm_castsi128_ps(STBIR__CONSTI(c_subnorm_magic))); // magic value to round output mantissa + __m128i subnorm2 = _mm_sub_epi32(_mm_castps_si128(subnorm1), STBIR__CONSTI(c_subnorm_magic)); // subtract out bias + + // "result is normal" path + __m128i mantoddbit = _mm_slli_epi32(absf_int, 31 - 13); // shift bit 13 (mantissa LSB) to sign + __m128i mantodd = _mm_srai_epi32(mantoddbit, 31); // -1 if FP16 mantissa odd, else 0 + + __m128i round1 = _mm_add_epi32(absf_int, STBIR__CONSTI(c_normal_bias)); + __m128i round2 = _mm_sub_epi32(round1, mantodd); // if mantissa LSB odd, bias towards rounding up (RTNE) + __m128i normal = _mm_srli_epi32(round2, 13); // rounded result + + // combine the two non-specials + __m128i nonspecial = _mm_or_si128(_mm_and_si128(subnorm2, b_issub), _mm_andnot_si128(b_issub, normal)); + + // merge in specials as well + __m128i joined = _mm_or_si128(_mm_and_si128(nonspecial, b_isregular), _mm_andnot_si128(b_isregular, inf_or_nan)); + + __m128i sign_shift = _mm_srai_epi32(_mm_castps_si128(justsign), 16); + __m128i final2, final= _mm_or_si128(joined, sign_shift); + + f = _mm_loadu_ps(input+4); + justsign = _mm_and_ps(msign, f); + absf = _mm_xor_ps(f, justsign); + absf_int = _mm_castps_si128(absf); // the cast is "free" (extra bypass latency, but no thruput hit) + b_isnan = _mm_cmpunord_ps(absf, absf); // is this a NaN? + b_isregular = _mm_cmpgt_epi32(f16max, absf_int); // (sub)normalized or special? + nanbit = _mm_and_si128(_mm_castps_si128(b_isnan), c_nanbit); + inf_or_nan = _mm_or_si128(nanbit, STBIR__CONSTI(c_infty_as_fp16)); // output for specials + + b_issub = _mm_cmpgt_epi32(min_normal, absf_int); + + // "result is subnormal" path + subnorm1 = _mm_add_ps(absf, _mm_castsi128_ps(STBIR__CONSTI(c_subnorm_magic))); // magic value to round output mantissa + subnorm2 = _mm_sub_epi32(_mm_castps_si128(subnorm1), STBIR__CONSTI(c_subnorm_magic)); // subtract out bias + + // "result is normal" path + mantoddbit = _mm_slli_epi32(absf_int, 31 - 13); // shift bit 13 (mantissa LSB) to sign + mantodd = _mm_srai_epi32(mantoddbit, 31); // -1 if FP16 mantissa odd, else 0 + + round1 = _mm_add_epi32(absf_int, STBIR__CONSTI(c_normal_bias)); + round2 = _mm_sub_epi32(round1, mantodd); // if mantissa LSB odd, bias towards rounding up (RTNE) + normal = _mm_srli_epi32(round2, 13); // rounded result + + // combine the two non-specials + nonspecial = _mm_or_si128(_mm_and_si128(subnorm2, b_issub), _mm_andnot_si128(b_issub, normal)); + + // merge in specials as well + joined = _mm_or_si128(_mm_and_si128(nonspecial, b_isregular), _mm_andnot_si128(b_isregular, inf_or_nan)); + + sign_shift = _mm_srai_epi32(_mm_castps_si128(justsign), 16); + final2 = _mm_or_si128(joined, sign_shift); + final = _mm_packs_epi32(final, final2); + stbir__simdi_store( output,final ); + } + +#elif defined(STBIR_WASM) || (defined(STBIR_NEON) && defined(_MSC_VER) && defined(_M_ARM)) // WASM or 32-bit ARM on MSVC/clang + + static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input) + { + for (int i=0; i<8; i++) + { + output[i] = stbir__half_to_float(input[i]); + } + } + + static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input) + { + for (int i=0; i<8; i++) + { + output[i] = stbir__float_to_half(input[i]); + } + } + +#elif defined(STBIR_NEON) && defined(_MSC_VER) && defined(_M_ARM64) && !defined(__clang__) // 64-bit ARM on MSVC (not clang) + + static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input) + { + float16x4_t in0 = vld1_f16(input + 0); + float16x4_t in1 = vld1_f16(input + 4); + vst1q_f32(output + 0, vcvt_f32_f16(in0)); + vst1q_f32(output + 4, vcvt_f32_f16(in1)); + } + + static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input) + { + float16x4_t out0 = vcvt_f16_f32(vld1q_f32(input + 0)); + float16x4_t out1 = vcvt_f16_f32(vld1q_f32(input + 4)); + vst1_f16(output+0, out0); + vst1_f16(output+4, out1); + } + + static stbir__inline float stbir__half_to_float( stbir__FP16 h ) + { + return vgetq_lane_f32(vcvt_f32_f16(vld1_dup_f16(&h)), 0); + } + + static stbir__inline stbir__FP16 stbir__float_to_half( float f ) + { + return vget_lane_f16(vcvt_f16_f32(vdupq_n_f32(f)), 0).n16_u16[0]; + } + +#elif defined(STBIR_NEON) // 64-bit ARM + + static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input) + { + float16x8_t in = vld1q_f16(input); + vst1q_f32(output + 0, vcvt_f32_f16(vget_low_f16(in))); + vst1q_f32(output + 4, vcvt_f32_f16(vget_high_f16(in))); + } + + static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input) + { + float16x4_t out0 = vcvt_f16_f32(vld1q_f32(input + 0)); + float16x4_t out1 = vcvt_f16_f32(vld1q_f32(input + 4)); + vst1q_f16(output, vcombine_f16(out0, out1)); + } + + static stbir__inline float stbir__half_to_float( stbir__FP16 h ) + { + return vgetq_lane_f32(vcvt_f32_f16(vdup_n_f16(h)), 0); + } + + static stbir__inline stbir__FP16 stbir__float_to_half( float f ) + { + return vget_lane_f16(vcvt_f16_f32(vdupq_n_f32(f)), 0); + } + +#endif + + +#ifdef STBIR_SIMD + +#define stbir__simdf_0123to3333( out, reg ) (out) = stbir__simdf_swiz( reg, 3,3,3,3 ) +#define stbir__simdf_0123to2222( out, reg ) (out) = stbir__simdf_swiz( reg, 2,2,2,2 ) +#define stbir__simdf_0123to1111( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,1,1 ) +#define stbir__simdf_0123to0000( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,0,0 ) +#define stbir__simdf_0123to0003( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,0,3 ) +#define stbir__simdf_0123to0001( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,0,1 ) +#define stbir__simdf_0123to1122( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,2,2 ) +#define stbir__simdf_0123to2333( out, reg ) (out) = stbir__simdf_swiz( reg, 2,3,3,3 ) +#define stbir__simdf_0123to0023( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,2,3 ) +#define stbir__simdf_0123to1230( out, reg ) (out) = stbir__simdf_swiz( reg, 1,2,3,0 ) +#define stbir__simdf_0123to2103( out, reg ) (out) = stbir__simdf_swiz( reg, 2,1,0,3 ) +#define stbir__simdf_0123to3210( out, reg ) (out) = stbir__simdf_swiz( reg, 3,2,1,0 ) +#define stbir__simdf_0123to2301( out, reg ) (out) = stbir__simdf_swiz( reg, 2,3,0,1 ) +#define stbir__simdf_0123to3012( out, reg ) (out) = stbir__simdf_swiz( reg, 3,0,1,2 ) +#define stbir__simdf_0123to0011( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,1,1 ) +#define stbir__simdf_0123to1100( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,0,0 ) +#define stbir__simdf_0123to2233( out, reg ) (out) = stbir__simdf_swiz( reg, 2,2,3,3 ) +#define stbir__simdf_0123to1133( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,3,3 ) +#define stbir__simdf_0123to0022( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,2,2 ) +#define stbir__simdf_0123to1032( out, reg ) (out) = stbir__simdf_swiz( reg, 1,0,3,2 ) + +typedef union stbir__simdi_u32 +{ + stbir_uint32 m128i_u32[4]; + int m128i_i32[4]; + stbir__simdi m128i_i128; +} stbir__simdi_u32; + +static const int STBIR_mask[9] = { 0,0,0,-1,-1,-1,0,0,0 }; + +static const STBIR__SIMDF_CONST(STBIR_max_uint8_as_float, stbir__max_uint8_as_float); +static const STBIR__SIMDF_CONST(STBIR_max_uint16_as_float, stbir__max_uint16_as_float); +static const STBIR__SIMDF_CONST(STBIR_max_uint8_as_float_inverted, stbir__max_uint8_as_float_inverted); +static const STBIR__SIMDF_CONST(STBIR_max_uint16_as_float_inverted, stbir__max_uint16_as_float_inverted); + +static const STBIR__SIMDF_CONST(STBIR_simd_point5, 0.5f); +static const STBIR__SIMDF_CONST(STBIR_ones, 1.0f); +static const STBIR__SIMDI_CONST(STBIR_almost_zero, (127 - 13) << 23); +static const STBIR__SIMDI_CONST(STBIR_almost_one, 0x3f7fffff); +static const STBIR__SIMDI_CONST(STBIR_mastissa_mask, 0xff); +static const STBIR__SIMDI_CONST(STBIR_topscale, 0x02000000); + +// Basically, in simd mode, we unroll the proper amount, and we don't want +// the non-simd remnant loops to be unroll because they only run a few times +// Adding this switch saves about 5K on clang which is Captain Unroll the 3rd. +#define STBIR_SIMD_STREAMOUT_PTR( star ) STBIR_STREAMOUT_PTR( star ) +#define STBIR_SIMD_NO_UNROLL(ptr) STBIR_NO_UNROLL(ptr) + +#ifdef STBIR_MEMCPY +#undef STBIR_MEMCPY +#endif +#define STBIR_MEMCPY stbir_simd_memcpy + +// override normal use of memcpy with much simpler copy (faster and smaller with our sized copies) +static void stbir_simd_memcpy( void * dest, void const * src, size_t bytes ) +{ + char STBIR_SIMD_STREAMOUT_PTR (*) d = (char*) dest; + char STBIR_SIMD_STREAMOUT_PTR( * ) d_end = ((char*) dest) + bytes; + ptrdiff_t ofs_to_src = (char*)src - (char*)dest; + + // check overlaps + STBIR_ASSERT( ( ( d >= ( (char*)src) + bytes ) ) || ( ( d + bytes ) <= (char*)src ) ); + + if ( bytes < (16*stbir__simdfX_float_count) ) + { + if ( bytes < 16 ) + { + if ( bytes ) + { + do + { + STBIR_SIMD_NO_UNROLL(d); + d[ 0 ] = d[ ofs_to_src ]; + ++d; + } while ( d < d_end ); + } + } + else + { + stbir__simdf x; + // do one unaligned to get us aligned for the stream out below + stbir__simdf_load( x, ( d + ofs_to_src ) ); + stbir__simdf_store( d, x ); + d = (char*)( ( ( (size_t)d ) + 16 ) & ~15 ); + + for(;;) + { + STBIR_SIMD_NO_UNROLL(d); + + if ( d > ( d_end - 16 ) ) + { + if ( d == d_end ) + return; + d = d_end - 16; + } + + stbir__simdf_load( x, ( d + ofs_to_src ) ); + stbir__simdf_store( d, x ); + d += 16; + } + } + } + else + { + stbir__simdfX x0,x1,x2,x3; + + // do one unaligned to get us aligned for the stream out below + stbir__simdfX_load( x0, ( d + ofs_to_src ) + 0*stbir__simdfX_float_count ); + stbir__simdfX_load( x1, ( d + ofs_to_src ) + 4*stbir__simdfX_float_count ); + stbir__simdfX_load( x2, ( d + ofs_to_src ) + 8*stbir__simdfX_float_count ); + stbir__simdfX_load( x3, ( d + ofs_to_src ) + 12*stbir__simdfX_float_count ); + stbir__simdfX_store( d + 0*stbir__simdfX_float_count, x0 ); + stbir__simdfX_store( d + 4*stbir__simdfX_float_count, x1 ); + stbir__simdfX_store( d + 8*stbir__simdfX_float_count, x2 ); + stbir__simdfX_store( d + 12*stbir__simdfX_float_count, x3 ); + d = (char*)( ( ( (size_t)d ) + (16*stbir__simdfX_float_count) ) & ~((16*stbir__simdfX_float_count)-1) ); + + for(;;) + { + STBIR_SIMD_NO_UNROLL(d); + + if ( d > ( d_end - (16*stbir__simdfX_float_count) ) ) + { + if ( d == d_end ) + return; + d = d_end - (16*stbir__simdfX_float_count); + } + + stbir__simdfX_load( x0, ( d + ofs_to_src ) + 0*stbir__simdfX_float_count ); + stbir__simdfX_load( x1, ( d + ofs_to_src ) + 4*stbir__simdfX_float_count ); + stbir__simdfX_load( x2, ( d + ofs_to_src ) + 8*stbir__simdfX_float_count ); + stbir__simdfX_load( x3, ( d + ofs_to_src ) + 12*stbir__simdfX_float_count ); + stbir__simdfX_store( d + 0*stbir__simdfX_float_count, x0 ); + stbir__simdfX_store( d + 4*stbir__simdfX_float_count, x1 ); + stbir__simdfX_store( d + 8*stbir__simdfX_float_count, x2 ); + stbir__simdfX_store( d + 12*stbir__simdfX_float_count, x3 ); + d += (16*stbir__simdfX_float_count); + } + } +} + +// memcpy that is specically intentionally overlapping (src is smaller then dest, so can be +// a normal forward copy, bytes is divisible by 4 and bytes is greater than or equal to +// the diff between dest and src) +static void stbir_overlapping_memcpy( void * dest, void const * src, size_t bytes ) +{ + char STBIR_SIMD_STREAMOUT_PTR (*) sd = (char*) src; + char STBIR_SIMD_STREAMOUT_PTR( * ) s_end = ((char*) src) + bytes; + ptrdiff_t ofs_to_dest = (char*)dest - (char*)src; + + if ( ofs_to_dest >= 16 ) // is the overlap more than 16 away? + { + char STBIR_SIMD_STREAMOUT_PTR( * ) s_end16 = ((char*) src) + (bytes&~15); + do + { + stbir__simdf x; + STBIR_SIMD_NO_UNROLL(sd); + stbir__simdf_load( x, sd ); + stbir__simdf_store( ( sd + ofs_to_dest ), x ); + sd += 16; + } while ( sd < s_end16 ); + + if ( sd == s_end ) + return; + } + + do + { + STBIR_SIMD_NO_UNROLL(sd); + *(int*)( sd + ofs_to_dest ) = *(int*) sd; + sd += 4; + } while ( sd < s_end ); +} + +#else // no SSE2 + +// when in scalar mode, we let unrolling happen, so this macro just does the __restrict +#define STBIR_SIMD_STREAMOUT_PTR( star ) STBIR_STREAMOUT_PTR( star ) +#define STBIR_SIMD_NO_UNROLL(ptr) + +#endif // SSE2 + + +#ifdef STBIR_PROFILE + +#if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(__SSE2__) || defined(STBIR_SSE) || defined( _M_IX86_FP ) || defined(__i386) || defined( __i386__ ) || defined( _M_IX86 ) || defined( _X86_ ) + +#ifdef _MSC_VER + + STBIRDEF stbir_uint64 __rdtsc(); + #define STBIR_PROFILE_FUNC() __rdtsc() + +#else // non msvc + + static stbir__inline stbir_uint64 STBIR_PROFILE_FUNC() + { + stbir_uint32 lo, hi; + asm volatile ("rdtsc" : "=a" (lo), "=d" (hi) ); + return ( ( (stbir_uint64) hi ) << 32 ) | ( (stbir_uint64) lo ); + } + +#endif // msvc + +#elif defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || defined(__ARM_NEON__) + +#if defined( _MSC_VER ) && !defined(__clang__) + + #define STBIR_PROFILE_FUNC() _ReadStatusReg(ARM64_CNTVCT) + +#else + + static stbir__inline stbir_uint64 STBIR_PROFILE_FUNC() + { + stbir_uint64 tsc; + asm volatile("mrs %0, cntvct_el0" : "=r" (tsc)); + return tsc; + } + +#endif + +#else // x64, arm + +#error Unknown platform for profiling. + +#endif //x64 and + + +#define STBIR_ONLY_PROFILE_GET_SPLIT_INFO ,stbir__per_split_info * split_info +#define STBIR_ONLY_PROFILE_SET_SPLIT_INFO ,split_info + +#define STBIR_ONLY_PROFILE_BUILD_GET_INFO ,stbir__info * profile_info +#define STBIR_ONLY_PROFILE_BUILD_SET_INFO ,profile_info + +// super light-weight micro profiler +#define STBIR_PROFILE_START_ll( info, wh ) { stbir_uint64 wh##thiszonetime = STBIR_PROFILE_FUNC(); stbir_uint64 * wh##save_parent_excluded_ptr = info->current_zone_excluded_ptr; stbir_uint64 wh##current_zone_excluded = 0; info->current_zone_excluded_ptr = &wh##current_zone_excluded; +#define STBIR_PROFILE_END_ll( info, wh ) wh##thiszonetime = STBIR_PROFILE_FUNC() - wh##thiszonetime; info->profile.named.wh += wh##thiszonetime - wh##current_zone_excluded; *wh##save_parent_excluded_ptr += wh##thiszonetime; info->current_zone_excluded_ptr = wh##save_parent_excluded_ptr; } +#define STBIR_PROFILE_FIRST_START_ll( info, wh ) { int i; info->current_zone_excluded_ptr = &info->profile.named.total; for(i=0;iprofile.array);i++) info->profile.array[i]=0; } STBIR_PROFILE_START_ll( info, wh ); +#define STBIR_PROFILE_CLEAR_EXTRAS_ll( info, num ) { int extra; for(extra=1;extra<(num);extra++) { int i; for(i=0;iprofile.array);i++) (info)[extra].profile.array[i]=0; } } + +// for thread data +#define STBIR_PROFILE_START( wh ) STBIR_PROFILE_START_ll( split_info, wh ) +#define STBIR_PROFILE_END( wh ) STBIR_PROFILE_END_ll( split_info, wh ) +#define STBIR_PROFILE_FIRST_START( wh ) STBIR_PROFILE_FIRST_START_ll( split_info, wh ) +#define STBIR_PROFILE_CLEAR_EXTRAS() STBIR_PROFILE_CLEAR_EXTRAS_ll( split_info, split_count ) + +// for build data +#define STBIR_PROFILE_BUILD_START( wh ) STBIR_PROFILE_START_ll( profile_info, wh ) +#define STBIR_PROFILE_BUILD_END( wh ) STBIR_PROFILE_END_ll( profile_info, wh ) +#define STBIR_PROFILE_BUILD_FIRST_START( wh ) STBIR_PROFILE_FIRST_START_ll( profile_info, wh ) +#define STBIR_PROFILE_BUILD_CLEAR( info ) { int i; for(i=0;iprofile.array);i++) info->profile.array[i]=0; } + +#else // no profile + +#define STBIR_ONLY_PROFILE_GET_SPLIT_INFO +#define STBIR_ONLY_PROFILE_SET_SPLIT_INFO + +#define STBIR_ONLY_PROFILE_BUILD_GET_INFO +#define STBIR_ONLY_PROFILE_BUILD_SET_INFO + +#define STBIR_PROFILE_START( wh ) +#define STBIR_PROFILE_END( wh ) +#define STBIR_PROFILE_FIRST_START( wh ) +#define STBIR_PROFILE_CLEAR_EXTRAS( ) + +#define STBIR_PROFILE_BUILD_START( wh ) +#define STBIR_PROFILE_BUILD_END( wh ) +#define STBIR_PROFILE_BUILD_FIRST_START( wh ) +#define STBIR_PROFILE_BUILD_CLEAR( info ) + +#endif // stbir_profile + +#ifndef STBIR_CEILF +#include +#if _MSC_VER <= 1200 // support VC6 for Sean +#define STBIR_CEILF(x) ((float)ceil((float)(x))) +#define STBIR_FLOORF(x) ((float)floor((float)(x))) +#else +#define STBIR_CEILF(x) ceilf(x) +#define STBIR_FLOORF(x) floorf(x) +#endif +#endif + +#ifndef STBIR_MEMCPY +// For memcpy +#include +#define STBIR_MEMCPY( dest, src, len ) memcpy( dest, src, len ) +#endif + +#ifndef STBIR_SIMD + +// memcpy that is specically intentionally overlapping (src is smaller then dest, so can be +// a normal forward copy, bytes is divisible by 4 and bytes is greater than or equal to +// the diff between dest and src) +static void stbir_overlapping_memcpy( void * dest, void const * src, size_t bytes ) +{ + char STBIR_SIMD_STREAMOUT_PTR (*) sd = (char*) src; + char STBIR_SIMD_STREAMOUT_PTR( * ) s_end = ((char*) src) + bytes; + ptrdiff_t ofs_to_dest = (char*)dest - (char*)src; + + if ( ofs_to_dest >= 8 ) // is the overlap more than 8 away? + { + char STBIR_SIMD_STREAMOUT_PTR( * ) s_end8 = ((char*) src) + (bytes&~7); + do + { + STBIR_NO_UNROLL(sd); + *(stbir_uint64*)( sd + ofs_to_dest ) = *(stbir_uint64*) sd; + sd += 8; + } while ( sd < s_end8 ); + + if ( sd == s_end ) + return; + } + + do + { + STBIR_NO_UNROLL(sd); + *(int*)( sd + ofs_to_dest ) = *(int*) sd; + sd += 4; + } while ( sd < s_end ); +} + +#endif + +static float stbir__filter_trapezoid(float x, float scale, void * user_data) +{ + float halfscale = scale / 2; + float t = 0.5f + halfscale; + STBIR_ASSERT(scale <= 1); + STBIR__UNUSED(user_data); + + if ( x < 0.0f ) x = -x; + + if (x >= t) + return 0.0f; + else + { + float r = 0.5f - halfscale; + if (x <= r) + return 1.0f; + else + return (t - x) / scale; + } +} + +static float stbir__support_trapezoid(float scale, void * user_data) +{ + STBIR__UNUSED(user_data); + return 0.5f + scale / 2.0f; +} + +static float stbir__filter_triangle(float x, float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + + if ( x < 0.0f ) x = -x; + + if (x <= 1.0f) + return 1.0f - x; + else + return 0.0f; +} + +static float stbir__filter_point(float x, float s, void * user_data) +{ + STBIR__UNUSED(x); + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + + return 1.0f; +} + +static float stbir__filter_cubic(float x, float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + + if ( x < 0.0f ) x = -x; + + if (x < 1.0f) + return (4.0f + x*x*(3.0f*x - 6.0f))/6.0f; + else if (x < 2.0f) + return (8.0f + x*(-12.0f + x*(6.0f - x)))/6.0f; + + return (0.0f); +} + +static float stbir__filter_catmullrom(float x, float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + + if ( x < 0.0f ) x = -x; + + if (x < 1.0f) + return 1.0f - x*x*(2.5f - 1.5f*x); + else if (x < 2.0f) + return 2.0f - x*(4.0f + x*(0.5f*x - 2.5f)); + + return (0.0f); +} + +static float stbir__filter_mitchell(float x, float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + + if ( x < 0.0f ) x = -x; + + if (x < 1.0f) + return (16.0f + x*x*(21.0f * x - 36.0f))/18.0f; + else if (x < 2.0f) + return (32.0f + x*(-60.0f + x*(36.0f - 7.0f*x)))/18.0f; + + return (0.0f); +} + +static float stbir__support_zero(float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + return 0; +} + +static float stbir__support_zeropoint5(float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + return 0.5f; +} + +static float stbir__support_one(float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + return 1; +} + +static float stbir__support_two(float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + return 2; +} + +// This is the maximum number of input samples that can affect an output sample +// with the given filter from the output pixel's perspective +static int stbir__get_filter_pixel_width(stbir__support_callback * support, float scale, void * user_data) +{ + STBIR_ASSERT(support != 0); + + if ( scale >= ( 1.0f-stbir__small_float ) ) // upscale + return (int)STBIR_CEILF(support(1.0f/scale,user_data) * 2.0f); + else + return (int)STBIR_CEILF(support(scale,user_data) * 2.0f / scale); +} + +// this is how many coefficents per run of the filter (which is different +// from the filter_pixel_width depending on if we are scattering or gathering) +static int stbir__get_coefficient_width(stbir__sampler * samp, int is_gather, void * user_data) +{ + float scale = samp->scale_info.scale; + stbir__support_callback * support = samp->filter_support; + + switch( is_gather ) + { + case 1: + return (int)STBIR_CEILF(support(1.0f / scale, user_data) * 2.0f); + case 2: + return (int)STBIR_CEILF(support(scale, user_data) * 2.0f / scale); + case 0: + return (int)STBIR_CEILF(support(scale, user_data) * 2.0f); + default: + STBIR_ASSERT( (is_gather >= 0 ) && (is_gather <= 2 ) ); + return 0; + } +} + +static int stbir__get_contributors(stbir__sampler * samp, int is_gather) +{ + if (is_gather) + return samp->scale_info.output_sub_size; + else + return (samp->scale_info.input_full_size + samp->filter_pixel_margin * 2); +} + +static int stbir__edge_zero_full( int n, int max ) +{ + STBIR__UNUSED(n); + STBIR__UNUSED(max); + return 0; // NOTREACHED +} + +static int stbir__edge_clamp_full( int n, int max ) +{ + if (n < 0) + return 0; + + if (n >= max) + return max - 1; + + return n; // NOTREACHED +} + +static int stbir__edge_reflect_full( int n, int max ) +{ + if (n < 0) + { + if (n > -max) + return -n; + else + return max - 1; + } + + if (n >= max) + { + int max2 = max * 2; + if (n >= max2) + return 0; + else + return max2 - n - 1; + } + + return n; // NOTREACHED +} + +static int stbir__edge_wrap_full( int n, int max ) +{ + if (n >= 0) + return (n % max); + else + { + int m = (-n) % max; + + if (m != 0) + m = max - m; + + return (m); + } +} + +typedef int stbir__edge_wrap_func( int n, int max ); +static stbir__edge_wrap_func * stbir__edge_wrap_slow[] = +{ + stbir__edge_clamp_full, // STBIR_EDGE_CLAMP + stbir__edge_reflect_full, // STBIR_EDGE_REFLECT + stbir__edge_wrap_full, // STBIR_EDGE_WRAP + stbir__edge_zero_full, // STBIR_EDGE_ZERO +}; + +stbir__inline static int stbir__edge_wrap(stbir_edge edge, int n, int max) +{ + // avoid per-pixel switch + if (n >= 0 && n < max) + return n; + return stbir__edge_wrap_slow[edge]( n, max ); +} + +#define STBIR__MERGE_RUNS_PIXEL_THRESHOLD 16 + +// get information on the extents of a sampler +static void stbir__get_extents( stbir__sampler * samp, stbir__extents * scanline_extents ) +{ + int j, stop; + int left_margin, right_margin; + int min_n = 0x7fffffff, max_n = -0x7fffffff; + int min_left = 0x7fffffff, max_left = -0x7fffffff; + int min_right = 0x7fffffff, max_right = -0x7fffffff; + stbir_edge edge = samp->edge; + stbir__contributors* contributors = samp->contributors; + int output_sub_size = samp->scale_info.output_sub_size; + int input_full_size = samp->scale_info.input_full_size; + int filter_pixel_margin = samp->filter_pixel_margin; + + STBIR_ASSERT( samp->is_gather ); + + stop = output_sub_size; + for (j = 0; j < stop; j++ ) + { + STBIR_ASSERT( contributors[j].n1 >= contributors[j].n0 ); + if ( contributors[j].n0 < min_n ) + { + min_n = contributors[j].n0; + stop = j + filter_pixel_margin; // if we find a new min, only scan another filter width + if ( stop > output_sub_size ) stop = output_sub_size; + } + } + + stop = 0; + for (j = output_sub_size - 1; j >= stop; j-- ) + { + STBIR_ASSERT( contributors[j].n1 >= contributors[j].n0 ); + if ( contributors[j].n1 > max_n ) + { + max_n = contributors[j].n1; + stop = j - filter_pixel_margin; // if we find a new max, only scan another filter width + if (stop<0) stop = 0; + } + } + + STBIR_ASSERT( scanline_extents->conservative.n0 <= min_n ); + STBIR_ASSERT( scanline_extents->conservative.n1 >= max_n ); + + // now calculate how much into the margins we really read + left_margin = 0; + if ( min_n < 0 ) + { + left_margin = -min_n; + min_n = 0; + } + + right_margin = 0; + if ( max_n >= input_full_size ) + { + right_margin = max_n - input_full_size + 1; + max_n = input_full_size - 1; + } + + // index 1 is margin pixel extents (how many pixels we hang over the edge) + scanline_extents->edge_sizes[0] = left_margin; + scanline_extents->edge_sizes[1] = right_margin; + + // index 2 is pixels read from the input + scanline_extents->spans[0].n0 = min_n; + scanline_extents->spans[0].n1 = max_n; + scanline_extents->spans[0].pixel_offset_for_input = min_n; + + // default to no other input range + scanline_extents->spans[1].n0 = 0; + scanline_extents->spans[1].n1 = -1; + scanline_extents->spans[1].pixel_offset_for_input = 0; + + // don't have to do edge calc for zero clamp + if ( edge == STBIR_EDGE_ZERO ) + return; + + // convert margin pixels to the pixels within the input (min and max) + for( j = -left_margin ; j < 0 ; j++ ) + { + int p = stbir__edge_wrap( edge, j, input_full_size ); + if ( p < min_left ) + min_left = p; + if ( p > max_left ) + max_left = p; + } + + for( j = input_full_size ; j < (input_full_size + right_margin) ; j++ ) + { + int p = stbir__edge_wrap( edge, j, input_full_size ); + if ( p < min_right ) + min_right = p; + if ( p > max_right ) + max_right = p; + } + + // merge the left margin pixel region if it connects within 4 pixels of main pixel region + if ( min_left != 0x7fffffff ) + { + if ( ( ( min_left <= min_n ) && ( ( max_left + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= min_n ) ) || + ( ( min_n <= min_left ) && ( ( max_n + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= max_left ) ) ) + { + scanline_extents->spans[0].n0 = min_n = stbir__min( min_n, min_left ); + scanline_extents->spans[0].n1 = max_n = stbir__max( max_n, max_left ); + scanline_extents->spans[0].pixel_offset_for_input = min_n; + left_margin = 0; + } + } + + // merge the right margin pixel region if it connects within 4 pixels of main pixel region + if ( min_right != 0x7fffffff ) + { + if ( ( ( min_right <= min_n ) && ( ( max_right + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= min_n ) ) || + ( ( min_n <= min_right ) && ( ( max_n + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= max_right ) ) ) + { + scanline_extents->spans[0].n0 = min_n = stbir__min( min_n, min_right ); + scanline_extents->spans[0].n1 = max_n = stbir__max( max_n, max_right ); + scanline_extents->spans[0].pixel_offset_for_input = min_n; + right_margin = 0; + } + } + + STBIR_ASSERT( scanline_extents->conservative.n0 <= min_n ); + STBIR_ASSERT( scanline_extents->conservative.n1 >= max_n ); + + // you get two ranges when you have the WRAP edge mode and you are doing just the a piece of the resize + // so you need to get a second run of pixels from the opposite side of the scanline (which you + // wouldn't need except for WRAP) + + + // if we can't merge the min_left range, add it as a second range + if ( ( left_margin ) && ( min_left != 0x7fffffff ) ) + { + stbir__span * newspan = scanline_extents->spans + 1; + STBIR_ASSERT( right_margin == 0 ); + if ( min_left < scanline_extents->spans[0].n0 ) + { + scanline_extents->spans[1].pixel_offset_for_input = scanline_extents->spans[0].n0; + scanline_extents->spans[1].n0 = scanline_extents->spans[0].n0; + scanline_extents->spans[1].n1 = scanline_extents->spans[0].n1; + --newspan; + } + newspan->pixel_offset_for_input = min_left; + newspan->n0 = -left_margin; + newspan->n1 = ( max_left - min_left ) - left_margin; + scanline_extents->edge_sizes[0] = 0; // don't need to copy the left margin, since we are directly decoding into the margin + return; + } + + // if we can't merge the min_left range, add it as a second range + if ( ( right_margin ) && ( min_right != 0x7fffffff ) ) + { + stbir__span * newspan = scanline_extents->spans + 1; + if ( min_right < scanline_extents->spans[0].n0 ) + { + scanline_extents->spans[1].pixel_offset_for_input = scanline_extents->spans[0].n0; + scanline_extents->spans[1].n0 = scanline_extents->spans[0].n0; + scanline_extents->spans[1].n1 = scanline_extents->spans[0].n1; + --newspan; + } + newspan->pixel_offset_for_input = min_right; + newspan->n0 = scanline_extents->spans[1].n1 + 1; + newspan->n1 = scanline_extents->spans[1].n1 + 1 + ( max_right - min_right ); + scanline_extents->edge_sizes[1] = 0; // don't need to copy the right margin, since we are directly decoding into the margin + return; + } +} + +static void stbir__calculate_in_pixel_range( int * first_pixel, int * last_pixel, float out_pixel_center, float out_filter_radius, float inv_scale, float out_shift, int input_size, stbir_edge edge ) +{ + int first, last; + float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius; + float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius; + + float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) * inv_scale; + float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) * inv_scale; + + first = (int)(STBIR_FLOORF(in_pixel_influence_lowerbound + 0.5f)); + last = (int)(STBIR_FLOORF(in_pixel_influence_upperbound - 0.5f)); + + if ( edge == STBIR_EDGE_WRAP ) + { + if ( first < -input_size ) + first = -input_size; + if ( last >= (input_size*2)) + last = (input_size*2) - 1; + } + + *first_pixel = first; + *last_pixel = last; +} + +static void stbir__calculate_coefficients_for_gather_upsample( float out_filter_radius, stbir__kernel_callback * kernel, stbir__scale_info * scale_info, int num_contributors, stbir__contributors* contributors, float* coefficient_group, int coefficient_width, stbir_edge edge, void * user_data ) +{ + int n, end; + float inv_scale = scale_info->inv_scale; + float out_shift = scale_info->pixel_shift; + int input_size = scale_info->input_full_size; + int numerator = scale_info->scale_numerator; + int polyphase = ( ( scale_info->scale_is_rational ) && ( numerator < num_contributors ) ); + + // Looping through out pixels + end = num_contributors; if ( polyphase ) end = numerator; + for (n = 0; n < end; n++) + { + int i; + int last_non_zero; + float out_pixel_center = (float)n + 0.5f; + float in_center_of_out = (out_pixel_center + out_shift) * inv_scale; + + int in_first_pixel, in_last_pixel; + + stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, out_pixel_center, out_filter_radius, inv_scale, out_shift, input_size, edge ); + + last_non_zero = -1; + for (i = 0; i <= in_last_pixel - in_first_pixel; i++) + { + float in_pixel_center = (float)(i + in_first_pixel) + 0.5f; + float coeff = kernel(in_center_of_out - in_pixel_center, inv_scale, user_data); + + // kill denormals + if ( ( ( coeff < stbir__small_float ) && ( coeff > -stbir__small_float ) ) ) + { + if ( i == 0 ) // if we're at the front, just eat zero contributors + { + STBIR_ASSERT ( ( in_last_pixel - in_first_pixel ) != 0 ); // there should be at least one contrib + ++in_first_pixel; + i--; + continue; + } + coeff = 0; // make sure is fully zero (should keep denormals away) + } + else + last_non_zero = i; + + coefficient_group[i] = coeff; + } + + in_last_pixel = last_non_zero+in_first_pixel; // kills trailing zeros + contributors->n0 = in_first_pixel; + contributors->n1 = in_last_pixel; + + STBIR_ASSERT(contributors->n1 >= contributors->n0); + + ++contributors; + coefficient_group += coefficient_width; + } +} + +static void stbir__insert_coeff( stbir__contributors * contribs, float * coeffs, int new_pixel, float new_coeff ) +{ + if ( new_pixel <= contribs->n1 ) // before the end + { + if ( new_pixel < contribs->n0 ) // before the front? + { + int j, o = contribs->n0 - new_pixel; + for ( j = contribs->n1 - contribs->n0 ; j <= 0 ; j-- ) + coeffs[ j + o ] = coeffs[ j ]; + for ( j = 1 ; j < o ; j-- ) + coeffs[ j ] = coeffs[ 0 ]; + coeffs[ 0 ] = new_coeff; + contribs->n0 = new_pixel; + } + else + { + coeffs[ new_pixel - contribs->n0 ] += new_coeff; + } + } + else + { + int j, e = new_pixel - contribs->n0; + for( j = ( contribs->n1 - contribs->n0 ) + 1 ; j < e ; j++ ) // clear in-betweens coeffs if there are any + coeffs[j] = 0; + + coeffs[ e ] = new_coeff; + contribs->n1 = new_pixel; + } +} + +static void stbir__calculate_out_pixel_range( int * first_pixel, int * last_pixel, float in_pixel_center, float in_pixels_radius, float scale, float out_shift, int out_size ) +{ + float in_pixel_influence_lowerbound = in_pixel_center - in_pixels_radius; + float in_pixel_influence_upperbound = in_pixel_center + in_pixels_radius; + float out_pixel_influence_lowerbound = in_pixel_influence_lowerbound * scale - out_shift; + float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale - out_shift; + int out_first_pixel = (int)(STBIR_FLOORF(out_pixel_influence_lowerbound + 0.5f)); + int out_last_pixel = (int)(STBIR_FLOORF(out_pixel_influence_upperbound - 0.5f)); + + if ( out_first_pixel < 0 ) + out_first_pixel = 0; + if ( out_last_pixel >= out_size ) + out_last_pixel = out_size - 1; + *first_pixel = out_first_pixel; + *last_pixel = out_last_pixel; +} + +static void stbir__calculate_coefficients_for_gather_downsample( int start, int end, float in_pixels_radius, stbir__kernel_callback * kernel, stbir__scale_info * scale_info, int coefficient_width, int num_contributors, stbir__contributors * contributors, float * coefficient_group, void * user_data ) +{ + int in_pixel; + int i; + int first_out_inited = -1; + float scale = scale_info->scale; + float out_shift = scale_info->pixel_shift; + int out_size = scale_info->output_sub_size; + int numerator = scale_info->scale_numerator; + int polyphase = ( ( scale_info->scale_is_rational ) && ( numerator < out_size ) ); + + STBIR__UNUSED(num_contributors); + + // Loop through the input pixels + for (in_pixel = start; in_pixel < end; in_pixel++) + { + float in_pixel_center = (float)in_pixel + 0.5f; + float out_center_of_in = in_pixel_center * scale - out_shift; + int out_first_pixel, out_last_pixel; + + stbir__calculate_out_pixel_range( &out_first_pixel, &out_last_pixel, in_pixel_center, in_pixels_radius, scale, out_shift, out_size ); + + if ( out_first_pixel > out_last_pixel ) + continue; + + // clamp or exit if we are using polyphase filtering, and the limit is up + if ( polyphase ) + { + // when polyphase, you only have to do coeffs up to the numerator count + if ( out_first_pixel == numerator ) + break; + + // don't do any extra work, clamp last pixel at numerator too + if ( out_last_pixel >= numerator ) + out_last_pixel = numerator - 1; + } + + for (i = 0; i <= out_last_pixel - out_first_pixel; i++) + { + float out_pixel_center = (float)(i + out_first_pixel) + 0.5f; + float x = out_pixel_center - out_center_of_in; + float coeff = kernel(x, scale, user_data) * scale; + + // kill the coeff if it's too small (avoid denormals) + if ( ( ( coeff < stbir__small_float ) && ( coeff > -stbir__small_float ) ) ) + coeff = 0.0f; + + { + int out = i + out_first_pixel; + float * coeffs = coefficient_group + out * coefficient_width; + stbir__contributors * contribs = contributors + out; + + // is this the first time this output pixel has been seen? Init it. + if ( out > first_out_inited ) + { + STBIR_ASSERT( out == ( first_out_inited + 1 ) ); // ensure we have only advanced one at time + first_out_inited = out; + contribs->n0 = in_pixel; + contribs->n1 = in_pixel; + coeffs[0] = coeff; + } + else + { + // insert on end (always in order) + if ( coeffs[0] == 0.0f ) // if the first coefficent is zero, then zap it for this coeffs + { + STBIR_ASSERT( ( in_pixel - contribs->n0 ) == 1 ); // ensure that when we zap, we're at the 2nd pos + contribs->n0 = in_pixel; + } + contribs->n1 = in_pixel; + STBIR_ASSERT( ( in_pixel - contribs->n0 ) < coefficient_width ); + coeffs[in_pixel - contribs->n0] = coeff; + } + } + } + } +} + +#ifdef STBIR_RENORMALIZE_IN_FLOAT +#define STBIR_RENORM_TYPE float +#else +#define STBIR_RENORM_TYPE double +#endif + +static void stbir__cleanup_gathered_coefficients( stbir_edge edge, stbir__filter_extent_info* filter_info, stbir__scale_info * scale_info, int num_contributors, stbir__contributors* contributors, float * coefficient_group, int coefficient_width ) +{ + int input_size = scale_info->input_full_size; + int input_last_n1 = input_size - 1; + int n, end; + int lowest = 0x7fffffff; + int highest = -0x7fffffff; + int widest = -1; + int numerator = scale_info->scale_numerator; + int denominator = scale_info->scale_denominator; + int polyphase = ( ( scale_info->scale_is_rational ) && ( numerator < num_contributors ) ); + float * coeffs; + stbir__contributors * contribs; + + // weight all the coeffs for each sample + coeffs = coefficient_group; + contribs = contributors; + end = num_contributors; if ( polyphase ) end = numerator; + for (n = 0; n < end; n++) + { + int i; + STBIR_RENORM_TYPE filter_scale, total_filter = 0; + int e; + + // add all contribs + e = contribs->n1 - contribs->n0; + for( i = 0 ; i <= e ; i++ ) + { + total_filter += (STBIR_RENORM_TYPE) coeffs[i]; + STBIR_ASSERT( ( coeffs[i] >= -2.0f ) && ( coeffs[i] <= 2.0f ) ); // check for wonky weights + } + + // rescale + if ( ( total_filter < stbir__small_float ) && ( total_filter > -stbir__small_float ) ) + { + // all coeffs are extremely small, just zero it + contribs->n1 = contribs->n0; + coeffs[0] = 0.0f; + } + else + { + // if the total isn't 1.0, rescale everything + if ( ( total_filter < (1.0f-stbir__small_float) ) || ( total_filter > (1.0f+stbir__small_float) ) ) + { + filter_scale = ((STBIR_RENORM_TYPE)1.0) / total_filter; + + // scale them all + for (i = 0; i <= e; i++) + coeffs[i] = (float) ( coeffs[i] * filter_scale ); + } + } + ++contribs; + coeffs += coefficient_width; + } + + // if we have a rational for the scale, we can exploit the polyphaseness to not calculate + // most of the coefficients, so we copy them here + if ( polyphase ) + { + stbir__contributors * prev_contribs = contributors; + stbir__contributors * cur_contribs = contributors + numerator; + + for( n = numerator ; n < num_contributors ; n++ ) + { + cur_contribs->n0 = prev_contribs->n0 + denominator; + cur_contribs->n1 = prev_contribs->n1 + denominator; + ++cur_contribs; + ++prev_contribs; + } + stbir_overlapping_memcpy( coefficient_group + numerator * coefficient_width, coefficient_group, ( num_contributors - numerator ) * coefficient_width * sizeof( coeffs[ 0 ] ) ); + } + + coeffs = coefficient_group; + contribs = contributors; + for (n = 0; n < num_contributors; n++) + { + int i; + + // in zero edge mode, just remove out of bounds contribs completely (since their weights are accounted for now) + if ( edge == STBIR_EDGE_ZERO ) + { + // shrink the right side if necessary + if ( contribs->n1 > input_last_n1 ) + contribs->n1 = input_last_n1; + + // shrink the left side + if ( contribs->n0 < 0 ) + { + int j, left, skips = 0; + + skips = -contribs->n0; + contribs->n0 = 0; + + // now move down the weights + left = contribs->n1 - contribs->n0 + 1; + if ( left > 0 ) + { + for( j = 0 ; j < left ; j++ ) + coeffs[ j ] = coeffs[ j + skips ]; + } + } + } + else if ( ( edge == STBIR_EDGE_CLAMP ) || ( edge == STBIR_EDGE_REFLECT ) ) + { + // for clamp and reflect, calculate the true inbounds position (based on edge type) and just add that to the existing weight + + // right hand side first + if ( contribs->n1 > input_last_n1 ) + { + int start = contribs->n0; + int endi = contribs->n1; + contribs->n1 = input_last_n1; + for( i = input_size; i <= endi; i++ ) + stbir__insert_coeff( contribs, coeffs, stbir__edge_wrap_slow[edge]( i, input_size ), coeffs[i-start] ); + } + + // now check left hand edge + if ( contribs->n0 < 0 ) + { + int save_n0; + float save_n0_coeff; + float * c = coeffs - ( contribs->n0 + 1 ); + + // reinsert the coeffs with it reflected or clamped (insert accumulates, if the coeffs exist) + for( i = -1 ; i > contribs->n0 ; i-- ) + stbir__insert_coeff( contribs, coeffs, stbir__edge_wrap_slow[edge]( i, input_size ), *c-- ); + save_n0 = contribs->n0; + save_n0_coeff = c[0]; // save it, since we didn't do the final one (i==n0), because there might be too many coeffs to hold (before we resize)! + + // now slide all the coeffs down (since we have accumulated them in the positive contribs) and reset the first contrib + contribs->n0 = 0; + for(i = 0 ; i <= contribs->n1 ; i++ ) + coeffs[i] = coeffs[i-save_n0]; + + // now that we have shrunk down the contribs, we insert the first one safely + stbir__insert_coeff( contribs, coeffs, stbir__edge_wrap_slow[edge]( save_n0, input_size ), save_n0_coeff ); + } + } + + if ( contribs->n0 <= contribs->n1 ) + { + int diff = contribs->n1 - contribs->n0 + 1; + while ( diff && ( coeffs[ diff-1 ] == 0.0f ) ) + --diff; + contribs->n1 = contribs->n0 + diff - 1; + + if ( contribs->n0 <= contribs->n1 ) + { + if ( contribs->n0 < lowest ) + lowest = contribs->n0; + if ( contribs->n1 > highest ) + highest = contribs->n1; + if ( diff > widest ) + widest = diff; + } + + // re-zero out unused coefficients (if any) + for( i = diff ; i < coefficient_width ; i++ ) + coeffs[i] = 0.0f; + } + + ++contribs; + coeffs += coefficient_width; + } + filter_info->lowest = lowest; + filter_info->highest = highest; + filter_info->widest = widest; +} + +#undef STBIR_RENORM_TYPE + +static int stbir__pack_coefficients( int num_contributors, stbir__contributors* contributors, float * coefficents, int coefficient_width, int widest, int row0, int row1 ) +{ + #define STBIR_MOVE_1( dest, src ) { STBIR_NO_UNROLL(dest); ((stbir_uint32*)(dest))[0] = ((stbir_uint32*)(src))[0]; } + #define STBIR_MOVE_2( dest, src ) { STBIR_NO_UNROLL(dest); ((stbir_uint64*)(dest))[0] = ((stbir_uint64*)(src))[0]; } + #ifdef STBIR_SIMD + #define STBIR_MOVE_4( dest, src ) { stbir__simdf t; STBIR_NO_UNROLL(dest); stbir__simdf_load( t, src ); stbir__simdf_store( dest, t ); } + #else + #define STBIR_MOVE_4( dest, src ) { STBIR_NO_UNROLL(dest); ((stbir_uint64*)(dest))[0] = ((stbir_uint64*)(src))[0]; ((stbir_uint64*)(dest))[1] = ((stbir_uint64*)(src))[1]; } + #endif + + int row_end = row1 + 1; + STBIR__UNUSED( row0 ); // only used in an assert + + if ( coefficient_width != widest ) + { + float * pc = coefficents; + float * coeffs = coefficents; + float * pc_end = coefficents + num_contributors * widest; + switch( widest ) + { + case 1: + do { + STBIR_MOVE_1( pc, coeffs ); + ++pc; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 2: + do { + STBIR_MOVE_2( pc, coeffs ); + pc += 2; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 3: + do { + STBIR_MOVE_2( pc, coeffs ); + STBIR_MOVE_1( pc+2, coeffs+2 ); + pc += 3; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 4: + do { + STBIR_MOVE_4( pc, coeffs ); + pc += 4; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 5: + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_1( pc+4, coeffs+4 ); + pc += 5; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 6: + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_2( pc+4, coeffs+4 ); + pc += 6; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 7: + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_2( pc+4, coeffs+4 ); + STBIR_MOVE_1( pc+6, coeffs+6 ); + pc += 7; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 8: + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_4( pc+4, coeffs+4 ); + pc += 8; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 9: + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_4( pc+4, coeffs+4 ); + STBIR_MOVE_1( pc+8, coeffs+8 ); + pc += 9; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 10: + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_4( pc+4, coeffs+4 ); + STBIR_MOVE_2( pc+8, coeffs+8 ); + pc += 10; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 11: + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_4( pc+4, coeffs+4 ); + STBIR_MOVE_2( pc+8, coeffs+8 ); + STBIR_MOVE_1( pc+10, coeffs+10 ); + pc += 11; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 12: + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_4( pc+4, coeffs+4 ); + STBIR_MOVE_4( pc+8, coeffs+8 ); + pc += 12; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + default: + do { + float * copy_end = pc + widest - 4; + float * c = coeffs; + do { + STBIR_NO_UNROLL( pc ); + STBIR_MOVE_4( pc, c ); + pc += 4; + c += 4; + } while ( pc <= copy_end ); + copy_end += 4; + while ( pc < copy_end ) + { + STBIR_MOVE_1( pc, c ); + ++pc; ++c; + } + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + } + } + + // some horizontal routines read one float off the end (which is then masked off), so put in a sentinal so we don't read an snan or denormal + coefficents[ widest * num_contributors ] = 8888.0f; + + // the minimum we might read for unrolled filters widths is 12. So, we need to + // make sure we never read outside the decode buffer, by possibly moving + // the sample area back into the scanline, and putting zeros weights first. + // we start on the right edge and check until we're well past the possible + // clip area (2*widest). + { + stbir__contributors * contribs = contributors + num_contributors - 1; + float * coeffs = coefficents + widest * ( num_contributors - 1 ); + + // go until no chance of clipping (this is usually less than 8 lops) + while ( ( contribs >= contributors ) && ( ( contribs->n0 + widest*2 ) >= row_end ) ) + { + // might we clip?? + if ( ( contribs->n0 + widest ) > row_end ) + { + int stop_range = widest; + + // if range is larger than 12, it will be handled by generic loops that can terminate on the exact length + // of this contrib n1, instead of a fixed widest amount - so calculate this + if ( widest > 12 ) + { + int mod; + + // how far will be read in the n_coeff loop (which depends on the widest count mod4); + mod = widest & 3; + stop_range = ( ( ( contribs->n1 - contribs->n0 + 1 ) - mod + 3 ) & ~3 ) + mod; + + // the n_coeff loops do a minimum amount of coeffs, so factor that in! + if ( stop_range < ( 8 + mod ) ) stop_range = 8 + mod; + } + + // now see if we still clip with the refined range + if ( ( contribs->n0 + stop_range ) > row_end ) + { + int new_n0 = row_end - stop_range; + int num = contribs->n1 - contribs->n0 + 1; + int backup = contribs->n0 - new_n0; + float * from_co = coeffs + num - 1; + float * to_co = from_co + backup; + + STBIR_ASSERT( ( new_n0 >= row0 ) && ( new_n0 < contribs->n0 ) ); + + // move the coeffs over + while( num ) + { + *to_co-- = *from_co--; + --num; + } + // zero new positions + while ( to_co >= coeffs ) + *to_co-- = 0; + // set new start point + contribs->n0 = new_n0; + if ( widest > 12 ) + { + int mod; + + // how far will be read in the n_coeff loop (which depends on the widest count mod4); + mod = widest & 3; + stop_range = ( ( ( contribs->n1 - contribs->n0 + 1 ) - mod + 3 ) & ~3 ) + mod; + + // the n_coeff loops do a minimum amount of coeffs, so factor that in! + if ( stop_range < ( 8 + mod ) ) stop_range = 8 + mod; + } + } + } + --contribs; + coeffs -= widest; + } + } + + return widest; + #undef STBIR_MOVE_1 + #undef STBIR_MOVE_2 + #undef STBIR_MOVE_4 +} + +static void stbir__calculate_filters( stbir__sampler * samp, stbir__sampler * other_axis_for_pivot, void * user_data STBIR_ONLY_PROFILE_BUILD_GET_INFO ) +{ + int n; + float scale = samp->scale_info.scale; + stbir__kernel_callback * kernel = samp->filter_kernel; + stbir__support_callback * support = samp->filter_support; + float inv_scale = samp->scale_info.inv_scale; + int input_full_size = samp->scale_info.input_full_size; + int gather_num_contributors = samp->num_contributors; + stbir__contributors* gather_contributors = samp->contributors; + float * gather_coeffs = samp->coefficients; + int gather_coefficient_width = samp->coefficient_width; + + switch ( samp->is_gather ) + { + case 1: // gather upsample + { + float out_pixels_radius = support(inv_scale,user_data) * scale; + + stbir__calculate_coefficients_for_gather_upsample( out_pixels_radius, kernel, &samp->scale_info, gather_num_contributors, gather_contributors, gather_coeffs, gather_coefficient_width, samp->edge, user_data ); + + STBIR_PROFILE_BUILD_START( cleanup ); + stbir__cleanup_gathered_coefficients( samp->edge, &samp->extent_info, &samp->scale_info, gather_num_contributors, gather_contributors, gather_coeffs, gather_coefficient_width ); + STBIR_PROFILE_BUILD_END( cleanup ); + } + break; + + case 0: // scatter downsample (only on vertical) + case 2: // gather downsample + { + float in_pixels_radius = support(scale,user_data) * inv_scale; + int filter_pixel_margin = samp->filter_pixel_margin; + int input_end = input_full_size + filter_pixel_margin; + + // if this is a scatter, we do a downsample gather to get the coeffs, and then pivot after + if ( !samp->is_gather ) + { + // check if we are using the same gather downsample on the horizontal as this vertical, + // if so, then we don't have to generate them, we can just pivot from the horizontal. + if ( other_axis_for_pivot ) + { + gather_contributors = other_axis_for_pivot->contributors; + gather_coeffs = other_axis_for_pivot->coefficients; + gather_coefficient_width = other_axis_for_pivot->coefficient_width; + gather_num_contributors = other_axis_for_pivot->num_contributors; + samp->extent_info.lowest = other_axis_for_pivot->extent_info.lowest; + samp->extent_info.highest = other_axis_for_pivot->extent_info.highest; + samp->extent_info.widest = other_axis_for_pivot->extent_info.widest; + goto jump_right_to_pivot; + } + + gather_contributors = samp->gather_prescatter_contributors; + gather_coeffs = samp->gather_prescatter_coefficients; + gather_coefficient_width = samp->gather_prescatter_coefficient_width; + gather_num_contributors = samp->gather_prescatter_num_contributors; + } + + stbir__calculate_coefficients_for_gather_downsample( -filter_pixel_margin, input_end, in_pixels_radius, kernel, &samp->scale_info, gather_coefficient_width, gather_num_contributors, gather_contributors, gather_coeffs, user_data ); + + STBIR_PROFILE_BUILD_START( cleanup ); + stbir__cleanup_gathered_coefficients( samp->edge, &samp->extent_info, &samp->scale_info, gather_num_contributors, gather_contributors, gather_coeffs, gather_coefficient_width ); + STBIR_PROFILE_BUILD_END( cleanup ); + + if ( !samp->is_gather ) + { + // if this is a scatter (vertical only), then we need to pivot the coeffs + stbir__contributors * scatter_contributors; + int highest_set; + + jump_right_to_pivot: + + STBIR_PROFILE_BUILD_START( pivot ); + + highest_set = (-filter_pixel_margin) - 1; + for (n = 0; n < gather_num_contributors; n++) + { + int k; + int gn0 = gather_contributors->n0, gn1 = gather_contributors->n1; + int scatter_coefficient_width = samp->coefficient_width; + float * scatter_coeffs = samp->coefficients + ( gn0 + filter_pixel_margin ) * scatter_coefficient_width; + float * g_coeffs = gather_coeffs; + scatter_contributors = samp->contributors + ( gn0 + filter_pixel_margin ); + + for (k = gn0 ; k <= gn1 ; k++ ) + { + float gc = *g_coeffs++; + + // skip zero and denormals - must skip zeros to avoid adding coeffs beyond scatter_coefficient_width + // (which happens when pivoting from horizontal, which might have dummy zeros) + if ( ( ( gc >= stbir__small_float ) || ( gc <= -stbir__small_float ) ) ) + { + if ( ( k > highest_set ) || ( scatter_contributors->n0 > scatter_contributors->n1 ) ) + { + { + // if we are skipping over several contributors, we need to clear the skipped ones + stbir__contributors * clear_contributors = samp->contributors + ( highest_set + filter_pixel_margin + 1); + while ( clear_contributors < scatter_contributors ) + { + clear_contributors->n0 = 0; + clear_contributors->n1 = -1; + ++clear_contributors; + } + } + scatter_contributors->n0 = n; + scatter_contributors->n1 = n; + scatter_coeffs[0] = gc; + highest_set = k; + } + else + { + stbir__insert_coeff( scatter_contributors, scatter_coeffs, n, gc ); + } + STBIR_ASSERT( ( scatter_contributors->n1 - scatter_contributors->n0 + 1 ) <= scatter_coefficient_width ); + } + ++scatter_contributors; + scatter_coeffs += scatter_coefficient_width; + } + + ++gather_contributors; + gather_coeffs += gather_coefficient_width; + } + + // now clear any unset contribs + { + stbir__contributors * clear_contributors = samp->contributors + ( highest_set + filter_pixel_margin + 1); + stbir__contributors * end_contributors = samp->contributors + samp->num_contributors; + while ( clear_contributors < end_contributors ) + { + clear_contributors->n0 = 0; + clear_contributors->n1 = -1; + ++clear_contributors; + } + } + + STBIR_PROFILE_BUILD_END( pivot ); + } + } + break; + } +} + + +//======================================================================================================== +// scanline decoders and encoders + +#define stbir__coder_min_num 1 +#define STB_IMAGE_RESIZE_DO_CODERS +#include STBIR__HEADER_FILENAME + +#define stbir__decode_suffix BGRA +#define stbir__decode_swizzle +#define stbir__decode_order0 2 +#define stbir__decode_order1 1 +#define stbir__decode_order2 0 +#define stbir__decode_order3 3 +#define stbir__encode_order0 2 +#define stbir__encode_order1 1 +#define stbir__encode_order2 0 +#define stbir__encode_order3 3 +#define stbir__coder_min_num 4 +#define STB_IMAGE_RESIZE_DO_CODERS +#include STBIR__HEADER_FILENAME + +#define stbir__decode_suffix ARGB +#define stbir__decode_swizzle +#define stbir__decode_order0 1 +#define stbir__decode_order1 2 +#define stbir__decode_order2 3 +#define stbir__decode_order3 0 +#define stbir__encode_order0 3 +#define stbir__encode_order1 0 +#define stbir__encode_order2 1 +#define stbir__encode_order3 2 +#define stbir__coder_min_num 4 +#define STB_IMAGE_RESIZE_DO_CODERS +#include STBIR__HEADER_FILENAME + +#define stbir__decode_suffix ABGR +#define stbir__decode_swizzle +#define stbir__decode_order0 3 +#define stbir__decode_order1 2 +#define stbir__decode_order2 1 +#define stbir__decode_order3 0 +#define stbir__encode_order0 3 +#define stbir__encode_order1 2 +#define stbir__encode_order2 1 +#define stbir__encode_order3 0 +#define stbir__coder_min_num 4 +#define STB_IMAGE_RESIZE_DO_CODERS +#include STBIR__HEADER_FILENAME + +#define stbir__decode_suffix AR +#define stbir__decode_swizzle +#define stbir__decode_order0 1 +#define stbir__decode_order1 0 +#define stbir__decode_order2 3 +#define stbir__decode_order3 2 +#define stbir__encode_order0 1 +#define stbir__encode_order1 0 +#define stbir__encode_order2 3 +#define stbir__encode_order3 2 +#define stbir__coder_min_num 2 +#define STB_IMAGE_RESIZE_DO_CODERS +#include STBIR__HEADER_FILENAME + + +// fancy alpha means we expand to keep both premultipied and non-premultiplied color channels +static void stbir__fancy_alpha_weight_4ch( float * out_buffer, int width_times_channels ) +{ + float STBIR_STREAMOUT_PTR(*) out = out_buffer; + float const * end_decode = out_buffer + ( width_times_channels / 4 ) * 7; // decode buffer aligned to end of out_buffer + float STBIR_STREAMOUT_PTR(*) decode = (float*)end_decode - width_times_channels; + + // fancy alpha is stored internally as R G B A Rpm Gpm Bpm + + #ifdef STBIR_SIMD + + #ifdef STBIR_SIMD8 + decode += 16; + while ( decode <= end_decode ) + { + stbir__simdf8 d0,d1,a0,a1,p0,p1; + STBIR_NO_UNROLL(decode); + stbir__simdf8_load( d0, decode-16 ); + stbir__simdf8_load( d1, decode-16+8 ); + stbir__simdf8_0123to33333333( a0, d0 ); + stbir__simdf8_0123to33333333( a1, d1 ); + stbir__simdf8_mult( p0, a0, d0 ); + stbir__simdf8_mult( p1, a1, d1 ); + stbir__simdf8_bot4s( a0, d0, p0 ); + stbir__simdf8_bot4s( a1, d1, p1 ); + stbir__simdf8_top4s( d0, d0, p0 ); + stbir__simdf8_top4s( d1, d1, p1 ); + stbir__simdf8_store ( out, a0 ); + stbir__simdf8_store ( out+7, d0 ); + stbir__simdf8_store ( out+14, a1 ); + stbir__simdf8_store ( out+21, d1 ); + decode += 16; + out += 28; + } + decode -= 16; + #else + decode += 8; + while ( decode <= end_decode ) + { + stbir__simdf d0,a0,d1,a1,p0,p1; + STBIR_NO_UNROLL(decode); + stbir__simdf_load( d0, decode-8 ); + stbir__simdf_load( d1, decode-8+4 ); + stbir__simdf_0123to3333( a0, d0 ); + stbir__simdf_0123to3333( a1, d1 ); + stbir__simdf_mult( p0, a0, d0 ); + stbir__simdf_mult( p1, a1, d1 ); + stbir__simdf_store ( out, d0 ); + stbir__simdf_store ( out+4, p0 ); + stbir__simdf_store ( out+7, d1 ); + stbir__simdf_store ( out+7+4, p1 ); + decode += 8; + out += 14; + } + decode -= 8; + #endif + + // might be one last odd pixel + #ifdef STBIR_SIMD8 + while ( decode < end_decode ) + #else + if ( decode < end_decode ) + #endif + { + stbir__simdf d,a,p; + stbir__simdf_load( d, decode ); + stbir__simdf_0123to3333( a, d ); + stbir__simdf_mult( p, a, d ); + stbir__simdf_store ( out, d ); + stbir__simdf_store ( out+4, p ); + decode += 4; + out += 7; + } + + #else + + while( decode < end_decode ) + { + float r = decode[0], g = decode[1], b = decode[2], alpha = decode[3]; + out[0] = r; + out[1] = g; + out[2] = b; + out[3] = alpha; + out[4] = r * alpha; + out[5] = g * alpha; + out[6] = b * alpha; + out += 7; + decode += 4; + } + + #endif +} + +static void stbir__fancy_alpha_weight_2ch( float * out_buffer, int width_times_channels ) +{ + float STBIR_STREAMOUT_PTR(*) out = out_buffer; + float const * end_decode = out_buffer + ( width_times_channels / 2 ) * 3; + float STBIR_STREAMOUT_PTR(*) decode = (float*)end_decode - width_times_channels; + + // for fancy alpha, turns into: [X A Xpm][X A Xpm],etc + + #ifdef STBIR_SIMD + + decode += 8; + if ( decode <= end_decode ) + { + do { + #ifdef STBIR_SIMD8 + stbir__simdf8 d0,a0,p0; + STBIR_NO_UNROLL(decode); + stbir__simdf8_load( d0, decode-8 ); + stbir__simdf8_0123to11331133( p0, d0 ); + stbir__simdf8_0123to00220022( a0, d0 ); + stbir__simdf8_mult( p0, p0, a0 ); + + stbir__simdf_store2( out, stbir__if_simdf8_cast_to_simdf4( d0 ) ); + stbir__simdf_store( out+2, stbir__if_simdf8_cast_to_simdf4( p0 ) ); + stbir__simdf_store2h( out+3, stbir__if_simdf8_cast_to_simdf4( d0 ) ); + + stbir__simdf_store2( out+6, stbir__simdf8_gettop4( d0 ) ); + stbir__simdf_store( out+8, stbir__simdf8_gettop4( p0 ) ); + stbir__simdf_store2h( out+9, stbir__simdf8_gettop4( d0 ) ); + #else + stbir__simdf d0,a0,d1,a1,p0,p1; + STBIR_NO_UNROLL(decode); + stbir__simdf_load( d0, decode-8 ); + stbir__simdf_load( d1, decode-8+4 ); + stbir__simdf_0123to1133( p0, d0 ); + stbir__simdf_0123to1133( p1, d1 ); + stbir__simdf_0123to0022( a0, d0 ); + stbir__simdf_0123to0022( a1, d1 ); + stbir__simdf_mult( p0, p0, a0 ); + stbir__simdf_mult( p1, p1, a1 ); + + stbir__simdf_store2( out, d0 ); + stbir__simdf_store( out+2, p0 ); + stbir__simdf_store2h( out+3, d0 ); + + stbir__simdf_store2( out+6, d1 ); + stbir__simdf_store( out+8, p1 ); + stbir__simdf_store2h( out+9, d1 ); + #endif + decode += 8; + out += 12; + } while ( decode <= end_decode ); + } + decode -= 8; + #endif + + while( decode < end_decode ) + { + float x = decode[0], y = decode[1]; + STBIR_SIMD_NO_UNROLL(decode); + out[0] = x; + out[1] = y; + out[2] = x * y; + out += 3; + decode += 2; + } +} + +static void stbir__fancy_alpha_unweight_4ch( float * encode_buffer, int width_times_channels ) +{ + float STBIR_SIMD_STREAMOUT_PTR(*) encode = encode_buffer; + float STBIR_SIMD_STREAMOUT_PTR(*) input = encode_buffer; + float const * end_output = encode_buffer + width_times_channels; + + // fancy RGBA is stored internally as R G B A Rpm Gpm Bpm + + do { + float alpha = input[3]; +#ifdef STBIR_SIMD + stbir__simdf i,ia; + STBIR_SIMD_NO_UNROLL(encode); + if ( alpha < stbir__small_float ) + { + stbir__simdf_load( i, input ); + stbir__simdf_store( encode, i ); + } + else + { + stbir__simdf_load1frep4( ia, 1.0f / alpha ); + stbir__simdf_load( i, input+4 ); + stbir__simdf_mult( i, i, ia ); + stbir__simdf_store( encode, i ); + encode[3] = alpha; + } +#else + if ( alpha < stbir__small_float ) + { + encode[0] = input[0]; + encode[1] = input[1]; + encode[2] = input[2]; + } + else + { + float ialpha = 1.0f / alpha; + encode[0] = input[4] * ialpha; + encode[1] = input[5] * ialpha; + encode[2] = input[6] * ialpha; + } + encode[3] = alpha; +#endif + + input += 7; + encode += 4; + } while ( encode < end_output ); +} + +// format: [X A Xpm][X A Xpm] etc +static void stbir__fancy_alpha_unweight_2ch( float * encode_buffer, int width_times_channels ) +{ + float STBIR_SIMD_STREAMOUT_PTR(*) encode = encode_buffer; + float STBIR_SIMD_STREAMOUT_PTR(*) input = encode_buffer; + float const * end_output = encode_buffer + width_times_channels; + + do { + float alpha = input[1]; + encode[0] = input[0]; + if ( alpha >= stbir__small_float ) + encode[0] = input[2] / alpha; + encode[1] = alpha; + + input += 3; + encode += 2; + } while ( encode < end_output ); +} + +static void stbir__simple_alpha_weight_4ch( float * decode_buffer, int width_times_channels ) +{ + float STBIR_STREAMOUT_PTR(*) decode = decode_buffer; + float const * end_decode = decode_buffer + width_times_channels; + + #ifdef STBIR_SIMD + { + decode += 2 * stbir__simdfX_float_count; + while ( decode <= end_decode ) + { + stbir__simdfX d0,a0,d1,a1; + STBIR_NO_UNROLL(decode); + stbir__simdfX_load( d0, decode-2*stbir__simdfX_float_count ); + stbir__simdfX_load( d1, decode-2*stbir__simdfX_float_count+stbir__simdfX_float_count ); + stbir__simdfX_aaa1( a0, d0, STBIR_onesX ); + stbir__simdfX_aaa1( a1, d1, STBIR_onesX ); + stbir__simdfX_mult( d0, d0, a0 ); + stbir__simdfX_mult( d1, d1, a1 ); + stbir__simdfX_store ( decode-2*stbir__simdfX_float_count, d0 ); + stbir__simdfX_store ( decode-2*stbir__simdfX_float_count+stbir__simdfX_float_count, d1 ); + decode += 2 * stbir__simdfX_float_count; + } + decode -= 2 * stbir__simdfX_float_count; + + // few last pixels remnants + #ifdef STBIR_SIMD8 + while ( decode < end_decode ) + #else + if ( decode < end_decode ) + #endif + { + stbir__simdf d,a; + stbir__simdf_load( d, decode ); + stbir__simdf_aaa1( a, d, STBIR__CONSTF(STBIR_ones) ); + stbir__simdf_mult( d, d, a ); + stbir__simdf_store ( decode, d ); + decode += 4; + } + } + + #else + + while( decode < end_decode ) + { + float alpha = decode[3]; + decode[0] *= alpha; + decode[1] *= alpha; + decode[2] *= alpha; + decode += 4; + } + + #endif +} + +static void stbir__simple_alpha_weight_2ch( float * decode_buffer, int width_times_channels ) +{ + float STBIR_STREAMOUT_PTR(*) decode = decode_buffer; + float const * end_decode = decode_buffer + width_times_channels; + + #ifdef STBIR_SIMD + decode += 2 * stbir__simdfX_float_count; + while ( decode <= end_decode ) + { + stbir__simdfX d0,a0,d1,a1; + STBIR_NO_UNROLL(decode); + stbir__simdfX_load( d0, decode-2*stbir__simdfX_float_count ); + stbir__simdfX_load( d1, decode-2*stbir__simdfX_float_count+stbir__simdfX_float_count ); + stbir__simdfX_a1a1( a0, d0, STBIR_onesX ); + stbir__simdfX_a1a1( a1, d1, STBIR_onesX ); + stbir__simdfX_mult( d0, d0, a0 ); + stbir__simdfX_mult( d1, d1, a1 ); + stbir__simdfX_store ( decode-2*stbir__simdfX_float_count, d0 ); + stbir__simdfX_store ( decode-2*stbir__simdfX_float_count+stbir__simdfX_float_count, d1 ); + decode += 2 * stbir__simdfX_float_count; + } + decode -= 2 * stbir__simdfX_float_count; + #endif + + while( decode < end_decode ) + { + float alpha = decode[1]; + STBIR_SIMD_NO_UNROLL(decode); + decode[0] *= alpha; + decode += 2; + } +} + +static void stbir__simple_alpha_unweight_4ch( float * encode_buffer, int width_times_channels ) +{ + float STBIR_SIMD_STREAMOUT_PTR(*) encode = encode_buffer; + float const * end_output = encode_buffer + width_times_channels; + + do { + float alpha = encode[3]; + +#ifdef STBIR_SIMD + stbir__simdf i,ia; + STBIR_SIMD_NO_UNROLL(encode); + if ( alpha >= stbir__small_float ) + { + stbir__simdf_load1frep4( ia, 1.0f / alpha ); + stbir__simdf_load( i, encode ); + stbir__simdf_mult( i, i, ia ); + stbir__simdf_store( encode, i ); + encode[3] = alpha; + } +#else + if ( alpha >= stbir__small_float ) + { + float ialpha = 1.0f / alpha; + encode[0] *= ialpha; + encode[1] *= ialpha; + encode[2] *= ialpha; + } +#endif + encode += 4; + } while ( encode < end_output ); +} + +static void stbir__simple_alpha_unweight_2ch( float * encode_buffer, int width_times_channels ) +{ + float STBIR_SIMD_STREAMOUT_PTR(*) encode = encode_buffer; + float const * end_output = encode_buffer + width_times_channels; + + do { + float alpha = encode[1]; + if ( alpha >= stbir__small_float ) + encode[0] /= alpha; + encode += 2; + } while ( encode < end_output ); +} + + +// only used in RGB->BGR or BGR->RGB +static void stbir__simple_flip_3ch( float * decode_buffer, int width_times_channels ) +{ + float STBIR_STREAMOUT_PTR(*) decode = decode_buffer; + float const * end_decode = decode_buffer + width_times_channels; + + decode += 12; + while( decode <= end_decode ) + { + float t0,t1,t2,t3; + STBIR_NO_UNROLL(decode); + t0 = decode[0]; t1 = decode[3]; t2 = decode[6]; t3 = decode[9]; + decode[0] = decode[2]; decode[3] = decode[5]; decode[6] = decode[8]; decode[9] = decode[11]; + decode[2] = t0; decode[5] = t1; decode[8] = t2; decode[11] = t3; + decode += 12; + } + decode -= 12; + + while( decode < end_decode ) + { + float t = decode[0]; + STBIR_NO_UNROLL(decode); + decode[0] = decode[2]; + decode[2] = t; + decode += 3; + } +} + + + +static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float * output_buffer STBIR_ONLY_PROFILE_GET_SPLIT_INFO ) +{ + int channels = stbir_info->channels; + int effective_channels = stbir_info->effective_channels; + int input_sample_in_bytes = stbir__type_size[stbir_info->input_type] * channels; + stbir_edge edge_horizontal = stbir_info->horizontal.edge; + stbir_edge edge_vertical = stbir_info->vertical.edge; + int row = stbir__edge_wrap(edge_vertical, n, stbir_info->vertical.scale_info.input_full_size); + const void* input_plane_data = ( (char *) stbir_info->input_data ) + (size_t)row * (size_t) stbir_info->input_stride_bytes; + stbir__span const * spans = stbir_info->scanline_extents.spans; + float* full_decode_buffer = output_buffer - stbir_info->scanline_extents.conservative.n0 * effective_channels; + + // if we are on edge_zero, and we get in here with an out of bounds n, then the calculate filters has failed + STBIR_ASSERT( !(edge_vertical == STBIR_EDGE_ZERO && (n < 0 || n >= stbir_info->vertical.scale_info.input_full_size)) ); + + do + { + float * decode_buffer; + void const * input_data; + float * end_decode; + int width_times_channels; + int width; + + if ( spans->n1 < spans->n0 ) + break; + + width = spans->n1 + 1 - spans->n0; + decode_buffer = full_decode_buffer + spans->n0 * effective_channels; + end_decode = full_decode_buffer + ( spans->n1 + 1 ) * effective_channels; + width_times_channels = width * channels; + + // read directly out of input plane by default + input_data = ( (char*)input_plane_data ) + spans->pixel_offset_for_input * input_sample_in_bytes; + + // if we have an input callback, call it to get the input data + if ( stbir_info->in_pixels_cb ) + { + // call the callback with a temp buffer (that they can choose to use or not). the temp is just right aligned memory in the decode_buffer itself + input_data = stbir_info->in_pixels_cb( ( (char*) end_decode ) - ( width * input_sample_in_bytes ), input_plane_data, width, spans->pixel_offset_for_input, row, stbir_info->user_data ); + } + + STBIR_PROFILE_START( decode ); + // convert the pixels info the float decode_buffer, (we index from end_decode, so that when channelsdecode_pixels( (float*)end_decode - width_times_channels, width_times_channels, input_data ); + STBIR_PROFILE_END( decode ); + + if (stbir_info->alpha_weight) + { + STBIR_PROFILE_START( alpha ); + stbir_info->alpha_weight( decode_buffer, width_times_channels ); + STBIR_PROFILE_END( alpha ); + } + + ++spans; + } while ( spans <= ( &stbir_info->scanline_extents.spans[1] ) ); + + // handle the edge_wrap filter (all other types are handled back out at the calculate_filter stage) + // basically the idea here is that if we have the whole scanline in memory, we don't redecode the + // wrapped edge pixels, and instead just memcpy them from the scanline into the edge positions + if ( ( edge_horizontal == STBIR_EDGE_WRAP ) && ( stbir_info->scanline_extents.edge_sizes[0] | stbir_info->scanline_extents.edge_sizes[1] ) ) + { + // this code only runs if we're in edge_wrap, and we're doing the entire scanline + int e, start_x[2]; + int input_full_size = stbir_info->horizontal.scale_info.input_full_size; + + start_x[0] = -stbir_info->scanline_extents.edge_sizes[0]; // left edge start x + start_x[1] = input_full_size; // right edge + + for( e = 0; e < 2 ; e++ ) + { + // do each margin + int margin = stbir_info->scanline_extents.edge_sizes[e]; + if ( margin ) + { + int x = start_x[e]; + float * marg = full_decode_buffer + x * effective_channels; + float const * src = full_decode_buffer + stbir__edge_wrap(edge_horizontal, x, input_full_size) * effective_channels; + STBIR_MEMCPY( marg, src, margin * effective_channels * sizeof(float) ); + } + } + } +} + + +//================= +// Do 1 channel horizontal routines + +#ifdef STBIR_SIMD + +#define stbir__1_coeff_only() \ + stbir__simdf tot,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1( c, hc ); \ + stbir__simdf_mult1_mem( tot, c, decode ); + +#define stbir__2_coeff_only() \ + stbir__simdf tot,c,d; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2z( c, hc ); \ + stbir__simdf_load2( d, decode ); \ + stbir__simdf_mult( tot, c, d ); \ + stbir__simdf_0123to1230( c, tot ); \ + stbir__simdf_add1( tot, tot, c ); + +#define stbir__3_coeff_only() \ + stbir__simdf tot,c,t; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( c, hc ); \ + stbir__simdf_mult_mem( tot, c, decode ); \ + stbir__simdf_0123to1230( c, tot ); \ + stbir__simdf_0123to2301( t, tot ); \ + stbir__simdf_add1( tot, tot, c ); \ + stbir__simdf_add1( tot, tot, t ); + +#define stbir__store_output_tiny() \ + stbir__simdf_store1( output, tot ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 1; + +#define stbir__4_coeff_start() \ + stbir__simdf tot,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( c, hc ); \ + stbir__simdf_mult_mem( tot, c, decode ); \ + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( c, hc + (ofs) ); \ + stbir__simdf_madd_mem( tot, tot, c, decode+(ofs) ); + +#define stbir__1_coeff_remnant( ofs ) \ + { stbir__simdf d; \ + stbir__simdf_load1z( c, hc + (ofs) ); \ + stbir__simdf_load1( d, decode + (ofs) ); \ + stbir__simdf_madd( tot, tot, d, c ); } + +#define stbir__2_coeff_remnant( ofs ) \ + { stbir__simdf d; \ + stbir__simdf_load2z( c, hc+(ofs) ); \ + stbir__simdf_load2( d, decode+(ofs) ); \ + stbir__simdf_madd( tot, tot, d, c ); } + +#define stbir__3_coeff_setup() \ + stbir__simdf mask; \ + stbir__simdf_load( mask, STBIR_mask + 3 ); + +#define stbir__3_coeff_remnant( ofs ) \ + stbir__simdf_load( c, hc+(ofs) ); \ + stbir__simdf_and( c, c, mask ); \ + stbir__simdf_madd_mem( tot, tot, c, decode+(ofs) ); + +#define stbir__store_output() \ + stbir__simdf_0123to2301( c, tot ); \ + stbir__simdf_add( tot, tot, c ); \ + stbir__simdf_0123to1230( c, tot ); \ + stbir__simdf_add1( tot, tot, c ); \ + stbir__simdf_store1( output, tot ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 1; + +#else + +#define stbir__1_coeff_only() \ + float tot; \ + tot = decode[0]*hc[0]; + +#define stbir__2_coeff_only() \ + float tot; \ + tot = decode[0] * hc[0]; \ + tot += decode[1] * hc[1]; + +#define stbir__3_coeff_only() \ + float tot; \ + tot = decode[0] * hc[0]; \ + tot += decode[1] * hc[1]; \ + tot += decode[2] * hc[2]; + +#define stbir__store_output_tiny() \ + output[0] = tot; \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 1; + +#define stbir__4_coeff_start() \ + float tot0,tot1,tot2,tot3; \ + tot0 = decode[0] * hc[0]; \ + tot1 = decode[1] * hc[1]; \ + tot2 = decode[2] * hc[2]; \ + tot3 = decode[3] * hc[3]; + +#define stbir__4_coeff_continue_from_4( ofs ) \ + tot0 += decode[0+(ofs)] * hc[0+(ofs)]; \ + tot1 += decode[1+(ofs)] * hc[1+(ofs)]; \ + tot2 += decode[2+(ofs)] * hc[2+(ofs)]; \ + tot3 += decode[3+(ofs)] * hc[3+(ofs)]; + +#define stbir__1_coeff_remnant( ofs ) \ + tot0 += decode[0+(ofs)] * hc[0+(ofs)]; + +#define stbir__2_coeff_remnant( ofs ) \ + tot0 += decode[0+(ofs)] * hc[0+(ofs)]; \ + tot1 += decode[1+(ofs)] * hc[1+(ofs)]; \ + +#define stbir__3_coeff_remnant( ofs ) \ + tot0 += decode[0+(ofs)] * hc[0+(ofs)]; \ + tot1 += decode[1+(ofs)] * hc[1+(ofs)]; \ + tot2 += decode[2+(ofs)] * hc[2+(ofs)]; + +#define stbir__store_output() \ + output[0] = (tot0+tot2)+(tot1+tot3); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 1; + +#endif + +#define STBIR__horizontal_channels 1 +#define STB_IMAGE_RESIZE_DO_HORIZONTALS +#include STBIR__HEADER_FILENAME + + +//================= +// Do 2 channel horizontal routines + +#ifdef STBIR_SIMD + +#define stbir__1_coeff_only() \ + stbir__simdf tot,c,d; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1z( c, hc ); \ + stbir__simdf_0123to0011( c, c ); \ + stbir__simdf_load2( d, decode ); \ + stbir__simdf_mult( tot, d, c ); + +#define stbir__2_coeff_only() \ + stbir__simdf tot,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2( c, hc ); \ + stbir__simdf_0123to0011( c, c ); \ + stbir__simdf_mult_mem( tot, c, decode ); + +#define stbir__3_coeff_only() \ + stbir__simdf tot,c,cs,d; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0011( c, cs ); \ + stbir__simdf_mult_mem( tot, c, decode ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_load2z( d, decode+4 ); \ + stbir__simdf_madd( tot, tot, d, c ); + +#define stbir__store_output_tiny() \ + stbir__simdf_0123to2301( c, tot ); \ + stbir__simdf_add( tot, tot, c ); \ + stbir__simdf_store2( output, tot ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 2; + +#ifdef STBIR_SIMD8 + +#define stbir__4_coeff_start() \ + stbir__simdf8 tot0,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc ); \ + stbir__simdf8_0123to00112233( c, cs ); \ + stbir__simdf8_mult_mem( tot0, c, decode ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00112233( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*2 ); + +#define stbir__1_coeff_remnant( ofs ) \ + { stbir__simdf t; \ + stbir__simdf_load1z( t, hc + (ofs) ); \ + stbir__simdf_0123to0011( t, t ); \ + stbir__simdf_mult_mem( t, t, decode+(ofs)*2 ); \ + stbir__simdf8_add4( tot0, tot0, t ); } + +#define stbir__2_coeff_remnant( ofs ) \ + { stbir__simdf t; \ + stbir__simdf_load2( t, hc + (ofs) ); \ + stbir__simdf_0123to0011( t, t ); \ + stbir__simdf_mult_mem( t, t, decode+(ofs)*2 ); \ + stbir__simdf8_add4( tot0, tot0, t ); } + +#define stbir__3_coeff_remnant( ofs ) \ + { stbir__simdf8 d; \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00112233( c, cs ); \ + stbir__simdf8_load6z( d, decode+(ofs)*2 ); \ + stbir__simdf8_madd( tot0, tot0, c, d ); } + +#define stbir__store_output() \ + { stbir__simdf t,d; \ + stbir__simdf8_add4halves( t, stbir__if_simdf8_cast_to_simdf4(tot0), tot0 ); \ + stbir__simdf_0123to2301( d, t ); \ + stbir__simdf_add( t, t, d ); \ + stbir__simdf_store2( output, t ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 2; } + +#else + +#define stbir__4_coeff_start() \ + stbir__simdf tot0,tot1,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0011( c, cs ); \ + stbir__simdf_mult_mem( tot0, c, decode ); \ + stbir__simdf_0123to2233( c, cs ); \ + stbir__simdf_mult_mem( tot1, c, decode+4 ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0011( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*2 ); \ + stbir__simdf_0123to2233( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*2+4 ); + +#define stbir__1_coeff_remnant( ofs ) \ + { stbir__simdf d; \ + stbir__simdf_load1z( cs, hc + (ofs) ); \ + stbir__simdf_0123to0011( c, cs ); \ + stbir__simdf_load2( d, decode + (ofs) * 2 ); \ + stbir__simdf_madd( tot0, tot0, d, c ); } + +#define stbir__2_coeff_remnant( ofs ) \ + stbir__simdf_load2( cs, hc + (ofs) ); \ + stbir__simdf_0123to0011( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*2 ); + +#define stbir__3_coeff_remnant( ofs ) \ + { stbir__simdf d; \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0011( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*2 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_load2z( d, decode + (ofs) * 2 + 4 ); \ + stbir__simdf_madd( tot1, tot1, d, c ); } + +#define stbir__store_output() \ + stbir__simdf_add( tot0, tot0, tot1 ); \ + stbir__simdf_0123to2301( c, tot0 ); \ + stbir__simdf_add( tot0, tot0, c ); \ + stbir__simdf_store2( output, tot0 ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 2; + +#endif + +#else + +#define stbir__1_coeff_only() \ + float tota,totb,c; \ + c = hc[0]; \ + tota = decode[0]*c; \ + totb = decode[1]*c; + +#define stbir__2_coeff_only() \ + float tota,totb,c; \ + c = hc[0]; \ + tota = decode[0]*c; \ + totb = decode[1]*c; \ + c = hc[1]; \ + tota += decode[2]*c; \ + totb += decode[3]*c; + +// this weird order of add matches the simd +#define stbir__3_coeff_only() \ + float tota,totb,c; \ + c = hc[0]; \ + tota = decode[0]*c; \ + totb = decode[1]*c; \ + c = hc[2]; \ + tota += decode[4]*c; \ + totb += decode[5]*c; \ + c = hc[1]; \ + tota += decode[2]*c; \ + totb += decode[3]*c; + +#define stbir__store_output_tiny() \ + output[0] = tota; \ + output[1] = totb; \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 2; + +#define stbir__4_coeff_start() \ + float tota0,tota1,tota2,tota3,totb0,totb1,totb2,totb3,c; \ + c = hc[0]; \ + tota0 = decode[0]*c; \ + totb0 = decode[1]*c; \ + c = hc[1]; \ + tota1 = decode[2]*c; \ + totb1 = decode[3]*c; \ + c = hc[2]; \ + tota2 = decode[4]*c; \ + totb2 = decode[5]*c; \ + c = hc[3]; \ + tota3 = decode[6]*c; \ + totb3 = decode[7]*c; + +#define stbir__4_coeff_continue_from_4( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*2]*c; \ + totb0 += decode[1+(ofs)*2]*c; \ + c = hc[1+(ofs)]; \ + tota1 += decode[2+(ofs)*2]*c; \ + totb1 += decode[3+(ofs)*2]*c; \ + c = hc[2+(ofs)]; \ + tota2 += decode[4+(ofs)*2]*c; \ + totb2 += decode[5+(ofs)*2]*c; \ + c = hc[3+(ofs)]; \ + tota3 += decode[6+(ofs)*2]*c; \ + totb3 += decode[7+(ofs)*2]*c; + +#define stbir__1_coeff_remnant( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*2] * c; \ + totb0 += decode[1+(ofs)*2] * c; + +#define stbir__2_coeff_remnant( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*2] * c; \ + totb0 += decode[1+(ofs)*2] * c; \ + c = hc[1+(ofs)]; \ + tota1 += decode[2+(ofs)*2] * c; \ + totb1 += decode[3+(ofs)*2] * c; + +#define stbir__3_coeff_remnant( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*2] * c; \ + totb0 += decode[1+(ofs)*2] * c; \ + c = hc[1+(ofs)]; \ + tota1 += decode[2+(ofs)*2] * c; \ + totb1 += decode[3+(ofs)*2] * c; \ + c = hc[2+(ofs)]; \ + tota2 += decode[4+(ofs)*2] * c; \ + totb2 += decode[5+(ofs)*2] * c; + +#define stbir__store_output() \ + output[0] = (tota0+tota2)+(tota1+tota3); \ + output[1] = (totb0+totb2)+(totb1+totb3); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 2; + +#endif + +#define STBIR__horizontal_channels 2 +#define STB_IMAGE_RESIZE_DO_HORIZONTALS +#include STBIR__HEADER_FILENAME + + +//================= +// Do 3 channel horizontal routines + +#ifdef STBIR_SIMD + +#define stbir__1_coeff_only() \ + stbir__simdf tot,c,d; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1z( c, hc ); \ + stbir__simdf_0123to0001( c, c ); \ + stbir__simdf_load( d, decode ); \ + stbir__simdf_mult( tot, d, c ); + +#define stbir__2_coeff_only() \ + stbir__simdf tot,c,cs,d; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_load( d, decode ); \ + stbir__simdf_mult( tot, d, c ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_load( d, decode+3 ); \ + stbir__simdf_madd( tot, tot, d, c ); + +#define stbir__3_coeff_only() \ + stbir__simdf tot,c,d,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_load( d, decode ); \ + stbir__simdf_mult( tot, d, c ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_load( d, decode+3 ); \ + stbir__simdf_madd( tot, tot, d, c ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_load( d, decode+6 ); \ + stbir__simdf_madd( tot, tot, d, c ); + +#define stbir__store_output_tiny() \ + stbir__simdf_store2( output, tot ); \ + stbir__simdf_0123to2301( tot, tot ); \ + stbir__simdf_store1( output+2, tot ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 3; + +#ifdef STBIR_SIMD8 + +// we're loading from the XXXYYY decode by -1 to get the XXXYYY into different halves of the AVX reg fyi +#define stbir__4_coeff_start() \ + stbir__simdf8 tot0,tot1,c,cs; stbir__simdf t; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc ); \ + stbir__simdf8_0123to00001111( c, cs ); \ + stbir__simdf8_mult_mem( tot0, c, decode - 1 ); \ + stbir__simdf8_0123to22223333( c, cs ); \ + stbir__simdf8_mult_mem( tot1, c, decode+6 - 1 ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00001111( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*3 - 1 ); \ + stbir__simdf8_0123to22223333( c, cs ); \ + stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*3 + 6 - 1 ); + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1rep4( t, hc + (ofs) ); \ + stbir__simdf8_madd_mem4( tot0, tot0, t, decode+(ofs)*3 - 1 ); + +#define stbir__2_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) - 2 ); \ + stbir__simdf8_0123to22223333( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*3 - 1 ); + + #define stbir__3_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00001111( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*3 - 1 ); \ + stbir__simdf8_0123to2222( t, cs ); \ + stbir__simdf8_madd_mem4( tot1, tot1, t, decode+(ofs)*3 + 6 - 1 ); + +#define stbir__store_output() \ + stbir__simdf8_add( tot0, tot0, tot1 ); \ + stbir__simdf_0123to1230( t, stbir__if_simdf8_cast_to_simdf4( tot0 ) ); \ + stbir__simdf8_add4halves( t, t, tot0 ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 3; \ + if ( output < output_end ) \ + { \ + stbir__simdf_store( output-3, t ); \ + continue; \ + } \ + { stbir__simdf tt; stbir__simdf_0123to2301( tt, t ); \ + stbir__simdf_store2( output-3, t ); \ + stbir__simdf_store1( output+2-3, tt ); } \ + break; + + +#else + +#define stbir__4_coeff_start() \ + stbir__simdf tot0,tot1,tot2,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0001( c, cs ); \ + stbir__simdf_mult_mem( tot0, c, decode ); \ + stbir__simdf_0123to1122( c, cs ); \ + stbir__simdf_mult_mem( tot1, c, decode+4 ); \ + stbir__simdf_0123to2333( c, cs ); \ + stbir__simdf_mult_mem( tot2, c, decode+8 ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0001( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 ); \ + stbir__simdf_0123to1122( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*3+4 ); \ + stbir__simdf_0123to2333( c, cs ); \ + stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*3+8 ); + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1z( c, hc + (ofs) ); \ + stbir__simdf_0123to0001( c, c ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 ); + +#define stbir__2_coeff_remnant( ofs ) \ + { stbir__simdf d; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2z( cs, hc + (ofs) ); \ + stbir__simdf_0123to0001( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 ); \ + stbir__simdf_0123to1122( c, cs ); \ + stbir__simdf_load2z( d, decode+(ofs)*3+4 ); \ + stbir__simdf_madd( tot1, tot1, c, d ); } + +#define stbir__3_coeff_remnant( ofs ) \ + { stbir__simdf d; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0001( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 ); \ + stbir__simdf_0123to1122( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*3+4 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_load1z( d, decode+(ofs)*3+8 ); \ + stbir__simdf_madd( tot2, tot2, c, d ); } + +#define stbir__store_output() \ + stbir__simdf_0123ABCDto3ABx( c, tot0, tot1 ); \ + stbir__simdf_0123ABCDto23Ax( cs, tot1, tot2 ); \ + stbir__simdf_0123to1230( tot2, tot2 ); \ + stbir__simdf_add( tot0, tot0, cs ); \ + stbir__simdf_add( c, c, tot2 ); \ + stbir__simdf_add( tot0, tot0, c ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 3; \ + if ( output < output_end ) \ + { \ + stbir__simdf_store( output-3, tot0 ); \ + continue; \ + } \ + stbir__simdf_0123to2301( tot1, tot0 ); \ + stbir__simdf_store2( output-3, tot0 ); \ + stbir__simdf_store1( output+2-3, tot1 ); \ + break; + +#endif + +#else + +#define stbir__1_coeff_only() \ + float tot0, tot1, tot2, c; \ + c = hc[0]; \ + tot0 = decode[0]*c; \ + tot1 = decode[1]*c; \ + tot2 = decode[2]*c; + +#define stbir__2_coeff_only() \ + float tot0, tot1, tot2, c; \ + c = hc[0]; \ + tot0 = decode[0]*c; \ + tot1 = decode[1]*c; \ + tot2 = decode[2]*c; \ + c = hc[1]; \ + tot0 += decode[3]*c; \ + tot1 += decode[4]*c; \ + tot2 += decode[5]*c; + +#define stbir__3_coeff_only() \ + float tot0, tot1, tot2, c; \ + c = hc[0]; \ + tot0 = decode[0]*c; \ + tot1 = decode[1]*c; \ + tot2 = decode[2]*c; \ + c = hc[1]; \ + tot0 += decode[3]*c; \ + tot1 += decode[4]*c; \ + tot2 += decode[5]*c; \ + c = hc[2]; \ + tot0 += decode[6]*c; \ + tot1 += decode[7]*c; \ + tot2 += decode[8]*c; + +#define stbir__store_output_tiny() \ + output[0] = tot0; \ + output[1] = tot1; \ + output[2] = tot2; \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 3; + +#define stbir__4_coeff_start() \ + float tota0,tota1,tota2,totb0,totb1,totb2,totc0,totc1,totc2,totd0,totd1,totd2,c; \ + c = hc[0]; \ + tota0 = decode[0]*c; \ + tota1 = decode[1]*c; \ + tota2 = decode[2]*c; \ + c = hc[1]; \ + totb0 = decode[3]*c; \ + totb1 = decode[4]*c; \ + totb2 = decode[5]*c; \ + c = hc[2]; \ + totc0 = decode[6]*c; \ + totc1 = decode[7]*c; \ + totc2 = decode[8]*c; \ + c = hc[3]; \ + totd0 = decode[9]*c; \ + totd1 = decode[10]*c; \ + totd2 = decode[11]*c; + +#define stbir__4_coeff_continue_from_4( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*3]*c; \ + tota1 += decode[1+(ofs)*3]*c; \ + tota2 += decode[2+(ofs)*3]*c; \ + c = hc[1+(ofs)]; \ + totb0 += decode[3+(ofs)*3]*c; \ + totb1 += decode[4+(ofs)*3]*c; \ + totb2 += decode[5+(ofs)*3]*c; \ + c = hc[2+(ofs)]; \ + totc0 += decode[6+(ofs)*3]*c; \ + totc1 += decode[7+(ofs)*3]*c; \ + totc2 += decode[8+(ofs)*3]*c; \ + c = hc[3+(ofs)]; \ + totd0 += decode[9+(ofs)*3]*c; \ + totd1 += decode[10+(ofs)*3]*c; \ + totd2 += decode[11+(ofs)*3]*c; + +#define stbir__1_coeff_remnant( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*3]*c; \ + tota1 += decode[1+(ofs)*3]*c; \ + tota2 += decode[2+(ofs)*3]*c; + +#define stbir__2_coeff_remnant( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*3]*c; \ + tota1 += decode[1+(ofs)*3]*c; \ + tota2 += decode[2+(ofs)*3]*c; \ + c = hc[1+(ofs)]; \ + totb0 += decode[3+(ofs)*3]*c; \ + totb1 += decode[4+(ofs)*3]*c; \ + totb2 += decode[5+(ofs)*3]*c; \ + +#define stbir__3_coeff_remnant( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*3]*c; \ + tota1 += decode[1+(ofs)*3]*c; \ + tota2 += decode[2+(ofs)*3]*c; \ + c = hc[1+(ofs)]; \ + totb0 += decode[3+(ofs)*3]*c; \ + totb1 += decode[4+(ofs)*3]*c; \ + totb2 += decode[5+(ofs)*3]*c; \ + c = hc[2+(ofs)]; \ + totc0 += decode[6+(ofs)*3]*c; \ + totc1 += decode[7+(ofs)*3]*c; \ + totc2 += decode[8+(ofs)*3]*c; + +#define stbir__store_output() \ + output[0] = (tota0+totc0)+(totb0+totd0); \ + output[1] = (tota1+totc1)+(totb1+totd1); \ + output[2] = (tota2+totc2)+(totb2+totd2); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 3; + +#endif + +#define STBIR__horizontal_channels 3 +#define STB_IMAGE_RESIZE_DO_HORIZONTALS +#include STBIR__HEADER_FILENAME + +//================= +// Do 4 channel horizontal routines + +#ifdef STBIR_SIMD + +#define stbir__1_coeff_only() \ + stbir__simdf tot,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1( c, hc ); \ + stbir__simdf_0123to0000( c, c ); \ + stbir__simdf_mult_mem( tot, c, decode ); + +#define stbir__2_coeff_only() \ + stbir__simdf tot,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_mult_mem( tot, c, decode ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot, tot, c, decode+4 ); + +#define stbir__3_coeff_only() \ + stbir__simdf tot,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_mult_mem( tot, c, decode ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot, tot, c, decode+4 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot, tot, c, decode+8 ); + +#define stbir__store_output_tiny() \ + stbir__simdf_store( output, tot ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 4; + +#ifdef STBIR_SIMD8 + +#define stbir__4_coeff_start() \ + stbir__simdf8 tot0,c,cs; stbir__simdf t; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc ); \ + stbir__simdf8_0123to00001111( c, cs ); \ + stbir__simdf8_mult_mem( tot0, c, decode ); \ + stbir__simdf8_0123to22223333( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+8 ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00001111( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); \ + stbir__simdf8_0123to22223333( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4+8 ); + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1rep4( t, hc + (ofs) ); \ + stbir__simdf8_madd_mem4( tot0, tot0, t, decode+(ofs)*4 ); + +#define stbir__2_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) - 2 ); \ + stbir__simdf8_0123to22223333( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); + + #define stbir__3_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00001111( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); \ + stbir__simdf8_0123to2222( t, cs ); \ + stbir__simdf8_madd_mem4( tot0, tot0, t, decode+(ofs)*4+8 ); + +#define stbir__store_output() \ + stbir__simdf8_add4halves( t, stbir__if_simdf8_cast_to_simdf4(tot0), tot0 ); \ + stbir__simdf_store( output, t ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 4; + +#else + +#define stbir__4_coeff_start() \ + stbir__simdf tot0,tot1,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_mult_mem( tot0, c, decode ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_mult_mem( tot1, c, decode+4 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+8 ); \ + stbir__simdf_0123to3333( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+12 ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+4 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4+8 ); \ + stbir__simdf_0123to3333( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+12 ); + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1( c, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, c ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); + +#define stbir__2_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2( cs, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+4 ); + +#define stbir__3_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+4 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4+8 ); + +#define stbir__store_output() \ + stbir__simdf_add( tot0, tot0, tot1 ); \ + stbir__simdf_store( output, tot0 ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 4; + +#endif + +#else + +#define stbir__1_coeff_only() \ + float p0,p1,p2,p3,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0]; \ + p0 = decode[0] * c; \ + p1 = decode[1] * c; \ + p2 = decode[2] * c; \ + p3 = decode[3] * c; + +#define stbir__2_coeff_only() \ + float p0,p1,p2,p3,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0]; \ + p0 = decode[0] * c; \ + p1 = decode[1] * c; \ + p2 = decode[2] * c; \ + p3 = decode[3] * c; \ + c = hc[1]; \ + p0 += decode[4] * c; \ + p1 += decode[5] * c; \ + p2 += decode[6] * c; \ + p3 += decode[7] * c; + +#define stbir__3_coeff_only() \ + float p0,p1,p2,p3,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0]; \ + p0 = decode[0] * c; \ + p1 = decode[1] * c; \ + p2 = decode[2] * c; \ + p3 = decode[3] * c; \ + c = hc[1]; \ + p0 += decode[4] * c; \ + p1 += decode[5] * c; \ + p2 += decode[6] * c; \ + p3 += decode[7] * c; \ + c = hc[2]; \ + p0 += decode[8] * c; \ + p1 += decode[9] * c; \ + p2 += decode[10] * c; \ + p3 += decode[11] * c; + +#define stbir__store_output_tiny() \ + output[0] = p0; \ + output[1] = p1; \ + output[2] = p2; \ + output[3] = p3; \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 4; + +#define stbir__4_coeff_start() \ + float x0,x1,x2,x3,y0,y1,y2,y3,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0]; \ + x0 = decode[0] * c; \ + x1 = decode[1] * c; \ + x2 = decode[2] * c; \ + x3 = decode[3] * c; \ + c = hc[1]; \ + y0 = decode[4] * c; \ + y1 = decode[5] * c; \ + y2 = decode[6] * c; \ + y3 = decode[7] * c; \ + c = hc[2]; \ + x0 += decode[8] * c; \ + x1 += decode[9] * c; \ + x2 += decode[10] * c; \ + x3 += decode[11] * c; \ + c = hc[3]; \ + y0 += decode[12] * c; \ + y1 += decode[13] * c; \ + y2 += decode[14] * c; \ + y3 += decode[15] * c; + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*4] * c; \ + x1 += decode[1+(ofs)*4] * c; \ + x2 += decode[2+(ofs)*4] * c; \ + x3 += decode[3+(ofs)*4] * c; \ + c = hc[1+(ofs)]; \ + y0 += decode[4+(ofs)*4] * c; \ + y1 += decode[5+(ofs)*4] * c; \ + y2 += decode[6+(ofs)*4] * c; \ + y3 += decode[7+(ofs)*4] * c; \ + c = hc[2+(ofs)]; \ + x0 += decode[8+(ofs)*4] * c; \ + x1 += decode[9+(ofs)*4] * c; \ + x2 += decode[10+(ofs)*4] * c; \ + x3 += decode[11+(ofs)*4] * c; \ + c = hc[3+(ofs)]; \ + y0 += decode[12+(ofs)*4] * c; \ + y1 += decode[13+(ofs)*4] * c; \ + y2 += decode[14+(ofs)*4] * c; \ + y3 += decode[15+(ofs)*4] * c; + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*4] * c; \ + x1 += decode[1+(ofs)*4] * c; \ + x2 += decode[2+(ofs)*4] * c; \ + x3 += decode[3+(ofs)*4] * c; + +#define stbir__2_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*4] * c; \ + x1 += decode[1+(ofs)*4] * c; \ + x2 += decode[2+(ofs)*4] * c; \ + x3 += decode[3+(ofs)*4] * c; \ + c = hc[1+(ofs)]; \ + y0 += decode[4+(ofs)*4] * c; \ + y1 += decode[5+(ofs)*4] * c; \ + y2 += decode[6+(ofs)*4] * c; \ + y3 += decode[7+(ofs)*4] * c; + +#define stbir__3_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*4] * c; \ + x1 += decode[1+(ofs)*4] * c; \ + x2 += decode[2+(ofs)*4] * c; \ + x3 += decode[3+(ofs)*4] * c; \ + c = hc[1+(ofs)]; \ + y0 += decode[4+(ofs)*4] * c; \ + y1 += decode[5+(ofs)*4] * c; \ + y2 += decode[6+(ofs)*4] * c; \ + y3 += decode[7+(ofs)*4] * c; \ + c = hc[2+(ofs)]; \ + x0 += decode[8+(ofs)*4] * c; \ + x1 += decode[9+(ofs)*4] * c; \ + x2 += decode[10+(ofs)*4] * c; \ + x3 += decode[11+(ofs)*4] * c; + +#define stbir__store_output() \ + output[0] = x0 + y0; \ + output[1] = x1 + y1; \ + output[2] = x2 + y2; \ + output[3] = x3 + y3; \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 4; + +#endif + +#define STBIR__horizontal_channels 4 +#define STB_IMAGE_RESIZE_DO_HORIZONTALS +#include STBIR__HEADER_FILENAME + + + +//================= +// Do 7 channel horizontal routines + +#ifdef STBIR_SIMD + +#define stbir__1_coeff_only() \ + stbir__simdf tot0,tot1,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1( c, hc ); \ + stbir__simdf_0123to0000( c, c ); \ + stbir__simdf_mult_mem( tot0, c, decode ); \ + stbir__simdf_mult_mem( tot1, c, decode+3 ); + +#define stbir__2_coeff_only() \ + stbir__simdf tot0,tot1,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_mult_mem( tot0, c, decode ); \ + stbir__simdf_mult_mem( tot1, c, decode+3 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+7 ); \ + stbir__simdf_madd_mem( tot1, tot1, c,decode+10 ); + +#define stbir__3_coeff_only() \ + stbir__simdf tot0,tot1,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_mult_mem( tot0, c, decode ); \ + stbir__simdf_mult_mem( tot1, c, decode+3 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+7 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+10 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+14 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+17 ); + +#define stbir__store_output_tiny() \ + stbir__simdf_store( output+3, tot1 ); \ + stbir__simdf_store( output, tot0 ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 7; + +#ifdef STBIR_SIMD8 + +#define stbir__4_coeff_start() \ + stbir__simdf8 tot0,tot1,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc ); \ + stbir__simdf8_0123to00000000( c, cs ); \ + stbir__simdf8_mult_mem( tot0, c, decode ); \ + stbir__simdf8_0123to11111111( c, cs ); \ + stbir__simdf8_mult_mem( tot1, c, decode+7 ); \ + stbir__simdf8_0123to22222222( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+14 ); \ + stbir__simdf8_0123to33333333( c, cs ); \ + stbir__simdf8_madd_mem( tot1, tot1, c, decode+21 ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00000000( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ + stbir__simdf8_0123to11111111( c, cs ); \ + stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+7 ); \ + stbir__simdf8_0123to22222222( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 ); \ + stbir__simdf8_0123to33333333( c, cs ); \ + stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+21 ); + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load1b( c, hc + (ofs) ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); + +#define stbir__2_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load1b( c, hc + (ofs) ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ + stbir__simdf8_load1b( c, hc + (ofs)+1 ); \ + stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+7 ); + +#define stbir__3_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00000000( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ + stbir__simdf8_0123to11111111( c, cs ); \ + stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+7 ); \ + stbir__simdf8_0123to22222222( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 ); + +#define stbir__store_output() \ + stbir__simdf8_add( tot0, tot0, tot1 ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 7; \ + if ( output < output_end ) \ + { \ + stbir__simdf8_store( output-7, tot0 ); \ + continue; \ + } \ + stbir__simdf_store( output-7+3, stbir__simdf_swiz(stbir__simdf8_gettop4(tot0),0,0,1,2) ); \ + stbir__simdf_store( output-7, stbir__if_simdf8_cast_to_simdf4(tot0) ); \ + break; + +#else + +#define stbir__4_coeff_start() \ + stbir__simdf tot0,tot1,tot2,tot3,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_mult_mem( tot0, c, decode ); \ + stbir__simdf_mult_mem( tot1, c, decode+3 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_mult_mem( tot2, c, decode+7 ); \ + stbir__simdf_mult_mem( tot3, c, decode+10 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+14 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+17 ); \ + stbir__simdf_0123to3333( c, cs ); \ + stbir__simdf_madd_mem( tot2, tot2, c, decode+21 ); \ + stbir__simdf_madd_mem( tot3, tot3, c, decode+24 ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+3 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+7 ); \ + stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+10 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+17 ); \ + stbir__simdf_0123to3333( c, cs ); \ + stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+21 ); \ + stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+24 ); + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1( c, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, c ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+3 ); \ + +#define stbir__2_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2( cs, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+3 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+7 ); \ + stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+10 ); + +#define stbir__3_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+3 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+7 ); \ + stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+10 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+17 ); + +#define stbir__store_output() \ + stbir__simdf_add( tot0, tot0, tot2 ); \ + stbir__simdf_add( tot1, tot1, tot3 ); \ + stbir__simdf_store( output+3, tot1 ); \ + stbir__simdf_store( output, tot0 ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 7; + +#endif + +#else + +#define stbir__1_coeff_only() \ + float tot0, tot1, tot2, tot3, tot4, tot5, tot6, c; \ + c = hc[0]; \ + tot0 = decode[0]*c; \ + tot1 = decode[1]*c; \ + tot2 = decode[2]*c; \ + tot3 = decode[3]*c; \ + tot4 = decode[4]*c; \ + tot5 = decode[5]*c; \ + tot6 = decode[6]*c; + +#define stbir__2_coeff_only() \ + float tot0, tot1, tot2, tot3, tot4, tot5, tot6, c; \ + c = hc[0]; \ + tot0 = decode[0]*c; \ + tot1 = decode[1]*c; \ + tot2 = decode[2]*c; \ + tot3 = decode[3]*c; \ + tot4 = decode[4]*c; \ + tot5 = decode[5]*c; \ + tot6 = decode[6]*c; \ + c = hc[1]; \ + tot0 += decode[7]*c; \ + tot1 += decode[8]*c; \ + tot2 += decode[9]*c; \ + tot3 += decode[10]*c; \ + tot4 += decode[11]*c; \ + tot5 += decode[12]*c; \ + tot6 += decode[13]*c; \ + +#define stbir__3_coeff_only() \ + float tot0, tot1, tot2, tot3, tot4, tot5, tot6, c; \ + c = hc[0]; \ + tot0 = decode[0]*c; \ + tot1 = decode[1]*c; \ + tot2 = decode[2]*c; \ + tot3 = decode[3]*c; \ + tot4 = decode[4]*c; \ + tot5 = decode[5]*c; \ + tot6 = decode[6]*c; \ + c = hc[1]; \ + tot0 += decode[7]*c; \ + tot1 += decode[8]*c; \ + tot2 += decode[9]*c; \ + tot3 += decode[10]*c; \ + tot4 += decode[11]*c; \ + tot5 += decode[12]*c; \ + tot6 += decode[13]*c; \ + c = hc[2]; \ + tot0 += decode[14]*c; \ + tot1 += decode[15]*c; \ + tot2 += decode[16]*c; \ + tot3 += decode[17]*c; \ + tot4 += decode[18]*c; \ + tot5 += decode[19]*c; \ + tot6 += decode[20]*c; \ + +#define stbir__store_output_tiny() \ + output[0] = tot0; \ + output[1] = tot1; \ + output[2] = tot2; \ + output[3] = tot3; \ + output[4] = tot4; \ + output[5] = tot5; \ + output[6] = tot6; \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 7; + +#define stbir__4_coeff_start() \ + float x0,x1,x2,x3,x4,x5,x6,y0,y1,y2,y3,y4,y5,y6,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0]; \ + x0 = decode[0] * c; \ + x1 = decode[1] * c; \ + x2 = decode[2] * c; \ + x3 = decode[3] * c; \ + x4 = decode[4] * c; \ + x5 = decode[5] * c; \ + x6 = decode[6] * c; \ + c = hc[1]; \ + y0 = decode[7] * c; \ + y1 = decode[8] * c; \ + y2 = decode[9] * c; \ + y3 = decode[10] * c; \ + y4 = decode[11] * c; \ + y5 = decode[12] * c; \ + y6 = decode[13] * c; \ + c = hc[2]; \ + x0 += decode[14] * c; \ + x1 += decode[15] * c; \ + x2 += decode[16] * c; \ + x3 += decode[17] * c; \ + x4 += decode[18] * c; \ + x5 += decode[19] * c; \ + x6 += decode[20] * c; \ + c = hc[3]; \ + y0 += decode[21] * c; \ + y1 += decode[22] * c; \ + y2 += decode[23] * c; \ + y3 += decode[24] * c; \ + y4 += decode[25] * c; \ + y5 += decode[26] * c; \ + y6 += decode[27] * c; + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*7] * c; \ + x1 += decode[1+(ofs)*7] * c; \ + x2 += decode[2+(ofs)*7] * c; \ + x3 += decode[3+(ofs)*7] * c; \ + x4 += decode[4+(ofs)*7] * c; \ + x5 += decode[5+(ofs)*7] * c; \ + x6 += decode[6+(ofs)*7] * c; \ + c = hc[1+(ofs)]; \ + y0 += decode[7+(ofs)*7] * c; \ + y1 += decode[8+(ofs)*7] * c; \ + y2 += decode[9+(ofs)*7] * c; \ + y3 += decode[10+(ofs)*7] * c; \ + y4 += decode[11+(ofs)*7] * c; \ + y5 += decode[12+(ofs)*7] * c; \ + y6 += decode[13+(ofs)*7] * c; \ + c = hc[2+(ofs)]; \ + x0 += decode[14+(ofs)*7] * c; \ + x1 += decode[15+(ofs)*7] * c; \ + x2 += decode[16+(ofs)*7] * c; \ + x3 += decode[17+(ofs)*7] * c; \ + x4 += decode[18+(ofs)*7] * c; \ + x5 += decode[19+(ofs)*7] * c; \ + x6 += decode[20+(ofs)*7] * c; \ + c = hc[3+(ofs)]; \ + y0 += decode[21+(ofs)*7] * c; \ + y1 += decode[22+(ofs)*7] * c; \ + y2 += decode[23+(ofs)*7] * c; \ + y3 += decode[24+(ofs)*7] * c; \ + y4 += decode[25+(ofs)*7] * c; \ + y5 += decode[26+(ofs)*7] * c; \ + y6 += decode[27+(ofs)*7] * c; + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*7] * c; \ + x1 += decode[1+(ofs)*7] * c; \ + x2 += decode[2+(ofs)*7] * c; \ + x3 += decode[3+(ofs)*7] * c; \ + x4 += decode[4+(ofs)*7] * c; \ + x5 += decode[5+(ofs)*7] * c; \ + x6 += decode[6+(ofs)*7] * c; \ + +#define stbir__2_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*7] * c; \ + x1 += decode[1+(ofs)*7] * c; \ + x2 += decode[2+(ofs)*7] * c; \ + x3 += decode[3+(ofs)*7] * c; \ + x4 += decode[4+(ofs)*7] * c; \ + x5 += decode[5+(ofs)*7] * c; \ + x6 += decode[6+(ofs)*7] * c; \ + c = hc[1+(ofs)]; \ + y0 += decode[7+(ofs)*7] * c; \ + y1 += decode[8+(ofs)*7] * c; \ + y2 += decode[9+(ofs)*7] * c; \ + y3 += decode[10+(ofs)*7] * c; \ + y4 += decode[11+(ofs)*7] * c; \ + y5 += decode[12+(ofs)*7] * c; \ + y6 += decode[13+(ofs)*7] * c; \ + +#define stbir__3_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*7] * c; \ + x1 += decode[1+(ofs)*7] * c; \ + x2 += decode[2+(ofs)*7] * c; \ + x3 += decode[3+(ofs)*7] * c; \ + x4 += decode[4+(ofs)*7] * c; \ + x5 += decode[5+(ofs)*7] * c; \ + x6 += decode[6+(ofs)*7] * c; \ + c = hc[1+(ofs)]; \ + y0 += decode[7+(ofs)*7] * c; \ + y1 += decode[8+(ofs)*7] * c; \ + y2 += decode[9+(ofs)*7] * c; \ + y3 += decode[10+(ofs)*7] * c; \ + y4 += decode[11+(ofs)*7] * c; \ + y5 += decode[12+(ofs)*7] * c; \ + y6 += decode[13+(ofs)*7] * c; \ + c = hc[2+(ofs)]; \ + x0 += decode[14+(ofs)*7] * c; \ + x1 += decode[15+(ofs)*7] * c; \ + x2 += decode[16+(ofs)*7] * c; \ + x3 += decode[17+(ofs)*7] * c; \ + x4 += decode[18+(ofs)*7] * c; \ + x5 += decode[19+(ofs)*7] * c; \ + x6 += decode[20+(ofs)*7] * c; \ + +#define stbir__store_output() \ + output[0] = x0 + y0; \ + output[1] = x1 + y1; \ + output[2] = x2 + y2; \ + output[3] = x3 + y3; \ + output[4] = x4 + y4; \ + output[5] = x5 + y5; \ + output[6] = x6 + y6; \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 7; + +#endif + +#define STBIR__horizontal_channels 7 +#define STB_IMAGE_RESIZE_DO_HORIZONTALS +#include STBIR__HEADER_FILENAME + + +// include all of the vertical resamplers (both scatter and gather versions) + +#define STBIR__vertical_channels 1 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 1 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 2 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 2 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 3 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 3 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 4 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 4 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 5 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 5 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 6 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 6 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 7 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 7 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 8 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 8 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +typedef void STBIR_VERTICAL_GATHERFUNC( float * output, float const * coeffs, float const ** inputs, float const * input0_end ); + +static STBIR_VERTICAL_GATHERFUNC * stbir__vertical_gathers[ 8 ] = +{ + stbir__vertical_gather_with_1_coeffs,stbir__vertical_gather_with_2_coeffs,stbir__vertical_gather_with_3_coeffs,stbir__vertical_gather_with_4_coeffs,stbir__vertical_gather_with_5_coeffs,stbir__vertical_gather_with_6_coeffs,stbir__vertical_gather_with_7_coeffs,stbir__vertical_gather_with_8_coeffs +}; + +static STBIR_VERTICAL_GATHERFUNC * stbir__vertical_gathers_continues[ 8 ] = +{ + stbir__vertical_gather_with_1_coeffs_cont,stbir__vertical_gather_with_2_coeffs_cont,stbir__vertical_gather_with_3_coeffs_cont,stbir__vertical_gather_with_4_coeffs_cont,stbir__vertical_gather_with_5_coeffs_cont,stbir__vertical_gather_with_6_coeffs_cont,stbir__vertical_gather_with_7_coeffs_cont,stbir__vertical_gather_with_8_coeffs_cont +}; + +typedef void STBIR_VERTICAL_SCATTERFUNC( float ** outputs, float const * coeffs, float const * input, float const * input_end ); + +static STBIR_VERTICAL_SCATTERFUNC * stbir__vertical_scatter_sets[ 8 ] = +{ + stbir__vertical_scatter_with_1_coeffs,stbir__vertical_scatter_with_2_coeffs,stbir__vertical_scatter_with_3_coeffs,stbir__vertical_scatter_with_4_coeffs,stbir__vertical_scatter_with_5_coeffs,stbir__vertical_scatter_with_6_coeffs,stbir__vertical_scatter_with_7_coeffs,stbir__vertical_scatter_with_8_coeffs +}; + +static STBIR_VERTICAL_SCATTERFUNC * stbir__vertical_scatter_blends[ 8 ] = +{ + stbir__vertical_scatter_with_1_coeffs_cont,stbir__vertical_scatter_with_2_coeffs_cont,stbir__vertical_scatter_with_3_coeffs_cont,stbir__vertical_scatter_with_4_coeffs_cont,stbir__vertical_scatter_with_5_coeffs_cont,stbir__vertical_scatter_with_6_coeffs_cont,stbir__vertical_scatter_with_7_coeffs_cont,stbir__vertical_scatter_with_8_coeffs_cont +}; + + +static void stbir__encode_scanline( stbir__info const * stbir_info, void *output_buffer_data, float * encode_buffer, int row STBIR_ONLY_PROFILE_GET_SPLIT_INFO ) +{ + int num_pixels = stbir_info->horizontal.scale_info.output_sub_size; + int channels = stbir_info->channels; + int width_times_channels = num_pixels * channels; + void * output_buffer; + + // un-alpha weight if we need to + if ( stbir_info->alpha_unweight ) + { + STBIR_PROFILE_START( unalpha ); + stbir_info->alpha_unweight( encode_buffer, width_times_channels ); + STBIR_PROFILE_END( unalpha ); + } + + // write directly into output by default + output_buffer = output_buffer_data; + + // if we have an output callback, we first convert the decode buffer in place (and then hand that to the callback) + if ( stbir_info->out_pixels_cb ) + output_buffer = encode_buffer; + + STBIR_PROFILE_START( encode ); + // convert into the output buffer + stbir_info->encode_pixels( output_buffer, width_times_channels, encode_buffer ); + STBIR_PROFILE_END( encode ); + + // if we have an output callback, call it to send the data + if ( stbir_info->out_pixels_cb ) + stbir_info->out_pixels_cb( output_buffer, num_pixels, row, stbir_info->user_data ); +} + + +// Get the ring buffer pointer for an index +static float* stbir__get_ring_buffer_entry(stbir__info const * stbir_info, stbir__per_split_info const * split_info, int index ) +{ + STBIR_ASSERT( index < stbir_info->ring_buffer_num_entries ); + + #ifdef STBIR__SEPARATE_ALLOCATIONS + return split_info->ring_buffers[ index ]; + #else + return (float*) ( ( (char*) split_info->ring_buffer ) + ( index * stbir_info->ring_buffer_length_bytes ) ); + #endif +} + +// Get the specified scan line from the ring buffer +static float* stbir__get_ring_buffer_scanline(stbir__info const * stbir_info, stbir__per_split_info const * split_info, int get_scanline) +{ + int ring_buffer_index = (split_info->ring_buffer_begin_index + (get_scanline - split_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries; + return stbir__get_ring_buffer_entry( stbir_info, split_info, ring_buffer_index ); +} + +static void stbir__resample_horizontal_gather(stbir__info const * stbir_info, float* output_buffer, float const * input_buffer STBIR_ONLY_PROFILE_GET_SPLIT_INFO ) +{ + float const * decode_buffer = input_buffer - ( stbir_info->scanline_extents.conservative.n0 * stbir_info->effective_channels ); + + STBIR_PROFILE_START( horizontal ); + if ( ( stbir_info->horizontal.filter_enum == STBIR_FILTER_POINT_SAMPLE ) && ( stbir_info->horizontal.scale_info.scale == 1.0f ) ) + STBIR_MEMCPY( output_buffer, input_buffer, stbir_info->horizontal.scale_info.output_sub_size * sizeof( float ) * stbir_info->effective_channels ); + else + stbir_info->horizontal_gather_channels( output_buffer, stbir_info->horizontal.scale_info.output_sub_size, decode_buffer, stbir_info->horizontal.contributors, stbir_info->horizontal.coefficients, stbir_info->horizontal.coefficient_width ); + STBIR_PROFILE_END( horizontal ); +} + +static void stbir__resample_vertical_gather(stbir__info const * stbir_info, stbir__per_split_info* split_info, int n, int contrib_n0, int contrib_n1, float const * vertical_coefficients ) +{ + float* encode_buffer = split_info->vertical_buffer; + float* decode_buffer = split_info->decode_buffer; + int vertical_first = stbir_info->vertical_first; + int width = (vertical_first) ? ( stbir_info->scanline_extents.conservative.n1-stbir_info->scanline_extents.conservative.n0+1 ) : stbir_info->horizontal.scale_info.output_sub_size; + int width_times_channels = stbir_info->effective_channels * width; + + STBIR_ASSERT( stbir_info->vertical.is_gather ); + + // loop over the contributing scanlines and scale into the buffer + STBIR_PROFILE_START( vertical ); + { + int k = 0, total = contrib_n1 - contrib_n0 + 1; + STBIR_ASSERT( total > 0 ); + do { + float const * inputs[8]; + int i, cnt = total; if ( cnt > 8 ) cnt = 8; + for( i = 0 ; i < cnt ; i++ ) + inputs[ i ] = stbir__get_ring_buffer_scanline(stbir_info, split_info, k+i+contrib_n0 ); + + // call the N scanlines at a time function (up to 8 scanlines of blending at once) + ((k==0)?stbir__vertical_gathers:stbir__vertical_gathers_continues)[cnt-1]( (vertical_first) ? decode_buffer : encode_buffer, vertical_coefficients + k, inputs, inputs[0] + width_times_channels ); + k += cnt; + total -= cnt; + } while ( total ); + } + STBIR_PROFILE_END( vertical ); + + if ( vertical_first ) + { + // Now resample the gathered vertical data in the horizontal axis into the encode buffer + stbir__resample_horizontal_gather(stbir_info, encode_buffer, decode_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + } + + stbir__encode_scanline( stbir_info, ( (char *) stbir_info->output_data ) + ((size_t)n * (size_t)stbir_info->output_stride_bytes), + encode_buffer, n STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); +} + +static void stbir__decode_and_resample_for_vertical_gather_loop(stbir__info const * stbir_info, stbir__per_split_info* split_info, int n) +{ + int ring_buffer_index; + float* ring_buffer; + + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline( stbir_info, n, split_info->decode_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + + // update new end scanline + split_info->ring_buffer_last_scanline = n; + + // get ring buffer + ring_buffer_index = (split_info->ring_buffer_begin_index + (split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries; + ring_buffer = stbir__get_ring_buffer_entry(stbir_info, split_info, ring_buffer_index); + + // Now resample it into the ring buffer. + stbir__resample_horizontal_gather( stbir_info, ring_buffer, split_info->decode_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + + // Now it's sitting in the ring buffer ready to be used as source for the vertical sampling. +} + +static void stbir__vertical_gather_loop( stbir__info const * stbir_info, stbir__per_split_info* split_info, int split_count ) +{ + int y, start_output_y, end_output_y; + stbir__contributors* vertical_contributors = stbir_info->vertical.contributors; + float const * vertical_coefficients = stbir_info->vertical.coefficients; + + STBIR_ASSERT( stbir_info->vertical.is_gather ); + + start_output_y = split_info->start_output_y; + end_output_y = split_info[split_count-1].end_output_y; + + vertical_contributors += start_output_y; + vertical_coefficients += start_output_y * stbir_info->vertical.coefficient_width; + + // initialize the ring buffer for gathering + split_info->ring_buffer_begin_index = 0; + split_info->ring_buffer_first_scanline = vertical_contributors->n0; + split_info->ring_buffer_last_scanline = split_info->ring_buffer_first_scanline - 1; // means "empty" + + for (y = start_output_y; y < end_output_y; y++) + { + int in_first_scanline, in_last_scanline; + + in_first_scanline = vertical_contributors->n0; + in_last_scanline = vertical_contributors->n1; + + // make sure the indexing hasn't broken + STBIR_ASSERT( in_first_scanline >= split_info->ring_buffer_first_scanline ); + + // Load in new scanlines + while (in_last_scanline > split_info->ring_buffer_last_scanline) + { + STBIR_ASSERT( ( split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline + 1 ) <= stbir_info->ring_buffer_num_entries ); + + // make sure there was room in the ring buffer when we add new scanlines + if ( ( split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline + 1 ) == stbir_info->ring_buffer_num_entries ) + { + split_info->ring_buffer_first_scanline++; + split_info->ring_buffer_begin_index++; + } + + if ( stbir_info->vertical_first ) + { + float * ring_buffer = stbir__get_ring_buffer_scanline( stbir_info, split_info, ++split_info->ring_buffer_last_scanline ); + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline( stbir_info, split_info->ring_buffer_last_scanline, ring_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + } + else + { + stbir__decode_and_resample_for_vertical_gather_loop(stbir_info, split_info, split_info->ring_buffer_last_scanline + 1); + } + } + + // Now all buffers should be ready to write a row of vertical sampling, so do it. + stbir__resample_vertical_gather(stbir_info, split_info, y, in_first_scanline, in_last_scanline, vertical_coefficients ); + + ++vertical_contributors; + vertical_coefficients += stbir_info->vertical.coefficient_width; + } +} + +#define STBIR__FLOAT_EMPTY_MARKER 3.0e+38F +#define STBIR__FLOAT_BUFFER_IS_EMPTY(ptr) ((ptr)[0]==STBIR__FLOAT_EMPTY_MARKER) + +static void stbir__encode_first_scanline_from_scatter(stbir__info const * stbir_info, stbir__per_split_info* split_info) +{ + // evict a scanline out into the output buffer + float* ring_buffer_entry = stbir__get_ring_buffer_entry(stbir_info, split_info, split_info->ring_buffer_begin_index ); + + // dump the scanline out + stbir__encode_scanline( stbir_info, ( (char *)stbir_info->output_data ) + ( (size_t)split_info->ring_buffer_first_scanline * (size_t)stbir_info->output_stride_bytes ), ring_buffer_entry, split_info->ring_buffer_first_scanline STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + + // mark it as empty + ring_buffer_entry[ 0 ] = STBIR__FLOAT_EMPTY_MARKER; + + // advance the first scanline + split_info->ring_buffer_first_scanline++; + if ( ++split_info->ring_buffer_begin_index == stbir_info->ring_buffer_num_entries ) + split_info->ring_buffer_begin_index = 0; +} + +static void stbir__horizontal_resample_and_encode_first_scanline_from_scatter(stbir__info const * stbir_info, stbir__per_split_info* split_info) +{ + // evict a scanline out into the output buffer + + float* ring_buffer_entry = stbir__get_ring_buffer_entry(stbir_info, split_info, split_info->ring_buffer_begin_index ); + + // Now resample it into the buffer. + stbir__resample_horizontal_gather( stbir_info, split_info->vertical_buffer, ring_buffer_entry STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + + // dump the scanline out + stbir__encode_scanline( stbir_info, ( (char *)stbir_info->output_data ) + ( (size_t)split_info->ring_buffer_first_scanline * (size_t)stbir_info->output_stride_bytes ), split_info->vertical_buffer, split_info->ring_buffer_first_scanline STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + + // mark it as empty + ring_buffer_entry[ 0 ] = STBIR__FLOAT_EMPTY_MARKER; + + // advance the first scanline + split_info->ring_buffer_first_scanline++; + if ( ++split_info->ring_buffer_begin_index == stbir_info->ring_buffer_num_entries ) + split_info->ring_buffer_begin_index = 0; +} + +static void stbir__resample_vertical_scatter(stbir__info const * stbir_info, stbir__per_split_info* split_info, int n0, int n1, float const * vertical_coefficients, float const * vertical_buffer, float const * vertical_buffer_end ) +{ + STBIR_ASSERT( !stbir_info->vertical.is_gather ); + + STBIR_PROFILE_START( vertical ); + { + int k = 0, total = n1 - n0 + 1; + STBIR_ASSERT( total > 0 ); + do { + float * outputs[8]; + int i, n = total; if ( n > 8 ) n = 8; + for( i = 0 ; i < n ; i++ ) + { + outputs[ i ] = stbir__get_ring_buffer_scanline(stbir_info, split_info, k+i+n0 ); + if ( ( i ) && ( STBIR__FLOAT_BUFFER_IS_EMPTY( outputs[i] ) != STBIR__FLOAT_BUFFER_IS_EMPTY( outputs[0] ) ) ) // make sure runs are of the same type + { + n = i; + break; + } + } + // call the scatter to N scanlines at a time function (up to 8 scanlines of scattering at once) + ((STBIR__FLOAT_BUFFER_IS_EMPTY( outputs[0] ))?stbir__vertical_scatter_sets:stbir__vertical_scatter_blends)[n-1]( outputs, vertical_coefficients + k, vertical_buffer, vertical_buffer_end ); + k += n; + total -= n; + } while ( total ); + } + + STBIR_PROFILE_END( vertical ); +} + +typedef void stbir__handle_scanline_for_scatter_func(stbir__info const * stbir_info, stbir__per_split_info* split_info); + +static void stbir__vertical_scatter_loop( stbir__info const * stbir_info, stbir__per_split_info* split_info, int split_count ) +{ + int y, start_output_y, end_output_y, start_input_y, end_input_y; + stbir__contributors* vertical_contributors = stbir_info->vertical.contributors; + float const * vertical_coefficients = stbir_info->vertical.coefficients; + stbir__handle_scanline_for_scatter_func * handle_scanline_for_scatter; + void * scanline_scatter_buffer; + void * scanline_scatter_buffer_end; + int on_first_input_y, last_input_y; + + STBIR_ASSERT( !stbir_info->vertical.is_gather ); + + start_output_y = split_info->start_output_y; + end_output_y = split_info[split_count-1].end_output_y; // may do multiple split counts + + start_input_y = split_info->start_input_y; + end_input_y = split_info[split_count-1].end_input_y; + + // adjust for starting offset start_input_y + y = start_input_y + stbir_info->vertical.filter_pixel_margin; + vertical_contributors += y ; + vertical_coefficients += stbir_info->vertical.coefficient_width * y; + + if ( stbir_info->vertical_first ) + { + handle_scanline_for_scatter = stbir__horizontal_resample_and_encode_first_scanline_from_scatter; + scanline_scatter_buffer = split_info->decode_buffer; + scanline_scatter_buffer_end = ( (char*) scanline_scatter_buffer ) + sizeof( float ) * stbir_info->effective_channels * (stbir_info->scanline_extents.conservative.n1-stbir_info->scanline_extents.conservative.n0+1); + } + else + { + handle_scanline_for_scatter = stbir__encode_first_scanline_from_scatter; + scanline_scatter_buffer = split_info->vertical_buffer; + scanline_scatter_buffer_end = ( (char*) scanline_scatter_buffer ) + sizeof( float ) * stbir_info->effective_channels * stbir_info->horizontal.scale_info.output_sub_size; + } + + // initialize the ring buffer for scattering + split_info->ring_buffer_first_scanline = start_output_y; + split_info->ring_buffer_last_scanline = -1; + split_info->ring_buffer_begin_index = -1; + + // mark all the buffers as empty to start + for( y = 0 ; y < stbir_info->ring_buffer_num_entries ; y++ ) + stbir__get_ring_buffer_entry( stbir_info, split_info, y )[0] = STBIR__FLOAT_EMPTY_MARKER; // only used on scatter + + // do the loop in input space + on_first_input_y = 1; last_input_y = start_input_y; + for (y = start_input_y ; y < end_input_y; y++) + { + int out_first_scanline, out_last_scanline; + + out_first_scanline = vertical_contributors->n0; + out_last_scanline = vertical_contributors->n1; + + STBIR_ASSERT(out_last_scanline - out_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); + + if ( ( out_last_scanline >= out_first_scanline ) && ( ( ( out_first_scanline >= start_output_y ) && ( out_first_scanline < end_output_y ) ) || ( ( out_last_scanline >= start_output_y ) && ( out_last_scanline < end_output_y ) ) ) ) + { + float const * vc = vertical_coefficients; + + // keep track of the range actually seen for the next resize + last_input_y = y; + if ( ( on_first_input_y ) && ( y > start_input_y ) ) + split_info->start_input_y = y; + on_first_input_y = 0; + + // clip the region + if ( out_first_scanline < start_output_y ) + { + vc += start_output_y - out_first_scanline; + out_first_scanline = start_output_y; + } + + if ( out_last_scanline >= end_output_y ) + out_last_scanline = end_output_y - 1; + + // if very first scanline, init the index + if (split_info->ring_buffer_begin_index < 0) + split_info->ring_buffer_begin_index = out_first_scanline - start_output_y; + + STBIR_ASSERT( split_info->ring_buffer_begin_index <= out_first_scanline ); + + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline( stbir_info, y, split_info->decode_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + + // When horizontal first, we resample horizontally into the vertical buffer before we scatter it out + if ( !stbir_info->vertical_first ) + stbir__resample_horizontal_gather( stbir_info, split_info->vertical_buffer, split_info->decode_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + + // Now it's sitting in the buffer ready to be distributed into the ring buffers. + + // evict from the ringbuffer, if we need are full + if ( ( ( split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline + 1 ) == stbir_info->ring_buffer_num_entries ) && + ( out_last_scanline > split_info->ring_buffer_last_scanline ) ) + handle_scanline_for_scatter( stbir_info, split_info ); + + // Now the horizontal buffer is ready to write to all ring buffer rows, so do it. + stbir__resample_vertical_scatter(stbir_info, split_info, out_first_scanline, out_last_scanline, vc, (float*)scanline_scatter_buffer, (float*)scanline_scatter_buffer_end ); + + // update the end of the buffer + if ( out_last_scanline > split_info->ring_buffer_last_scanline ) + split_info->ring_buffer_last_scanline = out_last_scanline; + } + ++vertical_contributors; + vertical_coefficients += stbir_info->vertical.coefficient_width; + } + + // now evict the scanlines that are left over in the ring buffer + while ( split_info->ring_buffer_first_scanline < end_output_y ) + handle_scanline_for_scatter(stbir_info, split_info); + + // update the end_input_y if we do multiple resizes with the same data + ++last_input_y; + for( y = 0 ; y < split_count; y++ ) + if ( split_info[y].end_input_y > last_input_y ) + split_info[y].end_input_y = last_input_y; +} + + +static stbir__kernel_callback * stbir__builtin_kernels[] = { 0, stbir__filter_trapezoid, stbir__filter_triangle, stbir__filter_cubic, stbir__filter_catmullrom, stbir__filter_mitchell, stbir__filter_point }; +static stbir__support_callback * stbir__builtin_supports[] = { 0, stbir__support_trapezoid, stbir__support_one, stbir__support_two, stbir__support_two, stbir__support_two, stbir__support_zeropoint5 }; + +static void stbir__set_sampler(stbir__sampler * samp, stbir_filter filter, stbir__kernel_callback * kernel, stbir__support_callback * support, stbir_edge edge, stbir__scale_info * scale_info, int always_gather, void * user_data ) +{ + // set filter + if (filter == 0) + { + filter = STBIR_DEFAULT_FILTER_DOWNSAMPLE; // default to downsample + if (scale_info->scale >= ( 1.0f - stbir__small_float ) ) + { + if ( (scale_info->scale <= ( 1.0f + stbir__small_float ) ) && ( STBIR_CEILF(scale_info->pixel_shift) == scale_info->pixel_shift ) ) + filter = STBIR_FILTER_POINT_SAMPLE; + else + filter = STBIR_DEFAULT_FILTER_UPSAMPLE; + } + } + samp->filter_enum = filter; + + STBIR_ASSERT(samp->filter_enum != 0); + STBIR_ASSERT((unsigned)samp->filter_enum < STBIR_FILTER_OTHER); + samp->filter_kernel = stbir__builtin_kernels[ filter ]; + samp->filter_support = stbir__builtin_supports[ filter ]; + + if ( kernel && support ) + { + samp->filter_kernel = kernel; + samp->filter_support = support; + samp->filter_enum = STBIR_FILTER_OTHER; + } + + samp->edge = edge; + samp->filter_pixel_width = stbir__get_filter_pixel_width (samp->filter_support, scale_info->scale, user_data ); + // Gather is always better, but in extreme downsamples, you have to most or all of the data in memory + // For horizontal, we always have all the pixels, so we always use gather here (always_gather==1). + // For vertical, we use gather if scaling up (which means we will have samp->filter_pixel_width + // scanlines in memory at once). + samp->is_gather = 0; + if ( scale_info->scale >= ( 1.0f - stbir__small_float ) ) + samp->is_gather = 1; + else if ( ( always_gather ) || ( samp->filter_pixel_width <= STBIR_FORCE_GATHER_FILTER_SCANLINES_AMOUNT ) ) + samp->is_gather = 2; + + // pre calculate stuff based on the above + samp->coefficient_width = stbir__get_coefficient_width(samp, samp->is_gather, user_data); + + // filter_pixel_width is the conservative size in pixels of input that affect an output pixel. + // In rare cases (only with 2 pix to 1 pix with the default filters), it's possible that the + // filter will extend before or after the scanline beyond just one extra entire copy of the + // scanline (we would hit the edge twice). We don't let you do that, so we clamp the total + // width to 3x the total of input pixel (once for the scanline, once for the left side + // overhang, and once for the right side). We only do this for edge mode, since the other + // modes can just re-edge clamp back in again. + if ( edge == STBIR_EDGE_WRAP ) + if ( samp->filter_pixel_width > ( scale_info->input_full_size * 3 ) ) + samp->filter_pixel_width = scale_info->input_full_size * 3; + + // This is how much to expand buffers to account for filters seeking outside + // the image boundaries. + samp->filter_pixel_margin = samp->filter_pixel_width / 2; + + // filter_pixel_margin is the amount that this filter can overhang on just one side of either + // end of the scanline (left or the right). Since we only allow you to overhang 1 scanline's + // worth of pixels, we clamp this one side of overhang to the input scanline size. Again, + // this clamping only happens in rare cases with the default filters (2 pix to 1 pix). + if ( edge == STBIR_EDGE_WRAP ) + if ( samp->filter_pixel_margin > scale_info->input_full_size ) + samp->filter_pixel_margin = scale_info->input_full_size; + + samp->num_contributors = stbir__get_contributors(samp, samp->is_gather); + + samp->contributors_size = samp->num_contributors * sizeof(stbir__contributors); + samp->coefficients_size = samp->num_contributors * samp->coefficient_width * sizeof(float) + sizeof(float); // extra sizeof(float) is padding + + samp->gather_prescatter_contributors = 0; + samp->gather_prescatter_coefficients = 0; + if ( samp->is_gather == 0 ) + { + samp->gather_prescatter_coefficient_width = samp->filter_pixel_width; + samp->gather_prescatter_num_contributors = stbir__get_contributors(samp, 2); + samp->gather_prescatter_contributors_size = samp->gather_prescatter_num_contributors * sizeof(stbir__contributors); + samp->gather_prescatter_coefficients_size = samp->gather_prescatter_num_contributors * samp->gather_prescatter_coefficient_width * sizeof(float); + } +} + +static void stbir__get_conservative_extents( stbir__sampler * samp, stbir__contributors * range, void * user_data ) +{ + float scale = samp->scale_info.scale; + float out_shift = samp->scale_info.pixel_shift; + stbir__support_callback * support = samp->filter_support; + int input_full_size = samp->scale_info.input_full_size; + stbir_edge edge = samp->edge; + float inv_scale = samp->scale_info.inv_scale; + + STBIR_ASSERT( samp->is_gather != 0 ); + + if ( samp->is_gather == 1 ) + { + int in_first_pixel, in_last_pixel; + float out_filter_radius = support(inv_scale, user_data) * scale; + + stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, 0.5, out_filter_radius, inv_scale, out_shift, input_full_size, edge ); + range->n0 = in_first_pixel; + stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, ( (float)(samp->scale_info.output_sub_size-1) ) + 0.5f, out_filter_radius, inv_scale, out_shift, input_full_size, edge ); + range->n1 = in_last_pixel; + } + else if ( samp->is_gather == 2 ) // downsample gather, refine + { + float in_pixels_radius = support(scale, user_data) * inv_scale; + int filter_pixel_margin = samp->filter_pixel_margin; + int output_sub_size = samp->scale_info.output_sub_size; + int input_end; + int n; + int in_first_pixel, in_last_pixel; + + // get a conservative area of the input range + stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, 0, 0, inv_scale, out_shift, input_full_size, edge ); + range->n0 = in_first_pixel; + stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, (float)output_sub_size, 0, inv_scale, out_shift, input_full_size, edge ); + range->n1 = in_last_pixel; + + // now go through the margin to the start of area to find bottom + n = range->n0 + 1; + input_end = -filter_pixel_margin; + while( n >= input_end ) + { + int out_first_pixel, out_last_pixel; + stbir__calculate_out_pixel_range( &out_first_pixel, &out_last_pixel, ((float)n)+0.5f, in_pixels_radius, scale, out_shift, output_sub_size ); + if ( out_first_pixel > out_last_pixel ) + break; + + if ( ( out_first_pixel < output_sub_size ) || ( out_last_pixel >= 0 ) ) + range->n0 = n; + --n; + } + + // now go through the end of the area through the margin to find top + n = range->n1 - 1; + input_end = n + 1 + filter_pixel_margin; + while( n <= input_end ) + { + int out_first_pixel, out_last_pixel; + stbir__calculate_out_pixel_range( &out_first_pixel, &out_last_pixel, ((float)n)+0.5f, in_pixels_radius, scale, out_shift, output_sub_size ); + if ( out_first_pixel > out_last_pixel ) + break; + if ( ( out_first_pixel < output_sub_size ) || ( out_last_pixel >= 0 ) ) + range->n1 = n; + ++n; + } + } + + if ( samp->edge == STBIR_EDGE_WRAP ) + { + // if we are wrapping, and we are very close to the image size (so the edges might merge), just use the scanline up to the edge + if ( ( range->n0 > 0 ) && ( range->n1 >= input_full_size ) ) + { + int marg = range->n1 - input_full_size + 1; + if ( ( marg + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= range->n0 ) + range->n0 = 0; + } + if ( ( range->n0 < 0 ) && ( range->n1 < (input_full_size-1) ) ) + { + int marg = -range->n0; + if ( ( input_full_size - marg - STBIR__MERGE_RUNS_PIXEL_THRESHOLD - 1 ) <= range->n1 ) + range->n1 = input_full_size - 1; + } + } + else + { + // for non-edge-wrap modes, we never read over the edge, so clamp + if ( range->n0 < 0 ) + range->n0 = 0; + if ( range->n1 >= input_full_size ) + range->n1 = input_full_size - 1; + } +} + +static void stbir__get_split_info( stbir__per_split_info* split_info, int splits, int output_height, int vertical_pixel_margin, int input_full_height ) +{ + int i, cur; + int left = output_height; + + cur = 0; + for( i = 0 ; i < splits ; i++ ) + { + int each; + split_info[i].start_output_y = cur; + each = left / ( splits - i ); + split_info[i].end_output_y = cur + each; + cur += each; + left -= each; + + // scatter range (updated to minimum as you run it) + split_info[i].start_input_y = -vertical_pixel_margin; + split_info[i].end_input_y = input_full_height + vertical_pixel_margin; + } +} + +static void stbir__free_internal_mem( stbir__info *info ) +{ + #define STBIR__FREE_AND_CLEAR( ptr ) { if ( ptr ) { void * p = (ptr); (ptr) = 0; STBIR_FREE( p, info->user_data); } } + + if ( info ) + { + #ifndef STBIR__SEPARATE_ALLOCATIONS + STBIR__FREE_AND_CLEAR( info->alloced_mem ); + #else + int i,j; + + if ( ( info->vertical.gather_prescatter_contributors ) && ( (void*)info->vertical.gather_prescatter_contributors != (void*)info->split_info[0].decode_buffer ) ) + { + STBIR__FREE_AND_CLEAR( info->vertical.gather_prescatter_coefficients ); + STBIR__FREE_AND_CLEAR( info->vertical.gather_prescatter_contributors ); + } + for( i = 0 ; i < info->splits ; i++ ) + { + for( j = 0 ; j < info->alloc_ring_buffer_num_entries ; j++ ) + { + #ifdef STBIR_SIMD8 + if ( info->effective_channels == 3 ) + --info->split_info[i].ring_buffers[j]; // avx in 3 channel mode needs one float at the start of the buffer + #endif + STBIR__FREE_AND_CLEAR( info->split_info[i].ring_buffers[j] ); + } + + #ifdef STBIR_SIMD8 + if ( info->effective_channels == 3 ) + --info->split_info[i].decode_buffer; // avx in 3 channel mode needs one float at the start of the buffer + #endif + STBIR__FREE_AND_CLEAR( info->split_info[i].decode_buffer ); + STBIR__FREE_AND_CLEAR( info->split_info[i].ring_buffers ); + STBIR__FREE_AND_CLEAR( info->split_info[i].vertical_buffer ); + } + STBIR__FREE_AND_CLEAR( info->split_info ); + if ( info->vertical.coefficients != info->horizontal.coefficients ) + { + STBIR__FREE_AND_CLEAR( info->vertical.coefficients ); + STBIR__FREE_AND_CLEAR( info->vertical.contributors ); + } + STBIR__FREE_AND_CLEAR( info->horizontal.coefficients ); + STBIR__FREE_AND_CLEAR( info->horizontal.contributors ); + STBIR__FREE_AND_CLEAR( info->alloced_mem ); + STBIR__FREE_AND_CLEAR( info ); + #endif + } + + #undef STBIR__FREE_AND_CLEAR +} + +static int stbir__get_max_split( int splits, int height ) +{ + int i; + int max = 0; + + for( i = 0 ; i < splits ; i++ ) + { + int each = height / ( splits - i ); + if ( each > max ) + max = each; + height -= each; + } + return max; +} + +static stbir__horizontal_gather_channels_func ** stbir__horizontal_gather_n_coeffs_funcs[8] = +{ + 0, stbir__horizontal_gather_1_channels_with_n_coeffs_funcs, stbir__horizontal_gather_2_channels_with_n_coeffs_funcs, stbir__horizontal_gather_3_channels_with_n_coeffs_funcs, stbir__horizontal_gather_4_channels_with_n_coeffs_funcs, 0,0, stbir__horizontal_gather_7_channels_with_n_coeffs_funcs +}; + +static stbir__horizontal_gather_channels_func ** stbir__horizontal_gather_channels_funcs[8] = +{ + 0, stbir__horizontal_gather_1_channels_funcs, stbir__horizontal_gather_2_channels_funcs, stbir__horizontal_gather_3_channels_funcs, stbir__horizontal_gather_4_channels_funcs, 0,0, stbir__horizontal_gather_7_channels_funcs +}; + +// there are six resize classifications: 0 == vertical scatter, 1 == vertical gather < 1x scale, 2 == vertical gather 1x-2x scale, 4 == vertical gather < 3x scale, 4 == vertical gather > 3x scale, 5 == <=4 pixel height, 6 == <=4 pixel wide column +#define STBIR_RESIZE_CLASSIFICATIONS 8 + +static float stbir__compute_weights[5][STBIR_RESIZE_CLASSIFICATIONS][4]= // 5 = 0=1chan, 1=2chan, 2=3chan, 3=4chan, 4=7chan +{ + { + { 1.00000f, 1.00000f, 0.31250f, 1.00000f }, + { 0.56250f, 0.59375f, 0.00000f, 0.96875f }, + { 1.00000f, 0.06250f, 0.00000f, 1.00000f }, + { 0.00000f, 0.09375f, 1.00000f, 1.00000f }, + { 1.00000f, 1.00000f, 1.00000f, 1.00000f }, + { 0.03125f, 0.12500f, 1.00000f, 1.00000f }, + { 0.06250f, 0.12500f, 0.00000f, 1.00000f }, + { 0.00000f, 1.00000f, 0.00000f, 0.03125f }, + }, { + { 0.00000f, 0.84375f, 0.00000f, 0.03125f }, + { 0.09375f, 0.93750f, 0.00000f, 0.78125f }, + { 0.87500f, 0.21875f, 0.00000f, 0.96875f }, + { 0.09375f, 0.09375f, 1.00000f, 1.00000f }, + { 1.00000f, 1.00000f, 1.00000f, 1.00000f }, + { 0.03125f, 0.12500f, 1.00000f, 1.00000f }, + { 0.06250f, 0.12500f, 0.00000f, 1.00000f }, + { 0.00000f, 1.00000f, 0.00000f, 0.53125f }, + }, { + { 0.00000f, 0.53125f, 0.00000f, 0.03125f }, + { 0.06250f, 0.96875f, 0.00000f, 0.53125f }, + { 0.87500f, 0.18750f, 0.00000f, 0.93750f }, + { 0.00000f, 0.09375f, 1.00000f, 1.00000f }, + { 1.00000f, 1.00000f, 1.00000f, 1.00000f }, + { 0.03125f, 0.12500f, 1.00000f, 1.00000f }, + { 0.06250f, 0.12500f, 0.00000f, 1.00000f }, + { 0.00000f, 1.00000f, 0.00000f, 0.56250f }, + }, { + { 0.00000f, 0.50000f, 0.00000f, 0.71875f }, + { 0.06250f, 0.84375f, 0.00000f, 0.87500f }, + { 1.00000f, 0.50000f, 0.50000f, 0.96875f }, + { 1.00000f, 0.09375f, 0.31250f, 0.50000f }, + { 1.00000f, 1.00000f, 1.00000f, 1.00000f }, + { 1.00000f, 0.03125f, 0.03125f, 0.53125f }, + { 0.18750f, 0.12500f, 0.00000f, 1.00000f }, + { 0.00000f, 1.00000f, 0.03125f, 0.18750f }, + }, { + { 0.00000f, 0.59375f, 0.00000f, 0.96875f }, + { 0.06250f, 0.81250f, 0.06250f, 0.59375f }, + { 0.75000f, 0.43750f, 0.12500f, 0.96875f }, + { 0.87500f, 0.06250f, 0.18750f, 0.43750f }, + { 1.00000f, 1.00000f, 1.00000f, 1.00000f }, + { 0.15625f, 0.12500f, 1.00000f, 1.00000f }, + { 0.06250f, 0.12500f, 0.00000f, 1.00000f }, + { 0.00000f, 1.00000f, 0.03125f, 0.34375f }, + } +}; + +// structure that allow us to query and override info for training the costs +typedef struct STBIR__V_FIRST_INFO +{ + double v_cost, h_cost; + int control_v_first; // 0 = no control, 1 = force hori, 2 = force vert + int v_first; + int v_resize_classification; + int is_gather; +} STBIR__V_FIRST_INFO; + +#ifdef STBIR__V_FIRST_INFO_BUFFER +static STBIR__V_FIRST_INFO STBIR__V_FIRST_INFO_BUFFER = {0}; +#define STBIR__V_FIRST_INFO_POINTER &STBIR__V_FIRST_INFO_BUFFER +#else +#define STBIR__V_FIRST_INFO_POINTER 0 +#endif + +// Figure out whether to scale along the horizontal or vertical first. +// This only *super* important when you are scaling by a massively +// different amount in the vertical vs the horizontal (for example, if +// you are scaling by 2x in the width, and 0.5x in the height, then you +// want to do the vertical scale first, because it's around 3x faster +// in that order. +// +// In more normal circumstances, this makes a 20-40% differences, so +// it's good to get right, but not critical. The normal way that you +// decide which direction goes first is just figuring out which +// direction does more multiplies. But with modern CPUs with their +// fancy caches and SIMD and high IPC abilities, so there's just a lot +// more that goes into it. +// +// My handwavy sort of solution is to have an app that does a whole +// bunch of timing for both vertical and horizontal first modes, +// and then another app that can read lots of these timing files +// and try to search for the best weights to use. Dotimings.c +// is the app that does a bunch of timings, and vf_train.c is the +// app that solves for the best weights (and shows how well it +// does currently). + +static int stbir__should_do_vertical_first( float weights_table[STBIR_RESIZE_CLASSIFICATIONS][4], int horizontal_filter_pixel_width, float horizontal_scale, int horizontal_output_size, int vertical_filter_pixel_width, float vertical_scale, int vertical_output_size, int is_gather, STBIR__V_FIRST_INFO * info ) +{ + double v_cost, h_cost; + float * weights; + int vertical_first; + int v_classification; + + // categorize the resize into buckets + if ( ( vertical_output_size <= 4 ) || ( horizontal_output_size <= 4 ) ) + v_classification = ( vertical_output_size < horizontal_output_size ) ? 6 : 7; + else if ( vertical_scale <= 1.0f ) + v_classification = ( is_gather ) ? 1 : 0; + else if ( vertical_scale <= 2.0f) + v_classification = 2; + else if ( vertical_scale <= 3.0f) + v_classification = 3; + else if ( vertical_scale <= 4.0f) + v_classification = 5; + else + v_classification = 6; + + // use the right weights + weights = weights_table[ v_classification ]; + + // this is the costs when you don't take into account modern CPUs with high ipc and simd and caches - wish we had a better estimate + h_cost = (float)horizontal_filter_pixel_width * weights[0] + horizontal_scale * (float)vertical_filter_pixel_width * weights[1]; + v_cost = (float)vertical_filter_pixel_width * weights[2] + vertical_scale * (float)horizontal_filter_pixel_width * weights[3]; + + // use computation estimate to decide vertical first or not + vertical_first = ( v_cost <= h_cost ) ? 1 : 0; + + // save these, if requested + if ( info ) + { + info->h_cost = h_cost; + info->v_cost = v_cost; + info->v_resize_classification = v_classification; + info->v_first = vertical_first; + info->is_gather = is_gather; + } + + // and this allows us to override everything for testing (see dotiming.c) + if ( ( info ) && ( info->control_v_first ) ) + vertical_first = ( info->control_v_first == 2 ) ? 1 : 0; + + return vertical_first; +} + +// layout lookups - must match stbir_internal_pixel_layout +static unsigned char stbir__pixel_channels[] = { + 1,2,3,3,4, // 1ch, 2ch, rgb, bgr, 4ch + 4,4,4,4,2,2, // RGBA,BGRA,ARGB,ABGR,RA,AR + 4,4,4,4,2,2, // RGBA_PM,BGRA_PM,ARGB_PM,ABGR_PM,RA_PM,AR_PM +}; + +// the internal pixel layout enums are in a different order, so we can easily do range comparisons of types +// the public pixel layout is ordered in a way that if you cast num_channels (1-4) to the enum, you get something sensible +static stbir_internal_pixel_layout stbir__pixel_layout_convert_public_to_internal[] = { + STBIRI_BGR, STBIRI_1CHANNEL, STBIRI_2CHANNEL, STBIRI_RGB, STBIRI_RGBA, + STBIRI_4CHANNEL, STBIRI_BGRA, STBIRI_ARGB, STBIRI_ABGR, STBIRI_RA, STBIRI_AR, + STBIRI_RGBA_PM, STBIRI_BGRA_PM, STBIRI_ARGB_PM, STBIRI_ABGR_PM, STBIRI_RA_PM, STBIRI_AR_PM, +}; + +static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sampler * horizontal, stbir__sampler * vertical, stbir__contributors * conservative, stbir_pixel_layout input_pixel_layout_public, stbir_pixel_layout output_pixel_layout_public, int splits, int new_x, int new_y, int fast_alpha, void * user_data STBIR_ONLY_PROFILE_BUILD_GET_INFO ) +{ + static char stbir_channel_count_index[8]={ 9,0,1,2, 3,9,9,4 }; + + stbir__info * info = 0; + void * alloced = 0; + size_t alloced_total = 0; + int vertical_first; + int decode_buffer_size, ring_buffer_length_bytes, ring_buffer_size, vertical_buffer_size, alloc_ring_buffer_num_entries; + + int alpha_weighting_type = 0; // 0=none, 1=simple, 2=fancy + int conservative_split_output_size = stbir__get_max_split( splits, vertical->scale_info.output_sub_size ); + stbir_internal_pixel_layout input_pixel_layout = stbir__pixel_layout_convert_public_to_internal[ input_pixel_layout_public ]; + stbir_internal_pixel_layout output_pixel_layout = stbir__pixel_layout_convert_public_to_internal[ output_pixel_layout_public ]; + int channels = stbir__pixel_channels[ input_pixel_layout ]; + int effective_channels = channels; + + // first figure out what type of alpha weighting to use (if any) + if ( ( horizontal->filter_enum != STBIR_FILTER_POINT_SAMPLE ) || ( vertical->filter_enum != STBIR_FILTER_POINT_SAMPLE ) ) // no alpha weighting on point sampling + { + if ( ( input_pixel_layout >= STBIRI_RGBA ) && ( input_pixel_layout <= STBIRI_AR ) && ( output_pixel_layout >= STBIRI_RGBA ) && ( output_pixel_layout <= STBIRI_AR ) ) + { + if ( fast_alpha ) + { + alpha_weighting_type = 4; + } + else + { + static int fancy_alpha_effective_cnts[6] = { 7, 7, 7, 7, 3, 3 }; + alpha_weighting_type = 2; + effective_channels = fancy_alpha_effective_cnts[ input_pixel_layout - STBIRI_RGBA ]; + } + } + else if ( ( input_pixel_layout >= STBIRI_RGBA_PM ) && ( input_pixel_layout <= STBIRI_AR_PM ) && ( output_pixel_layout >= STBIRI_RGBA ) && ( output_pixel_layout <= STBIRI_AR ) ) + { + // input premult, output non-premult + alpha_weighting_type = 3; + } + else if ( ( input_pixel_layout >= STBIRI_RGBA ) && ( input_pixel_layout <= STBIRI_AR ) && ( output_pixel_layout >= STBIRI_RGBA_PM ) && ( output_pixel_layout <= STBIRI_AR_PM ) ) + { + // input non-premult, output premult + alpha_weighting_type = 1; + } + } + + // channel in and out count must match currently + if ( channels != stbir__pixel_channels[ output_pixel_layout ] ) + return 0; + + // get vertical first + vertical_first = stbir__should_do_vertical_first( stbir__compute_weights[ (int)stbir_channel_count_index[ effective_channels ] ], horizontal->filter_pixel_width, horizontal->scale_info.scale, horizontal->scale_info.output_sub_size, vertical->filter_pixel_width, vertical->scale_info.scale, vertical->scale_info.output_sub_size, vertical->is_gather, STBIR__V_FIRST_INFO_POINTER ); + + // sometimes read one float off in some of the unrolled loops (with a weight of zero coeff, so it doesn't have an effect) + decode_buffer_size = ( conservative->n1 - conservative->n0 + 1 ) * effective_channels * sizeof(float) + sizeof(float); // extra float for padding + +#if defined( STBIR__SEPARATE_ALLOCATIONS ) && defined(STBIR_SIMD8) + if ( effective_channels == 3 ) + decode_buffer_size += sizeof(float); // avx in 3 channel mode needs one float at the start of the buffer (only with separate allocations) +#endif + + ring_buffer_length_bytes = horizontal->scale_info.output_sub_size * effective_channels * sizeof(float) + sizeof(float); // extra float for padding + + // if we do vertical first, the ring buffer holds a whole decoded line + if ( vertical_first ) + ring_buffer_length_bytes = ( decode_buffer_size + 15 ) & ~15; + + if ( ( ring_buffer_length_bytes & 4095 ) == 0 ) ring_buffer_length_bytes += 64*3; // avoid 4k alias + + // One extra entry because floating point precision problems sometimes cause an extra to be necessary. + alloc_ring_buffer_num_entries = vertical->filter_pixel_width + 1; + + // we never need more ring buffer entries than the scanlines we're outputting when in scatter mode + if ( ( !vertical->is_gather ) && ( alloc_ring_buffer_num_entries > conservative_split_output_size ) ) + alloc_ring_buffer_num_entries = conservative_split_output_size; + + ring_buffer_size = alloc_ring_buffer_num_entries * ring_buffer_length_bytes; + + // The vertical buffer is used differently, depending on whether we are scattering + // the vertical scanlines, or gathering them. + // If scattering, it's used at the temp buffer to accumulate each output. + // If gathering, it's just the output buffer. + vertical_buffer_size = horizontal->scale_info.output_sub_size * effective_channels * sizeof(float) + sizeof(float); // extra float for padding + + // we make two passes through this loop, 1st to add everything up, 2nd to allocate and init + for(;;) + { + int i; + void * advance_mem = alloced; + int copy_horizontal = 0; + stbir__sampler * possibly_use_horizontal_for_pivot = 0; + +#ifdef STBIR__SEPARATE_ALLOCATIONS + #define STBIR__NEXT_PTR( ptr, size, ntype ) if ( alloced ) { void * p = STBIR_MALLOC( size, user_data); if ( p == 0 ) { stbir__free_internal_mem( info ); return 0; } (ptr) = (ntype*)p; } +#else + #define STBIR__NEXT_PTR( ptr, size, ntype ) advance_mem = (void*) ( ( ((size_t)advance_mem) + 15 ) & ~15 ); if ( alloced ) ptr = (ntype*)advance_mem; advance_mem = ((char*)advance_mem) + (size); +#endif + + STBIR__NEXT_PTR( info, sizeof( stbir__info ), stbir__info ); + + STBIR__NEXT_PTR( info->split_info, sizeof( stbir__per_split_info ) * splits, stbir__per_split_info ); + + if ( info ) + { + static stbir__alpha_weight_func * fancy_alpha_weights[6] = { stbir__fancy_alpha_weight_4ch, stbir__fancy_alpha_weight_4ch, stbir__fancy_alpha_weight_4ch, stbir__fancy_alpha_weight_4ch, stbir__fancy_alpha_weight_2ch, stbir__fancy_alpha_weight_2ch }; + static stbir__alpha_unweight_func * fancy_alpha_unweights[6] = { stbir__fancy_alpha_unweight_4ch, stbir__fancy_alpha_unweight_4ch, stbir__fancy_alpha_unweight_4ch, stbir__fancy_alpha_unweight_4ch, stbir__fancy_alpha_unweight_2ch, stbir__fancy_alpha_unweight_2ch }; + static stbir__alpha_weight_func * simple_alpha_weights[6] = { stbir__simple_alpha_weight_4ch, stbir__simple_alpha_weight_4ch, stbir__simple_alpha_weight_4ch, stbir__simple_alpha_weight_4ch, stbir__simple_alpha_weight_2ch, stbir__simple_alpha_weight_2ch }; + static stbir__alpha_unweight_func * simple_alpha_unweights[6] = { stbir__simple_alpha_unweight_4ch, stbir__simple_alpha_unweight_4ch, stbir__simple_alpha_unweight_4ch, stbir__simple_alpha_unweight_4ch, stbir__simple_alpha_unweight_2ch, stbir__simple_alpha_unweight_2ch }; + + // initialize info fields + info->alloced_mem = alloced; + info->alloced_total = alloced_total; + + info->channels = channels; + info->effective_channels = effective_channels; + + info->offset_x = new_x; + info->offset_y = new_y; + info->alloc_ring_buffer_num_entries = alloc_ring_buffer_num_entries; + info->ring_buffer_num_entries = 0; + info->ring_buffer_length_bytes = ring_buffer_length_bytes; + info->splits = splits; + info->vertical_first = vertical_first; + + info->input_pixel_layout_internal = input_pixel_layout; + info->output_pixel_layout_internal = output_pixel_layout; + + // setup alpha weight functions + info->alpha_weight = 0; + info->alpha_unweight = 0; + + // handle alpha weighting functions and overrides + if ( alpha_weighting_type == 2 ) + { + // high quality alpha multiplying on the way in, dividing on the way out + info->alpha_weight = fancy_alpha_weights[ input_pixel_layout - STBIRI_RGBA ]; + info->alpha_unweight = fancy_alpha_unweights[ output_pixel_layout - STBIRI_RGBA ]; + } + else if ( alpha_weighting_type == 4 ) + { + // fast alpha multiplying on the way in, dividing on the way out + info->alpha_weight = simple_alpha_weights[ input_pixel_layout - STBIRI_RGBA ]; + info->alpha_unweight = simple_alpha_unweights[ output_pixel_layout - STBIRI_RGBA ]; + } + else if ( alpha_weighting_type == 1 ) + { + // fast alpha on the way in, leave in premultiplied form on way out + info->alpha_weight = simple_alpha_weights[ input_pixel_layout - STBIRI_RGBA ]; + } + else if ( alpha_weighting_type == 3 ) + { + // incoming is premultiplied, fast alpha dividing on the way out - non-premultiplied output + info->alpha_unweight = simple_alpha_unweights[ output_pixel_layout - STBIRI_RGBA ]; + } + + // handle 3-chan color flipping, using the alpha weight path + if ( ( ( input_pixel_layout == STBIRI_RGB ) && ( output_pixel_layout == STBIRI_BGR ) ) || + ( ( input_pixel_layout == STBIRI_BGR ) && ( output_pixel_layout == STBIRI_RGB ) ) ) + { + // do the flipping on the smaller of the two ends + if ( horizontal->scale_info.scale < 1.0f ) + info->alpha_unweight = stbir__simple_flip_3ch; + else + info->alpha_weight = stbir__simple_flip_3ch; + } + + } + + // get all the per-split buffers + for( i = 0 ; i < splits ; i++ ) + { + STBIR__NEXT_PTR( info->split_info[i].decode_buffer, decode_buffer_size, float ); + +#ifdef STBIR__SEPARATE_ALLOCATIONS + + #ifdef STBIR_SIMD8 + if ( ( info ) && ( effective_channels == 3 ) ) + ++info->split_info[i].decode_buffer; // avx in 3 channel mode needs one float at the start of the buffer + #endif + + STBIR__NEXT_PTR( info->split_info[i].ring_buffers, alloc_ring_buffer_num_entries * sizeof(float*), float* ); + { + int j; + for( j = 0 ; j < alloc_ring_buffer_num_entries ; j++ ) + { + STBIR__NEXT_PTR( info->split_info[i].ring_buffers[j], ring_buffer_length_bytes, float ); + #ifdef STBIR_SIMD8 + if ( ( info ) && ( effective_channels == 3 ) ) + ++info->split_info[i].ring_buffers[j]; // avx in 3 channel mode needs one float at the start of the buffer + #endif + } + } +#else + STBIR__NEXT_PTR( info->split_info[i].ring_buffer, ring_buffer_size, float ); +#endif + STBIR__NEXT_PTR( info->split_info[i].vertical_buffer, vertical_buffer_size, float ); + } + + // alloc memory for to-be-pivoted coeffs (if necessary) + if ( vertical->is_gather == 0 ) + { + int both; + int temp_mem_amt; + + // when in vertical scatter mode, we first build the coefficients in gather mode, and then pivot after, + // that means we need two buffers, so we try to use the decode buffer and ring buffer for this. if that + // is too small, we just allocate extra memory to use as this temp. + + both = vertical->gather_prescatter_contributors_size + vertical->gather_prescatter_coefficients_size; + +#ifdef STBIR__SEPARATE_ALLOCATIONS + temp_mem_amt = decode_buffer_size; +#else + temp_mem_amt = ( decode_buffer_size + ring_buffer_size + vertical_buffer_size ) * splits; +#endif + if ( temp_mem_amt >= both ) + { + if ( info ) + { + vertical->gather_prescatter_contributors = (stbir__contributors*)info->split_info[0].decode_buffer; + vertical->gather_prescatter_coefficients = (float*) ( ( (char*)info->split_info[0].decode_buffer ) + vertical->gather_prescatter_contributors_size ); + } + } + else + { + // ring+decode memory is too small, so allocate temp memory + STBIR__NEXT_PTR( vertical->gather_prescatter_contributors, vertical->gather_prescatter_contributors_size, stbir__contributors ); + STBIR__NEXT_PTR( vertical->gather_prescatter_coefficients, vertical->gather_prescatter_coefficients_size, float ); + } + } + + STBIR__NEXT_PTR( horizontal->contributors, horizontal->contributors_size, stbir__contributors ); + STBIR__NEXT_PTR( horizontal->coefficients, horizontal->coefficients_size, float ); + + // are the two filters identical?? (happens a lot with mipmap generation) + if ( ( horizontal->filter_kernel == vertical->filter_kernel ) && ( horizontal->filter_support == vertical->filter_support ) && ( horizontal->edge == vertical->edge ) && ( horizontal->scale_info.output_sub_size == vertical->scale_info.output_sub_size ) ) + { + float diff_scale = horizontal->scale_info.scale - vertical->scale_info.scale; + float diff_shift = horizontal->scale_info.pixel_shift - vertical->scale_info.pixel_shift; + if ( diff_scale < 0.0f ) diff_scale = -diff_scale; + if ( diff_shift < 0.0f ) diff_shift = -diff_shift; + if ( ( diff_scale <= stbir__small_float ) && ( diff_shift <= stbir__small_float ) ) + { + if ( horizontal->is_gather == vertical->is_gather ) + { + copy_horizontal = 1; + goto no_vert_alloc; + } + // everything matches, but vertical is scatter, horizontal is gather, use horizontal coeffs for vertical pivot coeffs + possibly_use_horizontal_for_pivot = horizontal; + } + } + + STBIR__NEXT_PTR( vertical->contributors, vertical->contributors_size, stbir__contributors ); + STBIR__NEXT_PTR( vertical->coefficients, vertical->coefficients_size, float ); + + no_vert_alloc: + + if ( info ) + { + STBIR_PROFILE_BUILD_START( horizontal ); + + stbir__calculate_filters( horizontal, 0, user_data STBIR_ONLY_PROFILE_BUILD_SET_INFO ); + + // setup the horizontal gather functions + // start with defaulting to the n_coeffs functions (specialized on channels and remnant leftover) + info->horizontal_gather_channels = stbir__horizontal_gather_n_coeffs_funcs[ effective_channels ][ horizontal->extent_info.widest & 3 ]; + // but if the number of coeffs <= 12, use another set of special cases. <=12 coeffs is any enlarging resize, or shrinking resize down to about 1/3 size + if ( horizontal->extent_info.widest <= 12 ) + info->horizontal_gather_channels = stbir__horizontal_gather_channels_funcs[ effective_channels ][ horizontal->extent_info.widest - 1 ]; + + info->scanline_extents.conservative.n0 = conservative->n0; + info->scanline_extents.conservative.n1 = conservative->n1; + + // get exact extents + stbir__get_extents( horizontal, &info->scanline_extents ); + + // pack the horizontal coeffs + horizontal->coefficient_width = stbir__pack_coefficients(horizontal->num_contributors, horizontal->contributors, horizontal->coefficients, horizontal->coefficient_width, horizontal->extent_info.widest, info->scanline_extents.conservative.n0, info->scanline_extents.conservative.n1 ); + + STBIR_MEMCPY( &info->horizontal, horizontal, sizeof( stbir__sampler ) ); + + STBIR_PROFILE_BUILD_END( horizontal ); + + if ( copy_horizontal ) + { + STBIR_MEMCPY( &info->vertical, horizontal, sizeof( stbir__sampler ) ); + } + else + { + STBIR_PROFILE_BUILD_START( vertical ); + + stbir__calculate_filters( vertical, possibly_use_horizontal_for_pivot, user_data STBIR_ONLY_PROFILE_BUILD_SET_INFO ); + STBIR_MEMCPY( &info->vertical, vertical, sizeof( stbir__sampler ) ); + + STBIR_PROFILE_BUILD_END( vertical ); + } + + // setup the vertical split ranges + stbir__get_split_info( info->split_info, info->splits, info->vertical.scale_info.output_sub_size, info->vertical.filter_pixel_margin, info->vertical.scale_info.input_full_size ); + + // now we know precisely how many entries we need + info->ring_buffer_num_entries = info->vertical.extent_info.widest; + + // we never need more ring buffer entries than the scanlines we're outputting + if ( ( !info->vertical.is_gather ) && ( info->ring_buffer_num_entries > conservative_split_output_size ) ) + info->ring_buffer_num_entries = conservative_split_output_size; + STBIR_ASSERT( info->ring_buffer_num_entries <= info->alloc_ring_buffer_num_entries ); + + // a few of the horizontal gather functions read one dword past the end (but mask it out), so put in a normal value so no snans or denormals accidentally sneak in + for( i = 0 ; i < splits ; i++ ) + { + int width, ofs; + + // find the right most span + if ( info->scanline_extents.spans[0].n1 > info->scanline_extents.spans[1].n1 ) + width = info->scanline_extents.spans[0].n1 - info->scanline_extents.spans[0].n0; + else + width = info->scanline_extents.spans[1].n1 - info->scanline_extents.spans[1].n0; + + // this calc finds the exact end of the decoded scanline for all filter modes. + // usually this is just the width * effective channels. But we have to account + // for the area to the left of the scanline for wrap filtering and alignment, this + // is stored as a negative value in info->scanline_extents.conservative.n0. Next, + // we need to skip the exact size of the right hand size filter area (again for + // wrap mode), this is in info->scanline_extents.edge_sizes[1]). + ofs = ( width + 1 - info->scanline_extents.conservative.n0 + info->scanline_extents.edge_sizes[1] ) * effective_channels; + + // place a known, but numerically valid value in the decode buffer + info->split_info[i].decode_buffer[ ofs ] = 9999.0f; + + // if vertical filtering first, place a known, but numerically valid value in the all + // of the ring buffer accumulators + if ( vertical_first ) + { + int j; + for( j = 0; j < info->ring_buffer_num_entries ; j++ ) + { + stbir__get_ring_buffer_entry( info, info->split_info + i, j )[ ofs ] = 9999.0f; + } + } + } + } + + #undef STBIR__NEXT_PTR + + + // is this the first time through loop? + if ( info == 0 ) + { + alloced_total = ( 15 + (size_t)advance_mem ); + alloced = STBIR_MALLOC( alloced_total, user_data ); + if ( alloced == 0 ) + return 0; + } + else + return info; // success + } +} + +static int stbir__perform_resize( stbir__info const * info, int split_start, int split_count ) +{ + stbir__per_split_info * split_info = info->split_info + split_start; + + STBIR_PROFILE_CLEAR_EXTRAS(); + + STBIR_PROFILE_FIRST_START( looping ); + if (info->vertical.is_gather) + stbir__vertical_gather_loop( info, split_info, split_count ); + else + stbir__vertical_scatter_loop( info, split_info, split_count ); + STBIR_PROFILE_END( looping ); + + return 1; +} + +static void stbir__update_info_from_resize( stbir__info * info, STBIR_RESIZE * resize ) +{ + static stbir__decode_pixels_func * decode_simple[STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]= + { + /* 1ch-4ch */ stbir__decode_uint8_srgb, stbir__decode_uint8_srgb, 0, stbir__decode_float_linear, stbir__decode_half_float_linear, + }; + + static stbir__decode_pixels_func * decode_alphas[STBIRI_AR-STBIRI_RGBA+1][STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]= + { + { /* RGBA */ stbir__decode_uint8_srgb4_linearalpha, stbir__decode_uint8_srgb, 0, stbir__decode_float_linear, stbir__decode_half_float_linear }, + { /* BGRA */ stbir__decode_uint8_srgb4_linearalpha_BGRA, stbir__decode_uint8_srgb_BGRA, 0, stbir__decode_float_linear_BGRA, stbir__decode_half_float_linear_BGRA }, + { /* ARGB */ stbir__decode_uint8_srgb4_linearalpha_ARGB, stbir__decode_uint8_srgb_ARGB, 0, stbir__decode_float_linear_ARGB, stbir__decode_half_float_linear_ARGB }, + { /* ABGR */ stbir__decode_uint8_srgb4_linearalpha_ABGR, stbir__decode_uint8_srgb_ABGR, 0, stbir__decode_float_linear_ABGR, stbir__decode_half_float_linear_ABGR }, + { /* RA */ stbir__decode_uint8_srgb2_linearalpha, stbir__decode_uint8_srgb, 0, stbir__decode_float_linear, stbir__decode_half_float_linear }, + { /* AR */ stbir__decode_uint8_srgb2_linearalpha_AR, stbir__decode_uint8_srgb_AR, 0, stbir__decode_float_linear_AR, stbir__decode_half_float_linear_AR }, + }; + + static stbir__decode_pixels_func * decode_simple_scaled_or_not[2][2]= + { + { stbir__decode_uint8_linear_scaled, stbir__decode_uint8_linear }, { stbir__decode_uint16_linear_scaled, stbir__decode_uint16_linear }, + }; + + static stbir__decode_pixels_func * decode_alphas_scaled_or_not[STBIRI_AR-STBIRI_RGBA+1][2][2]= + { + { /* RGBA */ { stbir__decode_uint8_linear_scaled, stbir__decode_uint8_linear }, { stbir__decode_uint16_linear_scaled, stbir__decode_uint16_linear } }, + { /* BGRA */ { stbir__decode_uint8_linear_scaled_BGRA, stbir__decode_uint8_linear_BGRA }, { stbir__decode_uint16_linear_scaled_BGRA, stbir__decode_uint16_linear_BGRA } }, + { /* ARGB */ { stbir__decode_uint8_linear_scaled_ARGB, stbir__decode_uint8_linear_ARGB }, { stbir__decode_uint16_linear_scaled_ARGB, stbir__decode_uint16_linear_ARGB } }, + { /* ABGR */ { stbir__decode_uint8_linear_scaled_ABGR, stbir__decode_uint8_linear_ABGR }, { stbir__decode_uint16_linear_scaled_ABGR, stbir__decode_uint16_linear_ABGR } }, + { /* RA */ { stbir__decode_uint8_linear_scaled, stbir__decode_uint8_linear }, { stbir__decode_uint16_linear_scaled, stbir__decode_uint16_linear } }, + { /* AR */ { stbir__decode_uint8_linear_scaled_AR, stbir__decode_uint8_linear_AR }, { stbir__decode_uint16_linear_scaled_AR, stbir__decode_uint16_linear_AR } } + }; + + static stbir__encode_pixels_func * encode_simple[STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]= + { + /* 1ch-4ch */ stbir__encode_uint8_srgb, stbir__encode_uint8_srgb, 0, stbir__encode_float_linear, stbir__encode_half_float_linear, + }; + + static stbir__encode_pixels_func * encode_alphas[STBIRI_AR-STBIRI_RGBA+1][STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]= + { + { /* RGBA */ stbir__encode_uint8_srgb4_linearalpha, stbir__encode_uint8_srgb, 0, stbir__encode_float_linear, stbir__encode_half_float_linear }, + { /* BGRA */ stbir__encode_uint8_srgb4_linearalpha_BGRA, stbir__encode_uint8_srgb_BGRA, 0, stbir__encode_float_linear_BGRA, stbir__encode_half_float_linear_BGRA }, + { /* ARGB */ stbir__encode_uint8_srgb4_linearalpha_ARGB, stbir__encode_uint8_srgb_ARGB, 0, stbir__encode_float_linear_ARGB, stbir__encode_half_float_linear_ARGB }, + { /* ABGR */ stbir__encode_uint8_srgb4_linearalpha_ABGR, stbir__encode_uint8_srgb_ABGR, 0, stbir__encode_float_linear_ABGR, stbir__encode_half_float_linear_ABGR }, + { /* RA */ stbir__encode_uint8_srgb2_linearalpha, stbir__encode_uint8_srgb, 0, stbir__encode_float_linear, stbir__encode_half_float_linear }, + { /* AR */ stbir__encode_uint8_srgb2_linearalpha_AR, stbir__encode_uint8_srgb_AR, 0, stbir__encode_float_linear_AR, stbir__encode_half_float_linear_AR } + }; + + static stbir__encode_pixels_func * encode_simple_scaled_or_not[2][2]= + { + { stbir__encode_uint8_linear_scaled, stbir__encode_uint8_linear }, { stbir__encode_uint16_linear_scaled, stbir__encode_uint16_linear }, + }; + + static stbir__encode_pixels_func * encode_alphas_scaled_or_not[STBIRI_AR-STBIRI_RGBA+1][2][2]= + { + { /* RGBA */ { stbir__encode_uint8_linear_scaled, stbir__encode_uint8_linear }, { stbir__encode_uint16_linear_scaled, stbir__encode_uint16_linear } }, + { /* BGRA */ { stbir__encode_uint8_linear_scaled_BGRA, stbir__encode_uint8_linear_BGRA }, { stbir__encode_uint16_linear_scaled_BGRA, stbir__encode_uint16_linear_BGRA } }, + { /* ARGB */ { stbir__encode_uint8_linear_scaled_ARGB, stbir__encode_uint8_linear_ARGB }, { stbir__encode_uint16_linear_scaled_ARGB, stbir__encode_uint16_linear_ARGB } }, + { /* ABGR */ { stbir__encode_uint8_linear_scaled_ABGR, stbir__encode_uint8_linear_ABGR }, { stbir__encode_uint16_linear_scaled_ABGR, stbir__encode_uint16_linear_ABGR } }, + { /* RA */ { stbir__encode_uint8_linear_scaled, stbir__encode_uint8_linear }, { stbir__encode_uint16_linear_scaled, stbir__encode_uint16_linear } }, + { /* AR */ { stbir__encode_uint8_linear_scaled_AR, stbir__encode_uint8_linear_AR }, { stbir__encode_uint16_linear_scaled_AR, stbir__encode_uint16_linear_AR } } + }; + + stbir__decode_pixels_func * decode_pixels = 0; + stbir__encode_pixels_func * encode_pixels = 0; + stbir_datatype input_type, output_type; + + input_type = resize->input_data_type; + output_type = resize->output_data_type; + info->input_data = resize->input_pixels; + info->input_stride_bytes = resize->input_stride_in_bytes; + info->output_stride_bytes = resize->output_stride_in_bytes; + + // if we're completely point sampling, then we can turn off SRGB + if ( ( info->horizontal.filter_enum == STBIR_FILTER_POINT_SAMPLE ) && ( info->vertical.filter_enum == STBIR_FILTER_POINT_SAMPLE ) ) + { + if ( ( ( input_type == STBIR_TYPE_UINT8_SRGB ) || ( input_type == STBIR_TYPE_UINT8_SRGB_ALPHA ) ) && + ( ( output_type == STBIR_TYPE_UINT8_SRGB ) || ( output_type == STBIR_TYPE_UINT8_SRGB_ALPHA ) ) ) + { + input_type = STBIR_TYPE_UINT8; + output_type = STBIR_TYPE_UINT8; + } + } + + // recalc the output and input strides + if ( info->input_stride_bytes == 0 ) + info->input_stride_bytes = info->channels * info->horizontal.scale_info.input_full_size * stbir__type_size[input_type]; + + if ( info->output_stride_bytes == 0 ) + info->output_stride_bytes = info->channels * info->horizontal.scale_info.output_sub_size * stbir__type_size[output_type]; + + // calc offset + info->output_data = ( (char*) resize->output_pixels ) + ( (size_t) info->offset_y * (size_t) resize->output_stride_in_bytes ) + ( info->offset_x * info->channels * stbir__type_size[output_type] ); + + info->in_pixels_cb = resize->input_cb; + info->user_data = resize->user_data; + info->out_pixels_cb = resize->output_cb; + + // setup the input format converters + if ( ( input_type == STBIR_TYPE_UINT8 ) || ( input_type == STBIR_TYPE_UINT16 ) ) + { + int non_scaled = 0; + + // check if we can run unscaled - 0-255.0/0-65535.0 instead of 0-1.0 (which is a tiny bit faster when doing linear 8->8 or 16->16) + if ( ( !info->alpha_weight ) && ( !info->alpha_unweight ) ) // don't short circuit when alpha weighting (get everything to 0-1.0 as usual) + if ( ( ( input_type == STBIR_TYPE_UINT8 ) && ( output_type == STBIR_TYPE_UINT8 ) ) || ( ( input_type == STBIR_TYPE_UINT16 ) && ( output_type == STBIR_TYPE_UINT16 ) ) ) + non_scaled = 1; + + if ( info->input_pixel_layout_internal <= STBIRI_4CHANNEL ) + decode_pixels = decode_simple_scaled_or_not[ input_type == STBIR_TYPE_UINT16 ][ non_scaled ]; + else + decode_pixels = decode_alphas_scaled_or_not[ ( info->input_pixel_layout_internal - STBIRI_RGBA ) % ( STBIRI_AR-STBIRI_RGBA+1 ) ][ input_type == STBIR_TYPE_UINT16 ][ non_scaled ]; + } + else + { + if ( info->input_pixel_layout_internal <= STBIRI_4CHANNEL ) + decode_pixels = decode_simple[ input_type - STBIR_TYPE_UINT8_SRGB ]; + else + decode_pixels = decode_alphas[ ( info->input_pixel_layout_internal - STBIRI_RGBA ) % ( STBIRI_AR-STBIRI_RGBA+1 ) ][ input_type - STBIR_TYPE_UINT8_SRGB ]; + } + + // setup the output format converters + if ( ( output_type == STBIR_TYPE_UINT8 ) || ( output_type == STBIR_TYPE_UINT16 ) ) + { + int non_scaled = 0; + + // check if we can run unscaled - 0-255.0/0-65535.0 instead of 0-1.0 (which is a tiny bit faster when doing linear 8->8 or 16->16) + if ( ( !info->alpha_weight ) && ( !info->alpha_unweight ) ) // don't short circuit when alpha weighting (get everything to 0-1.0 as usual) + if ( ( ( input_type == STBIR_TYPE_UINT8 ) && ( output_type == STBIR_TYPE_UINT8 ) ) || ( ( input_type == STBIR_TYPE_UINT16 ) && ( output_type == STBIR_TYPE_UINT16 ) ) ) + non_scaled = 1; + + if ( info->output_pixel_layout_internal <= STBIRI_4CHANNEL ) + encode_pixels = encode_simple_scaled_or_not[ output_type == STBIR_TYPE_UINT16 ][ non_scaled ]; + else + encode_pixels = encode_alphas_scaled_or_not[ ( info->output_pixel_layout_internal - STBIRI_RGBA ) % ( STBIRI_AR-STBIRI_RGBA+1 ) ][ output_type == STBIR_TYPE_UINT16 ][ non_scaled ]; + } + else + { + if ( info->output_pixel_layout_internal <= STBIRI_4CHANNEL ) + encode_pixels = encode_simple[ output_type - STBIR_TYPE_UINT8_SRGB ]; + else + encode_pixels = encode_alphas[ ( info->output_pixel_layout_internal - STBIRI_RGBA ) % ( STBIRI_AR-STBIRI_RGBA+1 ) ][ output_type - STBIR_TYPE_UINT8_SRGB ]; + } + + info->input_type = input_type; + info->output_type = output_type; + info->decode_pixels = decode_pixels; + info->encode_pixels = encode_pixels; +} + +static void stbir__clip( int * outx, int * outsubw, int outw, double * u0, double * u1 ) +{ + double per, adj; + int over; + + // do left/top edge + if ( *outx < 0 ) + { + per = ( (double)*outx ) / ( (double)*outsubw ); // is negative + adj = per * ( *u1 - *u0 ); + *u0 -= adj; // increases u0 + *outx = 0; + } + + // do right/bot edge + over = outw - ( *outx + *outsubw ); + if ( over < 0 ) + { + per = ( (double)over ) / ( (double)*outsubw ); // is negative + adj = per * ( *u1 - *u0 ); + *u1 += adj; // decrease u1 + *outsubw = outw - *outx; + } +} + +// converts a double to a rational that has less than one float bit of error (returns 0 if unable to do so) +static int stbir__double_to_rational(double f, stbir_uint32 limit, stbir_uint32 *numer, stbir_uint32 *denom, int limit_denom ) // limit_denom (1) or limit numer (0) +{ + double err; + stbir_uint64 top, bot; + stbir_uint64 numer_last = 0; + stbir_uint64 denom_last = 1; + stbir_uint64 numer_estimate = 1; + stbir_uint64 denom_estimate = 0; + + // scale to past float error range + top = (stbir_uint64)( f * (double)(1 << 25) ); + bot = 1 << 25; + + // keep refining, but usually stops in a few loops - usually 5 for bad cases + for(;;) + { + stbir_uint64 est, temp; + + // hit limit, break out and do best full range estimate + if ( ( ( limit_denom ) ? denom_estimate : numer_estimate ) >= limit ) + break; + + // is the current error less than 1 bit of a float? if so, we're done + if ( denom_estimate ) + { + err = ( (double)numer_estimate / (double)denom_estimate ) - f; + if ( err < 0.0 ) err = -err; + if ( err < ( 1.0 / (double)(1<<24) ) ) + { + // yup, found it + *numer = (stbir_uint32) numer_estimate; + *denom = (stbir_uint32) denom_estimate; + return 1; + } + } + + // no more refinement bits left? break out and do full range estimate + if ( bot == 0 ) + break; + + // gcd the estimate bits + est = top / bot; + temp = top % bot; + top = bot; + bot = temp; + + // move remainders + temp = est * denom_estimate + denom_last; + denom_last = denom_estimate; + denom_estimate = temp; + + // move remainders + temp = est * numer_estimate + numer_last; + numer_last = numer_estimate; + numer_estimate = temp; + } + + // we didn't fine anything good enough for float, use a full range estimate + if ( limit_denom ) + { + numer_estimate= (stbir_uint64)( f * (double)limit + 0.5 ); + denom_estimate = limit; + } + else + { + numer_estimate = limit; + denom_estimate = (stbir_uint64)( ( (double)limit / f ) + 0.5 ); + } + + *numer = (stbir_uint32) numer_estimate; + *denom = (stbir_uint32) denom_estimate; + + err = ( denom_estimate ) ? ( ( (double)(stbir_uint32)numer_estimate / (double)(stbir_uint32)denom_estimate ) - f ) : 1.0; + if ( err < 0.0 ) err = -err; + return ( err < ( 1.0 / (double)(1<<24) ) ) ? 1 : 0; +} + +static int stbir__calculate_region_transform( stbir__scale_info * scale_info, int output_full_range, int * output_offset, int output_sub_range, int input_full_range, double input_s0, double input_s1 ) +{ + double output_range, input_range, output_s, input_s, ratio, scale; + + input_s = input_s1 - input_s0; + + // null area + if ( ( output_full_range == 0 ) || ( input_full_range == 0 ) || + ( output_sub_range == 0 ) || ( input_s <= stbir__small_float ) ) + return 0; + + // are either of the ranges completely out of bounds? + if ( ( *output_offset >= output_full_range ) || ( ( *output_offset + output_sub_range ) <= 0 ) || ( input_s0 >= (1.0f-stbir__small_float) ) || ( input_s1 <= stbir__small_float ) ) + return 0; + + output_range = (double)output_full_range; + input_range = (double)input_full_range; + + output_s = ( (double)output_sub_range) / output_range; + + // figure out the scaling to use + ratio = output_s / input_s; + + // save scale before clipping + scale = ( output_range / input_range ) * ratio; + scale_info->scale = (float)scale; + scale_info->inv_scale = (float)( 1.0 / scale ); + + // clip output area to left/right output edges (and adjust input area) + stbir__clip( output_offset, &output_sub_range, output_full_range, &input_s0, &input_s1 ); + + // recalc input area + input_s = input_s1 - input_s0; + + // after clipping do we have zero input area? + if ( input_s <= stbir__small_float ) + return 0; + + // calculate and store the starting source offsets in output pixel space + scale_info->pixel_shift = (float) ( input_s0 * ratio * output_range ); + + scale_info->scale_is_rational = stbir__double_to_rational( scale, ( scale <= 1.0 ) ? output_full_range : input_full_range, &scale_info->scale_numerator, &scale_info->scale_denominator, ( scale >= 1.0 ) ); + + scale_info->input_full_size = input_full_range; + scale_info->output_sub_size = output_sub_range; + + return 1; +} + + +static void stbir__init_and_set_layout( STBIR_RESIZE * resize, stbir_pixel_layout pixel_layout, stbir_datatype data_type ) +{ + resize->input_cb = 0; + resize->output_cb = 0; + resize->user_data = resize; + resize->samplers = 0; + resize->called_alloc = 0; + resize->horizontal_filter = STBIR_FILTER_DEFAULT; + resize->horizontal_filter_kernel = 0; resize->horizontal_filter_support = 0; + resize->vertical_filter = STBIR_FILTER_DEFAULT; + resize->vertical_filter_kernel = 0; resize->vertical_filter_support = 0; + resize->horizontal_edge = STBIR_EDGE_CLAMP; + resize->vertical_edge = STBIR_EDGE_CLAMP; + resize->input_s0 = 0; resize->input_t0 = 0; resize->input_s1 = 1; resize->input_t1 = 1; + resize->output_subx = 0; resize->output_suby = 0; resize->output_subw = resize->output_w; resize->output_subh = resize->output_h; + resize->input_data_type = data_type; + resize->output_data_type = data_type; + resize->input_pixel_layout_public = pixel_layout; + resize->output_pixel_layout_public = pixel_layout; + resize->needs_rebuild = 1; +} + +STBIRDEF void stbir_resize_init( STBIR_RESIZE * resize, + const void *input_pixels, int input_w, int input_h, int input_stride_in_bytes, // stride can be zero + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, // stride can be zero + stbir_pixel_layout pixel_layout, stbir_datatype data_type ) +{ + resize->input_pixels = input_pixels; + resize->input_w = input_w; + resize->input_h = input_h; + resize->input_stride_in_bytes = input_stride_in_bytes; + resize->output_pixels = output_pixels; + resize->output_w = output_w; + resize->output_h = output_h; + resize->output_stride_in_bytes = output_stride_in_bytes; + resize->fast_alpha = 0; + + stbir__init_and_set_layout( resize, pixel_layout, data_type ); +} + +// You can update parameters any time after resize_init +STBIRDEF void stbir_set_datatypes( STBIR_RESIZE * resize, stbir_datatype input_type, stbir_datatype output_type ) // by default, datatype from resize_init +{ + resize->input_data_type = input_type; + resize->output_data_type = output_type; + if ( ( resize->samplers ) && ( !resize->needs_rebuild ) ) + stbir__update_info_from_resize( resize->samplers, resize ); +} + +STBIRDEF void stbir_set_pixel_callbacks( STBIR_RESIZE * resize, stbir_input_callback * input_cb, stbir_output_callback * output_cb ) // no callbacks by default +{ + resize->input_cb = input_cb; + resize->output_cb = output_cb; + + if ( ( resize->samplers ) && ( !resize->needs_rebuild ) ) + { + resize->samplers->in_pixels_cb = input_cb; + resize->samplers->out_pixels_cb = output_cb; + } +} + +STBIRDEF void stbir_set_user_data( STBIR_RESIZE * resize, void * user_data ) // pass back STBIR_RESIZE* by default +{ + resize->user_data = user_data; + if ( ( resize->samplers ) && ( !resize->needs_rebuild ) ) + resize->samplers->user_data = user_data; +} + +STBIRDEF void stbir_set_buffer_ptrs( STBIR_RESIZE * resize, const void * input_pixels, int input_stride_in_bytes, void * output_pixels, int output_stride_in_bytes ) +{ + resize->input_pixels = input_pixels; + resize->input_stride_in_bytes = input_stride_in_bytes; + resize->output_pixels = output_pixels; + resize->output_stride_in_bytes = output_stride_in_bytes; + if ( ( resize->samplers ) && ( !resize->needs_rebuild ) ) + stbir__update_info_from_resize( resize->samplers, resize ); +} + + +STBIRDEF int stbir_set_edgemodes( STBIR_RESIZE * resize, stbir_edge horizontal_edge, stbir_edge vertical_edge ) // CLAMP by default +{ + resize->horizontal_edge = horizontal_edge; + resize->vertical_edge = vertical_edge; + resize->needs_rebuild = 1; + return 1; +} + +STBIRDEF int stbir_set_filters( STBIR_RESIZE * resize, stbir_filter horizontal_filter, stbir_filter vertical_filter ) // STBIR_DEFAULT_FILTER_UPSAMPLE/DOWNSAMPLE by default +{ + resize->horizontal_filter = horizontal_filter; + resize->vertical_filter = vertical_filter; + resize->needs_rebuild = 1; + return 1; +} + +STBIRDEF int stbir_set_filter_callbacks( STBIR_RESIZE * resize, stbir__kernel_callback * horizontal_filter, stbir__support_callback * horizontal_support, stbir__kernel_callback * vertical_filter, stbir__support_callback * vertical_support ) +{ + resize->horizontal_filter_kernel = horizontal_filter; resize->horizontal_filter_support = horizontal_support; + resize->vertical_filter_kernel = vertical_filter; resize->vertical_filter_support = vertical_support; + resize->needs_rebuild = 1; + return 1; +} + +STBIRDEF int stbir_set_pixel_layouts( STBIR_RESIZE * resize, stbir_pixel_layout input_pixel_layout, stbir_pixel_layout output_pixel_layout ) // sets new pixel layouts +{ + resize->input_pixel_layout_public = input_pixel_layout; + resize->output_pixel_layout_public = output_pixel_layout; + resize->needs_rebuild = 1; + return 1; +} + + +STBIRDEF int stbir_set_non_pm_alpha_speed_over_quality( STBIR_RESIZE * resize, int non_pma_alpha_speed_over_quality ) // sets alpha speed +{ + resize->fast_alpha = non_pma_alpha_speed_over_quality; + resize->needs_rebuild = 1; + return 1; +} + +STBIRDEF int stbir_set_input_subrect( STBIR_RESIZE * resize, double s0, double t0, double s1, double t1 ) // sets input region (full region by default) +{ + resize->input_s0 = s0; + resize->input_t0 = t0; + resize->input_s1 = s1; + resize->input_t1 = t1; + resize->needs_rebuild = 1; + + // are we inbounds? + if ( ( s1 < stbir__small_float ) || ( (s1-s0) < stbir__small_float ) || + ( t1 < stbir__small_float ) || ( (t1-t0) < stbir__small_float ) || + ( s0 > (1.0f-stbir__small_float) ) || + ( t0 > (1.0f-stbir__small_float) ) ) + return 0; + + return 1; +} + +STBIRDEF int stbir_set_output_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, int subw, int subh ) // sets input region (full region by default) +{ + resize->output_subx = subx; + resize->output_suby = suby; + resize->output_subw = subw; + resize->output_subh = subh; + resize->needs_rebuild = 1; + + // are we inbounds? + if ( ( subx >= resize->output_w ) || ( ( subx + subw ) <= 0 ) || ( suby >= resize->output_h ) || ( ( suby + subh ) <= 0 ) || ( subw == 0 ) || ( subh == 0 ) ) + return 0; + + return 1; +} + +STBIRDEF int stbir_set_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, int subw, int subh ) // sets both regions (full regions by default) +{ + double s0, t0, s1, t1; + + s0 = ( (double)subx ) / ( (double)resize->output_w ); + t0 = ( (double)suby ) / ( (double)resize->output_h ); + s1 = ( (double)(subx+subw) ) / ( (double)resize->output_w ); + t1 = ( (double)(suby+subh) ) / ( (double)resize->output_h ); + + resize->input_s0 = s0; + resize->input_t0 = t0; + resize->input_s1 = s1; + resize->input_t1 = t1; + resize->output_subx = subx; + resize->output_suby = suby; + resize->output_subw = subw; + resize->output_subh = subh; + resize->needs_rebuild = 1; + + // are we inbounds? + if ( ( subx >= resize->output_w ) || ( ( subx + subw ) <= 0 ) || ( suby >= resize->output_h ) || ( ( suby + subh ) <= 0 ) || ( subw == 0 ) || ( subh == 0 ) ) + return 0; + + return 1; +} + +static int stbir__perform_build( STBIR_RESIZE * resize, int splits ) +{ + stbir__contributors conservative = { 0, 0 }; + stbir__sampler horizontal, vertical; + int new_output_subx, new_output_suby; + stbir__info * out_info; + #ifdef STBIR_PROFILE + stbir__info profile_infod; // used to contain building profile info before everything is allocated + stbir__info * profile_info = &profile_infod; + #endif + + // have we already built the samplers? + if ( resize->samplers ) + return 0; + + #define STBIR_RETURN_ERROR_AND_ASSERT( exp ) STBIR_ASSERT( !(exp) ); if (exp) return 0; + STBIR_RETURN_ERROR_AND_ASSERT( (unsigned)resize->horizontal_filter >= STBIR_FILTER_OTHER) + STBIR_RETURN_ERROR_AND_ASSERT( (unsigned)resize->vertical_filter >= STBIR_FILTER_OTHER) + #undef STBIR_RETURN_ERROR_AND_ASSERT + + if ( splits <= 0 ) + return 0; + + STBIR_PROFILE_BUILD_FIRST_START( build ); + + new_output_subx = resize->output_subx; + new_output_suby = resize->output_suby; + + // do horizontal clip and scale calcs + if ( !stbir__calculate_region_transform( &horizontal.scale_info, resize->output_w, &new_output_subx, resize->output_subw, resize->input_w, resize->input_s0, resize->input_s1 ) ) + return 0; + + // do vertical clip and scale calcs + if ( !stbir__calculate_region_transform( &vertical.scale_info, resize->output_h, &new_output_suby, resize->output_subh, resize->input_h, resize->input_t0, resize->input_t1 ) ) + return 0; + + // if nothing to do, just return + if ( ( horizontal.scale_info.output_sub_size == 0 ) || ( vertical.scale_info.output_sub_size == 0 ) ) + return 0; + + stbir__set_sampler(&horizontal, resize->horizontal_filter, resize->horizontal_filter_kernel, resize->horizontal_filter_support, resize->horizontal_edge, &horizontal.scale_info, 1, resize->user_data ); + stbir__get_conservative_extents( &horizontal, &conservative, resize->user_data ); + stbir__set_sampler(&vertical, resize->vertical_filter, resize->horizontal_filter_kernel, resize->vertical_filter_support, resize->vertical_edge, &vertical.scale_info, 0, resize->user_data ); + + if ( ( vertical.scale_info.output_sub_size / splits ) < STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS ) // each split should be a minimum of 4 scanlines (handwavey choice) + { + splits = vertical.scale_info.output_sub_size / STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS; + if ( splits == 0 ) splits = 1; + } + + STBIR_PROFILE_BUILD_START( alloc ); + out_info = stbir__alloc_internal_mem_and_build_samplers( &horizontal, &vertical, &conservative, resize->input_pixel_layout_public, resize->output_pixel_layout_public, splits, new_output_subx, new_output_suby, resize->fast_alpha, resize->user_data STBIR_ONLY_PROFILE_BUILD_SET_INFO ); + STBIR_PROFILE_BUILD_END( alloc ); + STBIR_PROFILE_BUILD_END( build ); + + if ( out_info ) + { + resize->splits = splits; + resize->samplers = out_info; + resize->needs_rebuild = 0; + #ifdef STBIR_PROFILE + STBIR_MEMCPY( &out_info->profile, &profile_infod.profile, sizeof( out_info->profile ) ); + #endif + + // update anything that can be changed without recalcing samplers + stbir__update_info_from_resize( out_info, resize ); + + return splits; + } + + return 0; +} + +void stbir_free_samplers( STBIR_RESIZE * resize ) +{ + if ( resize->samplers ) + { + stbir__free_internal_mem( resize->samplers ); + resize->samplers = 0; + resize->called_alloc = 0; + } +} + +STBIRDEF int stbir_build_samplers_with_splits( STBIR_RESIZE * resize, int splits ) +{ + if ( ( resize->samplers == 0 ) || ( resize->needs_rebuild ) ) + { + if ( resize->samplers ) + stbir_free_samplers( resize ); + + resize->called_alloc = 1; + return stbir__perform_build( resize, splits ); + } + + STBIR_PROFILE_BUILD_CLEAR( resize->samplers ); + + return 1; +} + +STBIRDEF int stbir_build_samplers( STBIR_RESIZE * resize ) +{ + return stbir_build_samplers_with_splits( resize, 1 ); +} + +STBIRDEF int stbir_resize_extended( STBIR_RESIZE * resize ) +{ + int result; + + if ( ( resize->samplers == 0 ) || ( resize->needs_rebuild ) ) + { + int alloc_state = resize->called_alloc; // remember allocated state + + if ( resize->samplers ) + { + stbir__free_internal_mem( resize->samplers ); + resize->samplers = 0; + } + + if ( !stbir_build_samplers( resize ) ) + return 0; + + resize->called_alloc = alloc_state; + + // if build_samplers succeeded (above), but there are no samplers set, then + // the area to stretch into was zero pixels, so don't do anything and return + // success + if ( resize->samplers == 0 ) + return 1; + } + else + { + // didn't build anything - clear it + STBIR_PROFILE_BUILD_CLEAR( resize->samplers ); + } + + // do resize + result = stbir__perform_resize( resize->samplers, 0, resize->splits ); + + // if we alloced, then free + if ( !resize->called_alloc ) + { + stbir_free_samplers( resize ); + resize->samplers = 0; + } + + return result; +} + +STBIRDEF int stbir_resize_extended_split( STBIR_RESIZE * resize, int split_start, int split_count ) +{ + STBIR_ASSERT( resize->samplers ); + + // if we're just doing the whole thing, call full + if ( ( split_start == -1 ) || ( ( split_start == 0 ) && ( split_count == resize->splits ) ) ) + return stbir_resize_extended( resize ); + + // you **must** build samplers first when using split resize + if ( ( resize->samplers == 0 ) || ( resize->needs_rebuild ) ) + return 0; + + if ( ( split_start >= resize->splits ) || ( split_start < 0 ) || ( ( split_start + split_count ) > resize->splits ) || ( split_count <= 0 ) ) + return 0; + + // do resize + return stbir__perform_resize( resize->samplers, split_start, split_count ); +} + +static int stbir__check_output_stuff( void ** ret_ptr, int * ret_pitch, void * output_pixels, int type_size, int output_w, int output_h, int output_stride_in_bytes, stbir_internal_pixel_layout pixel_layout ) +{ + size_t size; + int pitch; + void * ptr; + + pitch = output_w * type_size * stbir__pixel_channels[ pixel_layout ]; + if ( pitch == 0 ) + return 0; + + if ( output_stride_in_bytes == 0 ) + output_stride_in_bytes = pitch; + + if ( output_stride_in_bytes < pitch ) + return 0; + + size = (size_t)output_stride_in_bytes * (size_t)output_h; + if ( size == 0 ) + return 0; + + *ret_ptr = 0; + *ret_pitch = output_stride_in_bytes; + + if ( output_pixels == 0 ) + { + ptr = STBIR_MALLOC( size, 0 ); + if ( ptr == 0 ) + return 0; + + *ret_ptr = ptr; + *ret_pitch = pitch; + } + + return 1; +} + + +STBIRDEF unsigned char * stbir_resize_uint8_linear( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_layout ) +{ + STBIR_RESIZE resize; + unsigned char * optr; + int opitch; + + if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, sizeof( unsigned char ), output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) ) + return 0; + + stbir_resize_init( &resize, + input_pixels, input_w, input_h, input_stride_in_bytes, + (optr) ? optr : output_pixels, output_w, output_h, opitch, + pixel_layout, STBIR_TYPE_UINT8 ); + + if ( !stbir_resize_extended( &resize ) ) + { + if ( optr ) + STBIR_FREE( optr, 0 ); + return 0; + } + + return (optr) ? optr : output_pixels; +} + +STBIRDEF unsigned char * stbir_resize_uint8_srgb( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_layout ) +{ + STBIR_RESIZE resize; + unsigned char * optr; + int opitch; + + if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, sizeof( unsigned char ), output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) ) + return 0; + + stbir_resize_init( &resize, + input_pixels, input_w, input_h, input_stride_in_bytes, + (optr) ? optr : output_pixels, output_w, output_h, opitch, + pixel_layout, STBIR_TYPE_UINT8_SRGB ); + + if ( !stbir_resize_extended( &resize ) ) + { + if ( optr ) + STBIR_FREE( optr, 0 ); + return 0; + } + + return (optr) ? optr : output_pixels; +} + + +STBIRDEF float * stbir_resize_float_linear( const float *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_layout ) +{ + STBIR_RESIZE resize; + float * optr; + int opitch; + + if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, sizeof( float ), output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) ) + return 0; + + stbir_resize_init( &resize, + input_pixels, input_w, input_h, input_stride_in_bytes, + (optr) ? optr : output_pixels, output_w, output_h, opitch, + pixel_layout, STBIR_TYPE_FLOAT ); + + if ( !stbir_resize_extended( &resize ) ) + { + if ( optr ) + STBIR_FREE( optr, 0 ); + return 0; + } + + return (optr) ? optr : output_pixels; +} + + +STBIRDEF void * stbir_resize( const void *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_layout, stbir_datatype data_type, + stbir_edge edge, stbir_filter filter ) +{ + STBIR_RESIZE resize; + float * optr; + int opitch; + + if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, stbir__type_size[data_type], output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) ) + return 0; + + stbir_resize_init( &resize, + input_pixels, input_w, input_h, input_stride_in_bytes, + (optr) ? optr : output_pixels, output_w, output_h, output_stride_in_bytes, + pixel_layout, data_type ); + + resize.horizontal_edge = edge; + resize.vertical_edge = edge; + resize.horizontal_filter = filter; + resize.vertical_filter = filter; + + if ( !stbir_resize_extended( &resize ) ) + { + if ( optr ) + STBIR_FREE( optr, 0 ); + return 0; + } + + return (optr) ? optr : output_pixels; +} + +#ifdef STBIR_PROFILE + +STBIRDEF void stbir_resize_build_profile_info( STBIR_PROFILE_INFO * info, STBIR_RESIZE const * resize ) +{ + static char const * bdescriptions[6] = { "Building", "Allocating", "Horizontal sampler", "Vertical sampler", "Coefficient cleanup", "Coefficient piovot" } ; + stbir__info* samp = resize->samplers; + int i; + + typedef int testa[ (STBIR__ARRAY_SIZE( bdescriptions ) == (STBIR__ARRAY_SIZE( samp->profile.array )-1) )?1:-1]; + typedef int testb[ (sizeof( samp->profile.array ) == (sizeof(samp->profile.named)) )?1:-1]; + typedef int testc[ (sizeof( info->clocks ) >= (sizeof(samp->profile.named)) )?1:-1]; + + for( i = 0 ; i < STBIR__ARRAY_SIZE( bdescriptions ) ; i++) + info->clocks[i] = samp->profile.array[i+1]; + + info->total_clocks = samp->profile.named.total; + info->descriptions = bdescriptions; + info->count = STBIR__ARRAY_SIZE( bdescriptions ); +} + +STBIRDEF void stbir_resize_split_profile_info( STBIR_PROFILE_INFO * info, STBIR_RESIZE const * resize, int split_start, int split_count ) +{ + static char const * descriptions[7] = { "Looping", "Vertical sampling", "Horizontal sampling", "Scanline input", "Scanline output", "Alpha weighting", "Alpha unweighting" }; + stbir__per_split_info * split_info; + int s, i; + + typedef int testa[ (STBIR__ARRAY_SIZE( descriptions ) == (STBIR__ARRAY_SIZE( split_info->profile.array )-1) )?1:-1]; + typedef int testb[ (sizeof( split_info->profile.array ) == (sizeof(split_info->profile.named)) )?1:-1]; + typedef int testc[ (sizeof( info->clocks ) >= (sizeof(split_info->profile.named)) )?1:-1]; + + if ( split_start == -1 ) + { + split_start = 0; + split_count = resize->samplers->splits; + } + + if ( ( split_start >= resize->splits ) || ( split_start < 0 ) || ( ( split_start + split_count ) > resize->splits ) || ( split_count <= 0 ) ) + { + info->total_clocks = 0; + info->descriptions = 0; + info->count = 0; + return; + } + + split_info = resize->samplers->split_info + split_start; + + // sum up the profile from all the splits + for( i = 0 ; i < STBIR__ARRAY_SIZE( descriptions ) ; i++ ) + { + stbir_uint64 sum = 0; + for( s = 0 ; s < split_count ; s++ ) + sum += split_info[s].profile.array[i+1]; + info->clocks[i] = sum; + } + + info->total_clocks = split_info->profile.named.total; + info->descriptions = descriptions; + info->count = STBIR__ARRAY_SIZE( descriptions ); +} + +STBIRDEF void stbir_resize_extended_profile_info( STBIR_PROFILE_INFO * info, STBIR_RESIZE const * resize ) +{ + stbir_resize_split_profile_info( info, resize, -1, 0 ); +} + +#endif // STBIR_PROFILE + +#undef STBIR_BGR +#undef STBIR_1CHANNEL +#undef STBIR_2CHANNEL +#undef STBIR_RGB +#undef STBIR_RGBA +#undef STBIR_4CHANNEL +#undef STBIR_BGRA +#undef STBIR_ARGB +#undef STBIR_ABGR +#undef STBIR_RA +#undef STBIR_AR +#undef STBIR_RGBA_PM +#undef STBIR_BGRA_PM +#undef STBIR_ARGB_PM +#undef STBIR_ABGR_PM +#undef STBIR_RA_PM +#undef STBIR_AR_PM + +#endif // STB_IMAGE_RESIZE_IMPLEMENTATION + +#else // STB_IMAGE_RESIZE_HORIZONTALS&STB_IMAGE_RESIZE_DO_VERTICALS + +// we reinclude the header file to define all the horizontal functions +// specializing each function for the number of coeffs is 20-40% faster *OVERALL* + +// by including the header file again this way, we can still debug the functions + +#define STBIR_strs_join2( start, mid, end ) start##mid##end +#define STBIR_strs_join1( start, mid, end ) STBIR_strs_join2( start, mid, end ) + +#define STBIR_strs_join24( start, mid1, mid2, end ) start##mid1##mid2##end +#define STBIR_strs_join14( start, mid1, mid2, end ) STBIR_strs_join24( start, mid1, mid2, end ) + +#ifdef STB_IMAGE_RESIZE_DO_CODERS + +#ifdef stbir__decode_suffix +#define STBIR__CODER_NAME( name ) STBIR_strs_join1( name, _, stbir__decode_suffix ) +#else +#define STBIR__CODER_NAME( name ) name +#endif + +#ifdef stbir__decode_swizzle +#define stbir__decode_simdf8_flip(reg) STBIR_strs_join1( STBIR_strs_join1( STBIR_strs_join1( STBIR_strs_join1( stbir__simdf8_0123to,stbir__decode_order0,stbir__decode_order1),stbir__decode_order2,stbir__decode_order3),stbir__decode_order0,stbir__decode_order1),stbir__decode_order2,stbir__decode_order3)(reg, reg) +#define stbir__decode_simdf4_flip(reg) STBIR_strs_join1( STBIR_strs_join1( stbir__simdf_0123to,stbir__decode_order0,stbir__decode_order1),stbir__decode_order2,stbir__decode_order3)(reg, reg) +#define stbir__encode_simdf8_unflip(reg) STBIR_strs_join1( STBIR_strs_join1( STBIR_strs_join1( STBIR_strs_join1( stbir__simdf8_0123to,stbir__encode_order0,stbir__encode_order1),stbir__encode_order2,stbir__encode_order3),stbir__encode_order0,stbir__encode_order1),stbir__encode_order2,stbir__encode_order3)(reg, reg) +#define stbir__encode_simdf4_unflip(reg) STBIR_strs_join1( STBIR_strs_join1( stbir__simdf_0123to,stbir__encode_order0,stbir__encode_order1),stbir__encode_order2,stbir__encode_order3)(reg, reg) +#else +#define stbir__decode_order0 0 +#define stbir__decode_order1 1 +#define stbir__decode_order2 2 +#define stbir__decode_order3 3 +#define stbir__encode_order0 0 +#define stbir__encode_order1 1 +#define stbir__encode_order2 2 +#define stbir__encode_order3 3 +#define stbir__decode_simdf8_flip(reg) +#define stbir__decode_simdf4_flip(reg) +#define stbir__encode_simdf8_unflip(reg) +#define stbir__encode_simdf4_unflip(reg) +#endif + +#ifdef STBIR_SIMD8 +#define stbir__encode_simdfX_unflip stbir__encode_simdf8_unflip +#else +#define stbir__encode_simdfX_unflip stbir__encode_simdf4_unflip +#endif + +static void STBIR__CODER_NAME( stbir__decode_uint8_linear_scaled )( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float * decode_end = (float*) decode + width_times_channels; + unsigned char const * input = (unsigned char const*)inputp; + + #ifdef STBIR_SIMD + unsigned char const * end_input_m16 = input + width_times_channels - 16; + if ( width_times_channels >= 16 ) + { + decode_end -= 16; + for(;;) + { + #ifdef STBIR_SIMD8 + stbir__simdi i; stbir__simdi8 o0,o1; + stbir__simdf8 of0, of1; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi8_expand_u8_to_u32( o0, o1, i ); + stbir__simdi8_convert_i32_to_float( of0, o0 ); + stbir__simdi8_convert_i32_to_float( of1, o1 ); + stbir__simdf8_mult( of0, of0, STBIR_max_uint8_as_float_inverted8); + stbir__simdf8_mult( of1, of1, STBIR_max_uint8_as_float_inverted8); + stbir__decode_simdf8_flip( of0 ); + stbir__decode_simdf8_flip( of1 ); + stbir__simdf8_store( decode + 0, of0 ); + stbir__simdf8_store( decode + 8, of1 ); + #else + stbir__simdi i, o0, o1, o2, o3; + stbir__simdf of0, of1, of2, of3; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi_expand_u8_to_u32( o0,o1,o2,o3,i); + stbir__simdi_convert_i32_to_float( of0, o0 ); + stbir__simdi_convert_i32_to_float( of1, o1 ); + stbir__simdi_convert_i32_to_float( of2, o2 ); + stbir__simdi_convert_i32_to_float( of3, o3 ); + stbir__simdf_mult( of0, of0, STBIR__CONSTF(STBIR_max_uint8_as_float_inverted) ); + stbir__simdf_mult( of1, of1, STBIR__CONSTF(STBIR_max_uint8_as_float_inverted) ); + stbir__simdf_mult( of2, of2, STBIR__CONSTF(STBIR_max_uint8_as_float_inverted) ); + stbir__simdf_mult( of3, of3, STBIR__CONSTF(STBIR_max_uint8_as_float_inverted) ); + stbir__decode_simdf4_flip( of0 ); + stbir__decode_simdf4_flip( of1 ); + stbir__decode_simdf4_flip( of2 ); + stbir__decode_simdf4_flip( of3 ); + stbir__simdf_store( decode + 0, of0 ); + stbir__simdf_store( decode + 4, of1 ); + stbir__simdf_store( decode + 8, of2 ); + stbir__simdf_store( decode + 12, of3 ); + #endif + decode += 16; + input += 16; + if ( decode <= decode_end ) + continue; + if ( decode == ( decode_end + 16 ) ) + break; + decode = decode_end; // backup and do last couple + input = end_input_m16; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + decode += 4; + while( decode <= decode_end ) + { + STBIR_SIMD_NO_UNROLL(decode); + decode[0-4] = ((float)(input[stbir__decode_order0])) * stbir__max_uint8_as_float_inverted; + decode[1-4] = ((float)(input[stbir__decode_order1])) * stbir__max_uint8_as_float_inverted; + decode[2-4] = ((float)(input[stbir__decode_order2])) * stbir__max_uint8_as_float_inverted; + decode[3-4] = ((float)(input[stbir__decode_order3])) * stbir__max_uint8_as_float_inverted; + decode += 4; + input += 4; + } + decode -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + while( decode < decode_end ) + { + STBIR_NO_UNROLL(decode); + decode[0] = ((float)(input[stbir__decode_order0])) * stbir__max_uint8_as_float_inverted; + #if stbir__coder_min_num >= 2 + decode[1] = ((float)(input[stbir__decode_order1])) * stbir__max_uint8_as_float_inverted; + #endif + #if stbir__coder_min_num >= 3 + decode[2] = ((float)(input[stbir__decode_order2])) * stbir__max_uint8_as_float_inverted; + #endif + decode += stbir__coder_min_num; + input += stbir__coder_min_num; + } + #endif +} + +static void STBIR__CODER_NAME( stbir__encode_uint8_linear_scaled )( void * outputp, int width_times_channels, float const * encode ) +{ + unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char *) outputp; + unsigned char * end_output = ( (unsigned char *) output ) + width_times_channels; + + #ifdef STBIR_SIMD + if ( width_times_channels >= stbir__simdfX_float_count*2 ) + { + float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2; + end_output -= stbir__simdfX_float_count*2; + for(;;) + { + stbir__simdfX e0, e1; + stbir__simdi i; + STBIR_SIMD_NO_UNROLL(encode); + stbir__simdfX_madd_mem( e0, STBIR_simd_point5X, STBIR_max_uint8_as_floatX, encode ); + stbir__simdfX_madd_mem( e1, STBIR_simd_point5X, STBIR_max_uint8_as_floatX, encode+stbir__simdfX_float_count ); + stbir__encode_simdfX_unflip( e0 ); + stbir__encode_simdfX_unflip( e1 ); + #ifdef STBIR_SIMD8 + stbir__simdf8_pack_to_16bytes( i, e0, e1 ); + stbir__simdi_store( output, i ); + #else + stbir__simdf_pack_to_8bytes( i, e0, e1 ); + stbir__simdi_store2( output, i ); + #endif + encode += stbir__simdfX_float_count*2; + output += stbir__simdfX_float_count*2; + if ( output <= end_output ) + continue; + if ( output == ( end_output + stbir__simdfX_float_count*2 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m8; + } + return; + } + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + while( output <= end_output ) + { + stbir__simdf e0; + stbir__simdi i0; + STBIR_NO_UNROLL(encode); + stbir__simdf_load( e0, encode ); + stbir__simdf_madd( e0, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint8_as_float), e0 ); + stbir__encode_simdf4_unflip( e0 ); + stbir__simdf_pack_to_8bytes( i0, e0, e0 ); // only use first 4 + *(int*)(output-4) = stbir__simdi_to_int( i0 ); + output += 4; + encode += 4; + } + output -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + while( output < end_output ) + { + stbir__simdf e0; + STBIR_NO_UNROLL(encode); + stbir__simdf_madd1_mem( e0, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint8_as_float), encode+stbir__encode_order0 ); output[0] = stbir__simdf_convert_float_to_uint8( e0 ); + #if stbir__coder_min_num >= 2 + stbir__simdf_madd1_mem( e0, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint8_as_float), encode+stbir__encode_order1 ); output[1] = stbir__simdf_convert_float_to_uint8( e0 ); + #endif + #if stbir__coder_min_num >= 3 + stbir__simdf_madd1_mem( e0, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint8_as_float), encode+stbir__encode_order2 ); output[2] = stbir__simdf_convert_float_to_uint8( e0 ); + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif + + #else + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + while( output <= end_output ) + { + float f; + f = encode[stbir__encode_order0] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[0-4] = (unsigned char)f; + f = encode[stbir__encode_order1] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[1-4] = (unsigned char)f; + f = encode[stbir__encode_order2] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[2-4] = (unsigned char)f; + f = encode[stbir__encode_order3] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[3-4] = (unsigned char)f; + output += 4; + encode += 4; + } + output -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + while( output < end_output ) + { + float f; + STBIR_NO_UNROLL(encode); + f = encode[stbir__encode_order0] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[0] = (unsigned char)f; + #if stbir__coder_min_num >= 2 + f = encode[stbir__encode_order1] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[1] = (unsigned char)f; + #endif + #if stbir__coder_min_num >= 3 + f = encode[stbir__encode_order2] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[2] = (unsigned char)f; + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif + #endif +} + +static void STBIR__CODER_NAME(stbir__decode_uint8_linear)( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float * decode_end = (float*) decode + width_times_channels; + unsigned char const * input = (unsigned char const*)inputp; + + #ifdef STBIR_SIMD + unsigned char const * end_input_m16 = input + width_times_channels - 16; + if ( width_times_channels >= 16 ) + { + decode_end -= 16; + for(;;) + { + #ifdef STBIR_SIMD8 + stbir__simdi i; stbir__simdi8 o0,o1; + stbir__simdf8 of0, of1; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi8_expand_u8_to_u32( o0, o1, i ); + stbir__simdi8_convert_i32_to_float( of0, o0 ); + stbir__simdi8_convert_i32_to_float( of1, o1 ); + stbir__decode_simdf8_flip( of0 ); + stbir__decode_simdf8_flip( of1 ); + stbir__simdf8_store( decode + 0, of0 ); + stbir__simdf8_store( decode + 8, of1 ); + #else + stbir__simdi i, o0, o1, o2, o3; + stbir__simdf of0, of1, of2, of3; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi_expand_u8_to_u32( o0,o1,o2,o3,i); + stbir__simdi_convert_i32_to_float( of0, o0 ); + stbir__simdi_convert_i32_to_float( of1, o1 ); + stbir__simdi_convert_i32_to_float( of2, o2 ); + stbir__simdi_convert_i32_to_float( of3, o3 ); + stbir__decode_simdf4_flip( of0 ); + stbir__decode_simdf4_flip( of1 ); + stbir__decode_simdf4_flip( of2 ); + stbir__decode_simdf4_flip( of3 ); + stbir__simdf_store( decode + 0, of0 ); + stbir__simdf_store( decode + 4, of1 ); + stbir__simdf_store( decode + 8, of2 ); + stbir__simdf_store( decode + 12, of3 ); +#endif + decode += 16; + input += 16; + if ( decode <= decode_end ) + continue; + if ( decode == ( decode_end + 16 ) ) + break; + decode = decode_end; // backup and do last couple + input = end_input_m16; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + decode += 4; + while( decode <= decode_end ) + { + STBIR_SIMD_NO_UNROLL(decode); + decode[0-4] = ((float)(input[stbir__decode_order0])); + decode[1-4] = ((float)(input[stbir__decode_order1])); + decode[2-4] = ((float)(input[stbir__decode_order2])); + decode[3-4] = ((float)(input[stbir__decode_order3])); + decode += 4; + input += 4; + } + decode -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + while( decode < decode_end ) + { + STBIR_NO_UNROLL(decode); + decode[0] = ((float)(input[stbir__decode_order0])); + #if stbir__coder_min_num >= 2 + decode[1] = ((float)(input[stbir__decode_order1])); + #endif + #if stbir__coder_min_num >= 3 + decode[2] = ((float)(input[stbir__decode_order2])); + #endif + decode += stbir__coder_min_num; + input += stbir__coder_min_num; + } + #endif +} + +static void STBIR__CODER_NAME( stbir__encode_uint8_linear )( void * outputp, int width_times_channels, float const * encode ) +{ + unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char *) outputp; + unsigned char * end_output = ( (unsigned char *) output ) + width_times_channels; + + #ifdef STBIR_SIMD + if ( width_times_channels >= stbir__simdfX_float_count*2 ) + { + float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2; + end_output -= stbir__simdfX_float_count*2; + for(;;) + { + stbir__simdfX e0, e1; + stbir__simdi i; + STBIR_SIMD_NO_UNROLL(encode); + stbir__simdfX_add_mem( e0, STBIR_simd_point5X, encode ); + stbir__simdfX_add_mem( e1, STBIR_simd_point5X, encode+stbir__simdfX_float_count ); + stbir__encode_simdfX_unflip( e0 ); + stbir__encode_simdfX_unflip( e1 ); + #ifdef STBIR_SIMD8 + stbir__simdf8_pack_to_16bytes( i, e0, e1 ); + stbir__simdi_store( output, i ); + #else + stbir__simdf_pack_to_8bytes( i, e0, e1 ); + stbir__simdi_store2( output, i ); + #endif + encode += stbir__simdfX_float_count*2; + output += stbir__simdfX_float_count*2; + if ( output <= end_output ) + continue; + if ( output == ( end_output + stbir__simdfX_float_count*2 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m8; + } + return; + } + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + while( output <= end_output ) + { + stbir__simdf e0; + stbir__simdi i0; + STBIR_NO_UNROLL(encode); + stbir__simdf_load( e0, encode ); + stbir__simdf_add( e0, STBIR__CONSTF(STBIR_simd_point5), e0 ); + stbir__encode_simdf4_unflip( e0 ); + stbir__simdf_pack_to_8bytes( i0, e0, e0 ); // only use first 4 + *(int*)(output-4) = stbir__simdi_to_int( i0 ); + output += 4; + encode += 4; + } + output -= 4; + #endif + + #else + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + while( output <= end_output ) + { + float f; + f = encode[stbir__encode_order0] + 0.5f; STBIR_CLAMP(f, 0, 255); output[0-4] = (unsigned char)f; + f = encode[stbir__encode_order1] + 0.5f; STBIR_CLAMP(f, 0, 255); output[1-4] = (unsigned char)f; + f = encode[stbir__encode_order2] + 0.5f; STBIR_CLAMP(f, 0, 255); output[2-4] = (unsigned char)f; + f = encode[stbir__encode_order3] + 0.5f; STBIR_CLAMP(f, 0, 255); output[3-4] = (unsigned char)f; + output += 4; + encode += 4; + } + output -= 4; + #endif + + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + while( output < end_output ) + { + float f; + STBIR_NO_UNROLL(encode); + f = encode[stbir__encode_order0] + 0.5f; STBIR_CLAMP(f, 0, 255); output[0] = (unsigned char)f; + #if stbir__coder_min_num >= 2 + f = encode[stbir__encode_order1] + 0.5f; STBIR_CLAMP(f, 0, 255); output[1] = (unsigned char)f; + #endif + #if stbir__coder_min_num >= 3 + f = encode[stbir__encode_order2] + 0.5f; STBIR_CLAMP(f, 0, 255); output[2] = (unsigned char)f; + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif +} + +static void STBIR__CODER_NAME(stbir__decode_uint8_srgb)( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float const * decode_end = (float*) decode + width_times_channels; + unsigned char const * input = (unsigned char const *)inputp; + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + decode += 4; + while( decode <= decode_end ) + { + decode[0-4] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order0 ] ]; + decode[1-4] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order1 ] ]; + decode[2-4] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order2 ] ]; + decode[3-4] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order3 ] ]; + decode += 4; + input += 4; + } + decode -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + while( decode < decode_end ) + { + STBIR_NO_UNROLL(decode); + decode[0] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order0 ] ]; + #if stbir__coder_min_num >= 2 + decode[1] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order1 ] ]; + #endif + #if stbir__coder_min_num >= 3 + decode[2] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order2 ] ]; + #endif + decode += stbir__coder_min_num; + input += stbir__coder_min_num; + } + #endif +} + +#define stbir__min_max_shift20( i, f ) \ + stbir__simdf_max( f, f, stbir_simdf_casti(STBIR__CONSTI( STBIR_almost_zero )) ); \ + stbir__simdf_min( f, f, stbir_simdf_casti(STBIR__CONSTI( STBIR_almost_one )) ); \ + stbir__simdi_32shr( i, stbir_simdi_castf( f ), 20 ); + +#define stbir__scale_and_convert( i, f ) \ + stbir__simdf_madd( f, STBIR__CONSTF( STBIR_simd_point5 ), STBIR__CONSTF( STBIR_max_uint8_as_float ), f ); \ + stbir__simdf_max( f, f, stbir__simdf_zeroP() ); \ + stbir__simdf_min( f, f, STBIR__CONSTF( STBIR_max_uint8_as_float ) ); \ + stbir__simdf_convert_float_to_i32( i, f ); + +#define stbir__linear_to_srgb_finish( i, f ) \ +{ \ + stbir__simdi temp; \ + stbir__simdi_32shr( temp, stbir_simdi_castf( f ), 12 ) ; \ + stbir__simdi_and( temp, temp, STBIR__CONSTI(STBIR_mastissa_mask) ); \ + stbir__simdi_or( temp, temp, STBIR__CONSTI(STBIR_topscale) ); \ + stbir__simdi_16madd( i, i, temp ); \ + stbir__simdi_32shr( i, i, 16 ); \ +} + +#define stbir__simdi_table_lookup2( v0,v1, table ) \ +{ \ + stbir__simdi_u32 temp0,temp1; \ + temp0.m128i_i128 = v0; \ + temp1.m128i_i128 = v1; \ + temp0.m128i_u32[0] = table[temp0.m128i_i32[0]]; temp0.m128i_u32[1] = table[temp0.m128i_i32[1]]; temp0.m128i_u32[2] = table[temp0.m128i_i32[2]]; temp0.m128i_u32[3] = table[temp0.m128i_i32[3]]; \ + temp1.m128i_u32[0] = table[temp1.m128i_i32[0]]; temp1.m128i_u32[1] = table[temp1.m128i_i32[1]]; temp1.m128i_u32[2] = table[temp1.m128i_i32[2]]; temp1.m128i_u32[3] = table[temp1.m128i_i32[3]]; \ + v0 = temp0.m128i_i128; \ + v1 = temp1.m128i_i128; \ +} + +#define stbir__simdi_table_lookup3( v0,v1,v2, table ) \ +{ \ + stbir__simdi_u32 temp0,temp1,temp2; \ + temp0.m128i_i128 = v0; \ + temp1.m128i_i128 = v1; \ + temp2.m128i_i128 = v2; \ + temp0.m128i_u32[0] = table[temp0.m128i_i32[0]]; temp0.m128i_u32[1] = table[temp0.m128i_i32[1]]; temp0.m128i_u32[2] = table[temp0.m128i_i32[2]]; temp0.m128i_u32[3] = table[temp0.m128i_i32[3]]; \ + temp1.m128i_u32[0] = table[temp1.m128i_i32[0]]; temp1.m128i_u32[1] = table[temp1.m128i_i32[1]]; temp1.m128i_u32[2] = table[temp1.m128i_i32[2]]; temp1.m128i_u32[3] = table[temp1.m128i_i32[3]]; \ + temp2.m128i_u32[0] = table[temp2.m128i_i32[0]]; temp2.m128i_u32[1] = table[temp2.m128i_i32[1]]; temp2.m128i_u32[2] = table[temp2.m128i_i32[2]]; temp2.m128i_u32[3] = table[temp2.m128i_i32[3]]; \ + v0 = temp0.m128i_i128; \ + v1 = temp1.m128i_i128; \ + v2 = temp2.m128i_i128; \ +} + +#define stbir__simdi_table_lookup4( v0,v1,v2,v3, table ) \ +{ \ + stbir__simdi_u32 temp0,temp1,temp2,temp3; \ + temp0.m128i_i128 = v0; \ + temp1.m128i_i128 = v1; \ + temp2.m128i_i128 = v2; \ + temp3.m128i_i128 = v3; \ + temp0.m128i_u32[0] = table[temp0.m128i_i32[0]]; temp0.m128i_u32[1] = table[temp0.m128i_i32[1]]; temp0.m128i_u32[2] = table[temp0.m128i_i32[2]]; temp0.m128i_u32[3] = table[temp0.m128i_i32[3]]; \ + temp1.m128i_u32[0] = table[temp1.m128i_i32[0]]; temp1.m128i_u32[1] = table[temp1.m128i_i32[1]]; temp1.m128i_u32[2] = table[temp1.m128i_i32[2]]; temp1.m128i_u32[3] = table[temp1.m128i_i32[3]]; \ + temp2.m128i_u32[0] = table[temp2.m128i_i32[0]]; temp2.m128i_u32[1] = table[temp2.m128i_i32[1]]; temp2.m128i_u32[2] = table[temp2.m128i_i32[2]]; temp2.m128i_u32[3] = table[temp2.m128i_i32[3]]; \ + temp3.m128i_u32[0] = table[temp3.m128i_i32[0]]; temp3.m128i_u32[1] = table[temp3.m128i_i32[1]]; temp3.m128i_u32[2] = table[temp3.m128i_i32[2]]; temp3.m128i_u32[3] = table[temp3.m128i_i32[3]]; \ + v0 = temp0.m128i_i128; \ + v1 = temp1.m128i_i128; \ + v2 = temp2.m128i_i128; \ + v3 = temp3.m128i_i128; \ +} + +static void STBIR__CODER_NAME( stbir__encode_uint8_srgb )( void * outputp, int width_times_channels, float const * encode ) +{ + unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char*) outputp; + unsigned char * end_output = ( (unsigned char*) output ) + width_times_channels; + + #ifdef STBIR_SIMD + + if ( width_times_channels >= 16 ) + { + float const * end_encode_m16 = encode + width_times_channels - 16; + end_output -= 16; + for(;;) + { + stbir__simdf f0, f1, f2, f3; + stbir__simdi i0, i1, i2, i3; + STBIR_SIMD_NO_UNROLL(encode); + + stbir__simdf_load4_transposed( f0, f1, f2, f3, encode ); + + stbir__min_max_shift20( i0, f0 ); + stbir__min_max_shift20( i1, f1 ); + stbir__min_max_shift20( i2, f2 ); + stbir__min_max_shift20( i3, f3 ); + + stbir__simdi_table_lookup4( i0, i1, i2, i3, ( fp32_to_srgb8_tab4 - (127-13)*8 ) ); + + stbir__linear_to_srgb_finish( i0, f0 ); + stbir__linear_to_srgb_finish( i1, f1 ); + stbir__linear_to_srgb_finish( i2, f2 ); + stbir__linear_to_srgb_finish( i3, f3 ); + + stbir__interleave_pack_and_store_16_u8( output, STBIR_strs_join1(i, ,stbir__encode_order0), STBIR_strs_join1(i, ,stbir__encode_order1), STBIR_strs_join1(i, ,stbir__encode_order2), STBIR_strs_join1(i, ,stbir__encode_order3) ); + + encode += 16; + output += 16; + if ( output <= end_output ) + continue; + if ( output == ( end_output + 16 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m16; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + while ( output <= end_output ) + { + STBIR_SIMD_NO_UNROLL(encode); + + output[0-4] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order0] ); + output[1-4] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order1] ); + output[2-4] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order2] ); + output[3-4] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order3] ); + + output += 4; + encode += 4; + } + output -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + while( output < end_output ) + { + STBIR_NO_UNROLL(encode); + output[0] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order0] ); + #if stbir__coder_min_num >= 2 + output[1] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order1] ); + #endif + #if stbir__coder_min_num >= 3 + output[2] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order2] ); + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif +} + +#if ( stbir__coder_min_num == 4 ) || ( ( stbir__coder_min_num == 1 ) && ( !defined(stbir__decode_swizzle) ) ) + +static void STBIR__CODER_NAME(stbir__decode_uint8_srgb4_linearalpha)( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float const * decode_end = (float*) decode + width_times_channels; + unsigned char const * input = (unsigned char const *)inputp; + do { + decode[0] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order0] ]; + decode[1] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order1] ]; + decode[2] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order2] ]; + decode[3] = ( (float) input[stbir__decode_order3] ) * stbir__max_uint8_as_float_inverted; + input += 4; + decode += 4; + } while( decode < decode_end ); +} + + +static void STBIR__CODER_NAME( stbir__encode_uint8_srgb4_linearalpha )( void * outputp, int width_times_channels, float const * encode ) +{ + unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char*) outputp; + unsigned char * end_output = ( (unsigned char*) output ) + width_times_channels; + + #ifdef STBIR_SIMD + + if ( width_times_channels >= 16 ) + { + float const * end_encode_m16 = encode + width_times_channels - 16; + end_output -= 16; + for(;;) + { + stbir__simdf f0, f1, f2, f3; + stbir__simdi i0, i1, i2, i3; + + STBIR_SIMD_NO_UNROLL(encode); + stbir__simdf_load4_transposed( f0, f1, f2, f3, encode ); + + stbir__min_max_shift20( i0, f0 ); + stbir__min_max_shift20( i1, f1 ); + stbir__min_max_shift20( i2, f2 ); + stbir__scale_and_convert( i3, f3 ); + + stbir__simdi_table_lookup3( i0, i1, i2, ( fp32_to_srgb8_tab4 - (127-13)*8 ) ); + + stbir__linear_to_srgb_finish( i0, f0 ); + stbir__linear_to_srgb_finish( i1, f1 ); + stbir__linear_to_srgb_finish( i2, f2 ); + + stbir__interleave_pack_and_store_16_u8( output, STBIR_strs_join1(i, ,stbir__encode_order0), STBIR_strs_join1(i, ,stbir__encode_order1), STBIR_strs_join1(i, ,stbir__encode_order2), STBIR_strs_join1(i, ,stbir__encode_order3) ); + + output += 16; + encode += 16; + + if ( output <= end_output ) + continue; + if ( output == ( end_output + 16 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m16; + } + return; + } + #endif + + do { + float f; + STBIR_SIMD_NO_UNROLL(encode); + + output[stbir__decode_order0] = stbir__linear_to_srgb_uchar( encode[0] ); + output[stbir__decode_order1] = stbir__linear_to_srgb_uchar( encode[1] ); + output[stbir__decode_order2] = stbir__linear_to_srgb_uchar( encode[2] ); + + f = encode[3] * stbir__max_uint8_as_float + 0.5f; + STBIR_CLAMP(f, 0, 255); + output[stbir__decode_order3] = (unsigned char) f; + + output += 4; + encode += 4; + } while( output < end_output ); +} + +#endif + +#if ( stbir__coder_min_num == 2 ) || ( ( stbir__coder_min_num == 1 ) && ( !defined(stbir__decode_swizzle) ) ) + +static void STBIR__CODER_NAME(stbir__decode_uint8_srgb2_linearalpha)( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float const * decode_end = (float*) decode + width_times_channels; + unsigned char const * input = (unsigned char const *)inputp; + decode += 4; + while( decode <= decode_end ) + { + decode[0-4] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order0] ]; + decode[1-4] = ( (float) input[stbir__decode_order1] ) * stbir__max_uint8_as_float_inverted; + decode[2-4] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order0+2] ]; + decode[3-4] = ( (float) input[stbir__decode_order1+2] ) * stbir__max_uint8_as_float_inverted; + input += 4; + decode += 4; + } + decode -= 4; + if( decode < decode_end ) + { + decode[0] = stbir__srgb_uchar_to_linear_float[ stbir__decode_order0 ]; + decode[1] = ( (float) input[stbir__decode_order1] ) * stbir__max_uint8_as_float_inverted; + } +} + +static void STBIR__CODER_NAME( stbir__encode_uint8_srgb2_linearalpha )( void * outputp, int width_times_channels, float const * encode ) +{ + unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char*) outputp; + unsigned char * end_output = ( (unsigned char*) output ) + width_times_channels; + + #ifdef STBIR_SIMD + + if ( width_times_channels >= 16 ) + { + float const * end_encode_m16 = encode + width_times_channels - 16; + end_output -= 16; + for(;;) + { + stbir__simdf f0, f1, f2, f3; + stbir__simdi i0, i1, i2, i3; + + STBIR_SIMD_NO_UNROLL(encode); + stbir__simdf_load4_transposed( f0, f1, f2, f3, encode ); + + stbir__min_max_shift20( i0, f0 ); + stbir__scale_and_convert( i1, f1 ); + stbir__min_max_shift20( i2, f2 ); + stbir__scale_and_convert( i3, f3 ); + + stbir__simdi_table_lookup2( i0, i2, ( fp32_to_srgb8_tab4 - (127-13)*8 ) ); + + stbir__linear_to_srgb_finish( i0, f0 ); + stbir__linear_to_srgb_finish( i2, f2 ); + + stbir__interleave_pack_and_store_16_u8( output, STBIR_strs_join1(i, ,stbir__encode_order0), STBIR_strs_join1(i, ,stbir__encode_order1), STBIR_strs_join1(i, ,stbir__encode_order2), STBIR_strs_join1(i, ,stbir__encode_order3) ); + + output += 16; + encode += 16; + if ( output <= end_output ) + continue; + if ( output == ( end_output + 16 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m16; + } + return; + } + #endif + + do { + float f; + STBIR_SIMD_NO_UNROLL(encode); + + output[stbir__decode_order0] = stbir__linear_to_srgb_uchar( encode[0] ); + + f = encode[1] * stbir__max_uint8_as_float + 0.5f; + STBIR_CLAMP(f, 0, 255); + output[stbir__decode_order1] = (unsigned char) f; + + output += 2; + encode += 2; + } while( output < end_output ); +} + +#endif + +static void STBIR__CODER_NAME(stbir__decode_uint16_linear_scaled)( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float * decode_end = (float*) decode + width_times_channels; + unsigned short const * input = (unsigned short const *)inputp; + + #ifdef STBIR_SIMD + unsigned short const * end_input_m8 = input + width_times_channels - 8; + if ( width_times_channels >= 8 ) + { + decode_end -= 8; + for(;;) + { + #ifdef STBIR_SIMD8 + stbir__simdi i; stbir__simdi8 o; + stbir__simdf8 of; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi8_expand_u16_to_u32( o, i ); + stbir__simdi8_convert_i32_to_float( of, o ); + stbir__simdf8_mult( of, of, STBIR_max_uint16_as_float_inverted8); + stbir__decode_simdf8_flip( of ); + stbir__simdf8_store( decode + 0, of ); + #else + stbir__simdi i, o0, o1; + stbir__simdf of0, of1; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi_expand_u16_to_u32( o0,o1,i ); + stbir__simdi_convert_i32_to_float( of0, o0 ); + stbir__simdi_convert_i32_to_float( of1, o1 ); + stbir__simdf_mult( of0, of0, STBIR__CONSTF(STBIR_max_uint16_as_float_inverted) ); + stbir__simdf_mult( of1, of1, STBIR__CONSTF(STBIR_max_uint16_as_float_inverted)); + stbir__decode_simdf4_flip( of0 ); + stbir__decode_simdf4_flip( of1 ); + stbir__simdf_store( decode + 0, of0 ); + stbir__simdf_store( decode + 4, of1 ); + #endif + decode += 8; + input += 8; + if ( decode <= decode_end ) + continue; + if ( decode == ( decode_end + 8 ) ) + break; + decode = decode_end; // backup and do last couple + input = end_input_m8; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + decode += 4; + while( decode <= decode_end ) + { + STBIR_SIMD_NO_UNROLL(decode); + decode[0-4] = ((float)(input[stbir__decode_order0])) * stbir__max_uint16_as_float_inverted; + decode[1-4] = ((float)(input[stbir__decode_order1])) * stbir__max_uint16_as_float_inverted; + decode[2-4] = ((float)(input[stbir__decode_order2])) * stbir__max_uint16_as_float_inverted; + decode[3-4] = ((float)(input[stbir__decode_order3])) * stbir__max_uint16_as_float_inverted; + decode += 4; + input += 4; + } + decode -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + while( decode < decode_end ) + { + STBIR_NO_UNROLL(decode); + decode[0] = ((float)(input[stbir__decode_order0])) * stbir__max_uint16_as_float_inverted; + #if stbir__coder_min_num >= 2 + decode[1] = ((float)(input[stbir__decode_order1])) * stbir__max_uint16_as_float_inverted; + #endif + #if stbir__coder_min_num >= 3 + decode[2] = ((float)(input[stbir__decode_order2])) * stbir__max_uint16_as_float_inverted; + #endif + decode += stbir__coder_min_num; + input += stbir__coder_min_num; + } + #endif +} + + +static void STBIR__CODER_NAME(stbir__encode_uint16_linear_scaled)( void * outputp, int width_times_channels, float const * encode ) +{ + unsigned short STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned short*) outputp; + unsigned short * end_output = ( (unsigned short*) output ) + width_times_channels; + + #ifdef STBIR_SIMD + { + if ( width_times_channels >= stbir__simdfX_float_count*2 ) + { + float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2; + end_output -= stbir__simdfX_float_count*2; + for(;;) + { + stbir__simdfX e0, e1; + stbir__simdiX i; + STBIR_SIMD_NO_UNROLL(encode); + stbir__simdfX_madd_mem( e0, STBIR_simd_point5X, STBIR_max_uint16_as_floatX, encode ); + stbir__simdfX_madd_mem( e1, STBIR_simd_point5X, STBIR_max_uint16_as_floatX, encode+stbir__simdfX_float_count ); + stbir__encode_simdfX_unflip( e0 ); + stbir__encode_simdfX_unflip( e1 ); + stbir__simdfX_pack_to_words( i, e0, e1 ); + stbir__simdiX_store( output, i ); + encode += stbir__simdfX_float_count*2; + output += stbir__simdfX_float_count*2; + if ( output <= end_output ) + continue; + if ( output == ( end_output + stbir__simdfX_float_count*2 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m8; + } + return; + } + } + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + while( output <= end_output ) + { + stbir__simdf e; + stbir__simdi i; + STBIR_NO_UNROLL(encode); + stbir__simdf_load( e, encode ); + stbir__simdf_madd( e, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint16_as_float), e ); + stbir__encode_simdf4_unflip( e ); + stbir__simdf_pack_to_8words( i, e, e ); // only use first 4 + stbir__simdi_store2( output-4, i ); + output += 4; + encode += 4; + } + output -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + while( output < end_output ) + { + stbir__simdf e; + STBIR_NO_UNROLL(encode); + stbir__simdf_madd1_mem( e, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint16_as_float), encode+stbir__encode_order0 ); output[0] = stbir__simdf_convert_float_to_short( e ); + #if stbir__coder_min_num >= 2 + stbir__simdf_madd1_mem( e, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint16_as_float), encode+stbir__encode_order1 ); output[1] = stbir__simdf_convert_float_to_short( e ); + #endif + #if stbir__coder_min_num >= 3 + stbir__simdf_madd1_mem( e, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint16_as_float), encode+stbir__encode_order2 ); output[2] = stbir__simdf_convert_float_to_short( e ); + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif + + #else + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + while( output <= end_output ) + { + float f; + STBIR_SIMD_NO_UNROLL(encode); + f = encode[stbir__encode_order0] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[0-4] = (unsigned short)f; + f = encode[stbir__encode_order1] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[1-4] = (unsigned short)f; + f = encode[stbir__encode_order2] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[2-4] = (unsigned short)f; + f = encode[stbir__encode_order3] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[3-4] = (unsigned short)f; + output += 4; + encode += 4; + } + output -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + while( output < end_output ) + { + float f; + STBIR_NO_UNROLL(encode); + f = encode[stbir__encode_order0] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[0] = (unsigned short)f; + #if stbir__coder_min_num >= 2 + f = encode[stbir__encode_order1] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[1] = (unsigned short)f; + #endif + #if stbir__coder_min_num >= 3 + f = encode[stbir__encode_order2] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[2] = (unsigned short)f; + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif + #endif +} + +static void STBIR__CODER_NAME(stbir__decode_uint16_linear)( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float * decode_end = (float*) decode + width_times_channels; + unsigned short const * input = (unsigned short const *)inputp; + + #ifdef STBIR_SIMD + unsigned short const * end_input_m8 = input + width_times_channels - 8; + if ( width_times_channels >= 8 ) + { + decode_end -= 8; + for(;;) + { + #ifdef STBIR_SIMD8 + stbir__simdi i; stbir__simdi8 o; + stbir__simdf8 of; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi8_expand_u16_to_u32( o, i ); + stbir__simdi8_convert_i32_to_float( of, o ); + stbir__decode_simdf8_flip( of ); + stbir__simdf8_store( decode + 0, of ); + #else + stbir__simdi i, o0, o1; + stbir__simdf of0, of1; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi_expand_u16_to_u32( o0, o1, i ); + stbir__simdi_convert_i32_to_float( of0, o0 ); + stbir__simdi_convert_i32_to_float( of1, o1 ); + stbir__decode_simdf4_flip( of0 ); + stbir__decode_simdf4_flip( of1 ); + stbir__simdf_store( decode + 0, of0 ); + stbir__simdf_store( decode + 4, of1 ); + #endif + decode += 8; + input += 8; + if ( decode <= decode_end ) + continue; + if ( decode == ( decode_end + 8 ) ) + break; + decode = decode_end; // backup and do last couple + input = end_input_m8; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + decode += 4; + while( decode <= decode_end ) + { + STBIR_SIMD_NO_UNROLL(decode); + decode[0-4] = ((float)(input[stbir__decode_order0])); + decode[1-4] = ((float)(input[stbir__decode_order1])); + decode[2-4] = ((float)(input[stbir__decode_order2])); + decode[3-4] = ((float)(input[stbir__decode_order3])); + decode += 4; + input += 4; + } + decode -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + while( decode < decode_end ) + { + STBIR_NO_UNROLL(decode); + decode[0] = ((float)(input[stbir__decode_order0])); + #if stbir__coder_min_num >= 2 + decode[1] = ((float)(input[stbir__decode_order1])); + #endif + #if stbir__coder_min_num >= 3 + decode[2] = ((float)(input[stbir__decode_order2])); + #endif + decode += stbir__coder_min_num; + input += stbir__coder_min_num; + } + #endif +} + +static void STBIR__CODER_NAME(stbir__encode_uint16_linear)( void * outputp, int width_times_channels, float const * encode ) +{ + unsigned short STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned short*) outputp; + unsigned short * end_output = ( (unsigned short*) output ) + width_times_channels; + + #ifdef STBIR_SIMD + { + if ( width_times_channels >= stbir__simdfX_float_count*2 ) + { + float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2; + end_output -= stbir__simdfX_float_count*2; + for(;;) + { + stbir__simdfX e0, e1; + stbir__simdiX i; + STBIR_SIMD_NO_UNROLL(encode); + stbir__simdfX_add_mem( e0, STBIR_simd_point5X, encode ); + stbir__simdfX_add_mem( e1, STBIR_simd_point5X, encode+stbir__simdfX_float_count ); + stbir__encode_simdfX_unflip( e0 ); + stbir__encode_simdfX_unflip( e1 ); + stbir__simdfX_pack_to_words( i, e0, e1 ); + stbir__simdiX_store( output, i ); + encode += stbir__simdfX_float_count*2; + output += stbir__simdfX_float_count*2; + if ( output <= end_output ) + continue; + if ( output == ( end_output + stbir__simdfX_float_count*2 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m8; + } + return; + } + } + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + while( output <= end_output ) + { + stbir__simdf e; + stbir__simdi i; + STBIR_NO_UNROLL(encode); + stbir__simdf_load( e, encode ); + stbir__simdf_add( e, STBIR__CONSTF(STBIR_simd_point5), e ); + stbir__encode_simdf4_unflip( e ); + stbir__simdf_pack_to_8words( i, e, e ); // only use first 4 + stbir__simdi_store2( output-4, i ); + output += 4; + encode += 4; + } + output -= 4; + #endif + + #else + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + while( output <= end_output ) + { + float f; + STBIR_SIMD_NO_UNROLL(encode); + f = encode[stbir__encode_order0] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[0-4] = (unsigned short)f; + f = encode[stbir__encode_order1] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[1-4] = (unsigned short)f; + f = encode[stbir__encode_order2] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[2-4] = (unsigned short)f; + f = encode[stbir__encode_order3] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[3-4] = (unsigned short)f; + output += 4; + encode += 4; + } + output -= 4; + #endif + + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + while( output < end_output ) + { + float f; + STBIR_NO_UNROLL(encode); + f = encode[stbir__encode_order0] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[0] = (unsigned short)f; + #if stbir__coder_min_num >= 2 + f = encode[stbir__encode_order1] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[1] = (unsigned short)f; + #endif + #if stbir__coder_min_num >= 3 + f = encode[stbir__encode_order2] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[2] = (unsigned short)f; + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif +} + +static void STBIR__CODER_NAME(stbir__decode_half_float_linear)( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float * decode_end = (float*) decode + width_times_channels; + stbir__FP16 const * input = (stbir__FP16 const *)inputp; + + #ifdef STBIR_SIMD + if ( width_times_channels >= 8 ) + { + stbir__FP16 const * end_input_m8 = input + width_times_channels - 8; + decode_end -= 8; + for(;;) + { + STBIR_NO_UNROLL(decode); + + stbir__half_to_float_SIMD( decode, input ); + #ifdef stbir__decode_swizzle + #ifdef STBIR_SIMD8 + { + stbir__simdf8 of; + stbir__simdf8_load( of, decode ); + stbir__decode_simdf8_flip( of ); + stbir__simdf8_store( decode, of ); + } + #else + { + stbir__simdf of0,of1; + stbir__simdf_load( of0, decode ); + stbir__simdf_load( of1, decode+4 ); + stbir__decode_simdf4_flip( of0 ); + stbir__decode_simdf4_flip( of1 ); + stbir__simdf_store( decode, of0 ); + stbir__simdf_store( decode+4, of1 ); + } + #endif + #endif + decode += 8; + input += 8; + if ( decode <= decode_end ) + continue; + if ( decode == ( decode_end + 8 ) ) + break; + decode = decode_end; // backup and do last couple + input = end_input_m8; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + decode += 4; + while( decode <= decode_end ) + { + STBIR_SIMD_NO_UNROLL(decode); + decode[0-4] = stbir__half_to_float(input[stbir__decode_order0]); + decode[1-4] = stbir__half_to_float(input[stbir__decode_order1]); + decode[2-4] = stbir__half_to_float(input[stbir__decode_order2]); + decode[3-4] = stbir__half_to_float(input[stbir__decode_order3]); + decode += 4; + input += 4; + } + decode -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + while( decode < decode_end ) + { + STBIR_NO_UNROLL(decode); + decode[0] = stbir__half_to_float(input[stbir__decode_order0]); + #if stbir__coder_min_num >= 2 + decode[1] = stbir__half_to_float(input[stbir__decode_order1]); + #endif + #if stbir__coder_min_num >= 3 + decode[2] = stbir__half_to_float(input[stbir__decode_order2]); + #endif + decode += stbir__coder_min_num; + input += stbir__coder_min_num; + } + #endif +} + +static void STBIR__CODER_NAME( stbir__encode_half_float_linear )( void * outputp, int width_times_channels, float const * encode ) +{ + stbir__FP16 STBIR_SIMD_STREAMOUT_PTR( * ) output = (stbir__FP16*) outputp; + stbir__FP16 * end_output = ( (stbir__FP16*) output ) + width_times_channels; + + #ifdef STBIR_SIMD + if ( width_times_channels >= 8 ) + { + float const * end_encode_m8 = encode + width_times_channels - 8; + end_output -= 8; + for(;;) + { + STBIR_SIMD_NO_UNROLL(encode); + #ifdef stbir__decode_swizzle + #ifdef STBIR_SIMD8 + { + stbir__simdf8 of; + stbir__simdf8_load( of, encode ); + stbir__encode_simdf8_unflip( of ); + stbir__float_to_half_SIMD( output, (float*)&of ); + } + #else + { + stbir__simdf of[2]; + stbir__simdf_load( of[0], encode ); + stbir__simdf_load( of[1], encode+4 ); + stbir__encode_simdf4_unflip( of[0] ); + stbir__encode_simdf4_unflip( of[1] ); + stbir__float_to_half_SIMD( output, (float*)of ); + } + #endif + #else + stbir__float_to_half_SIMD( output, encode ); + #endif + encode += 8; + output += 8; + if ( output <= end_output ) + continue; + if ( output == ( end_output + 8 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m8; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + while( output <= end_output ) + { + STBIR_SIMD_NO_UNROLL(output); + output[0-4] = stbir__float_to_half(encode[stbir__encode_order0]); + output[1-4] = stbir__float_to_half(encode[stbir__encode_order1]); + output[2-4] = stbir__float_to_half(encode[stbir__encode_order2]); + output[3-4] = stbir__float_to_half(encode[stbir__encode_order3]); + output += 4; + encode += 4; + } + output -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + while( output < end_output ) + { + STBIR_NO_UNROLL(output); + output[0] = stbir__float_to_half(encode[stbir__encode_order0]); + #if stbir__coder_min_num >= 2 + output[1] = stbir__float_to_half(encode[stbir__encode_order1]); + #endif + #if stbir__coder_min_num >= 3 + output[2] = stbir__float_to_half(encode[stbir__encode_order2]); + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif +} + +static void STBIR__CODER_NAME(stbir__decode_float_linear)( float * decodep, int width_times_channels, void const * inputp ) +{ + #ifdef stbir__decode_swizzle + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float * decode_end = (float*) decode + width_times_channels; + float const * input = (float const *)inputp; + + #ifdef STBIR_SIMD + if ( width_times_channels >= 16 ) + { + float const * end_input_m16 = input + width_times_channels - 16; + decode_end -= 16; + for(;;) + { + STBIR_NO_UNROLL(decode); + #ifdef stbir__decode_swizzle + #ifdef STBIR_SIMD8 + { + stbir__simdf8 of0,of1; + stbir__simdf8_load( of0, input ); + stbir__simdf8_load( of1, input+8 ); + stbir__decode_simdf8_flip( of0 ); + stbir__decode_simdf8_flip( of1 ); + stbir__simdf8_store( decode, of0 ); + stbir__simdf8_store( decode+8, of1 ); + } + #else + { + stbir__simdf of0,of1,of2,of3; + stbir__simdf_load( of0, input ); + stbir__simdf_load( of1, input+4 ); + stbir__simdf_load( of2, input+8 ); + stbir__simdf_load( of3, input+12 ); + stbir__decode_simdf4_flip( of0 ); + stbir__decode_simdf4_flip( of1 ); + stbir__decode_simdf4_flip( of2 ); + stbir__decode_simdf4_flip( of3 ); + stbir__simdf_store( decode, of0 ); + stbir__simdf_store( decode+4, of1 ); + stbir__simdf_store( decode+8, of2 ); + stbir__simdf_store( decode+12, of3 ); + } + #endif + #endif + decode += 16; + input += 16; + if ( decode <= decode_end ) + continue; + if ( decode == ( decode_end + 16 ) ) + break; + decode = decode_end; // backup and do last couple + input = end_input_m16; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + decode += 4; + while( decode <= decode_end ) + { + STBIR_SIMD_NO_UNROLL(decode); + decode[0-4] = input[stbir__decode_order0]; + decode[1-4] = input[stbir__decode_order1]; + decode[2-4] = input[stbir__decode_order2]; + decode[3-4] = input[stbir__decode_order3]; + decode += 4; + input += 4; + } + decode -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + while( decode < decode_end ) + { + STBIR_NO_UNROLL(decode); + decode[0] = input[stbir__decode_order0]; + #if stbir__coder_min_num >= 2 + decode[1] = input[stbir__decode_order1]; + #endif + #if stbir__coder_min_num >= 3 + decode[2] = input[stbir__decode_order2]; + #endif + decode += stbir__coder_min_num; + input += stbir__coder_min_num; + } + #endif + + #else + + if ( (void*)decodep != inputp ) + STBIR_MEMCPY( decodep, inputp, width_times_channels * sizeof( float ) ); + + #endif +} + +static void STBIR__CODER_NAME( stbir__encode_float_linear )( void * outputp, int width_times_channels, float const * encode ) +{ + #if !defined( STBIR_FLOAT_HIGH_CLAMP ) && !defined(STBIR_FLOAT_LO_CLAMP) && !defined(stbir__decode_swizzle) + + if ( (void*)outputp != (void*) encode ) + STBIR_MEMCPY( outputp, encode, width_times_channels * sizeof( float ) ); + + #else + + float STBIR_SIMD_STREAMOUT_PTR( * ) output = (float*) outputp; + float * end_output = ( (float*) output ) + width_times_channels; + + #ifdef STBIR_FLOAT_HIGH_CLAMP + #define stbir_scalar_hi_clamp( v ) if ( v > STBIR_FLOAT_HIGH_CLAMP ) v = STBIR_FLOAT_HIGH_CLAMP; + #else + #define stbir_scalar_hi_clamp( v ) + #endif + #ifdef STBIR_FLOAT_LOW_CLAMP + #define stbir_scalar_lo_clamp( v ) if ( v < STBIR_FLOAT_LOW_CLAMP ) v = STBIR_FLOAT_LOW_CLAMP; + #else + #define stbir_scalar_lo_clamp( v ) + #endif + + #ifdef STBIR_SIMD + + #ifdef STBIR_FLOAT_HIGH_CLAMP + const stbir__simdfX high_clamp = stbir__simdf_frepX(STBIR_FLOAT_HIGH_CLAMP); + #endif + #ifdef STBIR_FLOAT_LOW_CLAMP + const stbir__simdfX low_clamp = stbir__simdf_frepX(STBIR_FLOAT_LOW_CLAMP); + #endif + + if ( width_times_channels >= ( stbir__simdfX_float_count * 2 ) ) + { + float const * end_encode_m8 = encode + width_times_channels - ( stbir__simdfX_float_count * 2 ); + end_output -= ( stbir__simdfX_float_count * 2 ); + for(;;) + { + stbir__simdfX e0, e1; + STBIR_SIMD_NO_UNROLL(encode); + stbir__simdfX_load( e0, encode ); + stbir__simdfX_load( e1, encode+stbir__simdfX_float_count ); +#ifdef STBIR_FLOAT_HIGH_CLAMP + stbir__simdfX_min( e0, e0, high_clamp ); + stbir__simdfX_min( e1, e1, high_clamp ); +#endif +#ifdef STBIR_FLOAT_LOW_CLAMP + stbir__simdfX_max( e0, e0, low_clamp ); + stbir__simdfX_max( e1, e1, low_clamp ); +#endif + stbir__encode_simdfX_unflip( e0 ); + stbir__encode_simdfX_unflip( e1 ); + stbir__simdfX_store( output, e0 ); + stbir__simdfX_store( output+stbir__simdfX_float_count, e1 ); + encode += stbir__simdfX_float_count * 2; + output += stbir__simdfX_float_count * 2; + if ( output < end_output ) + continue; + if ( output == ( end_output + ( stbir__simdfX_float_count * 2 ) ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m8; + } + return; + } + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + while( output <= end_output ) + { + stbir__simdf e0; + STBIR_NO_UNROLL(encode); + stbir__simdf_load( e0, encode ); +#ifdef STBIR_FLOAT_HIGH_CLAMP + stbir__simdf_min( e0, e0, high_clamp ); +#endif +#ifdef STBIR_FLOAT_LOW_CLAMP + stbir__simdf_max( e0, e0, low_clamp ); +#endif + stbir__encode_simdf4_unflip( e0 ); + stbir__simdf_store( output-4, e0 ); + output += 4; + encode += 4; + } + output -= 4; + #endif + + #else + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + while( output <= end_output ) + { + float e; + STBIR_SIMD_NO_UNROLL(encode); + e = encode[ stbir__encode_order0 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[0-4] = e; + e = encode[ stbir__encode_order1 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[1-4] = e; + e = encode[ stbir__encode_order2 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[2-4] = e; + e = encode[ stbir__encode_order3 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[3-4] = e; + output += 4; + encode += 4; + } + output -= 4; + + #endif + + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + while( output < end_output ) + { + float e; + STBIR_NO_UNROLL(encode); + e = encode[ stbir__encode_order0 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[0] = e; + #if stbir__coder_min_num >= 2 + e = encode[ stbir__encode_order1 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[1] = e; + #endif + #if stbir__coder_min_num >= 3 + e = encode[ stbir__encode_order2 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[2] = e; + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif + + #endif +} + +#undef stbir__decode_suffix +#undef stbir__decode_simdf8_flip +#undef stbir__decode_simdf4_flip +#undef stbir__decode_order0 +#undef stbir__decode_order1 +#undef stbir__decode_order2 +#undef stbir__decode_order3 +#undef stbir__encode_order0 +#undef stbir__encode_order1 +#undef stbir__encode_order2 +#undef stbir__encode_order3 +#undef stbir__encode_simdf8_unflip +#undef stbir__encode_simdf4_unflip +#undef stbir__encode_simdfX_unflip +#undef STBIR__CODER_NAME +#undef stbir__coder_min_num +#undef stbir__decode_swizzle +#undef stbir_scalar_hi_clamp +#undef stbir_scalar_lo_clamp +#undef STB_IMAGE_RESIZE_DO_CODERS + +#elif defined( STB_IMAGE_RESIZE_DO_VERTICALS) + +#ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#define STBIR_chans( start, end ) STBIR_strs_join14(start,STBIR__vertical_channels,end,_cont) +#else +#define STBIR_chans( start, end ) STBIR_strs_join1(start,STBIR__vertical_channels,end) +#endif + +#if STBIR__vertical_channels >= 1 +#define stbIF0( code ) code +#else +#define stbIF0( code ) +#endif +#if STBIR__vertical_channels >= 2 +#define stbIF1( code ) code +#else +#define stbIF1( code ) +#endif +#if STBIR__vertical_channels >= 3 +#define stbIF2( code ) code +#else +#define stbIF2( code ) +#endif +#if STBIR__vertical_channels >= 4 +#define stbIF3( code ) code +#else +#define stbIF3( code ) +#endif +#if STBIR__vertical_channels >= 5 +#define stbIF4( code ) code +#else +#define stbIF4( code ) +#endif +#if STBIR__vertical_channels >= 6 +#define stbIF5( code ) code +#else +#define stbIF5( code ) +#endif +#if STBIR__vertical_channels >= 7 +#define stbIF6( code ) code +#else +#define stbIF6( code ) +#endif +#if STBIR__vertical_channels >= 8 +#define stbIF7( code ) code +#else +#define stbIF7( code ) +#endif + +static void STBIR_chans( stbir__vertical_scatter_with_,_coeffs)( float ** outputs, float const * vertical_coefficients, float const * input, float const * input_end ) +{ + stbIF0( float STBIR_SIMD_STREAMOUT_PTR( * ) output0 = outputs[0]; float c0s = vertical_coefficients[0]; ) + stbIF1( float STBIR_SIMD_STREAMOUT_PTR( * ) output1 = outputs[1]; float c1s = vertical_coefficients[1]; ) + stbIF2( float STBIR_SIMD_STREAMOUT_PTR( * ) output2 = outputs[2]; float c2s = vertical_coefficients[2]; ) + stbIF3( float STBIR_SIMD_STREAMOUT_PTR( * ) output3 = outputs[3]; float c3s = vertical_coefficients[3]; ) + stbIF4( float STBIR_SIMD_STREAMOUT_PTR( * ) output4 = outputs[4]; float c4s = vertical_coefficients[4]; ) + stbIF5( float STBIR_SIMD_STREAMOUT_PTR( * ) output5 = outputs[5]; float c5s = vertical_coefficients[5]; ) + stbIF6( float STBIR_SIMD_STREAMOUT_PTR( * ) output6 = outputs[6]; float c6s = vertical_coefficients[6]; ) + stbIF7( float STBIR_SIMD_STREAMOUT_PTR( * ) output7 = outputs[7]; float c7s = vertical_coefficients[7]; ) + + #ifdef STBIR_SIMD + { + stbIF0(stbir__simdfX c0 = stbir__simdf_frepX( c0s ); ) + stbIF1(stbir__simdfX c1 = stbir__simdf_frepX( c1s ); ) + stbIF2(stbir__simdfX c2 = stbir__simdf_frepX( c2s ); ) + stbIF3(stbir__simdfX c3 = stbir__simdf_frepX( c3s ); ) + stbIF4(stbir__simdfX c4 = stbir__simdf_frepX( c4s ); ) + stbIF5(stbir__simdfX c5 = stbir__simdf_frepX( c5s ); ) + stbIF6(stbir__simdfX c6 = stbir__simdf_frepX( c6s ); ) + stbIF7(stbir__simdfX c7 = stbir__simdf_frepX( c7s ); ) + while ( ( (char*)input_end - (char*) input ) >= (16*stbir__simdfX_float_count) ) + { + stbir__simdfX o0, o1, o2, o3, r0, r1, r2, r3; + STBIR_SIMD_NO_UNROLL(output0); + + stbir__simdfX_load( r0, input ); stbir__simdfX_load( r1, input+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input+(3*stbir__simdfX_float_count) ); + + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( stbir__simdfX_load( o0, output0 ); stbir__simdfX_load( o1, output0+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output0+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output0+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c0 ); stbir__simdfX_madd( o1, o1, r1, c0 ); stbir__simdfX_madd( o2, o2, r2, c0 ); stbir__simdfX_madd( o3, o3, r3, c0 ); + stbir__simdfX_store( output0, o0 ); stbir__simdfX_store( output0+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output0+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output0+(3*stbir__simdfX_float_count), o3 ); ) + stbIF1( stbir__simdfX_load( o0, output1 ); stbir__simdfX_load( o1, output1+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output1+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output1+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c1 ); stbir__simdfX_madd( o1, o1, r1, c1 ); stbir__simdfX_madd( o2, o2, r2, c1 ); stbir__simdfX_madd( o3, o3, r3, c1 ); + stbir__simdfX_store( output1, o0 ); stbir__simdfX_store( output1+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output1+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output1+(3*stbir__simdfX_float_count), o3 ); ) + stbIF2( stbir__simdfX_load( o0, output2 ); stbir__simdfX_load( o1, output2+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output2+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output2+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c2 ); stbir__simdfX_madd( o1, o1, r1, c2 ); stbir__simdfX_madd( o2, o2, r2, c2 ); stbir__simdfX_madd( o3, o3, r3, c2 ); + stbir__simdfX_store( output2, o0 ); stbir__simdfX_store( output2+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output2+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output2+(3*stbir__simdfX_float_count), o3 ); ) + stbIF3( stbir__simdfX_load( o0, output3 ); stbir__simdfX_load( o1, output3+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output3+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output3+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c3 ); stbir__simdfX_madd( o1, o1, r1, c3 ); stbir__simdfX_madd( o2, o2, r2, c3 ); stbir__simdfX_madd( o3, o3, r3, c3 ); + stbir__simdfX_store( output3, o0 ); stbir__simdfX_store( output3+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output3+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output3+(3*stbir__simdfX_float_count), o3 ); ) + stbIF4( stbir__simdfX_load( o0, output4 ); stbir__simdfX_load( o1, output4+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output4+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output4+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c4 ); stbir__simdfX_madd( o1, o1, r1, c4 ); stbir__simdfX_madd( o2, o2, r2, c4 ); stbir__simdfX_madd( o3, o3, r3, c4 ); + stbir__simdfX_store( output4, o0 ); stbir__simdfX_store( output4+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output4+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output4+(3*stbir__simdfX_float_count), o3 ); ) + stbIF5( stbir__simdfX_load( o0, output5 ); stbir__simdfX_load( o1, output5+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output5+(2*stbir__simdfX_float_count)); stbir__simdfX_load( o3, output5+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c5 ); stbir__simdfX_madd( o1, o1, r1, c5 ); stbir__simdfX_madd( o2, o2, r2, c5 ); stbir__simdfX_madd( o3, o3, r3, c5 ); + stbir__simdfX_store( output5, o0 ); stbir__simdfX_store( output5+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output5+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output5+(3*stbir__simdfX_float_count), o3 ); ) + stbIF6( stbir__simdfX_load( o0, output6 ); stbir__simdfX_load( o1, output6+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output6+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output6+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c6 ); stbir__simdfX_madd( o1, o1, r1, c6 ); stbir__simdfX_madd( o2, o2, r2, c6 ); stbir__simdfX_madd( o3, o3, r3, c6 ); + stbir__simdfX_store( output6, o0 ); stbir__simdfX_store( output6+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output6+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output6+(3*stbir__simdfX_float_count), o3 ); ) + stbIF7( stbir__simdfX_load( o0, output7 ); stbir__simdfX_load( o1, output7+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output7+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output7+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c7 ); stbir__simdfX_madd( o1, o1, r1, c7 ); stbir__simdfX_madd( o2, o2, r2, c7 ); stbir__simdfX_madd( o3, o3, r3, c7 ); + stbir__simdfX_store( output7, o0 ); stbir__simdfX_store( output7+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output7+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output7+(3*stbir__simdfX_float_count), o3 ); ) + #else + stbIF0( stbir__simdfX_mult( o0, r0, c0 ); stbir__simdfX_mult( o1, r1, c0 ); stbir__simdfX_mult( o2, r2, c0 ); stbir__simdfX_mult( o3, r3, c0 ); + stbir__simdfX_store( output0, o0 ); stbir__simdfX_store( output0+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output0+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output0+(3*stbir__simdfX_float_count), o3 ); ) + stbIF1( stbir__simdfX_mult( o0, r0, c1 ); stbir__simdfX_mult( o1, r1, c1 ); stbir__simdfX_mult( o2, r2, c1 ); stbir__simdfX_mult( o3, r3, c1 ); + stbir__simdfX_store( output1, o0 ); stbir__simdfX_store( output1+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output1+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output1+(3*stbir__simdfX_float_count), o3 ); ) + stbIF2( stbir__simdfX_mult( o0, r0, c2 ); stbir__simdfX_mult( o1, r1, c2 ); stbir__simdfX_mult( o2, r2, c2 ); stbir__simdfX_mult( o3, r3, c2 ); + stbir__simdfX_store( output2, o0 ); stbir__simdfX_store( output2+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output2+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output2+(3*stbir__simdfX_float_count), o3 ); ) + stbIF3( stbir__simdfX_mult( o0, r0, c3 ); stbir__simdfX_mult( o1, r1, c3 ); stbir__simdfX_mult( o2, r2, c3 ); stbir__simdfX_mult( o3, r3, c3 ); + stbir__simdfX_store( output3, o0 ); stbir__simdfX_store( output3+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output3+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output3+(3*stbir__simdfX_float_count), o3 ); ) + stbIF4( stbir__simdfX_mult( o0, r0, c4 ); stbir__simdfX_mult( o1, r1, c4 ); stbir__simdfX_mult( o2, r2, c4 ); stbir__simdfX_mult( o3, r3, c4 ); + stbir__simdfX_store( output4, o0 ); stbir__simdfX_store( output4+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output4+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output4+(3*stbir__simdfX_float_count), o3 ); ) + stbIF5( stbir__simdfX_mult( o0, r0, c5 ); stbir__simdfX_mult( o1, r1, c5 ); stbir__simdfX_mult( o2, r2, c5 ); stbir__simdfX_mult( o3, r3, c5 ); + stbir__simdfX_store( output5, o0 ); stbir__simdfX_store( output5+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output5+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output5+(3*stbir__simdfX_float_count), o3 ); ) + stbIF6( stbir__simdfX_mult( o0, r0, c6 ); stbir__simdfX_mult( o1, r1, c6 ); stbir__simdfX_mult( o2, r2, c6 ); stbir__simdfX_mult( o3, r3, c6 ); + stbir__simdfX_store( output6, o0 ); stbir__simdfX_store( output6+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output6+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output6+(3*stbir__simdfX_float_count), o3 ); ) + stbIF7( stbir__simdfX_mult( o0, r0, c7 ); stbir__simdfX_mult( o1, r1, c7 ); stbir__simdfX_mult( o2, r2, c7 ); stbir__simdfX_mult( o3, r3, c7 ); + stbir__simdfX_store( output7, o0 ); stbir__simdfX_store( output7+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output7+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output7+(3*stbir__simdfX_float_count), o3 ); ) + #endif + + input += (4*stbir__simdfX_float_count); + stbIF0( output0 += (4*stbir__simdfX_float_count); ) stbIF1( output1 += (4*stbir__simdfX_float_count); ) stbIF2( output2 += (4*stbir__simdfX_float_count); ) stbIF3( output3 += (4*stbir__simdfX_float_count); ) stbIF4( output4 += (4*stbir__simdfX_float_count); ) stbIF5( output5 += (4*stbir__simdfX_float_count); ) stbIF6( output6 += (4*stbir__simdfX_float_count); ) stbIF7( output7 += (4*stbir__simdfX_float_count); ) + } + while ( ( (char*)input_end - (char*) input ) >= 16 ) + { + stbir__simdf o0, r0; + STBIR_SIMD_NO_UNROLL(output0); + + stbir__simdf_load( r0, input ); + + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( stbir__simdf_load( o0, output0 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c0 ) ); stbir__simdf_store( output0, o0 ); ) + stbIF1( stbir__simdf_load( o0, output1 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c1 ) ); stbir__simdf_store( output1, o0 ); ) + stbIF2( stbir__simdf_load( o0, output2 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c2 ) ); stbir__simdf_store( output2, o0 ); ) + stbIF3( stbir__simdf_load( o0, output3 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c3 ) ); stbir__simdf_store( output3, o0 ); ) + stbIF4( stbir__simdf_load( o0, output4 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c4 ) ); stbir__simdf_store( output4, o0 ); ) + stbIF5( stbir__simdf_load( o0, output5 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c5 ) ); stbir__simdf_store( output5, o0 ); ) + stbIF6( stbir__simdf_load( o0, output6 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c6 ) ); stbir__simdf_store( output6, o0 ); ) + stbIF7( stbir__simdf_load( o0, output7 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c7 ) ); stbir__simdf_store( output7, o0 ); ) + #else + stbIF0( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c0 ) ); stbir__simdf_store( output0, o0 ); ) + stbIF1( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c1 ) ); stbir__simdf_store( output1, o0 ); ) + stbIF2( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c2 ) ); stbir__simdf_store( output2, o0 ); ) + stbIF3( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c3 ) ); stbir__simdf_store( output3, o0 ); ) + stbIF4( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c4 ) ); stbir__simdf_store( output4, o0 ); ) + stbIF5( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c5 ) ); stbir__simdf_store( output5, o0 ); ) + stbIF6( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c6 ) ); stbir__simdf_store( output6, o0 ); ) + stbIF7( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c7 ) ); stbir__simdf_store( output7, o0 ); ) + #endif + + input += 4; + stbIF0( output0 += 4; ) stbIF1( output1 += 4; ) stbIF2( output2 += 4; ) stbIF3( output3 += 4; ) stbIF4( output4 += 4; ) stbIF5( output5 += 4; ) stbIF6( output6 += 4; ) stbIF7( output7 += 4; ) + } + } + #else + while ( ( (char*)input_end - (char*) input ) >= 16 ) + { + float r0, r1, r2, r3; + STBIR_NO_UNROLL(input); + + r0 = input[0], r1 = input[1], r2 = input[2], r3 = input[3]; + + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( output0[0] += ( r0 * c0s ); output0[1] += ( r1 * c0s ); output0[2] += ( r2 * c0s ); output0[3] += ( r3 * c0s ); ) + stbIF1( output1[0] += ( r0 * c1s ); output1[1] += ( r1 * c1s ); output1[2] += ( r2 * c1s ); output1[3] += ( r3 * c1s ); ) + stbIF2( output2[0] += ( r0 * c2s ); output2[1] += ( r1 * c2s ); output2[2] += ( r2 * c2s ); output2[3] += ( r3 * c2s ); ) + stbIF3( output3[0] += ( r0 * c3s ); output3[1] += ( r1 * c3s ); output3[2] += ( r2 * c3s ); output3[3] += ( r3 * c3s ); ) + stbIF4( output4[0] += ( r0 * c4s ); output4[1] += ( r1 * c4s ); output4[2] += ( r2 * c4s ); output4[3] += ( r3 * c4s ); ) + stbIF5( output5[0] += ( r0 * c5s ); output5[1] += ( r1 * c5s ); output5[2] += ( r2 * c5s ); output5[3] += ( r3 * c5s ); ) + stbIF6( output6[0] += ( r0 * c6s ); output6[1] += ( r1 * c6s ); output6[2] += ( r2 * c6s ); output6[3] += ( r3 * c6s ); ) + stbIF7( output7[0] += ( r0 * c7s ); output7[1] += ( r1 * c7s ); output7[2] += ( r2 * c7s ); output7[3] += ( r3 * c7s ); ) + #else + stbIF0( output0[0] = ( r0 * c0s ); output0[1] = ( r1 * c0s ); output0[2] = ( r2 * c0s ); output0[3] = ( r3 * c0s ); ) + stbIF1( output1[0] = ( r0 * c1s ); output1[1] = ( r1 * c1s ); output1[2] = ( r2 * c1s ); output1[3] = ( r3 * c1s ); ) + stbIF2( output2[0] = ( r0 * c2s ); output2[1] = ( r1 * c2s ); output2[2] = ( r2 * c2s ); output2[3] = ( r3 * c2s ); ) + stbIF3( output3[0] = ( r0 * c3s ); output3[1] = ( r1 * c3s ); output3[2] = ( r2 * c3s ); output3[3] = ( r3 * c3s ); ) + stbIF4( output4[0] = ( r0 * c4s ); output4[1] = ( r1 * c4s ); output4[2] = ( r2 * c4s ); output4[3] = ( r3 * c4s ); ) + stbIF5( output5[0] = ( r0 * c5s ); output5[1] = ( r1 * c5s ); output5[2] = ( r2 * c5s ); output5[3] = ( r3 * c5s ); ) + stbIF6( output6[0] = ( r0 * c6s ); output6[1] = ( r1 * c6s ); output6[2] = ( r2 * c6s ); output6[3] = ( r3 * c6s ); ) + stbIF7( output7[0] = ( r0 * c7s ); output7[1] = ( r1 * c7s ); output7[2] = ( r2 * c7s ); output7[3] = ( r3 * c7s ); ) + #endif + + input += 4; + stbIF0( output0 += 4; ) stbIF1( output1 += 4; ) stbIF2( output2 += 4; ) stbIF3( output3 += 4; ) stbIF4( output4 += 4; ) stbIF5( output5 += 4; ) stbIF6( output6 += 4; ) stbIF7( output7 += 4; ) + } + #endif + while ( input < input_end ) + { + float r = input[0]; + STBIR_NO_UNROLL(output0); + + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( output0[0] += ( r * c0s ); ) + stbIF1( output1[0] += ( r * c1s ); ) + stbIF2( output2[0] += ( r * c2s ); ) + stbIF3( output3[0] += ( r * c3s ); ) + stbIF4( output4[0] += ( r * c4s ); ) + stbIF5( output5[0] += ( r * c5s ); ) + stbIF6( output6[0] += ( r * c6s ); ) + stbIF7( output7[0] += ( r * c7s ); ) + #else + stbIF0( output0[0] = ( r * c0s ); ) + stbIF1( output1[0] = ( r * c1s ); ) + stbIF2( output2[0] = ( r * c2s ); ) + stbIF3( output3[0] = ( r * c3s ); ) + stbIF4( output4[0] = ( r * c4s ); ) + stbIF5( output5[0] = ( r * c5s ); ) + stbIF6( output6[0] = ( r * c6s ); ) + stbIF7( output7[0] = ( r * c7s ); ) + #endif + + ++input; + stbIF0( ++output0; ) stbIF1( ++output1; ) stbIF2( ++output2; ) stbIF3( ++output3; ) stbIF4( ++output4; ) stbIF5( ++output5; ) stbIF6( ++output6; ) stbIF7( ++output7; ) + } +} + +static void STBIR_chans( stbir__vertical_gather_with_,_coeffs)( float * outputp, float const * vertical_coefficients, float const ** inputs, float const * input0_end ) +{ + float STBIR_SIMD_STREAMOUT_PTR( * ) output = outputp; + + stbIF0( float const * input0 = inputs[0]; float c0s = vertical_coefficients[0]; ) + stbIF1( float const * input1 = inputs[1]; float c1s = vertical_coefficients[1]; ) + stbIF2( float const * input2 = inputs[2]; float c2s = vertical_coefficients[2]; ) + stbIF3( float const * input3 = inputs[3]; float c3s = vertical_coefficients[3]; ) + stbIF4( float const * input4 = inputs[4]; float c4s = vertical_coefficients[4]; ) + stbIF5( float const * input5 = inputs[5]; float c5s = vertical_coefficients[5]; ) + stbIF6( float const * input6 = inputs[6]; float c6s = vertical_coefficients[6]; ) + stbIF7( float const * input7 = inputs[7]; float c7s = vertical_coefficients[7]; ) + +#if ( STBIR__vertical_channels == 1 ) && !defined(STB_IMAGE_RESIZE_VERTICAL_CONTINUE) + // check single channel one weight + if ( ( c0s >= (1.0f-0.000001f) ) && ( c0s <= (1.0f+0.000001f) ) ) + { + STBIR_MEMCPY( output, input0, (char*)input0_end - (char*)input0 ); + return; + } +#endif + + #ifdef STBIR_SIMD + { + stbIF0(stbir__simdfX c0 = stbir__simdf_frepX( c0s ); ) + stbIF1(stbir__simdfX c1 = stbir__simdf_frepX( c1s ); ) + stbIF2(stbir__simdfX c2 = stbir__simdf_frepX( c2s ); ) + stbIF3(stbir__simdfX c3 = stbir__simdf_frepX( c3s ); ) + stbIF4(stbir__simdfX c4 = stbir__simdf_frepX( c4s ); ) + stbIF5(stbir__simdfX c5 = stbir__simdf_frepX( c5s ); ) + stbIF6(stbir__simdfX c6 = stbir__simdf_frepX( c6s ); ) + stbIF7(stbir__simdfX c7 = stbir__simdf_frepX( c7s ); ) + + while ( ( (char*)input0_end - (char*) input0 ) >= (16*stbir__simdfX_float_count) ) + { + stbir__simdfX o0, o1, o2, o3, r0, r1, r2, r3; + STBIR_SIMD_NO_UNROLL(output); + + // prefetch four loop iterations ahead (doesn't affect much for small resizes, but helps with big ones) + stbIF0( stbir__prefetch( input0 + (16*stbir__simdfX_float_count) ); ) + stbIF1( stbir__prefetch( input1 + (16*stbir__simdfX_float_count) ); ) + stbIF2( stbir__prefetch( input2 + (16*stbir__simdfX_float_count) ); ) + stbIF3( stbir__prefetch( input3 + (16*stbir__simdfX_float_count) ); ) + stbIF4( stbir__prefetch( input4 + (16*stbir__simdfX_float_count) ); ) + stbIF5( stbir__prefetch( input5 + (16*stbir__simdfX_float_count) ); ) + stbIF6( stbir__prefetch( input6 + (16*stbir__simdfX_float_count) ); ) + stbIF7( stbir__prefetch( input7 + (16*stbir__simdfX_float_count) ); ) + + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( stbir__simdfX_load( o0, output ); stbir__simdfX_load( o1, output+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output+(3*stbir__simdfX_float_count) ); + stbir__simdfX_load( r0, input0 ); stbir__simdfX_load( r1, input0+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input0+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input0+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c0 ); stbir__simdfX_madd( o1, o1, r1, c0 ); stbir__simdfX_madd( o2, o2, r2, c0 ); stbir__simdfX_madd( o3, o3, r3, c0 ); ) + #else + stbIF0( stbir__simdfX_load( r0, input0 ); stbir__simdfX_load( r1, input0+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input0+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input0+(3*stbir__simdfX_float_count) ); + stbir__simdfX_mult( o0, r0, c0 ); stbir__simdfX_mult( o1, r1, c0 ); stbir__simdfX_mult( o2, r2, c0 ); stbir__simdfX_mult( o3, r3, c0 ); ) + #endif + + stbIF1( stbir__simdfX_load( r0, input1 ); stbir__simdfX_load( r1, input1+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input1+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input1+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c1 ); stbir__simdfX_madd( o1, o1, r1, c1 ); stbir__simdfX_madd( o2, o2, r2, c1 ); stbir__simdfX_madd( o3, o3, r3, c1 ); ) + stbIF2( stbir__simdfX_load( r0, input2 ); stbir__simdfX_load( r1, input2+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input2+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input2+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c2 ); stbir__simdfX_madd( o1, o1, r1, c2 ); stbir__simdfX_madd( o2, o2, r2, c2 ); stbir__simdfX_madd( o3, o3, r3, c2 ); ) + stbIF3( stbir__simdfX_load( r0, input3 ); stbir__simdfX_load( r1, input3+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input3+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input3+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c3 ); stbir__simdfX_madd( o1, o1, r1, c3 ); stbir__simdfX_madd( o2, o2, r2, c3 ); stbir__simdfX_madd( o3, o3, r3, c3 ); ) + stbIF4( stbir__simdfX_load( r0, input4 ); stbir__simdfX_load( r1, input4+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input4+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input4+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c4 ); stbir__simdfX_madd( o1, o1, r1, c4 ); stbir__simdfX_madd( o2, o2, r2, c4 ); stbir__simdfX_madd( o3, o3, r3, c4 ); ) + stbIF5( stbir__simdfX_load( r0, input5 ); stbir__simdfX_load( r1, input5+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input5+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input5+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c5 ); stbir__simdfX_madd( o1, o1, r1, c5 ); stbir__simdfX_madd( o2, o2, r2, c5 ); stbir__simdfX_madd( o3, o3, r3, c5 ); ) + stbIF6( stbir__simdfX_load( r0, input6 ); stbir__simdfX_load( r1, input6+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input6+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input6+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c6 ); stbir__simdfX_madd( o1, o1, r1, c6 ); stbir__simdfX_madd( o2, o2, r2, c6 ); stbir__simdfX_madd( o3, o3, r3, c6 ); ) + stbIF7( stbir__simdfX_load( r0, input7 ); stbir__simdfX_load( r1, input7+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input7+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input7+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c7 ); stbir__simdfX_madd( o1, o1, r1, c7 ); stbir__simdfX_madd( o2, o2, r2, c7 ); stbir__simdfX_madd( o3, o3, r3, c7 ); ) + + stbir__simdfX_store( output, o0 ); stbir__simdfX_store( output+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output+(3*stbir__simdfX_float_count), o3 ); + output += (4*stbir__simdfX_float_count); + stbIF0( input0 += (4*stbir__simdfX_float_count); ) stbIF1( input1 += (4*stbir__simdfX_float_count); ) stbIF2( input2 += (4*stbir__simdfX_float_count); ) stbIF3( input3 += (4*stbir__simdfX_float_count); ) stbIF4( input4 += (4*stbir__simdfX_float_count); ) stbIF5( input5 += (4*stbir__simdfX_float_count); ) stbIF6( input6 += (4*stbir__simdfX_float_count); ) stbIF7( input7 += (4*stbir__simdfX_float_count); ) + } + + while ( ( (char*)input0_end - (char*) input0 ) >= 16 ) + { + stbir__simdf o0, r0; + STBIR_SIMD_NO_UNROLL(output); + + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( stbir__simdf_load( o0, output ); stbir__simdf_load( r0, input0 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c0 ) ); ) + #else + stbIF0( stbir__simdf_load( r0, input0 ); stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c0 ) ); ) + #endif + stbIF1( stbir__simdf_load( r0, input1 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c1 ) ); ) + stbIF2( stbir__simdf_load( r0, input2 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c2 ) ); ) + stbIF3( stbir__simdf_load( r0, input3 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c3 ) ); ) + stbIF4( stbir__simdf_load( r0, input4 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c4 ) ); ) + stbIF5( stbir__simdf_load( r0, input5 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c5 ) ); ) + stbIF6( stbir__simdf_load( r0, input6 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c6 ) ); ) + stbIF7( stbir__simdf_load( r0, input7 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c7 ) ); ) + + stbir__simdf_store( output, o0 ); + output += 4; + stbIF0( input0 += 4; ) stbIF1( input1 += 4; ) stbIF2( input2 += 4; ) stbIF3( input3 += 4; ) stbIF4( input4 += 4; ) stbIF5( input5 += 4; ) stbIF6( input6 += 4; ) stbIF7( input7 += 4; ) + } + } + #else + while ( ( (char*)input0_end - (char*) input0 ) >= 16 ) + { + float o0, o1, o2, o3; + STBIR_NO_UNROLL(output); + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( o0 = output[0] + input0[0] * c0s; o1 = output[1] + input0[1] * c0s; o2 = output[2] + input0[2] * c0s; o3 = output[3] + input0[3] * c0s; ) + #else + stbIF0( o0 = input0[0] * c0s; o1 = input0[1] * c0s; o2 = input0[2] * c0s; o3 = input0[3] * c0s; ) + #endif + stbIF1( o0 += input1[0] * c1s; o1 += input1[1] * c1s; o2 += input1[2] * c1s; o3 += input1[3] * c1s; ) + stbIF2( o0 += input2[0] * c2s; o1 += input2[1] * c2s; o2 += input2[2] * c2s; o3 += input2[3] * c2s; ) + stbIF3( o0 += input3[0] * c3s; o1 += input3[1] * c3s; o2 += input3[2] * c3s; o3 += input3[3] * c3s; ) + stbIF4( o0 += input4[0] * c4s; o1 += input4[1] * c4s; o2 += input4[2] * c4s; o3 += input4[3] * c4s; ) + stbIF5( o0 += input5[0] * c5s; o1 += input5[1] * c5s; o2 += input5[2] * c5s; o3 += input5[3] * c5s; ) + stbIF6( o0 += input6[0] * c6s; o1 += input6[1] * c6s; o2 += input6[2] * c6s; o3 += input6[3] * c6s; ) + stbIF7( o0 += input7[0] * c7s; o1 += input7[1] * c7s; o2 += input7[2] * c7s; o3 += input7[3] * c7s; ) + output[0] = o0; output[1] = o1; output[2] = o2; output[3] = o3; + output += 4; + stbIF0( input0 += 4; ) stbIF1( input1 += 4; ) stbIF2( input2 += 4; ) stbIF3( input3 += 4; ) stbIF4( input4 += 4; ) stbIF5( input5 += 4; ) stbIF6( input6 += 4; ) stbIF7( input7 += 4; ) + } + #endif + while ( input0 < input0_end ) + { + float o0; + STBIR_NO_UNROLL(output); + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( o0 = output[0] + input0[0] * c0s; ) + #else + stbIF0( o0 = input0[0] * c0s; ) + #endif + stbIF1( o0 += input1[0] * c1s; ) + stbIF2( o0 += input2[0] * c2s; ) + stbIF3( o0 += input3[0] * c3s; ) + stbIF4( o0 += input4[0] * c4s; ) + stbIF5( o0 += input5[0] * c5s; ) + stbIF6( o0 += input6[0] * c6s; ) + stbIF7( o0 += input7[0] * c7s; ) + output[0] = o0; + ++output; + stbIF0( ++input0; ) stbIF1( ++input1; ) stbIF2( ++input2; ) stbIF3( ++input3; ) stbIF4( ++input4; ) stbIF5( ++input5; ) stbIF6( ++input6; ) stbIF7( ++input7; ) + } +} + +#undef stbIF0 +#undef stbIF1 +#undef stbIF2 +#undef stbIF3 +#undef stbIF4 +#undef stbIF5 +#undef stbIF6 +#undef stbIF7 +#undef STB_IMAGE_RESIZE_DO_VERTICALS +#undef STBIR__vertical_channels +#undef STB_IMAGE_RESIZE_DO_HORIZONTALS +#undef STBIR_strs_join24 +#undef STBIR_strs_join14 +#undef STBIR_chans +#ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#undef STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#endif + +#else // !STB_IMAGE_RESIZE_DO_VERTICALS + +#define STBIR_chans( start, end ) STBIR_strs_join1(start,STBIR__horizontal_channels,end) + +#ifndef stbir__2_coeff_only +#define stbir__2_coeff_only() \ + stbir__1_coeff_only(); \ + stbir__1_coeff_remnant(1); +#endif + +#ifndef stbir__2_coeff_remnant +#define stbir__2_coeff_remnant( ofs ) \ + stbir__1_coeff_remnant(ofs); \ + stbir__1_coeff_remnant((ofs)+1); +#endif + +#ifndef stbir__3_coeff_only +#define stbir__3_coeff_only() \ + stbir__2_coeff_only(); \ + stbir__1_coeff_remnant(2); +#endif + +#ifndef stbir__3_coeff_remnant +#define stbir__3_coeff_remnant( ofs ) \ + stbir__2_coeff_remnant(ofs); \ + stbir__1_coeff_remnant((ofs)+2); +#endif + +#ifndef stbir__3_coeff_setup +#define stbir__3_coeff_setup() +#endif + +#ifndef stbir__4_coeff_start +#define stbir__4_coeff_start() \ + stbir__2_coeff_only(); \ + stbir__2_coeff_remnant(2); +#endif + +#ifndef stbir__4_coeff_continue_from_4 +#define stbir__4_coeff_continue_from_4( ofs ) \ + stbir__2_coeff_remnant(ofs); \ + stbir__2_coeff_remnant((ofs)+2); +#endif + +#ifndef stbir__store_output_tiny +#define stbir__store_output_tiny stbir__store_output +#endif + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_1_coeff)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__1_coeff_only(); + stbir__store_output_tiny(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_2_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__2_coeff_only(); + stbir__store_output_tiny(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_3_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__3_coeff_only(); + stbir__store_output_tiny(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_4_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_5_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__1_coeff_remnant(4); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_6_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__2_coeff_remnant(4); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_7_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + stbir__3_coeff_setup(); + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + + stbir__4_coeff_start(); + stbir__3_coeff_remnant(4); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_8_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__4_coeff_continue_from_4(4); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_9_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__4_coeff_continue_from_4(4); + stbir__1_coeff_remnant(8); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_10_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__4_coeff_continue_from_4(4); + stbir__2_coeff_remnant(8); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_11_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + stbir__3_coeff_setup(); + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__4_coeff_continue_from_4(4); + stbir__3_coeff_remnant(8); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_12_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__4_coeff_continue_from_4(4); + stbir__4_coeff_continue_from_4(8); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod0 )( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 4 + 3 ) >> 2; + float const * hc = horizontal_coefficients; + + stbir__4_coeff_start(); + do { + hc += 4; + decode += STBIR__horizontal_channels * 4; + stbir__4_coeff_continue_from_4( 0 ); + --n; + } while ( n > 0 ); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod1 )( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 5 + 3 ) >> 2; + float const * hc = horizontal_coefficients; + + stbir__4_coeff_start(); + do { + hc += 4; + decode += STBIR__horizontal_channels * 4; + stbir__4_coeff_continue_from_4( 0 ); + --n; + } while ( n > 0 ); + stbir__1_coeff_remnant( 4 ); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod2 )( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 6 + 3 ) >> 2; + float const * hc = horizontal_coefficients; + + stbir__4_coeff_start(); + do { + hc += 4; + decode += STBIR__horizontal_channels * 4; + stbir__4_coeff_continue_from_4( 0 ); + --n; + } while ( n > 0 ); + stbir__2_coeff_remnant( 4 ); + + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod3 )( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + stbir__3_coeff_setup(); + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 7 + 3 ) >> 2; + float const * hc = horizontal_coefficients; + + stbir__4_coeff_start(); + do { + hc += 4; + decode += STBIR__horizontal_channels * 4; + stbir__4_coeff_continue_from_4( 0 ); + --n; + } while ( n > 0 ); + stbir__3_coeff_remnant( 4 ); + + stbir__store_output(); + } while ( output < output_end ); +} + +static stbir__horizontal_gather_channels_func * STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_funcs)[4]= +{ + STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod0), + STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod1), + STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod2), + STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod3), +}; + +static stbir__horizontal_gather_channels_func * STBIR_chans(stbir__horizontal_gather_,_channels_funcs)[12]= +{ + STBIR_chans(stbir__horizontal_gather_,_channels_with_1_coeff), + STBIR_chans(stbir__horizontal_gather_,_channels_with_2_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_3_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_4_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_5_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_6_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_7_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_8_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_9_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_10_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_11_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_12_coeffs), +}; + +#undef STBIR__horizontal_channels +#undef STB_IMAGE_RESIZE_DO_HORIZONTALS +#undef stbir__1_coeff_only +#undef stbir__1_coeff_remnant +#undef stbir__2_coeff_only +#undef stbir__2_coeff_remnant +#undef stbir__3_coeff_only +#undef stbir__3_coeff_remnant +#undef stbir__3_coeff_setup +#undef stbir__4_coeff_start +#undef stbir__4_coeff_continue_from_4 +#undef stbir__store_output +#undef stbir__store_output_tiny +#undef STBIR_chans + +#endif // HORIZONALS + +#undef STBIR_strs_join2 +#undef STBIR_strs_join1 + +#endif // STB_IMAGE_RESIZE_DO_HORIZONTALS/VERTICALS/CODERS + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/deps/stb/stb_image_resize_test/dotimings.c b/deps/stb/stb_image_resize_test/dotimings.c new file mode 100644 index 00000000..515c5d51 --- /dev/null +++ b/deps/stb/stb_image_resize_test/dotimings.c @@ -0,0 +1,224 @@ +#include +#include +#include + +#ifdef _MSC_VER + +#define stop() __debugbreak() +#include +#define int64 __int64 +#pragma warning(disable:4127) + +#define get_milliseconds GetTickCount + +#else + +#define stop() __builtin_trap() +#define int64 long long + +typedef unsigned int U32; +typedef unsigned long long U64; + +#include +static int get_milliseconds() +{ + struct timespec ts; + clock_gettime( CLOCK_MONOTONIC, &ts ); + return (U32) ( ( ((U64)(U32)ts.tv_sec) * 1000LL ) + (U64)(((U32)ts.tv_nsec+500000)/1000000) ); +} + +#endif + +#if defined(TIME_SIMD) + // default for most platforms +#elif defined(TIME_SCALAR) + #define STBIR_NO_SIMD +#else + #error You must define TIME_SIMD or TIME_SCALAR when compiling this file. +#endif + +#define STBIR_PROFILE +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#define STBIR__V_FIRST_INFO_BUFFER v_info +#include "stb_image_resize2.h" // new one! + +#if defined(TIME_SIMD) && !defined(STBIR_SIMD) +#error Timing SIMD, but scalar was ON! +#endif + +#if defined(TIME_SCALAR) && defined(STBIR_SIMD) +#error Timing scalar, but SIMD was ON! +#endif + +#define HEADER 32 + + +static int file_write( const char *filename, void * buffer, size_t size ) +{ + FILE * f = fopen( filename, "wb" ); + if ( f == 0 ) return 0; + if ( fwrite( buffer, 1, size, f) != size ) return 0; + fclose(f); + return 1; +} + +int64 nresize( void * o, int ox, int oy, int op, void * i, int ix, int iy, int ip, int buf, int type, int edg, int flt ) +{ + STBIR_RESIZE resize; + int t; + int64 b; + + stbir_resize_init( &resize, i, ix, iy, ip, o, ox, oy, op, buf, type ); + stbir_set_edgemodes( &resize, edg, edg ); + stbir_set_filters( &resize, flt, flt ); + + stbir_build_samplers_with_splits( &resize, 1 ); + + b = 0x7fffffffffffffffULL; + for( t = 0 ; t < 16 ; t++ ) + { + STBIR_PROFILE_INFO profile; + int64 v; + if(!stbir_resize_extended( &resize ) ) + stop(); + stbir_resize_extended_profile_info( &profile, &resize ); + v = profile.clocks[1]+profile.clocks[2]; + if ( v < b ) + { + b = v; + t = 0; + } + } + + stbir_free_samplers( &resize ); + + return b; +} + + +#define INSIZES 5 +#define TYPESCOUNT 5 +#define NUM 64 + +static const int sizes[INSIZES]={63,126,252,520,772}; +static const int types[TYPESCOUNT]={STBIR_1CHANNEL,STBIR_2CHANNEL,STBIR_RGB,STBIR_4CHANNEL,STBIR_RGBA}; +static const int effective[TYPESCOUNT]={1,2,3,4,7}; + +int main( int argc, char ** argv ) +{ + unsigned char * input; + unsigned char * output; + int dimensionx, dimensiony; + int scalex, scaley; + int totalms; + int timing_count; + int ir; + int * file; + int * ts; + int64 totalcycles; + + if ( argc != 6 ) + { + printf("command: dotimings x_samps y_samps x_scale y_scale outfilename\n"); + exit(1); + } + + input = malloc( 4*1200*1200 ); + memset( input, 0x80, 4*1200*1200 ); + output = malloc( 4*10000*10000ULL ); + + dimensionx = atoi( argv[1] ); + dimensiony = atoi( argv[2] ); + scalex = atoi( argv[3] ); + scaley = atoi( argv[4] ); + + timing_count = dimensionx * dimensiony * INSIZES * TYPESCOUNT; + + file = malloc( sizeof(int) * ( 2 * timing_count + HEADER ) ); + ts = file + HEADER; + + totalms = get_milliseconds(); + totalcycles = STBIR_PROFILE_FUNC(); + for( ir = 0 ; ir < INSIZES ; ir++ ) + { + int ix, iy, ty; + ix = iy = sizes[ir]; + + for( ty = 0 ; ty < TYPESCOUNT ; ty++ ) + { + int h, hh; + + h = 1; + for( hh = 0 ; hh < dimensiony; hh++ ) + { + int ww, w = 1; + for( ww = 0 ; ww < dimensionx; ww++ ) + { + int64 VF, HF; + int good; + + v_info.control_v_first = 2; // vertical first + VF = nresize( output, w, h, (w*4*1)&~3, input, ix, iy, ix*4*1, types[ty], STBIR_TYPE_UINT8, STBIR_EDGE_CLAMP, STBIR_FILTER_MITCHELL ); + v_info.control_v_first = 1; // horizonal first + HF = nresize( output, w, h, (w*4*1)&~3, input, ix, iy, ix*4*1, types[ty], STBIR_TYPE_UINT8, STBIR_EDGE_CLAMP, STBIR_FILTER_MITCHELL ); + + good = ( ((HF<=VF) && (!v_info.v_first)) || ((VF<=HF) && (v_info.v_first))); + +// printf("\r%d,%d, %d,%d, %d, %I64d,%I64d, // Good: %c(%c-%d) CompEst: %.1f %.1f\n", ix, iy, w, h, ty, VF, HF, good?'y':'n', v_info.v_first?'v':'h', v_info.v_resize_classification, v_info.v_cost,v_info.h_cost ); + ts[0] = (int)VF; + ts[1] = (int)HF; + + ts += 2; + + w += scalex; + } + printf("."); + h += scaley; + } + } + } + totalms = get_milliseconds() - totalms; + totalcycles = STBIR_PROFILE_FUNC() - totalcycles; + + printf("\n"); + + file[0] = 'VFT1'; + + #if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(__SSE2__) || defined( _M_IX86_FP ) || defined(__i386) || defined( __i386__ ) || defined( _M_IX86 ) || defined( _X86_ ) + file[1] = 1; // x64 + #elif defined( _M_AMD64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || defined(__ARM_NEON__) || defined(__ARM_NEON) || defined(__arm__) || defined( _M_ARM ) + file[1] = 2; // arm + #else + file[1] = 99; // who knows??? + #endif + + #ifdef STBIR_SIMD8 + file[2] = 2; // simd-8 + #elif defined( STBIR_SIMD ) + file[2] = 1; // simd-4 + #else + file[2] = 0; // nosimd + #endif + + file[3] = dimensionx; // dimx + file[4] = dimensiony; // dimy + file[5] = TYPESCOUNT; // channel types + file[ 6] = types[0]; file[7] = types[1]; file[8] = types[2]; file[9] = types[3]; file[10] = types[4]; // buffer_type + file[11] = effective[0]; file[12] = effective[1]; file[13] = effective[2]; file[14] = effective[3]; file[15] = effective[4]; // effective channels + file[16] = INSIZES; // resizes + file[17] = sizes[0]; file[18] = sizes[0]; // input sizes (w x h) + file[19] = sizes[1]; file[20] = sizes[1]; + file[21] = sizes[2]; file[22] = sizes[2]; + file[23] = sizes[3]; file[24] = sizes[3]; + file[25] = sizes[4]; file[26] = sizes[4]; + file[27] = scalex; file[28] = scaley; // scale the dimx and dimy amount ( for(i=0;i2GB) images + 0.91 (2016-04-02) fix warnings; fix handling of subpixel regions + 0.90 (2014-09-17) first released version + + LICENSE + See end of file for license information. + + TODO + Don't decode all of the image data when only processing a partial tile + Don't use full-width decode buffers when only processing a partial tile + When processing wide images, break processing into tiles so data fits in L1 cache + Installable filters? + Resize that respects alpha test coverage + (Reference code: FloatImage::alphaTestCoverage and FloatImage::scaleAlphaToCoverage: + https://code.google.com/p/nvidia-texture-tools/source/browse/trunk/src/nvimage/FloatImage.cpp ) +*/ + +#ifndef STBIR_INCLUDE_STB_IMAGE_RESIZE_H +#define STBIR_INCLUDE_STB_IMAGE_RESIZE_H + +#ifdef _MSC_VER +typedef unsigned char stbir_uint8; +typedef unsigned short stbir_uint16; +typedef unsigned int stbir_uint32; +typedef unsigned __int64 stbir_uint64; +#else +#include +typedef uint8_t stbir_uint8; +typedef uint16_t stbir_uint16; +typedef uint32_t stbir_uint32; +typedef uint64_t stbir_uint64; +#endif + +#ifndef STBIRDEF +#ifdef STB_IMAGE_RESIZE_STATIC +#define STBIRDEF static +#else +#ifdef __cplusplus +#define STBIRDEF extern "C" +#else +#define STBIRDEF extern +#endif +#endif +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// Easy-to-use API: +// +// * "input pixels" points to an array of image data with 'num_channels' channels (e.g. RGB=3, RGBA=4) +// * input_w is input image width (x-axis), input_h is input image height (y-axis) +// * stride is the offset between successive rows of image data in memory, in bytes. you can +// specify 0 to mean packed continuously in memory +// * alpha channel is treated identically to other channels. +// * colorspace is linear or sRGB as specified by function name +// * returned result is 1 for success or 0 in case of an error. +// #define STBIR_ASSERT() to trigger an assert on parameter validation errors. +// * Memory required grows approximately linearly with input and output size, but with +// discontinuities at input_w == output_w and input_h == output_h. +// * These functions use a "default" resampling filter defined at compile time. To change the filter, +// you can change the compile-time defaults by #defining STBIR_DEFAULT_FILTER_UPSAMPLE +// and STBIR_DEFAULT_FILTER_DOWNSAMPLE, or you can use the medium-complexity API. + +STBIRDEF int stbir_resize_uint8( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels); + +STBIRDEF int stbir_resize_float( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels); + + +// The following functions interpret image data as gamma-corrected sRGB. +// Specify STBIR_ALPHA_CHANNEL_NONE if you have no alpha channel, +// or otherwise provide the index of the alpha channel. Flags value +// of 0 will probably do the right thing if you're not sure what +// the flags mean. + +#define STBIR_ALPHA_CHANNEL_NONE -1 + +// Set this flag if your texture has premultiplied alpha. Otherwise, stbir will +// use alpha-weighted resampling (effectively premultiplying, resampling, +// then unpremultiplying). +#define STBIR_FLAG_ALPHA_PREMULTIPLIED (1 << 0) +// The specified alpha channel should be handled as gamma-corrected value even +// when doing sRGB operations. +#define STBIR_FLAG_ALPHA_USES_COLORSPACE (1 << 1) + +#define STBIR_FLAG_ALPHA_OUT_PREMULTIPLIED (1 << 2) + +STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags); + + +typedef enum +{ + STBIR_EDGE_CLAMP = 1, + STBIR_EDGE_REFLECT = 2, + STBIR_EDGE_WRAP = 3, + STBIR_EDGE_ZERO = 4, +} stbir_edge; + +// This function adds the ability to specify how requests to sample off the edge of the image are handled. +STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode); + +////////////////////////////////////////////////////////////////////////////// +// +// Medium-complexity API +// +// This extends the easy-to-use API as follows: +// +// * Alpha-channel can be processed separately +// * If alpha_channel is not STBIR_ALPHA_CHANNEL_NONE +// * Alpha channel will not be gamma corrected (unless flags&STBIR_FLAG_GAMMA_CORRECT) +// * Filters will be weighted by alpha channel (unless flags&STBIR_FLAG_ALPHA_PREMULTIPLIED) +// * Filter can be selected explicitly +// * uint16 image type +// * sRGB colorspace available for all types +// * context parameter for passing to STBIR_MALLOC + +typedef enum +{ + STBIR_FILTER_DEFAULT = 0, // use same filter type that easy-to-use API chooses + STBIR_FILTER_BOX = 1, // A trapezoid w/1-pixel wide ramps, same result as box for integer scale ratios + STBIR_FILTER_TRIANGLE = 2, // On upsampling, produces same results as bilinear texture filtering + STBIR_FILTER_CUBICBSPLINE = 3, // The cubic b-spline (aka Mitchell-Netrevalli with B=1,C=0), gaussian-esque + STBIR_FILTER_CATMULLROM = 4, // An interpolating cubic spline + STBIR_FILTER_MITCHELL = 5, // Mitchell-Netrevalli filter with B=1/3, C=1/3 +} stbir_filter; + +typedef enum +{ + STBIR_COLORSPACE_LINEAR, + STBIR_COLORSPACE_SRGB, + + STBIR_MAX_COLORSPACES, +} stbir_colorspace; + +// The following functions are all identical except for the type of the image data + +STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + +STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + +STBIRDEF int stbir_resize_float_generic( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + + + +////////////////////////////////////////////////////////////////////////////// +// +// Full-complexity API +// +// This extends the medium API as follows: +// +// * uint32 image type +// * not typesafe +// * separate filter types for each axis +// * separate edge modes for each axis +// * can specify scale explicitly for subpixel correctness +// * can specify image source tile using texture coordinates + +typedef enum +{ + STBIR_TYPE_UINT8 , + STBIR_TYPE_UINT16, + STBIR_TYPE_FLOAT , + STBIR_TYPE_UINT32, + + STBIR_MAX_TYPES +} stbir_datatype; + +STBIRDEF int stbir_resize( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context); + +STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float x_scale, float y_scale, + float x_offset, float y_offset); + +STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float s0, float t0, float s1, float t1); +// (s0, t0) & (s1, t1) are the top-left and bottom right corner (uv addressing style: [0, 1]x[0, 1]) of a region of the input image to use. + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBIR_INCLUDE_STB_IMAGE_RESIZE_H + + + + + +#ifdef STB_IMAGE_RESIZE_IMPLEMENTATION + +#ifndef STBIR_ASSERT +#include +#define STBIR_ASSERT(x) assert(x) +#endif + +// For memset +#include + +#include + +#ifndef STBIR_MALLOC +#include +// use comma operator to evaluate c, to avoid "unused parameter" warnings +#define STBIR_MALLOC(size,c) ((void)(c), malloc(size)) +#define STBIR_FREE(ptr,c) ((void)(c), free(ptr)) +#endif + +#ifndef _MSC_VER +#ifdef __cplusplus +#define stbir__inline inline +#else +#define stbir__inline +#endif +#else +#define stbir__inline __forceinline +#endif + +#ifdef STBIR_PROFILE + +union +{ + struct { stbir_uint64 total, setup, filters, looping, vertical, horizontal, decode, encode, alpha, unalpha; } named; + stbir_uint64 array[10]; +} oldprofile; +stbir_uint64 * current_zone_excluded_ptr; + +#if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(__SSE2__) || defined(STBIR_SSE) || defined( _M_IX86_FP ) || defined(__i386) || defined( __i386__ ) || defined( _M_IX86 ) || defined( _X86_ ) + +#ifdef _MSC_VER + + STBIRDEF stbir_uint64 __rdtsc(); + #define STBIR_PROFILE_FUNC() __rdtsc() + +#else // non msvc + + static stbir__inline stbir_uint64 STBIR_PROFILE_FUNC() + { + stbir_uint32 lo, hi; + asm volatile ("rdtsc" : "=a" (lo), "=d" (hi) ); + return ( ( (stbir_uint64) hi ) << 32 ) | ( (stbir_uint64) lo ); + } + +#endif // msvc + +#elif defined( _M_AMD64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || defined(__ARM_NEON__) || defined(__ARM_NEON) + +#ifdef _MSC_VER + + #error Not sure what the intrinsic for cntvct_el0 is on MSVC + +#else // no msvc + + static stbir__inline stbir_uint64 STBIR_PROFILE_FUNC() + { + stbir_uint64 tsc; + asm volatile("mrs %0, cntvct_el0" : "=r" (tsc)); + return tsc; + } + +#endif + +#elif // x64, arm + +#error Unknown platform for profiling. + +#endif //x64 and + +#define STBIR_PROFILE_START() { stbir_uint64 thiszonetime = STBIR_PROFILE_FUNC(); stbir_uint64 * save_parent_excluded_ptr = current_zone_excluded_ptr; stbir_uint64 current_zone_excluded = 0; current_zone_excluded_ptr = ¤t_zone_excluded; +#define STBIR_PROFILE_END( wh ) thiszonetime = STBIR_PROFILE_FUNC() - thiszonetime; oldprofile.named.wh += thiszonetime - current_zone_excluded; *save_parent_excluded_ptr += thiszonetime; current_zone_excluded_ptr = save_parent_excluded_ptr; } +#define STBIR_PROFILE_FIRST_START() { int i; current_zone_excluded_ptr = &oldprofile.named.total; for(i=0;i 65536 +#error "Too many channels; STBIR_MAX_CHANNELS must be no more than 65536." +// because we store the indices in 16-bit variables +#endif + +// This value is added to alpha just before premultiplication to avoid +// zeroing out color values. It is equivalent to 2^-80. If you don't want +// that behavior (it may interfere if you have floating point images with +// very small alpha values) then you can define STBIR_NO_ALPHA_EPSILON to +// disable it. +#ifndef STBIR_ALPHA_EPSILON +#define STBIR_ALPHA_EPSILON ((float)1 / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20)) +#endif + + + +#ifdef _MSC_VER +#define STBIR__UNUSED_PARAM(v) (void)(v) +#else +#define STBIR__UNUSED_PARAM(v) (void)sizeof(v) +#endif + +// must match stbir_datatype +static unsigned char stbir__type_size[] = { + 1, // STBIR_TYPE_UINT8 + 2, // STBIR_TYPE_UINT16 + 4, // STBIR_TYPE_UINT32 + 4, // STBIR_TYPE_FLOAT +}; + +// Kernel function centered at 0 +typedef float (stbir__kernel_fn)(float x, float scale); +typedef float (stbir__support_fn)(float scale); + +typedef struct +{ + stbir__kernel_fn* kernel; + stbir__support_fn* support; +} stbir__filter_info; + +// When upsampling, the contributors are which source pixels contribute. +// When downsampling, the contributors are which destination pixels are contributed to. +typedef struct +{ + int n0; // First contributing pixel + int n1; // Last contributing pixel +} stbir__contributors; + +typedef struct +{ + const void* input_data; + int input_w; + int input_h; + int input_stride_bytes; + + void* output_data; + int output_w; + int output_h; + int output_stride_bytes; + + float s0, t0, s1, t1; + + float horizontal_shift; // Units: output pixels + float vertical_shift; // Units: output pixels + float horizontal_scale; + float vertical_scale; + + int channels; + int alpha_channel; + stbir_uint32 flags; + stbir_datatype type; + stbir_filter horizontal_filter; + stbir_filter vertical_filter; + stbir_edge edge_horizontal; + stbir_edge edge_vertical; + stbir_colorspace colorspace; + + stbir__contributors* horizontal_contributors; + float* horizontal_coefficients; + + stbir__contributors* vertical_contributors; + float* vertical_coefficients; + + int decode_buffer_pixels; + float* decode_buffer; + + float* horizontal_buffer; + + // cache these because ceil/floor are inexplicably showing up in profile + int horizontal_coefficient_width; + int vertical_coefficient_width; + int horizontal_filter_pixel_width; + int vertical_filter_pixel_width; + int horizontal_filter_pixel_margin; + int vertical_filter_pixel_margin; + int horizontal_num_contributors; + int vertical_num_contributors; + + int ring_buffer_length_bytes; // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter) + int ring_buffer_num_entries; // Total number of entries in the ring buffer. + int ring_buffer_first_scanline; + int ring_buffer_last_scanline; + int ring_buffer_begin_index; // first_scanline is at this index in the ring buffer + float* ring_buffer; + + float* encode_buffer; // A temporary buffer to store floats so we don't lose precision while we do multiply-adds. + + int horizontal_contributors_size; + int horizontal_coefficients_size; + int vertical_contributors_size; + int vertical_coefficients_size; + int decode_buffer_size; + int horizontal_buffer_size; + int ring_buffer_size; + int encode_buffer_size; +} ostbir__info; + + +static const float stbir__max_uint8_as_float = 255.0f; +static const float stbir__max_uint16_as_float = 65535.0f; +static const double stbir__max_uint32_as_float = 4294967295.0; + + +static stbir__inline int stbir__min(int a, int b) +{ + return a < b ? a : b; +} + +static stbir__inline float stbir__saturate(float x) +{ + if (x < 0) + return 0; + + if (x > 1) + return 1; + + return x; +} + +#ifdef STBIR_SATURATE_INT +static stbir__inline stbir_uint8 stbir__saturate8(int x) +{ + if ((unsigned int) x <= 255) + return (stbir_uint8) x; + + if (x < 0) + return 0; + + return 255; +} + +static stbir__inline stbir_uint16 stbir__saturate16(int x) +{ + if ((unsigned int) x <= 65535) + return (stbir_uint16) x; + + if (x < 0) + return 0; + + return 65535; +} +#endif + +static float stbir__srgb_uchar_to_linear_float[256] = { + 0.000000f, 0.000304f, 0.000607f, 0.000911f, 0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f, + 0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f, 0.006049f, 0.006512f, 0.006995f, 0.007499f, + 0.008023f, 0.008568f, 0.009134f, 0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f, 0.014444f, + 0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f, 0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f, + 0.025187f, 0.026241f, 0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f, 0.035601f, 0.036889f, + 0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f, 0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f, + 0.054480f, 0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f, 0.068478f, 0.070360f, 0.072272f, + 0.074214f, 0.076185f, 0.078187f, 0.080220f, 0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f, + 0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f, 0.114435f, 0.116971f, 0.119538f, 0.122139f, + 0.124772f, 0.127438f, 0.130136f, 0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f, 0.152926f, + 0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f, 0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f, + 0.191202f, 0.194618f, 0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f, 0.223228f, 0.226966f, + 0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f, 0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f, + 0.274677f, 0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f, 0.309469f, 0.313989f, 0.318547f, + 0.323143f, 0.327778f, 0.332452f, 0.337164f, 0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f, + 0.376262f, 0.381326f, 0.386430f, 0.391573f, 0.396755f, 0.401978f, 0.407240f, 0.412543f, 0.417885f, 0.423268f, 0.428691f, + 0.434154f, 0.439657f, 0.445201f, 0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473532f, 0.479320f, 0.485150f, 0.491021f, + 0.496933f, 0.502887f, 0.508881f, 0.514918f, 0.520996f, 0.527115f, 0.533276f, 0.539480f, 0.545725f, 0.552011f, 0.558340f, + 0.564712f, 0.571125f, 0.577581f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f, 0.623960f, 0.630757f, + 0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f, 0.672443f, 0.679543f, 0.686685f, 0.693872f, 0.701102f, 0.708376f, + 0.715694f, 0.723055f, 0.730461f, 0.737911f, 0.745404f, 0.752942f, 0.760525f, 0.768151f, 0.775822f, 0.783538f, 0.791298f, + 0.799103f, 0.806952f, 0.814847f, 0.822786f, 0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f, + 0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f, 0.947307f, 0.955974f, 0.964686f, 0.973445f, + 0.982251f, 0.991102f, 1.0f +}; + +static float stbir__srgb_to_linear(float f) +{ + if (f <= 0.04045f) + return f / 12.92f; + else + return (float)pow((f + 0.055f) / 1.055f, 2.4f); +} + +static float stbir__linear_to_srgb(float f) +{ + if (f <= 0.0031308f) + return f * 12.92f; + else + return 1.055f * (float)pow(f, 1 / 2.4f) - 0.055f; +} + +#ifndef STBIR_NON_IEEE_FLOAT +// From https://gist.github.com/rygorous/2203834 + +typedef union +{ + stbir_uint32 u; + float f; +} stbir__FP32; + +static const stbir_uint32 fp32_to_srgb8_tab4[104] = { + 0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d, 0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d, + 0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a, 0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a, + 0x010e0033, 0x01280033, 0x01410033, 0x015b0033, 0x01750033, 0x018f0033, 0x01a80033, 0x01c20033, + 0x01dc0067, 0x020f0067, 0x02430067, 0x02760067, 0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067, + 0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce, 0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5, + 0x06970158, 0x07420142, 0x07e30130, 0x087b0120, 0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2, + 0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180, 0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143, + 0x11070264, 0x1238023e, 0x1357021d, 0x14660201, 0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af, + 0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad, 0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240, + 0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392, 0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300, + 0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5, 0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401, + 0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d, 0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559, + 0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f, 0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723, +}; + +static stbir_uint8 stbir__linear_to_srgb_uchar(float in) +{ + static const stbir__FP32 almostone = { 0x3f7fffff }; // 1-eps + static const stbir__FP32 minval = { (127-13) << 23 }; + stbir_uint32 tab,bias,scale,t; + stbir__FP32 f; + + // Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively. + // The tests are carefully written so that NaNs map to 0, same as in the reference + // implementation. + if (!(in > minval.f)) // written this way to catch NaNs + in = minval.f; + if (in > almostone.f) + in = almostone.f; + + // Do the table lookup and unpack bias, scale + f.f = in; + tab = fp32_to_srgb8_tab4[(f.u - minval.u) >> 20]; + bias = (tab >> 16) << 9; + scale = tab & 0xffff; + + // Grab next-highest mantissa bits and perform linear interpolation + t = (f.u >> 12) & 0xff; + return (unsigned char) ((bias + scale*t) >> 16); +} + +#else +// sRGB transition values, scaled by 1<<28 +static int stbir__srgb_offset_to_linear_scaled[256] = +{ + 0, 40738, 122216, 203693, 285170, 366648, 448125, 529603, + 611080, 692557, 774035, 855852, 942009, 1033024, 1128971, 1229926, + 1335959, 1447142, 1563542, 1685229, 1812268, 1944725, 2082664, 2226148, + 2375238, 2529996, 2690481, 2856753, 3028870, 3206888, 3390865, 3580856, + 3776916, 3979100, 4187460, 4402049, 4622919, 4850123, 5083710, 5323731, + 5570236, 5823273, 6082892, 6349140, 6622065, 6901714, 7188133, 7481369, + 7781466, 8088471, 8402427, 8723380, 9051372, 9386448, 9728650, 10078021, + 10434603, 10798439, 11169569, 11548036, 11933879, 12327139, 12727857, 13136073, + 13551826, 13975156, 14406100, 14844697, 15290987, 15745007, 16206795, 16676389, + 17153826, 17639142, 18132374, 18633560, 19142734, 19659934, 20185196, 20718552, + 21260042, 21809696, 22367554, 22933648, 23508010, 24090680, 24681686, 25281066, + 25888850, 26505076, 27129772, 27762974, 28404716, 29055026, 29713942, 30381490, + 31057708, 31742624, 32436272, 33138682, 33849884, 34569912, 35298800, 36036568, + 36783260, 37538896, 38303512, 39077136, 39859796, 40651528, 41452360, 42262316, + 43081432, 43909732, 44747252, 45594016, 46450052, 47315392, 48190064, 49074096, + 49967516, 50870356, 51782636, 52704392, 53635648, 54576432, 55526772, 56486700, + 57456236, 58435408, 59424248, 60422780, 61431036, 62449032, 63476804, 64514376, + 65561776, 66619028, 67686160, 68763192, 69850160, 70947088, 72053992, 73170912, + 74297864, 75434880, 76581976, 77739184, 78906536, 80084040, 81271736, 82469648, + 83677792, 84896192, 86124888, 87363888, 88613232, 89872928, 91143016, 92423512, + 93714432, 95015816, 96327688, 97650056, 98982952, 100326408, 101680440, 103045072, + 104420320, 105806224, 107202800, 108610064, 110028048, 111456776, 112896264, 114346544, + 115807632, 117279552, 118762328, 120255976, 121760536, 123276016, 124802440, 126339832, + 127888216, 129447616, 131018048, 132599544, 134192112, 135795792, 137410592, 139036528, + 140673648, 142321952, 143981456, 145652208, 147334208, 149027488, 150732064, 152447968, + 154175200, 155913792, 157663776, 159425168, 161197984, 162982240, 164777968, 166585184, + 168403904, 170234160, 172075968, 173929344, 175794320, 177670896, 179559120, 181458992, + 183370528, 185293776, 187228736, 189175424, 191133888, 193104112, 195086128, 197079968, + 199085648, 201103184, 203132592, 205173888, 207227120, 209292272, 211369392, 213458480, + 215559568, 217672656, 219797792, 221934976, 224084240, 226245600, 228419056, 230604656, + 232802400, 235012320, 237234432, 239468736, 241715280, 243974080, 246245120, 248528464, + 250824112, 253132064, 255452368, 257785040, 260130080, 262487520, 264857376, 267239664, +}; + +static stbir_uint8 stbir__linear_to_srgb_uchar(float f) +{ + int x = (int) (f * (1 << 28)); // has headroom so you don't need to clamp + int v = 0; + int i; + + // Refine the guess with a short binary search. + i = v + 128; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 64; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 32; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 16; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 8; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 4; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 2; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 1; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + + return (stbir_uint8) v; +} +#endif + +static float stbir__filter_trapezoid(float x, float scale) +{ + float halfscale = scale / 2; + float t = 0.5f + halfscale; + STBIR_ASSERT(scale <= 1); + + x = (float)fabs(x); + + if (x >= t) + return 0; + else + { + float r = 0.5f - halfscale; + if (x <= r) + return 1; + else + return (t - x) / scale; + } +} + +static float stbir__support_trapezoid(float scale) +{ + STBIR_ASSERT(scale <= 1); + return 0.5f + scale / 2; +} + +static float stbir__filter_triangle(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x <= 1.0f) + return 1 - x; + else + return 0; +} + +static float stbir__filter_cubic(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return (4 + x*x*(3*x - 6))/6; + else if (x < 2.0f) + return (8 + x*(-12 + x*(6 - x)))/6; + + return (0.0f); +} + +static float stbir__filter_catmullrom(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return 1 - x*x*(2.5f - 1.5f*x); + else if (x < 2.0f) + return 2 - x*(4 + x*(0.5f*x - 2.5f)); + + return (0.0f); +} + +static float stbir__filter_mitchell(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return (16 + x*x*(21 * x - 36))/18; + else if (x < 2.0f) + return (32 + x*(-60 + x*(36 - 7*x)))/18; + + return (0.0f); +} + +static float stbir__support_zero(float s) +{ + STBIR__UNUSED_PARAM(s); + return 0; +} + +static float stbir__support_one(float s) +{ + STBIR__UNUSED_PARAM(s); + return 1; +} + +static float stbir__support_two(float s) +{ + STBIR__UNUSED_PARAM(s); + return 2; +} + +static stbir__filter_info stbir__filter_info_table[] = { + { NULL, stbir__support_zero }, + { stbir__filter_trapezoid, stbir__support_trapezoid }, + { stbir__filter_triangle, stbir__support_one }, + { stbir__filter_cubic, stbir__support_two }, + { stbir__filter_catmullrom, stbir__support_two }, + { stbir__filter_mitchell, stbir__support_two }, +}; + +stbir__inline static int stbir__use_upsampling(float ratio) +{ + return ratio > 1; +} + +stbir__inline static int stbir__use_width_upsampling(ostbir__info* stbir_info) +{ + return stbir__use_upsampling(stbir_info->horizontal_scale); +} + +stbir__inline static int stbir__use_height_upsampling(ostbir__info* stbir_info) +{ + return stbir__use_upsampling(stbir_info->vertical_scale); +} + +// This is the maximum number of input samples that can affect an output sample +// with the given filter +static int stbir__get_filter_pixel_width(stbir_filter filter, float scale) +{ + STBIR_ASSERT(filter != 0); + STBIR_ASSERT(filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + + if (stbir__use_upsampling(scale)) + return (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2); + else + return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2 / scale); +} + +// This is how much to expand buffers to account for filters seeking outside +// the image boundaries. +static int stbir__get_filter_pixel_margin(stbir_filter filter, float scale) +{ + return stbir__get_filter_pixel_width(filter, scale) / 2; +} + +static int stbir__get_coefficient_width(stbir_filter filter, float scale) +{ + if (stbir__use_upsampling(scale)) + return (int)ceil(stbir__filter_info_table[filter].support(1 / scale) * 2); + else + return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2); +} + +static int stbir__get_contributors(float scale, stbir_filter filter, int input_size, int output_size) +{ + if (stbir__use_upsampling(scale)) + return output_size; + else + return (input_size + stbir__get_filter_pixel_margin(filter, scale) * 2); +} + +static int stbir__get_total_horizontal_coefficients(ostbir__info* info) +{ + return info->horizontal_num_contributors + * stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale); +} + +static int stbir__get_total_vertical_coefficients(ostbir__info* info) +{ + return info->vertical_num_contributors + * stbir__get_coefficient_width (info->vertical_filter, info->vertical_scale); +} + +static stbir__contributors* stbir__get_contributor(stbir__contributors* contributors, int n) +{ + return &contributors[n]; +} + +// For perf reasons this code is duplicated in stbir__resample_horizontal_upsample/downsample, +// if you change it here change it there too. +static float* stbir__get_coefficient(float* coefficients, stbir_filter filter, float scale, int n, int c) +{ + int width = stbir__get_coefficient_width(filter, scale); + return &coefficients[width*n + c]; +} + +static int stbir__edge_wrap_slow(stbir_edge edge, int n, int max) +{ + switch (edge) + { + case STBIR_EDGE_ZERO: + return 0; // we'll decode the wrong pixel here, and then overwrite with 0s later + + case STBIR_EDGE_CLAMP: + if (n < 0) + return 0; + + if (n >= max) + return max - 1; + + return n; // NOTREACHED + + case STBIR_EDGE_REFLECT: + { + if (n < 0) + { + if (n > -max) + return -n; + else + return max - 1; + } + + if (n >= max) + { + int max2 = max * 2; + if (n >= max2) + return 0; + else + return max2 - n - 1; + } + + return n; // NOTREACHED + } + + case STBIR_EDGE_WRAP: + if (n >= 0) + return (n % max); + else + { + int m = (-n) % max; + + if (m != 0) + m = max - m; + + return (m); + } + // NOTREACHED + + default: + STBIR_ASSERT(!"Unimplemented edge type"); + return 0; + } +} + +stbir__inline static int stbir__edge_wrap(stbir_edge edge, int n, int max) +{ + // avoid per-pixel switch + if (n >= 0 && n < max) + return n; + return stbir__edge_wrap_slow(edge, n, max); +} + +// What input pixels contribute to this output pixel? +static void stbir__calculate_sample_range_upsample(int n, float out_filter_radius, float scale_ratio, float out_shift, int* in_first_pixel, int* in_last_pixel, float* in_center_of_out) +{ + float out_pixel_center = (float)n + 0.5f; + float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius; + float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius; + + float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) / scale_ratio; + float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) / scale_ratio; + + *in_center_of_out = (out_pixel_center + out_shift) / scale_ratio; + *in_first_pixel = (int)(floor(in_pixel_influence_lowerbound + 0.5)); + *in_last_pixel = (int)(floor(in_pixel_influence_upperbound - 0.5)); +} + +// What output pixels does this input pixel contribute to? +static void stbir__calculate_sample_range_downsample(int n, float in_pixels_radius, float scale_ratio, float out_shift, int* out_first_pixel, int* out_last_pixel, float* out_center_of_in) +{ + float in_pixel_center = (float)n + 0.5f; + float in_pixel_influence_lowerbound = in_pixel_center - in_pixels_radius; + float in_pixel_influence_upperbound = in_pixel_center + in_pixels_radius; + + float out_pixel_influence_lowerbound = in_pixel_influence_lowerbound * scale_ratio - out_shift; + float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale_ratio - out_shift; + + *out_center_of_in = in_pixel_center * scale_ratio - out_shift; + *out_first_pixel = (int)(floor(out_pixel_influence_lowerbound + 0.5)); + *out_last_pixel = (int)(floor(out_pixel_influence_upperbound - 0.5)); +} + +static void stbir__calculate_coefficients_upsample(stbir_filter filter, float scale, int in_first_pixel, int in_last_pixel, float in_center_of_out, stbir__contributors* contributor, float* coefficient_group) +{ + int i; + float total_filter = 0; + float filter_scale; + + STBIR_ASSERT(in_last_pixel - in_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + + contributor->n0 = in_first_pixel; + contributor->n1 = in_last_pixel; + + STBIR_ASSERT(contributor->n1 >= contributor->n0); + + for (i = 0; i <= in_last_pixel - in_first_pixel; i++) + { + float in_pixel_center = (float)(i + in_first_pixel) + 0.5f; + coefficient_group[i] = stbir__filter_info_table[filter].kernel(in_center_of_out - in_pixel_center, 1 / scale); + + // If the coefficient is zero, skip it. (Don't do the <0 check here, we want the influence of those outside pixels.) + if (i == 0 && !coefficient_group[i]) + { + contributor->n0 = ++in_first_pixel; + i--; + continue; + } + + total_filter += coefficient_group[i]; + } + + STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0); + + STBIR_ASSERT(total_filter > 0.9); + STBIR_ASSERT(total_filter < 1.1f); // Make sure it's not way off. + + // Make sure the sum of all coefficients is 1. + filter_scale = 1 / total_filter; + + for (i = 0; i <= in_last_pixel - in_first_pixel; i++) + coefficient_group[i] *= filter_scale; + + for (i = in_last_pixel - in_first_pixel; i >= 0; i--) + { + if (coefficient_group[i]) + break; + + // This line has no weight. We can skip it. + contributor->n1 = contributor->n0 + i - 1; + } +} + +static void stbir__calculate_coefficients_downsample(stbir_filter filter, float scale_ratio, int out_first_pixel, int out_last_pixel, float out_center_of_in, stbir__contributors* contributor, float* coefficient_group) +{ + int i; + + STBIR_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + + contributor->n0 = out_first_pixel; + contributor->n1 = out_last_pixel; + + STBIR_ASSERT(contributor->n1 >= contributor->n0); + + for (i = 0; i <= out_last_pixel - out_first_pixel; i++) + { + float out_pixel_center = (float)(i + out_first_pixel) + 0.5f; + float x = out_pixel_center - out_center_of_in; + coefficient_group[i] = stbir__filter_info_table[filter].kernel(x, scale_ratio) * scale_ratio; + } + + STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0); + + for (i = out_last_pixel - out_first_pixel; i >= 0; i--) + { + if (coefficient_group[i]) + break; + + // This line has no weight. We can skip it. + contributor->n1 = contributor->n0 + i - 1; + } +} + +static void stbir__normalize_downsample_coefficients(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, int input_size, int output_size) +{ + int num_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); + int num_coefficients = stbir__get_coefficient_width(filter, scale_ratio); + int i, j; + int skip; + + for (i = 0; i < output_size; i++) + { + float scale; + float total = 0; + + for (j = 0; j < num_contributors; j++) + { + if (i >= contributors[j].n0 && i <= contributors[j].n1) + { + float coefficient = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0); + total += coefficient; + } + else if (i < contributors[j].n0) + break; + } + + //STBIR_ASSERT(total > 0.9f); + //STBIR_ASSERT(total < 1.5f); + + scale = 1 / total; + + for (j = 0; j < num_contributors; j++) + { + if (i >= contributors[j].n0 && i <= contributors[j].n1) + *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0) *= scale; + else if (i < contributors[j].n0) + break; + } + } + + // Optimize: Skip zero coefficients and contributions outside of image bounds. + // Do this after normalizing because normalization depends on the n0/n1 values. + for (j = 0; j < num_contributors; j++) + { + int range, max, width; + + skip = 0; + while (*stbir__get_coefficient(coefficients, filter, scale_ratio, j, skip) == 0) + skip++; + + contributors[j].n0 += skip; + + while (contributors[j].n0 < 0) + { + contributors[j].n0++; + skip++; + } + + range = contributors[j].n1 - contributors[j].n0 + 1; + max = stbir__min(num_coefficients, range); + + width = stbir__get_coefficient_width(filter, scale_ratio); + for (i = 0; i < max; i++) + { + if (i + skip >= width) + break; + + *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i) = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i + skip); + } + + continue; + } + + // Using min to avoid writing into invalid pixels. + for (i = 0; i < num_contributors; i++) + contributors[i].n1 = stbir__min(contributors[i].n1, output_size - 1); +} + +// Each scan line uses the same kernel values so we should calculate the kernel +// values once and then we can use them for every scan line. +static void stbir__calculate_filters(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, float shift, int input_size, int output_size) +{ + int n; + int total_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); + + if (stbir__use_upsampling(scale_ratio)) + { + float out_pixels_radius = stbir__filter_info_table[filter].support(1 / scale_ratio) * scale_ratio; + + // Looping through out pixels + for (n = 0; n < total_contributors; n++) + { + float in_center_of_out; // Center of the current out pixel in the in pixel space + int in_first_pixel, in_last_pixel; + + stbir__calculate_sample_range_upsample(n, out_pixels_radius, scale_ratio, shift, &in_first_pixel, &in_last_pixel, &in_center_of_out); + + stbir__calculate_coefficients_upsample(filter, scale_ratio, in_first_pixel, in_last_pixel, in_center_of_out, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + } + } + else + { + float in_pixels_radius = stbir__filter_info_table[filter].support(scale_ratio) / scale_ratio; + + // Looping through in pixels + for (n = 0; n < total_contributors; n++) + { + float out_center_of_in; // Center of the current out pixel in the in pixel space + int out_first_pixel, out_last_pixel; + int n_adjusted = n - stbir__get_filter_pixel_margin(filter, scale_ratio); + + stbir__calculate_sample_range_downsample(n_adjusted, in_pixels_radius, scale_ratio, shift, &out_first_pixel, &out_last_pixel, &out_center_of_in); + + stbir__calculate_coefficients_downsample(filter, scale_ratio, out_first_pixel, out_last_pixel, out_center_of_in, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + } + + stbir__normalize_downsample_coefficients(contributors, coefficients, filter, scale_ratio, input_size, output_size); + } +} + +static float* stbir__get_decode_buffer(ostbir__info* stbir_info) +{ + // The 0 index of the decode buffer starts after the margin. This makes + // it okay to use negative indexes on the decode buffer. + return &stbir_info->decode_buffer[stbir_info->horizontal_filter_pixel_margin * stbir_info->channels]; +} + +#define STBIR__DECODE(type, colorspace) ((type) * (STBIR_MAX_COLORSPACES) + (colorspace)) + +static void stbir__decode_scanline(ostbir__info* stbir_info, int n) +{ + int c; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int input_w = stbir_info->input_w; + size_t input_stride_bytes = stbir_info->input_stride_bytes; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir_edge edge_horizontal = stbir_info->edge_horizontal; + stbir_edge edge_vertical = stbir_info->edge_vertical; + size_t in_buffer_row_offset = stbir__edge_wrap(edge_vertical, n, stbir_info->input_h) * input_stride_bytes; + const void* input_data = (char *) stbir_info->input_data + in_buffer_row_offset; + int max_x = input_w + stbir_info->horizontal_filter_pixel_margin; + int decode = STBIR__DECODE(type, colorspace); + + int x = -stbir_info->horizontal_filter_pixel_margin; + + // special handling for STBIR_EDGE_ZERO because it needs to return an item that doesn't appear in the input, + // and we want to avoid paying overhead on every pixel if not STBIR_EDGE_ZERO + if (edge_vertical == STBIR_EDGE_ZERO && (n < 0 || n >= stbir_info->input_h)) + { + for (; x < max_x; x++) + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + return; + } + + STBIR_PROFILE_START( ); + switch (decode) + { + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned char*)input_data)[input_pixel_index + c]) / stbir__max_uint8_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_uchar_to_linear_float[((const unsigned char*)input_data)[input_pixel_index + c]]; + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned char*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint8_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned short*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint16_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear((float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float)); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((const float*)input_data)[input_pixel_index + c]; + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((const float*)input_data)[input_pixel_index + c]); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((const float*)input_data)[input_pixel_index + alpha_channel]; + } + + break; + + default: + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); + break; + } + STBIR_PROFILE_END( decode ); + + if (!(stbir_info->flags & STBIR_FLAG_ALPHA_PREMULTIPLIED)) + { + STBIR_PROFILE_START(); + + for (x = -stbir_info->horizontal_filter_pixel_margin; x < max_x; x++) + { + int decode_pixel_index = x * channels; + + // If the alpha value is 0 it will clobber the color values. Make sure it's not. + float alpha = decode_buffer[decode_pixel_index + alpha_channel]; +#ifndef STBIR_NO_ALPHA_EPSILON + if (stbir_info->type != STBIR_TYPE_FLOAT) { + alpha += STBIR_ALPHA_EPSILON; + decode_buffer[decode_pixel_index + alpha_channel] = alpha; + } +#endif + for (c = 0; c < channels; c++) + { + if (c == alpha_channel) + continue; + + decode_buffer[decode_pixel_index + c] *= alpha; + } + } + STBIR_PROFILE_END( alpha ); + } + + if (edge_horizontal == STBIR_EDGE_ZERO) + { + for (x = -stbir_info->horizontal_filter_pixel_margin; x < 0; x++) + { + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + } + for (x = input_w; x < max_x; x++) + { + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + } + } +} + +static float* stbir__get_ring_buffer_entry(float* ring_buffer, int index, int ring_buffer_length) +{ + return &ring_buffer[index * ring_buffer_length]; +} + +static float* stbir__add_empty_ring_buffer_entry(ostbir__info* stbir_info, int n) +{ + int ring_buffer_index; + float* ring_buffer; + + stbir_info->ring_buffer_last_scanline = n; + + if (stbir_info->ring_buffer_begin_index < 0) + { + ring_buffer_index = stbir_info->ring_buffer_begin_index = 0; + stbir_info->ring_buffer_first_scanline = n; + } + else + { + ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries; + STBIR_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index); + } + + ring_buffer = stbir__get_ring_buffer_entry(stbir_info->ring_buffer, ring_buffer_index, stbir_info->ring_buffer_length_bytes / sizeof(float)); + + memset(ring_buffer, 0, stbir_info->ring_buffer_length_bytes); + + return ring_buffer; +} + + +static void stbir__resample_horizontal_upsample(ostbir__info* stbir_info, float* output_buffer) +{ + int x, k; + int output_w = stbir_info->output_w; + int channels = stbir_info->channels; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; + float* horizontal_coefficients = stbir_info->horizontal_coefficients; + int coefficient_width = stbir_info->horizontal_coefficient_width; + + STBIR_PROFILE_START( ); + for (x = 0; x < output_w; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int out_pixel_index = x * channels; + int coefficient_group = coefficient_width * x; + int coefficient_counter = 0; + + STBIR_ASSERT(n1 >= n0); + STBIR_ASSERT(n0 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n0 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + + switch (channels) { + case 1: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 1; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + } + break; + case 2: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 2; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + } + break; + case 3: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 3; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + } + break; + case 4: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 4; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient; + } + break; + default: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * channels; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + int c; + STBIR_ASSERT(coefficient != 0); + for (c = 0; c < channels; c++) + output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; + } + break; + } + } + STBIR_PROFILE_END( horizontal ); +} + +static void stbir__resample_horizontal_downsample(ostbir__info* stbir_info, float* output_buffer) +{ + int x, k; + int input_w = stbir_info->input_w; + int channels = stbir_info->channels; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; + float* horizontal_coefficients = stbir_info->horizontal_coefficients; + int coefficient_width = stbir_info->horizontal_coefficient_width; + int filter_pixel_margin = stbir_info->horizontal_filter_pixel_margin; + int max_x = input_w + filter_pixel_margin * 2; + + STBIR_ASSERT(!stbir__use_width_upsampling(stbir_info)); + + STBIR_PROFILE_START( ); + switch (channels) { + case 1: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 1; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 1; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + } + } + break; + + case 2: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 2; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 2; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + } + } + break; + + case 3: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 3; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 3; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + //STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + } + } + break; + + case 4: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 4; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 4; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient; + } + } + break; + + default: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * channels; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int c; + int out_pixel_index = k * channels; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + for (c = 0; c < channels; c++) + output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; + } + } + break; + } + STBIR_PROFILE_END( horizontal ); +} + +static void stbir__decode_and_resample_upsample(ostbir__info* stbir_info, int n) +{ + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline(stbir_info, n); + + // Now resample it into the ring buffer. + if (stbir__use_width_upsampling(stbir_info)) + stbir__resample_horizontal_upsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + else + stbir__resample_horizontal_downsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + + // Now it's sitting in the ring buffer ready to be used as source for the vertical sampling. +} + +static void stbir__decode_and_resample_downsample(ostbir__info* stbir_info, int n) +{ + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline(stbir_info, n); + + memset(stbir_info->horizontal_buffer, 0, stbir_info->output_w * stbir_info->channels * sizeof(float)); + + // Now resample it into the horizontal buffer. + if (stbir__use_width_upsampling(stbir_info)) + stbir__resample_horizontal_upsample(stbir_info, stbir_info->horizontal_buffer); + else + stbir__resample_horizontal_downsample(stbir_info, stbir_info->horizontal_buffer); + + // Now it's sitting in the horizontal buffer ready to be distributed into the ring buffers. +} + +// Get the specified scan line from the ring buffer. +static float* stbir__get_ring_buffer_scanline(int get_scanline, float* ring_buffer, int begin_index, int first_scanline, int ring_buffer_num_entries, int ring_buffer_length) +{ + int ring_buffer_index = (begin_index + (get_scanline - first_scanline)) % ring_buffer_num_entries; + return stbir__get_ring_buffer_entry(ring_buffer, ring_buffer_index, ring_buffer_length); +} + + +static void stbir__encode_scanline(ostbir__info* stbir_info, int num_pixels, void *output_buffer, float *encode_buffer, int channels, int alpha_channel, int decode) +{ + int x; + int n; + int num_nonalpha; + stbir_uint16 nonalpha[STBIR_MAX_CHANNELS]; + + if ((!(stbir_info->flags&STBIR_FLAG_ALPHA_OUT_PREMULTIPLIED))&&(alpha_channel!=-1)) + { + STBIR_PROFILE_START( ); + + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + float alpha = encode_buffer[pixel_index + alpha_channel]; + float reciprocal_alpha = alpha ? 1.0f / alpha : 0; + + // unrolling this produced a 1% slowdown upscaling a large RGBA linear-space image on my machine - stb + for (n = 0; n < channels; n++) + if (n != alpha_channel) + encode_buffer[pixel_index + n] *= reciprocal_alpha; + + // We added in a small epsilon to prevent the color channel from being deleted with zero alpha. + // Because we only add it for integer types, it will automatically be discarded on integer + // conversion, so we don't need to subtract it back out (which would be problematic for + // numeric precision reasons). + } + STBIR_PROFILE_END( unalpha ); + } + + // build a table of all channels that need colorspace correction, so + // we don't perform colorspace correction on channels that don't need it. + for (x = 0, num_nonalpha = 0; x < channels; ++x) + { + if (x != alpha_channel || (stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) + { + nonalpha[num_nonalpha++] = (stbir_uint16)x; + } + } + + #define STBIR__ROUND_INT(f) ((int) ((f)+0.5)) + #define STBIR__ROUND_UINT(f) ((stbir_uint32) ((f)+0.5)) + + #ifdef STBIR__SATURATE_INT + #define STBIR__ENCODE_LINEAR8(f) stbir__saturate8 (STBIR__ROUND_INT((f) * stbir__max_uint8_as_float )) + #define STBIR__ENCODE_LINEAR16(f) stbir__saturate16(STBIR__ROUND_INT((f) * stbir__max_uint16_as_float)) + #else + #define STBIR__ENCODE_LINEAR8(f) (unsigned char ) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint8_as_float ) + #define STBIR__ENCODE_LINEAR16(f) (unsigned short) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint16_as_float) + #endif + + STBIR_PROFILE_START( ); + + switch (decode) + { + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned char*)output_buffer)[index] = STBIR__ENCODE_LINEAR8(encode_buffer[index]); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned char*)output_buffer)[index] = stbir__linear_to_srgb_uchar(encode_buffer[index]); + } + + if (!(stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned char *)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR8(encode_buffer[pixel_index+alpha_channel]); + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned short*)output_buffer)[index] = STBIR__ENCODE_LINEAR16(encode_buffer[index]); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned short*)output_buffer)[index] = (unsigned short)STBIR__ROUND_INT(stbir__linear_to_srgb(stbir__saturate(encode_buffer[index])) * stbir__max_uint16_as_float); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned short*)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR16(encode_buffer[pixel_index + alpha_channel]); + } + + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__saturate(encode_buffer[index])) * stbir__max_uint32_as_float); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__linear_to_srgb(stbir__saturate(encode_buffer[index]))) * stbir__max_uint32_as_float); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned int*)output_buffer)[pixel_index + alpha_channel] = (unsigned int)STBIR__ROUND_INT(((double)stbir__saturate(encode_buffer[pixel_index + alpha_channel])) * stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((float*)output_buffer)[index] = encode_buffer[index]; + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + float p = encode_buffer[index]; + if ( p <= 0 ) p = 0; if ( p >= 1.0 ) p = 1.0; + ((float*)output_buffer)[index] = stbir__linear_to_srgb(p); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + { + float p = encode_buffer[pixel_index + alpha_channel]; + if ( p <= 0 ) p = 0; if ( p >= 1.0 ) p = 1.0; + ((float*)output_buffer)[pixel_index + alpha_channel] = p; + } + } + break; + + default: + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); + break; + } + STBIR_PROFILE_END( encode ); +} + +static void stbir__resample_vertical_upsample(ostbir__info* stbir_info, int n) +{ + int x, k; + int output_w = stbir_info->output_w; + stbir__contributors* vertical_contributors = stbir_info->vertical_contributors; + float* vertical_coefficients = stbir_info->vertical_coefficients; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; + void* output_data = stbir_info->output_data; + float* encode_buffer = stbir_info->encode_buffer; + int decode = STBIR__DECODE(type, colorspace); + int coefficient_width = stbir_info->vertical_coefficient_width; + int coefficient_counter; + int contributor = n; + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; + int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + + int n0,n1, output_row_start; + int coefficient_group = coefficient_width * contributor; + + n0 = vertical_contributors[contributor].n0; + n1 = vertical_contributors[contributor].n1; + + output_row_start = n * stbir_info->output_stride_bytes; + + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); + + STBIR_PROFILE_START( ); + + memset(encode_buffer, 0, output_w * sizeof(float) * channels); + + // I tried reblocking this for better cache usage of encode_buffer + // (using x_outer, k, x_inner), but it lost speed. -- stb + + coefficient_counter = 0; + switch (channels) { + case 1: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 1; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + } + } + break; + case 2: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 2; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + } + } + break; + case 3: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 3; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient; + } + } + break; + case 4: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 4; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient; + encode_buffer[in_pixel_index + 3] += ring_buffer_entry[in_pixel_index + 3] * coefficient; + } + } + break; + default: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * channels; + int c; + for (c = 0; c < channels; c++) + encode_buffer[in_pixel_index + c] += ring_buffer_entry[in_pixel_index + c] * coefficient; + } + } + break; + } + STBIR_PROFILE_END( vertical ); + stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, encode_buffer, channels, alpha_channel, decode); +} + +static void stbir__resample_vertical_downsample(ostbir__info* stbir_info, int n) +{ + int x, k; + int output_w = stbir_info->output_w; + stbir__contributors* vertical_contributors = stbir_info->vertical_contributors; + float* vertical_coefficients = stbir_info->vertical_coefficients; + int channels = stbir_info->channels; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; + float* horizontal_buffer = stbir_info->horizontal_buffer; + int coefficient_width = stbir_info->vertical_coefficient_width; + int contributor = n + stbir_info->vertical_filter_pixel_margin; + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; + int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + int n0,n1; + + n0 = vertical_contributors[contributor].n0; + n1 = vertical_contributors[contributor].n1; + + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); + + STBIR_PROFILE_START( ); + for (k = n0; k <= n1; k++) + { + int coefficient_index = k - n0; + int coefficient_group = coefficient_width * contributor; + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + + switch (channels) { + case 1: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 1; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + } + break; + case 2: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 2; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + } + break; + case 3: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 3; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient; + } + break; + case 4: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 4; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient; + ring_buffer_entry[in_pixel_index + 3] += horizontal_buffer[in_pixel_index + 3] * coefficient; + } + break; + default: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * channels; + + int c; + for (c = 0; c < channels; c++) + ring_buffer_entry[in_pixel_index + c] += horizontal_buffer[in_pixel_index + c] * coefficient; + } + break; + } + } + STBIR_PROFILE_END( vertical ); +} + +static void stbir__buffer_loop_upsample(ostbir__info* stbir_info) +{ + int y; + float scale_ratio = stbir_info->vertical_scale; + float out_scanlines_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(1/scale_ratio) * scale_ratio; + + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); + + for (y = 0; y < stbir_info->output_h; y++) + { + float in_center_of_out = 0; // Center of the current out scanline in the in scanline space + int in_first_scanline = 0, in_last_scanline = 0; + + stbir__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, stbir_info->vertical_shift, &in_first_scanline, &in_last_scanline, &in_center_of_out); + + STBIR_ASSERT(in_last_scanline - in_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); + + if (stbir_info->ring_buffer_begin_index >= 0) + { + // Get rid of whatever we don't need anymore. + while (in_first_scanline > stbir_info->ring_buffer_first_scanline) + { + if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline) + { + // We just popped the last scanline off the ring buffer. + // Reset it to the empty state. + stbir_info->ring_buffer_begin_index = -1; + stbir_info->ring_buffer_first_scanline = 0; + stbir_info->ring_buffer_last_scanline = 0; + break; + } + else + { + stbir_info->ring_buffer_first_scanline++; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; + } + } + } + + // Load in new ones. + if (stbir_info->ring_buffer_begin_index < 0) + stbir__decode_and_resample_upsample(stbir_info, in_first_scanline); + + while (in_last_scanline > stbir_info->ring_buffer_last_scanline) + stbir__decode_and_resample_upsample(stbir_info, stbir_info->ring_buffer_last_scanline + 1); + + // Now all buffers should be ready to write a row of vertical sampling. + stbir__resample_vertical_upsample(stbir_info, y); + + STBIR_PROGRESS_REPORT((float)y / stbir_info->output_h); + } +} + +static void stbir__empty_ring_buffer(ostbir__info* stbir_info, int first_necessary_scanline) +{ + int output_stride_bytes = stbir_info->output_stride_bytes; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int output_w = stbir_info->output_w; + void* output_data = stbir_info->output_data; + int decode = STBIR__DECODE(type, colorspace); + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + + if (stbir_info->ring_buffer_begin_index >= 0) + { + // Get rid of whatever we don't need anymore. + while (first_necessary_scanline > stbir_info->ring_buffer_first_scanline) + { + if (stbir_info->ring_buffer_first_scanline >= 0 && stbir_info->ring_buffer_first_scanline < stbir_info->output_h) + { + int output_row_start = stbir_info->ring_buffer_first_scanline * output_stride_bytes; + float* ring_buffer_entry = stbir__get_ring_buffer_entry(ring_buffer, stbir_info->ring_buffer_begin_index, ring_buffer_length); + stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, ring_buffer_entry, channels, alpha_channel, decode); + STBIR_PROGRESS_REPORT((float)stbir_info->ring_buffer_first_scanline / stbir_info->output_h); + } + + if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline) + { + // We just popped the last scanline off the ring buffer. + // Reset it to the empty state. + stbir_info->ring_buffer_begin_index = -1; + stbir_info->ring_buffer_first_scanline = 0; + stbir_info->ring_buffer_last_scanline = 0; + break; + } + else + { + stbir_info->ring_buffer_first_scanline++; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; + } + } + } +} + +static void stbir__buffer_loop_downsample(ostbir__info* stbir_info) +{ + int y; + float scale_ratio = stbir_info->vertical_scale; + int output_h = stbir_info->output_h; + float in_pixels_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(scale_ratio) / scale_ratio; + int pixel_margin = stbir_info->vertical_filter_pixel_margin; + int max_y = stbir_info->input_h + pixel_margin; + + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); + + for (y = -pixel_margin; y < max_y; y++) + { + float out_center_of_in; // Center of the current out scanline in the in scanline space + int out_first_scanline, out_last_scanline; + + stbir__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, stbir_info->vertical_shift, &out_first_scanline, &out_last_scanline, &out_center_of_in); + + STBIR_ASSERT(out_last_scanline - out_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); + + if (out_last_scanline < 0 || out_first_scanline >= output_h) + continue; + + stbir__empty_ring_buffer(stbir_info, out_first_scanline); + + stbir__decode_and_resample_downsample(stbir_info, y); + + // Load in new ones. + if (stbir_info->ring_buffer_begin_index < 0) + stbir__add_empty_ring_buffer_entry(stbir_info, out_first_scanline); + + while (out_last_scanline > stbir_info->ring_buffer_last_scanline) + stbir__add_empty_ring_buffer_entry(stbir_info, stbir_info->ring_buffer_last_scanline + 1); + + // Now the horizontal buffer is ready to write to all ring buffer rows. + stbir__resample_vertical_downsample(stbir_info, y); + } + + stbir__empty_ring_buffer(stbir_info, stbir_info->output_h); +} + +static void stbir__setup(ostbir__info *info, int input_w, int input_h, int output_w, int output_h, int channels) +{ + info->input_w = input_w; + info->input_h = input_h; + info->output_w = output_w; + info->output_h = output_h; + info->channels = channels; +} + +static void stbir__calculate_transform(ostbir__info *info, float s0, float t0, float s1, float t1, float *transform) +{ + info->s0 = s0; + info->t0 = t0; + info->s1 = s1; + info->t1 = t1; + + if (transform) + { + info->horizontal_scale = transform[0]; + info->vertical_scale = transform[1]; + info->horizontal_shift = transform[2]; + info->vertical_shift = transform[3]; + } + else + { + info->horizontal_scale = ((float)info->output_w / info->input_w) / (s1 - s0); + info->vertical_scale = ((float)info->output_h / info->input_h) / (t1 - t0); + + info->horizontal_shift = s0 * info->output_w / (s1 - s0); + info->vertical_shift = t0 * info->output_h / (t1 - t0); + } +} + +static void stbir__choose_filter(ostbir__info *info, stbir_filter h_filter, stbir_filter v_filter) +{ + if (h_filter == 0) + h_filter = stbir__use_upsampling(info->horizontal_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE; + if (v_filter == 0) + v_filter = stbir__use_upsampling(info->vertical_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE; + info->horizontal_filter = h_filter; + info->vertical_filter = v_filter; +} + +static stbir_uint32 stbir__calculate_memory(ostbir__info *info) +{ + int pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale); + int filter_height = stbir__get_filter_pixel_width(info->vertical_filter, info->vertical_scale); + + info->horizontal_num_contributors = stbir__get_contributors(info->horizontal_scale, info->horizontal_filter, info->input_w, info->output_w); + info->vertical_num_contributors = stbir__get_contributors(info->vertical_scale , info->vertical_filter , info->input_h, info->output_h); + + // One extra entry because floating point precision problems sometimes cause an extra to be necessary. + info->ring_buffer_num_entries = filter_height + 1; + + info->horizontal_contributors_size = info->horizontal_num_contributors * sizeof(stbir__contributors); + info->horizontal_coefficients_size = stbir__get_total_horizontal_coefficients(info) * sizeof(float); + info->vertical_contributors_size = info->vertical_num_contributors * sizeof(stbir__contributors); + info->vertical_coefficients_size = stbir__get_total_vertical_coefficients(info) * sizeof(float); + info->decode_buffer_size = (info->input_w + pixel_margin * 2) * info->channels * sizeof(float); + info->horizontal_buffer_size = info->output_w * info->channels * sizeof(float); + info->ring_buffer_size = info->output_w * info->channels * info->ring_buffer_num_entries * sizeof(float); + info->encode_buffer_size = info->output_w * info->channels * sizeof(float); + + STBIR_ASSERT(info->horizontal_filter != 0); + STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late + STBIR_ASSERT(info->vertical_filter != 0); + STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late + + if (stbir__use_height_upsampling(info)) + // The horizontal buffer is for when we're downsampling the height and we + // can't output the result of sampling the decode buffer directly into the + // ring buffers. + info->horizontal_buffer_size = 0; + else + // The encode buffer is to retain precision in the height upsampling method + // and isn't used when height downsampling. + info->encode_buffer_size = 0; + + return info->horizontal_contributors_size + info->horizontal_coefficients_size + + info->vertical_contributors_size + info->vertical_coefficients_size + + info->decode_buffer_size + info->horizontal_buffer_size + + info->ring_buffer_size + info->encode_buffer_size; +} + +static int stbir__resize_allocated(ostbir__info *info, + const void* input_data, int input_stride_in_bytes, + void* output_data, int output_stride_in_bytes, + int alpha_channel, stbir_uint32 flags, stbir_datatype type, + stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace, + void* tempmem, size_t tempmem_size_in_bytes) +{ + size_t memory_required = stbir__calculate_memory(info); + + int width_stride_input = input_stride_in_bytes ? input_stride_in_bytes : info->channels * info->input_w * stbir__type_size[type]; + int width_stride_output = output_stride_in_bytes ? output_stride_in_bytes : info->channels * info->output_w * stbir__type_size[type]; + +#ifdef STBIR_DEBUG_OVERWRITE_TEST +#define OVERWRITE_ARRAY_SIZE 8 + unsigned char overwrite_output_before_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_tempmem_before_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_output_after_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_tempmem_after_pre[OVERWRITE_ARRAY_SIZE]; + + size_t begin_forbidden = width_stride_output * (info->output_h - 1) + info->output_w * info->channels * stbir__type_size[type]; + memcpy(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE); +#endif + + STBIR_ASSERT(info->channels >= 0); + STBIR_ASSERT(info->channels <= STBIR_MAX_CHANNELS); + + if (info->channels < 0 || info->channels > STBIR_MAX_CHANNELS) + return 0; + + STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + + if (info->horizontal_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table)) + return 0; + if (info->vertical_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table)) + return 0; + + if (alpha_channel < 0) + flags |= STBIR_FLAG_ALPHA_USES_COLORSPACE | STBIR_FLAG_ALPHA_PREMULTIPLIED; + + if (!(flags&STBIR_FLAG_ALPHA_USES_COLORSPACE) || !(flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)) { + STBIR_ASSERT(alpha_channel >= 0 && alpha_channel < info->channels); + } + + if (alpha_channel >= info->channels) + return 0; + + STBIR_ASSERT(tempmem); + + if (!tempmem) + return 0; + + STBIR_ASSERT(tempmem_size_in_bytes >= memory_required); + + if (tempmem_size_in_bytes < memory_required) + return 0; + + memset(tempmem, 0, tempmem_size_in_bytes); + + info->input_data = input_data; + info->input_stride_bytes = width_stride_input; + + info->output_data = output_data; + info->output_stride_bytes = width_stride_output; + + info->alpha_channel = alpha_channel; + info->flags = flags; + info->type = type; + info->edge_horizontal = edge_horizontal; + info->edge_vertical = edge_vertical; + info->colorspace = colorspace; + + STBIR_PROFILE_START(); + + info->horizontal_coefficient_width = stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale); + info->vertical_coefficient_width = stbir__get_coefficient_width (info->vertical_filter , info->vertical_scale ); + info->horizontal_filter_pixel_width = stbir__get_filter_pixel_width (info->horizontal_filter, info->horizontal_scale); + info->vertical_filter_pixel_width = stbir__get_filter_pixel_width (info->vertical_filter , info->vertical_scale ); + info->horizontal_filter_pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale); + info->vertical_filter_pixel_margin = stbir__get_filter_pixel_margin(info->vertical_filter , info->vertical_scale ); + + info->ring_buffer_length_bytes = info->output_w * info->channels * sizeof(float); + info->decode_buffer_pixels = info->input_w + info->horizontal_filter_pixel_margin * 2; + +#define STBIR__NEXT_MEMPTR(current, newtype) (newtype*)(((unsigned char*)current) + current##_size) + + info->horizontal_contributors = (stbir__contributors *) tempmem; + info->horizontal_coefficients = STBIR__NEXT_MEMPTR(info->horizontal_contributors, float); + info->vertical_contributors = STBIR__NEXT_MEMPTR(info->horizontal_coefficients, stbir__contributors); + info->vertical_coefficients = STBIR__NEXT_MEMPTR(info->vertical_contributors, float); + info->decode_buffer = STBIR__NEXT_MEMPTR(info->vertical_coefficients, float); + + if (stbir__use_height_upsampling(info)) + { + info->horizontal_buffer = NULL; + info->ring_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float); + info->encode_buffer = STBIR__NEXT_MEMPTR(info->ring_buffer, float); + + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->encode_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + } + else + { + info->horizontal_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float); + info->ring_buffer = STBIR__NEXT_MEMPTR(info->horizontal_buffer, float); + info->encode_buffer = NULL; + + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->ring_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + } + +#undef STBIR__NEXT_MEMPTR + + // This signals that the ring buffer is empty + info->ring_buffer_begin_index = -1; + + stbir__calculate_filters(info->horizontal_contributors, info->horizontal_coefficients, info->horizontal_filter, info->horizontal_scale, info->horizontal_shift, info->input_w, info->output_w); + stbir__calculate_filters(info->vertical_contributors, info->vertical_coefficients, info->vertical_filter, info->vertical_scale, info->vertical_shift, info->input_h, info->output_h); + STBIR_PROFILE_END( filters ); + + STBIR_PROGRESS_REPORT(0); + + STBIR_PROFILE_START(); + if (stbir__use_height_upsampling(info)) + { + stbir__buffer_loop_upsample(info); + } + else + { + stbir__buffer_loop_downsample(info); + } + STBIR_PROFILE_END( looping ); + + + STBIR_PROGRESS_REPORT(1); + +#ifdef STBIR_DEBUG_OVERWRITE_TEST + STBIR_ASSERT(memcmp(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0); +#endif + + return 1; +} + + +static int stbir__resize_arbitrary( + void *alloc_context, + const void* input_data, int input_w, int input_h, int input_stride_in_bytes, + void* output_data, int output_w, int output_h, int output_stride_in_bytes, + float s0, float t0, float s1, float t1, float *transform, + int channels, int alpha_channel, stbir_uint32 flags, stbir_datatype type, + stbir_filter h_filter, stbir_filter v_filter, + stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace) +{ + ostbir__info info; + int result; + size_t memory_required; + void* extra_memory; + + STBIR_PROFILE_FIRST_START(); + + stbir__setup(&info, input_w, input_h, output_w, output_h, channels); + stbir__calculate_transform(&info, s0,t0,s1,t1,transform); + stbir__choose_filter(&info, h_filter, v_filter); + memory_required = stbir__calculate_memory(&info); + extra_memory = STBIR_MALLOC(memory_required, alloc_context); + + if (!extra_memory) + { + return 0; + } + + result = stbir__resize_allocated(&info, input_data, input_stride_in_bytes, + output_data, output_stride_in_bytes, + alpha_channel, flags, type, + edge_horizontal, edge_vertical, + colorspace, extra_memory, memory_required); + + STBIR_PROFILE_END( setup); + + STBIR_FREE(extra_memory, alloc_context); + + return result; +} + +STBIRDEF int stbir_resize_uint8( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR); +} + +STBIRDEF int stbir_resize_float( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_FLOAT, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR); +} + +STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB); +} + +STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + edge_wrap_mode, edge_wrap_mode, STBIR_COLORSPACE_SRGB); +} + +STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + +STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT16, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + + +STBIRDEF int stbir_resize_float_generic( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_FLOAT, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + + +STBIRDEF int stbir_resize( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + + +STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float x_scale, float y_scale, + float x_offset, float y_offset) +{ + float transform[4]; + transform[0] = x_scale; + transform[1] = y_scale; + transform[2] = x_offset; + transform[3] = y_offset; + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,transform,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + +STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float s0, float t0, float s1, float t1) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + s0,t0,s1,t1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + +#endif // STB_IMAGE_RESIZE_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/deps/stb/stb_image_resize_test/oldir.c b/deps/stb/stb_image_resize_test/oldir.c new file mode 100644 index 00000000..e1f35057 --- /dev/null +++ b/deps/stb/stb_image_resize_test/oldir.c @@ -0,0 +1,56 @@ +#include +#include + +#ifdef _MSC_VER +#define stop() __debugbreak() +#else +#define stop() __builtin_trap() +#endif + +//#define HEAVYTM +#include "tm.h" + +#define STBIR_SATURATE_INT +#define STB_IMAGE_RESIZE_STATIC +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include "old_image_resize.h" + + +static int types[4] = { STBIR_TYPE_UINT8, STBIR_TYPE_UINT8, STBIR_TYPE_UINT16, STBIR_TYPE_FLOAT }; +static int edges[4] = { STBIR_EDGE_CLAMP, STBIR_EDGE_REFLECT, STBIR_EDGE_ZERO, STBIR_EDGE_WRAP }; +static int flts[5] = { STBIR_FILTER_BOX, STBIR_FILTER_TRIANGLE, STBIR_FILTER_CUBICBSPLINE, STBIR_FILTER_CATMULLROM, STBIR_FILTER_MITCHELL }; +static int channels[20] = { 1, 2, 3, 4, 4,4, 2,2, 4,4, 2,2, 4,4, 2,2, 4,4, 2,2 }; +static int alphapos[20] = { -1, -1, -1, -1, 3,0, 1,0, 3,0, 1,0, 3,0, 1,0, 3,0, 1,0 }; + + +void oresize( void * o, int ox, int oy, int op, void * i, int ix, int iy, int ip, int buf, int type, int edg, int flt ) +{ + int t = types[type]; + int ic = channels[buf]; + int alpha = alphapos[buf]; + int e = edges[edg]; + int f = flts[flt]; + int space = ( type == 1 ) ? STBIR_COLORSPACE_SRGB : 0; + int flags = ( buf >= 16 ) ? STBIR_FLAG_ALPHA_PREMULTIPLIED : ( ( buf >= 12 ) ? STBIR_FLAG_ALPHA_OUT_PREMULTIPLIED : ( ( buf >= 8 ) ? (STBIR_FLAG_ALPHA_PREMULTIPLIED|STBIR_FLAG_ALPHA_OUT_PREMULTIPLIED) : 0 ) ); + stbir_uint64 start; + + ENTER( "Resize (old)" ); + start = tmGetAccumulationStart( tm_mask ); + + if(!stbir_resize( i, ix, iy, ip, o, ox, oy, op, t, ic, alpha, flags, e, e, f, f, space, 0 ) ) + stop(); + + #ifdef STBIR_PROFILE + tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.setup, "Setup (old)" ); + tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.filters, "Filters (old)" ); + tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.looping, "Looping (old)" ); + tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.vertical, "Vertical (old)" ); + tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.horizontal, "Horizontal (old)" ); + tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.decode, "Scanline input (old)" ); + tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.encode, "Scanline output (old)" ); + tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.alpha, "Alpha weighting (old)" ); + tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.unalpha, "Alpha unweighting (old)" ); + #endif + + LEAVE(); +} diff --git a/deps/stb/stb_image_resize_test/stbirtest.c b/deps/stb/stb_image_resize_test/stbirtest.c new file mode 100644 index 00000000..22e1b824 --- /dev/null +++ b/deps/stb/stb_image_resize_test/stbirtest.c @@ -0,0 +1,992 @@ +#include +#include +#include + +//#define HEAVYTM +#include "tm.h" + +#ifdef RADUSETM3 +tm_api * g_tm_api; +//#define PROFILE_MODE +#endif + +#include + +#ifdef _MSC_VER +#define stop() __debugbreak() +#include +#define int64 __int64 +#define uint64 unsigned __int64 +#else +#define stop() __builtin_trap() +#define int64 long long +#define uint64 unsigned long long +#endif + +#ifdef _MSC_VER +#pragma warning(disable:4127) +#endif + +//#define NOCOMP + + +//#define PROFILE_NEW_ONLY +//#define PROFILE_MODE + + +#if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(__SSE2__) || defined(STBIR_SSE) || defined( _M_IX86_FP ) || defined(__i386) || defined( __i386__ ) || defined( _M_IX86 ) || defined( _X86_ ) + +#ifdef _MSC_VER + + uint64 __rdtsc(); + #define __cycles() __rdtsc() + +#else // non msvc + + static inline uint64 __cycles() + { + unsigned int lo, hi; + asm volatile ("rdtsc" : "=a" (lo), "=d" (hi) ); + return ( ( (uint64) hi ) << 32 ) | ( (uint64) lo ); + } + +#endif // msvc + +#elif defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || defined(__ARM_NEON__) + +#ifdef _MSC_VER + + #define __cycles() _ReadStatusReg(ARM64_CNTVCT) + +#else + + static inline uint64 __cycles() + { + uint64 tsc; + asm volatile("mrs %0, cntvct_el0" : "=r" (tsc)); + return tsc; + } + +#endif + +#else // x64, arm + +#error Unknown platform for timing. + +#endif //x64 and + + +#ifdef PROFILE_MODE + +#define STBIR_ASSERT(cond) + +#endif + +#ifdef _DEBUG +#undef STBIR_ASSERT +#define STBIR_ASSERT(cond) { if (!(cond)) stop(); } +#endif + + +#define SHRINKBYW 2 +#define ZOOMBYW 2 +#define SHRINKBYH 2 +#define ZOOMBYH 2 + + +int mem_count = 0; + +#ifdef TEST_WITH_VALLOC + +#define STBIR__SEPARATE_ALLOCATIONS + +#if TEST_WITH_LIMIT_AT_FRONT + + void * wmalloc(SIZE_T size) + { + static unsigned int pagesize=0; + void* p; + SIZE_T s; + + // get the page size, if we haven't yet + if (pagesize==0) + { + SYSTEM_INFO si; + GetSystemInfo(&si); + pagesize=si.dwPageSize; + } + + // we need room for the size, 8 bytes to hide the original pointer and a + // validation dword, and enough data to completely fill one page + s=(size+(pagesize-1))&~(pagesize-1); + + // allocate the size plus a page (for the guard) + p=VirtualAlloc(0,(SIZE_T)s,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE); + + return p; + } + + void wfree(void * ptr) + { + if (ptr) + { + if ( ((ptrdiff_t)ptr) & 4095 ) stop(); + if ( VirtualFree(ptr,0,MEM_RELEASE) == 0 ) stop(); + } + } + +#else + + void * wmalloc(SIZE_T size) + { + static unsigned int pagesize=0; + void* p; + SIZE_T s; + + // get the page size, if we haven't yet + if (pagesize==0) + { + SYSTEM_INFO si; + GetSystemInfo(&si); + pagesize=si.dwPageSize; + } + + // we need room for the size, 8 bytes to hide the original pointer and a + // validation dword, and enough data to completely fill one page + s=(size+16+(pagesize-1))&~(pagesize-1); + + // allocate the size plus a page (for the guard) + p=VirtualAlloc(0,(SIZE_T)(s+pagesize+pagesize),MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE); + + if (p) + { + DWORD oldprot; + void* orig=p; + + // protect the first page + VirtualProtect(((char*)p),pagesize,PAGE_NOACCESS,&oldprot); + + // protect the final page + VirtualProtect(((char*)p)+s+pagesize,pagesize,PAGE_NOACCESS,&oldprot); + + // now move the returned pointer so that it bumps right up against the + // the next (protected) page (this may result in unaligned return + // addresses - pre-align the sizes if you always want aligned ptrs) +//#define ERROR_ON_FRONT +#ifdef ERROR_ON_FRONT + p=((char*)p)+pagesize+16; +#else + p=((char*)p)+(s-size)+pagesize; +#endif + + // hide the validation value and the original pointer (which we'll + // need used for freeing) right behind the returned pointer + ((unsigned int*)p)[-1]=0x98765432; + ((void**)p)[-2]=orig; + ++mem_count; +//printf("aloc: %p bytes: %d\n",p,(int)size); + return(p); + } + + return 0; + } + + void wfree(void * ptr) + { + if (ptr) + { + int err=0; + + // is this one of our allocations? + if (((((unsigned int*)ptr)[-1])!=0x98765432) || ((((void**)ptr)[-2])==0)) + { + err=1; + } + + if (err) + { + __debugbreak(); + } + else + { + + // back up to find the original pointer + void* p=((void**)ptr)[-2]; + + // clear the validation value and the original pointer + ((unsigned int*)ptr)[-1]=0; + ((void**)ptr)[-2]=0; + +//printf("free: %p\n",ptr); + + --mem_count; + + // now free the pages + if (p) + VirtualFree(p,0,MEM_RELEASE); + + } + } + } + +#endif + +#define STBIR_MALLOC(size,user_data) ((void)(user_data), wmalloc(size)) +#define STBIR_FREE(ptr,user_data) ((void)(user_data), wfree(ptr)) + +#endif + +#define STBIR_PROFILE +//#define STBIR_NO_SIMD +//#define STBIR_AVX +//#define STBIR_AVX2 +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include "stb_image_resize2.h" // new one! + +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" + +int tsizes[5] = { 1, 1, 2, 4, 2 }; +int ttypes[5] = { STBIR_TYPE_UINT8, STBIR_TYPE_UINT8_SRGB, STBIR_TYPE_UINT16, STBIR_TYPE_FLOAT, STBIR_TYPE_HALF_FLOAT }; + +int cedges[4] = { STBIR_EDGE_CLAMP, STBIR_EDGE_REFLECT, STBIR_EDGE_ZERO, STBIR_EDGE_WRAP }; +int flts[5] = { STBIR_FILTER_BOX, STBIR_FILTER_TRIANGLE, STBIR_FILTER_CUBICBSPLINE, STBIR_FILTER_CATMULLROM, STBIR_FILTER_MITCHELL }; +int buffers[20] = { STBIR_1CHANNEL, STBIR_2CHANNEL, STBIR_RGB, STBIR_4CHANNEL, + STBIR_BGRA, STBIR_ARGB, STBIR_RA, STBIR_AR, + STBIR_RGBA_PM, STBIR_ARGB_PM, STBIR_RA_PM, STBIR_AR_PM, + STBIR_RGBA, STBIR_ARGB, STBIR_RA, STBIR_AR, + STBIR_RGBA_PM, STBIR_ARGB_PM, STBIR_RA_PM, STBIR_AR_PM, + }; +int obuffers[20] = { STBIR_1CHANNEL, STBIR_2CHANNEL, STBIR_RGB, STBIR_4CHANNEL, + STBIR_BGRA, STBIR_ARGB, STBIR_RA, STBIR_AR, + STBIR_RGBA_PM, STBIR_ARGB_PM, STBIR_RA_PM, STBIR_AR_PM, + STBIR_RGBA_PM, STBIR_ARGB_PM, STBIR_RA_PM, STBIR_AR_PM, + STBIR_RGBA, STBIR_ARGB, STBIR_RA, STBIR_AR, + }; + +int bchannels[20] = { 1, 2, 3, 4, 4,4, 2,2, 4,4, 2,2, 4,4, 2,2, 4,4, 2,2 }; +int alphapos[20] = { -1, -1, -1, -1, 3,0, 1,0, 3,0, 1,0, 3,0, 1,0,3,0, 1,0 }; + + +char const * buffstrs[20] = { "1ch", "2ch", "3ch", "4ch", "RGBA", "ARGB", "RA", "AR", "RGBA_both_pre", "ARGB_both_pre", "RA_both_pre", "AR_both_pre", "RGBA_out_pre", "ARGB_out_pre", "RA_out_pre", "AR_out_pre", "RGBA_in_pre", "ARGB_in_pre", "RA_in_pre", "AR_in_pre" }; +char const * typestrs[5] = { "Bytes", "BytesSRGB", "Shorts", "Floats", "Half Floats"}; +char const * edgestrs[4] = { "Clamp", "Reflect", "Zero", "Wrap" }; +char const * fltstrs[5] = { "Box", "Triangle", "Cubic", "Catmullrom", "Mitchell" }; + +#ifdef STBIR_PROFILE + static void do_acc_zones( STBIR_PROFILE_INFO * profile ) + { + stbir_uint32 j; + stbir_uint64 start = tmGetAccumulationStart( tm_mask ); start=start; + + for( j = 0 ; j < profile->count ; j++ ) + { + if ( profile->clocks[j] ) + tmEmitAccumulationZone( 0, 0, (tm_uint64*)&start, 0, profile->clocks[j], profile->descriptions[j] ); + } + } +#else + #define do_acc_zones(...) +#endif + +int64 vert; + +//#define WINTHREADTEST +#ifdef WINTHREADTEST + +static STBIR_RESIZE * thread_resize; +static LONG which; +static int threads_started = 0; +static HANDLE threads[32]; +static HANDLE starts,stops; + +static DWORD resize_shim( LPVOID p ) +{ + for(;;) + { + LONG wh; + + WaitForSingleObject( starts, INFINITE ); + + wh = InterlockedAdd( &which, 1 ) - 1; + + ENTER( "Split %d", wh ); + stbir_resize_split( thread_resize, wh, 1 ); + #ifdef STBIR_PROFILE + { STBIR_PROFILE_INFO profile; stbir_resize_split_profile_info( &profile, thread_resize, wh, 1 ); do_acc_zones( &profile ); vert = profile.clocks[1]; } + #endif + LEAVE(); + + ReleaseSemaphore( stops, 1, 0 ); + } +} + +#endif + +void nresize( void * o, int ox, int oy, int op, void * i, int ix, int iy, int ip, int buf, int type, int edg, int flt ) +{ + STBIR_RESIZE resize; + + stbir_resize_init( &resize, i, ix, iy, ip, o, ox, oy, op, buffers[buf], ttypes[type] ); + stbir_set_pixel_layouts( &resize, buffers[buf], obuffers[buf] ); + stbir_set_edgemodes( &resize, cedges[edg], cedges[edg] ); + stbir_set_filters( &resize, flts[flt], /*STBIR_FILTER_POINT_SAMPLE */ flts[flt] ); + //stbir_set_input_subrect( &resize, 0.55f,0.333f,0.75f,0.50f); + //stbir_set_output_pixel_subrect( &resize, 00, 00, ox/2,oy/2); + //stbir_set_pixel_subrect(&resize, 1430,1361,30,30); + + ENTER( "Resize" ); + + #ifndef WINTHREADTEST + + ENTER( "Filters" ); + stbir_build_samplers_with_splits( &resize, 1 ); + #ifdef STBIR_PROFILE + { STBIR_PROFILE_INFO profile; stbir_resize_build_profile_info( &profile, &resize ); do_acc_zones( &profile ); } + #endif + LEAVE(); + + ENTER( "Resize" ); + if(!stbir_resize_extended( &resize ) ) + stop(); + #ifdef STBIR_PROFILE + { STBIR_PROFILE_INFO profile; stbir_resize_extended_profile_info( &profile, &resize ); do_acc_zones( &profile ); vert = profile.clocks[1]; } + #endif + LEAVE(); + + #else + { + int c, cnt; + + ENTER( "Filters" ); + cnt = stbir_build_samplers_with_splits( &resize, 4 ); + #ifdef STBIR_PROFILE + { STBIR_PROFILE_INFO profile; stbir_resize_build_profile_info( &profile, &resize ); do_acc_zones( &profile ); } + #endif + LEAVE(); + + ENTER( "Thread start" ); + if ( threads_started == 0 ) + { + starts = CreateSemaphore( 0, 0, 32, 0 ); + stops = CreateSemaphore( 0, 0, 32, 0 ); + } + for( c = threads_started ; c < cnt ; c++ ) + threads[ c ] = CreateThread( 0, 2048*1024, resize_shim, 0, 0, 0 ); + + threads_started = cnt; + thread_resize = &resize; + which = 0; + LEAVE(); + + // starts the threads + ReleaseSemaphore( starts, cnt, 0 ); + + ENTER( "Wait" ); + for( c = 0 ; c < cnt; c++ ) + WaitForSingleObject( stops, INFINITE ); + LEAVE(); + } + #endif + + ENTER( "Free" ); + stbir_free_samplers( &resize ); + LEAVE(); + LEAVE(); +} + + +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" + +extern void oresize( void * o, int ox, int oy, int op, void * i, int ix, int iy, int ip, int buf, int type, int edg, int flt ); + + + +#define TYPESTART 0 +#define TYPEEND 4 + +#define LAYOUTSTART 0 +#define LAYOUTEND 19 + +#define SIZEWSTART 0 +#define SIZEWEND 2 + +#define SIZEHSTART 0 +#define SIZEHEND 2 + +#define EDGESTART 0 +#define EDGEEND 3 + +#define FILTERSTART 0 +#define FILTEREND 4 + +#define HEIGHTSTART 0 +#define HEIGHTEND 2 + +#define WIDTHSTART 0 +#define WIDTHEND 2 + + + + +static void * convert8to16( unsigned char * i, int w, int h, int c ) +{ + unsigned short * ret; + int p; + + ret = malloc( w*h*c*sizeof(short) ); + for(p = 0 ; p < (w*h*c) ; p++ ) + { + ret[p]=(short)((((int)i[p])<<8)+i[p]); + } + + return ret; +} + +static void * convert8tof( unsigned char * i, int w, int h, int c ) +{ + float * ret; + int p; + + ret = malloc( w*h*c*sizeof(float) ); + for(p = 0 ; p < (w*h*c) ; p++ ) + { + ret[p]=((float)i[p])*(1.0f/255.0f); + } + + return ret; +} + +static void * convert8tohf( unsigned char * i, int w, int h, int c ) +{ + stbir__FP16 * ret; + int p; + + ret = malloc( w*h*c*sizeof(stbir__FP16) ); + for(p = 0 ; p < (w*h*c) ; p++ ) + { + ret[p]=stbir__float_to_half(((float)i[p])*(1.0f/255.0f)); + } + + return ret; +} + +static void * convert8tohff( unsigned char * i, int w, int h, int c ) +{ + float * ret; + int p; + + ret = malloc( w*h*c*sizeof(float) ); + for(p = 0 ; p < (w*h*c) ; p++ ) + { + ret[p]=stbir__half_to_float(stbir__float_to_half(((float)i[p])*(1.0f/255.0f))); + } + + return ret; +} + +static int isprime( int v ) +{ + int i; + + if ( v <= 3 ) + return ( v > 1 ); + if ( ( v & 1 ) == 0 ) + return 0; + if ( ( v % 3 ) == 0 ) + return 0; + i = 5; + while ( (i*i) <= v ) + { + if ( ( v % i ) == 0 ) + return 0; + if ( ( v % ( i + 2 ) ) == 0 ) + return 0; + i += 6; + } + + return 1; +} + +static int getprime( int v ) +{ + int i; + i = 0; + for(;;) + { + if ( i >= v ) + return v; // can't find any, just return orig + if (isprime(v - i)) + return v - i; + if (isprime(v + i)) + return v + i; + ++i; + } +} + + +int main( int argc, char ** argv ) +{ + int ix, iy, ic; + unsigned char * input[6]; + char * ir1; + char * ir2; + int szhs[3]; + int szws[3]; + int aw, ah, ac; + unsigned char * correctalpha; + int layouts, types, heights, widths, edges, filters; + + if ( argc != 2 ) + { + printf("command: stbirtest [imagefile]\n"); + exit(1); + } + + SetupTM( "127.0.0.1" ); + + correctalpha = stbi_load( "correctalpha.png", &aw, &ah, &ac, 0 ); + + input[0] = stbi_load( argv[1], &ix, &iy, &ic, 0 ); + input[1] = input[0]; + input[2] = convert8to16( input[0], ix, iy, ic ); + input[3] = convert8tof( input[0], ix, iy, ic ); + input[4] = convert8tohf( input[0], ix, iy, ic ); + input[5] = convert8tohff( input[0], ix, iy, ic ); + + printf("Input %dx%d (%d channels)\n",ix,iy,ic); + + ir1 = malloc( 4 * 4 * 3000 * 3000ULL ); + ir2 = malloc( 4 * 4 * 3000 * 3000ULL ); + + szhs[0] = getprime( iy/SHRINKBYH ); + szhs[1] = iy; + szhs[2] = getprime( iy*ZOOMBYH ); + + szws[0] = getprime( ix/SHRINKBYW ); + szws[1] = ix; + szws[2] = getprime( ix*ZOOMBYW ); + + #if 1 + for( types = TYPESTART ; types <= TYPEEND ; types++ ) + #else + for( types = 1 ; types <= 1 ; types++ ) + #endif + { + ENTER( "Test type: %s",typestrs[types]); + #if 1 + for( layouts = LAYOUTSTART ; layouts <= LAYOUTEND ; layouts++ ) + #else + for( layouts = 16; layouts <= 16 ; layouts++ ) + #endif + { + ENTER( "Test layout: %s",buffstrs[layouts]); + + #if 0 + for( heights = HEIGHTSTART ; heights <= HEIGHTEND ; heights++ ) + { + int w, h = szhs[heights]; + #else + for( heights = 0 ; heights <= 11 ; heights++ ) + { + static int szhsz[12]={32, 200, 350, 400, 450, 509, 532, 624, 700, 824, 1023, 2053 }; + int w, h = szhsz[heights]; + #endif + + ENTER( "Test height: %d %s %d",iy,(hiy)?"Up":"Same"),h); + + #if 0 + for( widths = WIDTHSTART ; widths <= WIDTHEND ; widths++ ) + { + w = szws[widths]; + #else + for( widths = 0 ; widths <= 12 ; widths++ ) + { + static int szwsz[13]={2, 32, 200, 350, 400, 450, 509, 532, 624, 700, 824, 1023, 2053 }; + w = szwsz[widths]; + #endif + + ENTER( "Test width: %d %s %d",ix, (wix)?"Up":"Same"), w); + + #if 0 + for( edges = EDGESTART ; edges <= EDGEEND ; edges++ ) + #else + for( edges = 0 ; edges <= 0 ; edges++ ) + #endif + { + ENTER( "Test edge: %s",edgestrs[edges]); + #if 0 + for( filters = FILTERSTART ; filters <= FILTEREND ; filters++ ) + #else + for( filters = 3 ; filters <= 3 ; filters++ ) + #endif + { + int op, opw, np,npw, c, a; + #ifdef COMPARE_SAME + int oldtypes = types; + #else + int oldtypes = (types==4)?3:types; + #endif + + ENTER( "Test filter: %s",fltstrs[filters]); + { + c = bchannels[layouts]; + a = alphapos[layouts]; + + op = w*tsizes[oldtypes]*c + 60; + opw = w*tsizes[oldtypes]*c; + + np = w*tsizes[types]*c + 60; + npw = w*tsizes[types]*c; + + printf( "%s:layout: %s w: %d h: %d edge: %s filt: %s\n", typestrs[types],buffstrs[layouts], w, h, edgestrs[edges], fltstrs[filters] ); + + + // clear pixel area to different, right edge to zero + #ifndef NOCLEAR + ENTER( "Test clear padding" ); + { + int d; + for( d = 0 ; d < h ; d++ ) + { + int oofs = d * op; + int nofs = d * np; + memset( ir1 + oofs, 192, opw ); + memset( ir1 + oofs+opw, 79, op-opw ); + memset( ir2 + nofs, 255, npw ); + memset( ir2 + nofs+npw, 79, np-npw ); + } + } + LEAVE(); + + #endif + + #ifdef COMPARE_SAME + #define TIMINGS 1 + #else + #define TIMINGS 1 + #endif + ENTER( "Test both" ); + { + #ifndef PROFILE_NEW_ONLY + { + int ttt, max = 0x7fffffff; + ENTER( "Test old" ); + for( ttt = 0 ; ttt < TIMINGS ; ttt++ ) + { + int64 m = __cycles(); + + oresize( ir1, w, h, op, + #ifdef COMPARE_SAME + input[types], + #else + input[(types==4)?5:types], + #endif + ix, iy, ix*ic*tsizes[oldtypes], layouts, oldtypes, edges, filters ); + + m = __cycles() - m; + if ( ( (int)m ) < max ) + max = (int) m; + } + LEAVE(); + printf("old: %d\n", max ); + } + #endif + + { + int ttt, max = 0x7fffffff, maxv = 0x7fffffff; + ENTER( "Test new" ); + for( ttt = 0 ; ttt < TIMINGS ; ttt++ ) + { + int64 m = __cycles(); + + nresize( ir2, w, h, np, input[types], ix, iy, ix*ic*tsizes[types], layouts, types, edges, filters ); + + m = __cycles() - m; + if ( ( (int)m ) < max ) + max = (int) m; + if ( ( (int)vert ) < maxv ) + maxv = (int) vert; + } + LEAVE(); // test new + printf("new: %d (v: %d)\n", max, maxv ); + } + } + LEAVE(); // test both + + if ( mem_count!= 0 ) + stop(); + + #ifndef NOCOMP + ENTER( "Test compare" ); + { + int x,y,ch; + int nums = 0; + for( y = 0 ; y < h ; y++ ) + { + for( x = 0 ; x < w ; x++ ) + { + switch(types) + { + case 0: + case 1: //SRGB + { + unsigned char * p1 = (unsigned char *)&ir1[y*op+x*c]; + unsigned char * p2 = (unsigned char *)&ir2[y*np+x*c]; + for( ch = 0 ; ch < c ; ch++ ) + { + float pp1,pp2,d; + float av = (a==-1)?1.0f:((float)p1[a]/255.0f); + + pp1 = p1[ch]; + pp2 = p2[ch]; + + // compare in premult space + #ifndef COMPARE_SAME + if ( ( ( layouts >=4 ) && ( layouts <= 7 ) ) || ( ( layouts >=16 ) && ( layouts <= 19 ) ) ) + { + pp1 *= av; + pp2 *= av; + } + #endif + + d = pp1 - pp2; + if ( d < 0 ) d = -d; + + #ifdef COMPARE_SAME + if ( d > 0 ) + #else + if ( d > 1 ) + #endif + { + printf("Error at %d x %d (chan %d) (d: %g a: %g) [%d %d %d %d] [%d %d %d %d]\n",x,y,ch, d,av, p1[0],p1[1],p1[2],p1[3], p2[0],p2[1],p2[2],p2[3]); + ++nums; + if ( nums > 16 ) goto ex; + //if (d) exit(1); + //goto ex; + } + } + } + break; + + case 2: + { + unsigned short * p1 = (unsigned short *)&ir1[y*op+x*c*sizeof(short)]; + unsigned short * p2 = (unsigned short *)&ir2[y*np+x*c*sizeof(short)]; + for( ch = 0 ; ch < c ; ch++ ) + { + float thres,pp1,pp2,d; + float av = (a==-1)?1.0f:((float)p1[a]/65535.0f); + + pp1 = p1[ch]; + pp2 = p2[ch]; + + // compare in premult space + #ifndef COMPARE_SAME + if ( ( ( layouts >=4 ) && ( layouts <= 7 ) ) || ( ( layouts >= 16 ) && ( layouts <= 19 ) ) ) + { + pp1 *= av; + pp2 *= av; + } + #endif + + d = pp1 - pp2; + if ( d < 0 ) d = -d; + + thres=((float)p1[ch]*0.007f)+2.0f; + if (thres<4) thres = 4; + + #ifdef COMPARE_SAME + if ( d > 0 ) + #else + if ( d > thres) + #endif + { + printf("Error at %d x %d (chan %d) %d %d [df: %g th: %g al: %g] (%d %d %d %d) (%d %d %d %d)\n",x,y,ch, p1[ch],p2[ch],d,thres,av,p1[0],p1[1],p1[2],p1[3],p2[0],p2[1],p2[2],p2[3]); + ++nums; + if ( nums > 16 ) goto ex; + //if (d) exit(1); + //goto ex; + } + } + } + break; + + case 3: + { + float * p1 = (float *)&ir1[y*op+x*c*sizeof(float)]; + float * p2 = (float *)&ir2[y*np+x*c*sizeof(float)]; + for( ch = 0 ; ch < c ; ch++ ) + { + float pp1 = p1[ch], pp2 = p2[ch]; + float av = (a==-1)?1.0f:p1[a]; + float thres, d; + + // clamp + if (pp1<=0.0f) pp1 = 0; + if (pp2<=0.0f) pp2 = 0; + if (av<=0.0f) av = 0; + if (pp1>1.0f) pp1 = 1.0f; + if (pp2>1.0f) pp2 = 1.0f; + if (av>1.0f) av = 1.0f; + + // compare in premult space + #ifndef COMPARE_SAME + if ( ( ( layouts >=4 ) && ( layouts <= 7 ) ) || ( ( layouts >= 16 ) && ( layouts <= 19 ) ) ) + { + pp1 *= av; + pp2 *= av; + } + #endif + + d = pp1 - pp2; + if ( d < 0 ) d = -d; + + thres=(p1[ch]*0.002f)+0.0002f; + if ( thres < 0 ) thres = -thres; + + #ifdef COMPARE_SAME + if ( d != 0.0f ) + #else + if ( d > thres ) + #endif + { + printf("Error at %d x %d (chan %d) %g %g [df: %g th: %g al: %g] (%g %g %g %g) (%g %g %g %g)\n",x,y,ch, p1[ch],p2[ch],d,thres,av,p1[0],p1[1],p1[2],p1[3],p2[0],p2[1],p2[2],p2[3]); + ++nums; + if ( nums > 16 ) goto ex; + //if (d) exit(1); + //goto ex; + } + } + } + break; + + case 4: + { + #ifdef COMPARE_SAME + stbir__FP16 * p1 = (stbir__FP16 *)&ir1[y*op+x*c*sizeof(stbir__FP16)]; + #else + float * p1 = (float *)&ir1[y*op+x*c*sizeof(float)]; + #endif + stbir__FP16 * p2 = (stbir__FP16 *)&ir2[y*np+x*c*sizeof(stbir__FP16)]; + for( ch = 0 ; ch < c ; ch++ ) + { + #ifdef COMPARE_SAME + float pp1 = stbir__half_to_float(p1[ch]); + float av = (a==-1)?1.0f:stbir__half_to_float(p1[a]); + #else + float pp1 = stbir__half_to_float(stbir__float_to_half(p1[ch])); + float av = (a==-1)?1.0f:stbir__half_to_float(stbir__float_to_half(p1[a])); + #endif + float pp2 = stbir__half_to_float(p2[ch]); + float d, thres; + + // clamp + if (pp1<=0.0f) pp1 = 0; + if (pp2<=0.0f) pp2 = 0; + if (av<=0.0f) av = 0; + if (pp1>1.0f) pp1 = 1.0f; + if (pp2>1.0f) pp2 = 1.0f; + if (av>1.0f) av = 1.0f; + + thres=(pp1*0.002f)+0.0002f; + + // compare in premult space + #ifndef COMPARE_SAME + if ( ( ( layouts >=4 ) && ( layouts <= 7 ) ) || ( ( layouts >= 16 ) && ( layouts <= 19 ) ) ) + { + pp1 *= av; + pp2 *= av; + } + #endif + + d = pp1 - pp2; + if ( d < 0 ) d = -d; + + + #ifdef COMPARE_SAME + if ( d != 0.0f ) + #else + if ( d > thres ) + #endif + { + printf("Error at %d x %d (chan %d) %g %g [df: %g th: %g al: %g] (%g %g %g %g) (%g %g %g %g)\n",x,y,ch, + #ifdef COMPARE_SAME + stbir__half_to_float(p1[ch]), + #else + p1[ch], + #endif + stbir__half_to_float(p2[ch]), + d,thres,av, + #ifdef COMPARE_SAME + stbir__half_to_float(p1[0]),stbir__half_to_float(p1[1]),stbir__half_to_float(p1[2]),stbir__half_to_float(p1[3]), + #else + p1[0],p1[1],p1[2],p1[3], + #endif + stbir__half_to_float(p2[0]),stbir__half_to_float(p2[1]),stbir__half_to_float(p2[2]),stbir__half_to_float(p2[3]) ); + ++nums; + if ( nums > 16 ) goto ex; + //if (d) exit(1); + //goto ex; + } + } + } + break; + } + } + + for( x = (w*c)*tsizes[oldtypes]; x < op; x++ ) + { + if ( ir1[y*op+x] != 79 ) + { + printf("Margin error at %d x %d %d (should be 79) OLD!\n",x,y,(unsigned char)ir1[y*op+x]); + goto ex; + } + } + + for( x = (w*c)*tsizes[types]; x < np; x++ ) + { + if ( ir2[y*np+x] != 79 ) + { + printf("Margin error at %d x %d %d (should be 79) NEW\n",x,y,(unsigned char)ir2[y*np+x]); + goto ex; + } + } + } + + ex: + ENTER( "OUTPUT IMAGES" ); + printf(" tot pix: %d, errs: %d\n", w*h*c,nums ); + + if (nums) + { + stbi_write_png("old.png", w, h, c, ir1, op); + stbi_write_png("new.png", w, h, c, ir2, np); + exit(1); + } + + LEAVE(); // output images + } + LEAVE(); //test compare + #endif + + + + } + LEAVE(); // test filter + } + LEAVE(); // test edge + } + LEAVE(); // test width + } + LEAVE(); // test height + } + LEAVE(); // test type + } + LEAVE(); // test layout + } + + CloseTM(); + return 0; +} diff --git a/deps/stb/stb_image_resize_test/vf_train.c b/deps/stb/stb_image_resize_test/vf_train.c new file mode 100644 index 00000000..0fdbe27a --- /dev/null +++ b/deps/stb/stb_image_resize_test/vf_train.c @@ -0,0 +1,999 @@ +#include +#include +#include + +#define stop() __debugbreak() +#include +#define int64 __int64 + +#pragma warning(disable:4127) + +#define STBIR__WEIGHT_TABLES +#define STBIR_PROFILE +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include "stb_image_resize2.h" + +static int * file_read( char const * filename ) +{ + size_t s; + int * m; + FILE * f = fopen( filename, "rb" ); + if ( f == 0 ) return 0; + + fseek( f, 0, SEEK_END); + s = ftell( f ); + fseek( f, 0, SEEK_SET); + m = malloc( s + 4 ); + m[0] = (int)s; + fread( m+1, 1, s, f); + fclose(f); + + return( m ); +} + +typedef struct fileinfo +{ + int * timings; + int timing_count; + int dimensionx, dimensiony; + int numtypes; + int * types; + int * effective; + int cpu; + int simd; + int numinputrects; + int * inputrects; + int outputscalex, outputscaley; + int milliseconds; + int64 cycles; + double scale_time; + int bitmapx, bitmapy; + char const * filename; +} fileinfo; + +int numfileinfo; +fileinfo fi[256]; +unsigned char * bitmap; +int bitmapw, bitmaph, bitmapp; + +static int use_timing_file( char const * filename, int index ) +{ + int * base = file_read( filename ); + int * file = base; + + if ( base == 0 ) return 0; + + ++file; // skip file image size; + if ( *file++ != 'VFT1' ) return 0; + fi[index].cpu = *file++; + fi[index].simd = *file++; + fi[index].dimensionx = *file++; + fi[index].dimensiony = *file++; + fi[index].numtypes = *file++; + fi[index].types = file; file += fi[index].numtypes; + fi[index].effective = file; file += fi[index].numtypes; + fi[index].numinputrects = *file++; + fi[index].inputrects = file; file += fi[index].numinputrects * 2; + fi[index].outputscalex = *file++; + fi[index].outputscaley = *file++; + fi[index].milliseconds = *file++; + fi[index].cycles = ((int64*)file)[0]; file += 2; + fi[index].filename = filename; + + fi[index].timings = file; + fi[index].timing_count = (int) ( ( base[0] - ( ((char*)file - (char*)base - sizeof(int) ) ) ) / (sizeof(int)*2) ); + + fi[index].scale_time = (double)fi[index].milliseconds / (double)fi[index].cycles; + + return 1; +} + +static int vert_first( float weights_table[STBIR_RESIZE_CLASSIFICATIONS][4], int ox, int oy, int ix, int iy, int filter, STBIR__V_FIRST_INFO * v_info ) +{ + float h_scale=(float)ox/(float)(ix); + float v_scale=(float)oy/(float)(iy); + stbir__support_callback * support = stbir__builtin_supports[filter]; + int vertical_filter_width = stbir__get_filter_pixel_width(support,v_scale,0); + int vertical_gather = ( v_scale >= ( 1.0f - stbir__small_float ) ) || ( vertical_filter_width <= STBIR_FORCE_GATHER_FILTER_SCANLINES_AMOUNT ); + + return stbir__should_do_vertical_first( weights_table, stbir__get_filter_pixel_width(support,h_scale,0), h_scale, ox, vertical_filter_width, v_scale, oy, vertical_gather, v_info ); +} + +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" + +static void alloc_bitmap() +{ + int findex; + int x = 0, y = 0; + int w = 0, h = 0; + + for( findex = 0 ; findex < numfileinfo ; findex++ ) + { + int nx, ny; + int thisw, thish; + + thisw = ( fi[findex].dimensionx * fi[findex].numtypes ) + ( fi[findex].numtypes - 1 ); + thish = ( fi[findex].dimensiony * fi[findex].numinputrects ) + ( fi[findex].numinputrects - 1 ); + + for(;;) + { + nx = x + ((x)?4:0) + thisw; + ny = y + ((y)?4:0) + thish; + if ( ( nx <= 3600 ) || ( x == 0 ) ) + { + fi[findex].bitmapx = x + ((x)?4:0); + fi[findex].bitmapy = y + ((y)?4:0); + x = nx; + if ( x > w ) w = x; + if ( ny > h ) h = ny; + break; + } + else + { + x = 0; + y = h; + } + } + } + + w = (w+3) & ~3; + bitmapw = w; + bitmaph = h; + bitmapp = w * 3; // RGB + bitmap = malloc( bitmapp * bitmaph ); + + memset( bitmap, 0, bitmapp * bitmaph ); +} + +static void build_bitmap( float weights[STBIR_RESIZE_CLASSIFICATIONS][4], int do_channel_count_index, int findex ) +{ + static int colors[STBIR_RESIZE_CLASSIFICATIONS]; + STBIR__V_FIRST_INFO v_info = {0}; + + int * ts; + int ir; + unsigned char * bitm = bitmap + ( fi[findex].bitmapx*3 ) + ( fi[findex].bitmapy*bitmapp) ; + + for( ir = 0; ir < STBIR_RESIZE_CLASSIFICATIONS ; ir++ ) colors[ ir ] = 127*ir/STBIR_RESIZE_CLASSIFICATIONS+128; + + ts = fi[findex].timings; + + for( ir = 0 ; ir < fi[findex].numinputrects ; ir++ ) + { + int ix, iy, chanind; + ix = fi[findex].inputrects[ir*2]; + iy = fi[findex].inputrects[ir*2+1]; + + for( chanind = 0 ; chanind < fi[findex].numtypes ; chanind++ ) + { + int ofs, h, hh; + + // just do the type that we're on + if ( chanind != do_channel_count_index ) + { + ts += 2 * fi[findex].dimensionx * fi[findex].dimensiony; + continue; + } + + // bitmap offset + ofs=chanind*(fi[findex].dimensionx+1)*3+ir*(fi[findex].dimensiony+1)*bitmapp; + + h = 1; + for( hh = 0 ; hh < fi[findex].dimensiony; hh++ ) + { + int ww, w = 1; + for( ww = 0 ; ww < fi[findex].dimensionx; ww++ ) + { + int good, v_first, VF, HF; + + VF = ts[0]; + HF = ts[1]; + + v_first = vert_first( weights, w, h, ix, iy, STBIR_FILTER_MITCHELL, &v_info ); + + good = ( ((HF<=VF) && (!v_first)) || ((VF<=HF) && (v_first))); + + if ( good ) + { + bitm[ofs+2] = 0; + bitm[ofs+1] = (unsigned char)colors[v_info.v_resize_classification]; + } + else + { + double r; + + if ( HF < VF ) + r = (double)(VF-HF)/(double)HF; + else + r = (double)(HF-VF)/(double)VF; + + if ( r > 0.4f) r = 0.4; + r *= 1.0f/0.4f; + + bitm[ofs+2] = (char)(255.0f*r); + bitm[ofs+1] = (char)(((float)colors[v_info.v_resize_classification])*(1.0f-r)); + } + bitm[ofs] = 0; + + ofs += 3; + ts += 2; + w += fi[findex].outputscalex; + } + ofs += bitmapp - fi[findex].dimensionx*3; + h += fi[findex].outputscaley; + } + } + } +} + +static void build_comp_bitmap( float weights[STBIR_RESIZE_CLASSIFICATIONS][4], int do_channel_count_index ) +{ + int * ts0; + int * ts1; + int ir; + unsigned char * bitm = bitmap + ( fi[0].bitmapx*3 ) + ( fi[0].bitmapy*bitmapp) ; + + ts0 = fi[0].timings; + ts1 = fi[1].timings; + + for( ir = 0 ; ir < fi[0].numinputrects ; ir++ ) + { + int ix, iy, chanind; + ix = fi[0].inputrects[ir*2]; + iy = fi[0].inputrects[ir*2+1]; + + for( chanind = 0 ; chanind < fi[0].numtypes ; chanind++ ) + { + int ofs, h, hh; + + // just do the type that we're on + if ( chanind != do_channel_count_index ) + { + ts0 += 2 * fi[0].dimensionx * fi[0].dimensiony; + ts1 += 2 * fi[0].dimensionx * fi[0].dimensiony; + continue; + } + + // bitmap offset + ofs=chanind*(fi[0].dimensionx+1)*3+ir*(fi[0].dimensiony+1)*bitmapp; + + h = 1; + for( hh = 0 ; hh < fi[0].dimensiony; hh++ ) + { + int ww, w = 1; + for( ww = 0 ; ww < fi[0].dimensionx; ww++ ) + { + int v_first, time0, time1; + + v_first = vert_first( weights, w, h, ix, iy, STBIR_FILTER_MITCHELL, 0 ); + + time0 = ( v_first ) ? ts0[0] : ts0[1]; + time1 = ( v_first ) ? ts1[0] : ts1[1]; + + if ( time0 < time1 ) + { + double r = (double)(time1-time0)/(double)time0; + if ( r > 0.4f) r = 0.4; + r *= 1.0f/0.4f; + bitm[ofs+2] = 0; + bitm[ofs+1] = (char)(255.0f*r); + bitm[ofs] = (char)(64.0f*(1.0f-r)); + } + else + { + double r = (double)(time0-time1)/(double)time1; + if ( r > 0.4f) r = 0.4; + r *= 1.0f/0.4f; + bitm[ofs+2] = (char)(255.0f*r); + bitm[ofs+1] = 0; + bitm[ofs] = (char)(64.0f*(1.0f-r)); + } + ofs += 3; + ts0 += 2; + ts1 += 2; + w += fi[0].outputscalex; + } + ofs += bitmapp - fi[0].dimensionx*3; + h += fi[0].outputscaley; + } + } + } +} + +static void write_bitmap() +{ + stbi_write_png( "results.png", bitmapp / 3, bitmaph, 3|STB_IMAGE_BGR, bitmap, bitmapp ); +} + + +static void calc_errors( float weights_table[STBIR_RESIZE_CLASSIFICATIONS][4], int * curtot, double * curerr, int do_channel_count_index ) +{ + int th, findex; + STBIR__V_FIRST_INFO v_info = {0}; + + for(th=0;th 200 ) + { + int findex; + + do_bitmap: + lasttick = t; + newbest = 0; + + for( findex = 0 ; findex < numfileinfo ; findex++ ) + build_bitmap( best_output_weights, channel_count_index, findex ); + + lasttick = GetTickCount(); + } + } + } + + windowranges[ channel_count_index ] = range; + + // advance all the weights and loop + --range; + } while( ( range >= 0 ) && ( !windowstatus ) ); + + // if we hit here, then we tried all weights for this opt, so save them +} + +static void print_struct( float weight[5][STBIR_RESIZE_CLASSIFICATIONS][4], char const * name ) +{ + printf("\n\nstatic float %s[5][STBIR_RESIZE_CLASSIFICATIONS][4]=\n{", name ); + { + int i; + for(i=0;i<5;i++) + { + int th; + for(th=0;th 60000) + sprintf( time, "%dm %ds",ms/60000, (ms/1000)%60 ); + else + sprintf( time, "%ds",ms/1000 ); + return time; +} + +static BITMAPINFOHEADER bmiHeader; +static DWORD extrawindoww, extrawindowh; +static HINSTANCE instance; +static int curzoom = 1; + +static LRESULT WINAPI WindowProc( HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam ) +{ + switch( message ) + { + case WM_CHAR: + if ( wparam != 27 ) + break; + // falls through + + case WM_CLOSE: + { + int i; + int max = 0; + + for( i = 0 ; i < fi[0].numtypes ; i++ ) + if( windowranges[i] > max ) max = windowranges[i]; + + if ( ( max == 0 ) || ( MessageBox( window, "Cancel before training is finished?", "Vertical First Training", MB_OKCANCEL|MB_ICONSTOP ) == IDOK ) ) + { + for( i = 0 ; i < fi[0].numtypes ; i++ ) + if( windowranges[i] > max ) max = windowranges[i]; + if ( max ) + windowstatus = 1; + DestroyWindow( window ); + } + } + return 0; + + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC dc; + + dc = BeginPaint( window, &ps ); + StretchDIBits( dc, + 0, 0, bitmapw*curzoom, bitmaph*curzoom, + 0, 0, bitmapw, bitmaph, + bitmap, (BITMAPINFO*)&bmiHeader, DIB_RGB_COLORS, SRCCOPY ); + + PatBlt( dc, bitmapw*curzoom, 0, 4096, 4096, WHITENESS ); + PatBlt( dc, 0, bitmaph*curzoom, 4096, 4096, WHITENESS ); + + SetTextColor( dc, RGB(0,0,0) ); + SetBkColor( dc, RGB(255,255,255) ); + SetBkMode( dc, OPAQUE ); + + { + int i, l = 0, max = 0; + char buf[1024]; + RECT rc; + POINT p; + + for( i = 0 ; i < fi[0].numtypes ; i++ ) + { + l += sprintf( buf + l, "channels: %d %s\n", fi[0].effective[i], windowranges[i] ? expand_to_string( windowranges[i] ) : "Done." ); + if ( windowranges[i] > max ) max = windowranges[i]; + } + + rc.left = 32; rc.top = bitmaph*curzoom+10; + rc.right = 512; rc.bottom = rc.top + 512; + DrawText( dc, buf, -1, &rc, DT_TOP ); + + l = 0; + if ( max == 0 ) + { + static DWORD traindone = 0; + if ( traindone == 0 ) traindone = GetTickCount(); + l = sprintf( buf, "Finished in %s.", gettime( traindone - trainstart ) ); + } + else if ( max != MAXRANGE ) + l = sprintf( buf, "Done in %s...", gettime( (int) ( ( ( (int64)max * ( (int64)GetTickCount() - (int64)trainstart ) ) ) / (int64) ( MAXRANGE - max ) ) ) ); + + GetCursorPos( &p ); + ScreenToClient( window, &p ); + + if ( ( p.x >= 0 ) && ( p.y >= 0 ) && ( p.x < (bitmapw*curzoom) ) && ( p.y < (bitmaph*curzoom) ) ) + { + int findex; + int x, y, w, h, sx, sy, ix, iy, ox, oy; + int ir, chanind; + int * ts; + char badstr[64]; + STBIR__V_FIRST_INFO v_info={0}; + + p.x /= curzoom; + p.y /= curzoom; + + for( findex = 0 ; findex < numfileinfo ; findex++ ) + { + x = fi[findex].bitmapx; + y = fi[findex].bitmapy; + w = x + ( fi[findex].dimensionx + 1 ) * fi[findex].numtypes; + h = y + ( fi[findex].dimensiony + 1 ) * fi[findex].numinputrects; + + if ( ( p.x >= x ) && ( p.y >= y ) && ( p.x < w ) && ( p.y < h ) ) + goto found; + } + goto nope; + + found: + + ir = ( p.y - y ) / ( fi[findex].dimensiony + 1 ); + sy = ( p.y - y ) % ( fi[findex].dimensiony + 1 ); + if ( sy >= fi[findex].dimensiony ) goto nope; + + chanind = ( p.x - x ) / ( fi[findex].dimensionx + 1 ); + sx = ( p.x - x ) % ( fi[findex].dimensionx + 1 ); + if ( sx >= fi[findex].dimensionx ) goto nope; + + ix = fi[findex].inputrects[ir*2]; + iy = fi[findex].inputrects[ir*2+1]; + + ts = fi[findex].timings + ( ( fi[findex].dimensionx * fi[findex].dimensiony * fi[findex].numtypes * ir ) + ( fi[findex].dimensionx * fi[findex].dimensiony * chanind ) + ( fi[findex].dimensionx * sy ) + sx ) * 2; + + ox = 1+fi[findex].outputscalex*sx; + oy = 1+fi[findex].outputscaley*sy; + + if ( windowstatus != 2 ) + { + int VF, HF, v_first, good; + VF = ts[0]; + HF = ts[1]; + + v_first = vert_first( retrain_weights[chanind], ox, oy, ix, iy, STBIR_FILTER_MITCHELL, &v_info ); + + good = ( ((HF<=VF) && (!v_first)) || ((VF<=HF) && (v_first))); + + if ( good ) + badstr[0] = 0; + else + { + double r; + + if ( HF < VF ) + r = (double)(VF-HF)/(double)HF; + else + r = (double)(HF-VF)/(double)VF; + sprintf( badstr, " %.1f%% off", r*100 ); + } + sprintf( buf + l, "\n\n%s\nCh: %d Resize: %dx%d to %dx%d\nV: %d H: %d Order: %c (%s%s)\nClass: %d Scale: %.2f %s", fi[findex].filename,fi[findex].effective[chanind], ix,iy,ox,oy, VF, HF, v_first?'V':'H', good?"Good":"Wrong", badstr, v_info.v_resize_classification, (double)oy/(double)iy, v_info.is_gather ? "Gather" : "Scatter" ); + } + else + { + int v_first, time0, time1; + float (* weights)[4] = stbir__compute_weights[chanind]; + int * ts1; + char b0[32], b1[32]; + + ts1 = fi[1].timings + ( ts - fi[0].timings ); + + v_first = vert_first( weights, ox, oy, ix, iy, STBIR_FILTER_MITCHELL, &v_info ); + + time0 = ( v_first ) ? ts[0] : ts[1]; + time1 = ( v_first ) ? ts1[0] : ts1[1]; + + b0[0] = b1[0] = 0; + if ( time0 < time1 ) + sprintf( b0," (%.f%% better)", ((double)time1-(double)time0)*100.0f/(double)time0); + else + sprintf( b1," (%.f%% better)", ((double)time0-(double)time1)*100.0f/(double)time1); + + sprintf( buf + l, "\n\n0: %s\n1: %s\nCh: %d Resize: %dx%d to %dx%d\nClass: %d Scale: %.2f %s\nTime0: %d%s\nTime1: %d%s", fi[0].filename, fi[1].filename, fi[0].effective[chanind], ix,iy,ox,oy, v_info.v_resize_classification, (double)oy/(double)iy, v_info.is_gather ? "Gather" : "Scatter", time0, b0, time1, b1 ); + } + } + nope: + + rc.left = 32+320; rc.right = 512+320; + SetTextColor( dc, RGB(0,0,128) ); + DrawText( dc, buf, -1, &rc, DT_TOP ); + + } + EndPaint( window, &ps ); + return 0; + } + + case WM_TIMER: + InvalidateRect( window, 0, 0 ); + return 0; + + case WM_DESTROY: + PostQuitMessage( 0 ); + return 0; + } + + + return DefWindowProc( window, message, wparam, lparam ); +} + +static void SetHighDPI(void) +{ + typedef HRESULT WINAPI setdpitype(int v); + HMODULE h=LoadLibrary("Shcore.dll"); + if (h) + { + setdpitype * sd = (setdpitype*)GetProcAddress(h,"SetProcessDpiAwareness"); + if (sd ) + sd(1); + } +} + +static void draw_window() +{ + WNDCLASS wc; + HWND w; + MSG msg; + + instance = GetModuleHandle(NULL); + + wc.style = 0; + wc.lpfnWndProc = WindowProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = instance; + wc.hIcon = 0; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = 0; + wc.lpszMenuName = 0; + wc.lpszClassName = "WHTrain"; + + if ( !RegisterClass( &wc ) ) + exit(1); + + SetHighDPI(); + + bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmiHeader.biWidth = bitmapp/3; + bmiHeader.biHeight = -bitmaph; + bmiHeader.biPlanes = 1; + bmiHeader.biBitCount = 24; + bmiHeader.biCompression = BI_RGB; + + w = CreateWindow( "WHTrain", + "Vertical First Training", + WS_CAPTION | WS_POPUP| WS_CLIPCHILDREN | + WS_SYSMENU | WS_MINIMIZEBOX | WS_SIZEBOX, + CW_USEDEFAULT,CW_USEDEFAULT, + CW_USEDEFAULT,CW_USEDEFAULT, + 0, 0, instance, 0 ); + + { + RECT r, c; + GetWindowRect( w, &r ); + GetClientRect( w, &c ); + extrawindoww = ( r.right - r.left ) - ( c.right - c.left ); + extrawindowh = ( r.bottom - r.top ) - ( c.bottom - c.top ); + SetWindowPos( w, 0, 0, 0, bitmapw * curzoom + extrawindoww, bitmaph * curzoom + extrawindowh + 164, SWP_NOMOVE ); + } + + ShowWindow( w, SW_SHOWNORMAL ); + SetTimer( w, 1, 250, 0 ); + + { + BOOL ret; + while( ( ret = GetMessage( &msg, w, 0, 0 ) ) != 0 ) + { + if ( ret == -1 ) + break; + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } + } +} + +static void retrain() +{ + HANDLE threads[ 16 ]; + int chanind; + + trainstart = GetTickCount(); + for( chanind = 0 ; chanind < fi[0].numtypes ; chanind++ ) + threads[ chanind ] = CreateThread( 0, 2048*1024, retrain_shim, (LPVOID)(size_t)chanind, 0, 0 ); + + draw_window(); + + for( chanind = 0 ; chanind < fi[0].numtypes ; chanind++ ) + { + WaitForSingleObject( threads[ chanind ], INFINITE ); + CloseHandle( threads[ chanind ] ); + } + + write_bitmap(); + + print_struct( retrain_weights, "retained_weights" ); + if ( windowstatus ) printf( "CANCELLED!\n" ); +} + +static void info() +{ + int findex; + + // display info about each input file + for( findex = 0 ; findex < numfileinfo ; findex++ ) + { + int i, h,m,s; + if ( findex ) printf( "\n" ); + printf( "Timing file: %s\n", fi[findex].filename ); + printf( "CPU type: %d %s\n", fi[findex].cpu, fi[findex].simd?(fi[findex].simd==2?"SIMD8":"SIMD4"):"Scalar" ); + h = fi[findex].milliseconds/3600000; + m = (fi[findex].milliseconds-h*3600000)/60000; + s = (fi[findex].milliseconds-h*3600000-m*60000)/1000; + printf( "Total time in test: %dh %dm %ds Cycles/sec: %.f\n", h,m,s, 1000.0/fi[findex].scale_time ); + printf( "Each tile of samples is %dx%d, and is scaled by %dx%d.\n", fi[findex].dimensionx,fi[findex].dimensiony, fi[findex].outputscalex,fi[findex].outputscaley ); + printf( "So the x coords are: " ); + for( i=0; i < fi[findex].dimensionx ; i++ ) printf( "%d ",1+i*fi[findex].outputscalex ); + printf( "\n" ); + printf( "And the y coords are: " ); + for( i=0; i < fi[findex].dimensiony ; i++ ) printf( "%d ",1+i*fi[findex].outputscaley ); + printf( "\n" ); + printf( "There are %d channel counts and they are: ", fi[findex].numtypes ); + for( i=0; i < fi[findex].numtypes ; i++ ) printf( "%d ",fi[findex].effective[i] ); + printf( "\n" ); + printf( "There are %d input rect sizes and they are: ", fi[findex].numinputrects ); + for( i=0; i < fi[findex].numtypes ; i++ ) printf( "%dx%d ",fi[findex].inputrects[i*2],fi[findex].inputrects[i*2+1] ); + printf( "\n" ); + } +} + +static void current( int do_win, int do_bitmap ) +{ + int i, findex; + + trainstart = GetTickCount(); + + // clear progress + memset( windowranges, 0, sizeof( windowranges ) ); + // copy in appropriate weights + memcpy( retrain_weights, stbir__compute_weights, sizeof( retrain_weights ) ); + + // build and print current errors and build current bitmap + for( i = 0 ; i < fi[0].numtypes ; i++ ) + { + double curerr[STBIR_RESIZE_CLASSIFICATIONS]; + int curtot[STBIR_RESIZE_CLASSIFICATIONS]; + float (* weights)[4] = retrain_weights[i]; + + calc_errors( weights, curtot, curerr, i ); + if ( !do_bitmap ) + print_weights( weights, i, curtot, curerr ); + + for( findex = 0 ; findex < numfileinfo ; findex++ ) + build_bitmap( weights, i, findex ); + } + + if ( do_win ) + draw_window(); + + if ( do_bitmap ) + write_bitmap(); +} + +static void compare() +{ + int i; + + trainstart = GetTickCount(); + windowstatus = 2; // comp mode + + // clear progress + memset( windowranges, 0, sizeof( windowranges ) ); + + if ( ( fi[0].numtypes != fi[1].numtypes ) || ( fi[0].numinputrects != fi[1].numinputrects ) || + ( fi[0].dimensionx != fi[1].dimensionx ) || ( fi[0].dimensiony != fi[1].dimensiony ) || + ( fi[0].outputscalex != fi[1].outputscalex ) || ( fi[0].outputscaley != fi[1].outputscaley ) ) + { + err: + printf( "Timing files don't match.\n" ); + exit(5); + } + + for( i=0; i < fi[0].numtypes ; i++ ) + { + if ( fi[0].effective[i] != fi[1].effective[i] ) goto err; + if ( fi[0].inputrects[i*2] != fi[1].inputrects[i*2] ) goto err; + if ( fi[0].inputrects[i*2+1] != fi[1].inputrects[i*2+1] ) goto err; + } + + alloc_bitmap( 1 ); + + for( i = 0 ; i < fi[0].numtypes ; i++ ) + { + float (* weights)[4] = stbir__compute_weights[i]; + build_comp_bitmap( weights, i ); + } + + draw_window(); +} + +static void load_files( char ** args, int count ) +{ + int i; + + if ( count == 0 ) + { + printf( "No timing files listed!" ); + exit(3); + } + + for ( i = 0 ; i < count ; i++ ) + { + if ( !use_timing_file( args[i], i ) ) + { + printf( "Bad timing file %s\n", args[i] ); + exit(2); + } + } + numfileinfo = count; +} + +int main( int argc, char ** argv ) +{ + int check; + if ( argc < 3 ) + { + err: + printf( "vf_train retrain [timing_filenames....] - recalcs weights for all the files on the command line.\n"); + printf( "vf_train info [timing_filenames....] - shows info about each timing file.\n"); + printf( "vf_train check [timing_filenames...] - show results for the current weights for all files listed.\n"); + printf( "vf_train compare - compare two timing files (must only be two files and same resolution).\n"); + printf( "vf_train bitmap [timing_filenames...] - write out results.png, comparing against the current weights for all files listed.\n"); + exit(1); + } + + check = ( strcmp( argv[1], "check" ) == 0 ); + if ( ( check ) || ( strcmp( argv[1], "bitmap" ) == 0 ) ) + { + load_files( argv + 2, argc - 2 ); + alloc_bitmap( numfileinfo ); + current( check, !check ); + } + else if ( strcmp( argv[1], "info" ) == 0 ) + { + load_files( argv + 2, argc - 2 ); + info(); + } + else if ( strcmp( argv[1], "compare" ) == 0 ) + { + if ( argc != 4 ) + { + printf( "You must specify two files to compare.\n" ); + exit(4); + } + + load_files( argv + 2, argc - 2 ); + compare(); + } + else if ( strcmp( argv[1], "retrain" ) == 0 ) + { + load_files( argv + 2, argc - 2 ); + alloc_bitmap( numfileinfo ); + retrain(); + } + else + { + goto err; + } + + return 0; +} diff --git a/deps/stb/tests/oversample/oversample.exe b/deps/stb/tests/oversample/oversample.exe deleted file mode 100644 index 00406931..00000000 Binary files a/deps/stb/tests/oversample/oversample.exe and /dev/null differ diff --git a/deps/stb/tests/pngsuite/ref_results.csv b/deps/stb/tests/pngsuite/ref_results.csv new file mode 100644 index 00000000..74dc2e63 --- /dev/null +++ b/deps/stb/tests/pngsuite/ref_results.csv @@ -0,0 +1,259 @@ +filename,width,height,ncomp,error,hash +pngsuite/16bit/basi0g16.png,32,32,1,,0xfc8f2f99 +pngsuite/16bit/basi2c16.png,32,32,3,,0x65567ed5 +pngsuite/16bit/basi4a16.png,32,32,2,,0x198cf245 +pngsuite/16bit/basi6a16.png,32,32,4,,0x3016e9b5 +pngsuite/16bit/basn0g16.png,32,32,1,,0xfc8f2f99 +pngsuite/16bit/basn2c16.png,32,32,3,,0x65567ed5 +pngsuite/16bit/basn4a16.png,32,32,2,,0x198cf245 +pngsuite/16bit/basn6a16.png,32,32,4,,0x3016e9b5 +pngsuite/16bit/bgai4a16.png,32,32,2,,0x198cf245 +pngsuite/16bit/bgan6a16.png,32,32,4,,0x3016e9b5 +pngsuite/16bit/bggn4a16.png,32,32,2,,0x198cf245 +pngsuite/16bit/bgyn6a16.png,32,32,4,,0x3016e9b5 +pngsuite/16bit/oi1n0g16.png,32,32,1,,0xfc8f2f99 +pngsuite/16bit/oi1n2c16.png,32,32,3,,0x65567ed5 +pngsuite/16bit/oi2n0g16.png,32,32,1,,0xfc8f2f99 +pngsuite/16bit/oi2n2c16.png,32,32,3,,0x65567ed5 +pngsuite/16bit/oi4n0g16.png,32,32,1,,0xfc8f2f99 +pngsuite/16bit/oi4n2c16.png,32,32,3,,0x65567ed5 +pngsuite/16bit/oi9n0g16.png,32,32,1,,0xfc8f2f99 +pngsuite/16bit/oi9n2c16.png,32,32,3,,0x65567ed5 +pngsuite/16bit/tbbn2c16.png,32,32,4,,0xaa9bfe44 +pngsuite/16bit/tbgn2c16.png,32,32,4,,0xaa9bfe44 +pngsuite/16bit/tbwn0g16.png,32,32,2,,0x075e519a +pngsuite/corrupt/xc1n0g08.png,32,32,2,bad ctype,0x00000000 +pngsuite/corrupt/xc9n2c08.png,32,32,2,bad ctype,0x00000000 +pngsuite/corrupt/xcrn0g04.png,32,32,2,unknown image type,0x00000000 +pngsuite/corrupt/xcsn0g01.png,32,32,1,,0x43b9891f +pngsuite/corrupt/xd0n2c08.png,32,32,1,1/2/4/8/16-bit only,0x00000000 +pngsuite/corrupt/xd3n2c08.png,32,32,1,1/2/4/8/16-bit only,0x00000000 +pngsuite/corrupt/xd9n2c08.png,32,32,1,1/2/4/8/16-bit only,0x00000000 +pngsuite/corrupt/xdtn0g01.png,32,32,1,no IDAT,0x00000000 +pngsuite/corrupt/xhdn0g08.png,32,32,1,,0x414f1ca9 +pngsuite/corrupt/xlfn0g04.png,32,32,1,unknown image type,0x00000000 +pngsuite/corrupt/xs1n0g01.png,32,32,1,unknown image type,0x00000000 +pngsuite/corrupt/xs2n0g01.png,32,32,1,unknown image type,0x00000000 +pngsuite/corrupt/xs4n0g01.png,32,32,1,unknown image type,0x00000000 +pngsuite/corrupt/xs7n0g01.png,32,32,1,unknown image type,0x00000000 +pngsuite/iphone/iphone_basi0g01.png,32,32,4,,0x5fb33cfd +pngsuite/iphone/iphone_basi0g02.png,32,32,4,,0x5bbe95c5 +pngsuite/iphone/iphone_basi3p02.png,32,32,4,,0x50ba29c5 +pngsuite/iphone/iphone_bgwn6a08.png,32,32,4,,0x45d8548a +pngsuite/iphone/iphone_bgyn6a16.png,32,32,4,,0x4b2b7545 +pngsuite/iphone/iphone_tbyn3p08.png,32,32,4,,0x8ea9aaaf +pngsuite/iphone/iphone_z06n2c08.png,32,32,4,,0xb5dd034b +pngsuite/primary/basi0g01.png,32,32,1,,0x43b9891f +pngsuite/primary/basi0g02.png,32,32,1,,0xaf0bb3c5 +pngsuite/primary/basi0g04.png,32,32,1,,0x6fbaeb45 +pngsuite/primary/basi0g08.png,32,32,1,,0x414f1ca9 +pngsuite/primary/basi2c08.png,32,32,3,,0x522345c5 +pngsuite/primary/basi3p01.png,32,32,3,,0x9c5b75c5 +pngsuite/primary/basi3p02.png,32,32,3,,0x46f26ec5 +pngsuite/primary/basi3p04.png,32,32,3,,0x35b2e4a5 +pngsuite/primary/basi3p08.png,32,32,3,,0xfe066865 +pngsuite/primary/basi4a08.png,32,32,2,,0x77cbbfa5 +pngsuite/primary/basi6a08.png,32,32,4,,0xb472197d +pngsuite/primary/basn0g01.png,32,32,1,,0x43b9891f +pngsuite/primary/basn0g02.png,32,32,1,,0xaf0bb3c5 +pngsuite/primary/basn0g04.png,32,32,1,,0x6fbaeb45 +pngsuite/primary/basn0g08.png,32,32,1,,0x414f1ca9 +pngsuite/primary/basn2c08.png,32,32,3,,0x522345c5 +pngsuite/primary/basn3p01.png,32,32,3,,0x9c5b75c5 +pngsuite/primary/basn3p02.png,32,32,3,,0x46f26ec5 +pngsuite/primary/basn3p04.png,32,32,3,,0x35b2e4a5 +pngsuite/primary/basn3p08.png,32,32,3,,0xfe066865 +pngsuite/primary/basn4a08.png,32,32,2,,0x77cbbfa5 +pngsuite/primary/basn6a08.png,32,32,4,,0xb472197d +pngsuite/primary/bgai4a08.png,32,32,2,,0x77cbbfa5 +pngsuite/primary/bgan6a08.png,32,32,4,,0xb472197d +pngsuite/primary/bgbn4a08.png,32,32,2,,0x77cbbfa5 +pngsuite/primary/bgwn6a08.png,32,32,4,,0xb472197d +pngsuite/primary/s01i3p01.png,1,1,3,,0xafb003b6 +pngsuite/primary/s01n3p01.png,1,1,3,,0xafb003b6 +pngsuite/primary/s02i3p01.png,2,2,3,,0x96f3dd85 +pngsuite/primary/s02n3p01.png,2,2,3,,0x96f3dd85 +pngsuite/primary/s03i3p01.png,3,3,3,,0xb0cf1241 +pngsuite/primary/s03n3p01.png,3,3,3,,0xb0cf1241 +pngsuite/primary/s04i3p01.png,4,4,3,,0xbfcedd75 +pngsuite/primary/s04n3p01.png,4,4,3,,0xbfcedd75 +pngsuite/primary/s05i3p02.png,5,5,3,,0xc322cedd +pngsuite/primary/s05n3p02.png,5,5,3,,0xc322cedd +pngsuite/primary/s06i3p02.png,6,6,3,,0x46916799 +pngsuite/primary/s06n3p02.png,6,6,3,,0x46916799 +pngsuite/primary/s07i3p02.png,7,7,3,,0xfdabc297 +pngsuite/primary/s07n3p02.png,7,7,3,,0xfdabc297 +pngsuite/primary/s08i3p02.png,8,8,3,,0x8f036d09 +pngsuite/primary/s08n3p02.png,8,8,3,,0x8f036d09 +pngsuite/primary/s09i3p02.png,9,9,3,,0x16a46830 +pngsuite/primary/s09n3p02.png,9,9,3,,0x16a46830 +pngsuite/primary/s32i3p04.png,32,32,3,,0x4bd4fbd3 +pngsuite/primary/s32n3p04.png,32,32,3,,0x4bd4fbd3 +pngsuite/primary/s33i3p04.png,33,33,3,,0x51aa005e +pngsuite/primary/s33n3p04.png,33,33,3,,0x51aa005e +pngsuite/primary/s34i3p04.png,34,34,3,,0x84818775 +pngsuite/primary/s34n3p04.png,34,34,3,,0x84818775 +pngsuite/primary/s35i3p04.png,35,35,3,,0x6359ec75 +pngsuite/primary/s35n3p04.png,35,35,3,,0x6359ec75 +pngsuite/primary/s36i3p04.png,36,36,3,,0xe4878065 +pngsuite/primary/s36n3p04.png,36,36,3,,0xe4878065 +pngsuite/primary/s37i3p04.png,37,37,3,,0x3cefc423 +pngsuite/primary/s37n3p04.png,37,37,3,,0x3cefc423 +pngsuite/primary/s38i3p04.png,38,38,3,,0xffc55a2b +pngsuite/primary/s38n3p04.png,38,38,3,,0xffc55a2b +pngsuite/primary/s39i3p04.png,39,39,3,,0x0c790240 +pngsuite/primary/s39n3p04.png,39,39,3,,0x0c790240 +pngsuite/primary/s40i3p04.png,40,40,3,,0x951a316d +pngsuite/primary/s40n3p04.png,40,40,3,,0x951a316d +pngsuite/primary/tbbn0g04.png,32,32,2,,0x9c8410ea +pngsuite/primary/tbbn3p08.png,32,32,4,,0x82bf9a57 +pngsuite/primary/tbgn3p08.png,32,32,4,,0x82bf9a57 +pngsuite/primary/tbrn2c08.png,32,32,4,,0xaa9bfe44 +pngsuite/primary/tbwn3p08.png,32,32,4,,0x82bf9a57 +pngsuite/primary/tbyn3p08.png,32,32,4,,0x82bf9a57 +pngsuite/primary/tm3n3p02.png,32,32,4,,0xf59745c5 +pngsuite/primary/tp0n0g08.png,32,32,1,,0xbac0864c +pngsuite/primary/tp0n2c08.png,32,32,3,,0x82687c37 +pngsuite/primary/tp0n3p08.png,32,32,3,,0x61f54e37 +pngsuite/primary/tp1n3p08.png,32,32,4,,0x82bf9a57 +pngsuite/primary/z00n2c08.png,32,32,3,,0x65b4a72f +pngsuite/primary/z03n2c08.png,32,32,3,,0x65b4a72f +pngsuite/primary/z06n2c08.png,32,32,3,,0x65b4a72f +pngsuite/primary/z09n2c08.png,32,32,3,,0x65b4a72f +pngsuite/primary_check/basi0g01.png,32,32,4,,0x5fb33cfd +pngsuite/primary_check/basi0g02.png,32,32,4,,0x5bbe95c5 +pngsuite/primary_check/basi0g04.png,32,32,4,,0x3468b9c5 +pngsuite/primary_check/basi0g08.png,32,32,4,,0x262ef46d +pngsuite/primary_check/basi2c08.png,32,32,4,,0x1fc92bc5 +pngsuite/primary_check/basi3p01.png,32,32,4,,0x28a3e1c5 +pngsuite/primary_check/basi3p02.png,32,32,4,,0x803be5c5 +pngsuite/primary_check/basi3p04.png,32,32,4,,0xf3fc60e5 +pngsuite/primary_check/basi3p08.png,32,32,4,,0x30ef4f45 +pngsuite/primary_check/basi4a08.png,32,32,4,,0x23c8536d +pngsuite/primary_check/basi6a08.png,32,32,4,,0xb472197d +pngsuite/primary_check/basn0g01.png,32,32,4,,0x5fb33cfd +pngsuite/primary_check/basn0g02.png,32,32,4,,0x5bbe95c5 +pngsuite/primary_check/basn0g04.png,32,32,4,,0x3468b9c5 +pngsuite/primary_check/basn0g08.png,32,32,4,,0x262ef46d +pngsuite/primary_check/basn2c08.png,32,32,4,,0x1fc92bc5 +pngsuite/primary_check/basn3p01.png,32,32,4,,0x28a3e1c5 +pngsuite/primary_check/basn3p02.png,32,32,4,,0x803be5c5 +pngsuite/primary_check/basn3p04.png,32,32,4,,0xf3fc60e5 +pngsuite/primary_check/basn3p08.png,32,32,4,,0x30ef4f45 +pngsuite/primary_check/basn4a08.png,32,32,4,,0x23c8536d +pngsuite/primary_check/basn6a08.png,32,32,4,,0xb472197d +pngsuite/primary_check/bgai4a08.png,32,32,4,,0x23c8536d +pngsuite/primary_check/bgan6a08.png,32,32,4,,0xb472197d +pngsuite/primary_check/bgbn4a08.png,32,32,4,,0x23c8536d +pngsuite/primary_check/bgwn6a08.png,32,32,4,,0xb472197d +pngsuite/primary_check/s01i3p01.png,1,1,4,,0xdb152beb +pngsuite/primary_check/s01n3p01.png,1,1,4,,0xdb152beb +pngsuite/primary_check/s02i3p01.png,2,2,4,,0xa344a3a5 +pngsuite/primary_check/s02n3p01.png,2,2,4,,0xa344a3a5 +pngsuite/primary_check/s03i3p01.png,3,3,4,,0x594d3bfa +pngsuite/primary_check/s03n3p01.png,3,3,4,,0x594d3bfa +pngsuite/primary_check/s04i3p01.png,4,4,4,,0xd59d4605 +pngsuite/primary_check/s04n3p01.png,4,4,4,,0xd59d4605 +pngsuite/primary_check/s05i3p02.png,5,5,4,,0x41e58366 +pngsuite/primary_check/s05n3p02.png,5,5,4,,0x41e58366 +pngsuite/primary_check/s06i3p02.png,6,6,4,,0xcad1a885 +pngsuite/primary_check/s06n3p02.png,6,6,4,,0xcad1a885 +pngsuite/primary_check/s07i3p02.png,7,7,4,,0x09184108 +pngsuite/primary_check/s07n3p02.png,7,7,4,,0x09184108 +pngsuite/primary_check/s08i3p02.png,8,8,4,,0x4fd11cad +pngsuite/primary_check/s08n3p02.png,8,8,4,,0x4fd11cad +pngsuite/primary_check/s09i3p02.png,9,9,4,,0xc50dbecd +pngsuite/primary_check/s09n3p02.png,9,9,4,,0xc50dbecd +pngsuite/primary_check/s32i3p04.png,32,32,4,,0x95cbb1d3 +pngsuite/primary_check/s32n3p04.png,32,32,4,,0x95cbb1d3 +pngsuite/primary_check/s33i3p04.png,33,33,4,,0x6649fc5b +pngsuite/primary_check/s33n3p04.png,33,33,4,,0x6649fc5b +pngsuite/primary_check/s34i3p04.png,34,34,4,,0x35b98e15 +pngsuite/primary_check/s34n3p04.png,34,34,4,,0x35b98e15 +pngsuite/primary_check/s35i3p04.png,35,35,4,,0xc9ddf938 +pngsuite/primary_check/s35n3p04.png,35,35,4,,0xc9ddf938 +pngsuite/primary_check/s36i3p04.png,36,36,4,,0x7bb4e1cd +pngsuite/primary_check/s36n3p04.png,36,36,4,,0x7bb4e1cd +pngsuite/primary_check/s37i3p04.png,37,37,4,,0xee50001c +pngsuite/primary_check/s37n3p04.png,37,37,4,,0xee50001c +pngsuite/primary_check/s38i3p04.png,38,38,4,,0x51b76813 +pngsuite/primary_check/s38n3p04.png,38,38,4,,0x51b76813 +pngsuite/primary_check/s39i3p04.png,39,39,4,,0x42f23327 +pngsuite/primary_check/s39n3p04.png,39,39,4,,0x42f23327 +pngsuite/primary_check/s40i3p04.png,40,40,4,,0xf91b6a7d +pngsuite/primary_check/s40n3p04.png,40,40,4,,0xf91b6a7d +pngsuite/primary_check/tbbn0g04.png,32,32,4,,0x8a0117a4 +pngsuite/primary_check/tbbn3p08.png,32,32,4,,0x82bf9a57 +pngsuite/primary_check/tbgn3p08.png,32,32,4,,0x82bf9a57 +pngsuite/primary_check/tbrn2c08.png,32,32,4,,0xaa9bfe44 +pngsuite/primary_check/tbwn3p08.png,32,32,4,,0x82bf9a57 +pngsuite/primary_check/tbyn3p08.png,32,32,4,,0x82bf9a57 +pngsuite/primary_check/tm3n3p02.png,32,32,4,,0xf59745c5 +pngsuite/primary_check/tp0n0g08.png,32,32,4,,0xd405ad2e +pngsuite/primary_check/tp0n2c08.png,32,32,4,,0x5a66ca09 +pngsuite/primary_check/tp0n3p08.png,32,32,4,,0x06e81adf +pngsuite/primary_check/tp1n3p08.png,32,32,4,,0x82bf9a57 +pngsuite/primary_check/z00n2c08.png,32,32,4,,0xaa698493 +pngsuite/primary_check/z03n2c08.png,32,32,4,,0xaa698493 +pngsuite/primary_check/z06n2c08.png,32,32,4,,0xaa698493 +pngsuite/primary_check/z09n2c08.png,32,32,4,,0xaa698493 +pngsuite/unused/ccwn2c08.png,32,32,3,,0xbb576418 +pngsuite/unused/ccwn3p08.png,32,32,3,,0x5c4df060 +pngsuite/unused/cdfn2c08.png,8,32,3,,0xe30ed48f +pngsuite/unused/cdhn2c08.png,32,8,3,,0x999321f5 +pngsuite/unused/cdsn2c08.png,8,8,3,,0x7f63fa01 +pngsuite/unused/cdun2c08.png,32,32,3,,0xbd325d71 +pngsuite/unused/ch1n3p04.png,32,32,3,,0x35b2e4a5 +pngsuite/unused/ch2n3p08.png,32,32,3,,0xfe066865 +pngsuite/unused/cm0n0g04.png,32,32,1,,0xe9f53e6c +pngsuite/unused/cm7n0g04.png,32,32,1,,0xe9f53e6c +pngsuite/unused/cm9n0g04.png,32,32,1,,0xe9f53e6c +pngsuite/unused/cs3n2c16.png,32,32,3,,0x7f0fa2c5 +pngsuite/unused/cs3n3p08.png,32,32,3,,0x5533bac5 +pngsuite/unused/cs5n2c08.png,32,32,3,,0x8a80f8c5 +pngsuite/unused/cs5n3p08.png,32,32,3,,0x8a80f8c5 +pngsuite/unused/cs8n2c08.png,32,32,3,,0x7f0fa2c5 +pngsuite/unused/cs8n3p08.png,32,32,3,,0x7f0fa2c5 +pngsuite/unused/ct0n0g04.png,32,32,1,,0xe9f53e6c +pngsuite/unused/ct1n0g04.png,32,32,1,,0xe9f53e6c +pngsuite/unused/cten0g04.png,32,32,1,,0x1c073b45 +pngsuite/unused/ctfn0g04.png,32,32,1,,0xfa9fd205 +pngsuite/unused/ctgn0g04.png,32,32,1,,0xf28c8085 +pngsuite/unused/cthn0g04.png,32,32,1,,0x7c039595 +pngsuite/unused/ctjn0g04.png,32,32,1,,0xc520f455 +pngsuite/unused/ctzn0g04.png,32,32,1,,0xe9f53e6c +pngsuite/unused/f00n0g08.png,32,32,1,,0x21db411b +pngsuite/unused/f00n2c08.png,32,32,3,,0x1f25ded0 +pngsuite/unused/f01n0g08.png,32,32,1,,0x7437b32a +pngsuite/unused/f01n2c08.png,32,32,3,,0x0d4507ae +pngsuite/unused/f02n0g08.png,32,32,1,,0x6b633c7c +pngsuite/unused/f02n2c08.png,32,32,3,,0x4b278986 +pngsuite/unused/f03n0g08.png,32,32,1,,0x2f31c08e +pngsuite/unused/f03n2c08.png,32,32,3,,0x843ecc7e +pngsuite/unused/f04n0g08.png,32,32,1,,0xfd3a0b73 +pngsuite/unused/f04n2c08.png,32,32,3,,0x557174bc +pngsuite/unused/f99n0g04.png,32,32,1,,0xb79aa6e1 +pngsuite/unused/g03n0g16.png,32,32,1,,0xecd13817 +pngsuite/unused/g03n2c08.png,32,32,3,,0x242407a8 +pngsuite/unused/g03n3p04.png,32,32,3,,0xe801ecc8 +pngsuite/unused/g04n0g16.png,32,32,1,,0xc11bc972 +pngsuite/unused/g04n2c08.png,32,32,3,,0xdf843cc4 +pngsuite/unused/g04n3p04.png,32,32,3,,0x60e41f3b +pngsuite/unused/g05n0g16.png,32,32,1,,0xbe6615a5 +pngsuite/unused/g05n2c08.png,32,32,3,,0x5c312116 +pngsuite/unused/g05n3p04.png,32,32,3,,0x2e0fbf86 +pngsuite/unused/g07n0g16.png,32,32,1,,0x2b54a398 +pngsuite/unused/g07n2c08.png,32,32,3,,0xf765fb10 +pngsuite/unused/g07n3p04.png,32,32,3,,0x9a8c3338 +pngsuite/unused/g10n0g16.png,32,32,1,,0xb08a92e1 +pngsuite/unused/g10n2c08.png,32,32,3,,0xa43f2291 +pngsuite/unused/g10n3p04.png,32,32,3,,0xb733194c +pngsuite/unused/g25n0g16.png,32,32,1,,0xa6b1f5dd +pngsuite/unused/g25n2c08.png,32,32,3,,0x767aee0c +pngsuite/unused/g25n3p04.png,32,32,3,,0x4cf349a8 +pngsuite/unused/pp0n2c16.png,32,32,3,,0x65567ed5 +pngsuite/unused/pp0n6a08.png,32,32,4,,0x3188c645 +pngsuite/unused/ps1n0g08.png,32,32,1,,0x414f1ca9 +pngsuite/unused/ps1n2c16.png,32,32,3,,0x65567ed5 +pngsuite/unused/ps2n0g08.png,32,32,1,,0x414f1ca9 +pngsuite/unused/ps2n2c16.png,32,32,3,,0x65567ed5 diff --git a/deps/stb/tests/resample_test.cpp b/deps/stb/tests/resample_test.cpp index 21f874f1..6595e37e 100644 --- a/deps/stb/tests/resample_test.cpp +++ b/deps/stb/tests/resample_test.cpp @@ -64,7 +64,7 @@ void stbir_progress(float p) #define STBIR_PROGRESS_REPORT stbir_progress #define STB_IMAGE_RESIZE_IMPLEMENTATION #define STB_IMAGE_RESIZE_STATIC -#include "stb_image_resize.h" +#include "stb_image_resize2.h" #define STB_IMAGE_WRITE_IMPLEMENTATION #include "stb_image_write.h" @@ -143,7 +143,7 @@ void resizer(int argc, char **argv) out_h = h*3; output_pixels = (unsigned char*) malloc(out_w*out_h*n); //stbir_resize_uint8_srgb(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, n, -1,0); - stbir_resize_uint8(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, n); + stbir_resize_uint8_linear(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, (stbir_pixel_layout) n); stbi_write_png("output.png", out_w, out_h, n, output_pixels, 0); exit(0); } @@ -171,9 +171,9 @@ void performance(int argc, char **argv) output_pixels = (unsigned char*) malloc(out_w*out_h*n); for (i=0; i < count; ++i) if (srgb) - stbir_resize_uint8_srgb(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, n,-1,0); + stbir_resize_uint8_srgb(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, (stbir_pixel_layout) n); else - stbir_resize(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, STBIR_TYPE_UINT8, n,-1, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, STBIR_COLORSPACE_LINEAR, NULL); + stbir_resize_uint8_linear(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, (stbir_pixel_layout) n); exit(0); } @@ -188,6 +188,7 @@ int main(int argc, char** argv) return 0; } +#if 0 void resize_image(const char* filename, float width_percent, float height_percent, stbir_filter filter, stbir_edge edge, stbir_colorspace colorspace, const char* output_filename) { int w, h, n; @@ -1120,3 +1121,7 @@ void test_suite(int argc, char **argv) resize_image("gamma_2.2.jpg", .5f, .5f, STBIR_FILTER_CATMULLROM, STBIR_EDGE_REFLECT, STBIR_COLORSPACE_SRGB, "test-output/gamma_2.2.jpg"); resize_image("gamma_dalai_lama_gray.jpg", .5f, .5f, STBIR_FILTER_CATMULLROM, STBIR_EDGE_REFLECT, STBIR_COLORSPACE_SRGB, "test-output/gamma_dalai_lama_gray.jpg"); } +#endif +void test_suite(int argc, char **argv) +{ +} diff --git a/deps/stb/tests/resize.dsp b/deps/stb/tests/resize.dsp index 0aa1bbaf..cfb96088 100644 --- a/deps/stb/tests/resize.dsp +++ b/deps/stb/tests/resize.dsp @@ -88,7 +88,7 @@ SOURCE=.\resample_test.cpp # End Source File # Begin Source File -SOURCE=..\stb_image_resize.h +SOURCE=..\stb_image_resize2.h # End Source File # End Target # End Project diff --git a/deps/stb/tests/stb.dsp b/deps/stb/tests/stb.dsp index ba13ba13..b7039c74 100644 --- a/deps/stb/tests/stb.dsp +++ b/deps/stb/tests/stb.dsp @@ -130,7 +130,7 @@ SOURCE=..\stb_image.h # End Source File # Begin Source File -SOURCE=..\stb_image_resize.h +SOURCE=..\stb_image_resize2.h # End Source File # Begin Source File diff --git a/deps/stb/tests/test_c_compilation.c b/deps/stb/tests/test_c_compilation.c index 11f60231..8141d2ba 100644 --- a/deps/stb/tests/test_c_compilation.c +++ b/deps/stb/tests/test_c_compilation.c @@ -1,3 +1,6 @@ +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include "stb_image_resize2.h" + #define STB_SPRINTF_IMPLEMENTATION #include "stb_sprintf.h" @@ -7,7 +10,6 @@ #define STB_DIVIDE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION #define STB_HERRINGBONE_WANG_TILE_IMEPLEMENTATIOn -#define STB_IMAGE_RESIZE_IMPLEMENTATION #define STB_RECT_PACK_IMPLEMENTATION #define STB_VOXEL_RENDER_IMPLEMENTATION #define STB_EASY_FONT_IMPLEMENTATION @@ -20,7 +22,6 @@ #include "stb_perlin.h" #include "stb_c_lexer.h" #include "stb_divide.h" -#include "stb_image_resize.h" #include "stb_rect_pack.h" #include "stb_dxt.h" #include "stb_include.h" diff --git a/deps/stb/tests/test_cpp_compilation.cpp b/deps/stb/tests/test_cpp_compilation.cpp index fd8c5b64..d1d10b85 100644 --- a/deps/stb/tests/test_cpp_compilation.cpp +++ b/deps/stb/tests/test_cpp_compilation.cpp @@ -70,7 +70,7 @@ void my_free(void *) { } #include "stb_leakcheck.h" #define STB_IMAGE_RESIZE_IMPLEMENTATION -#include "stb_image_resize.h" +#include "stb_image_resize2.h" //#include "stretchy_buffer.h" // deprecating diff --git a/deps/stb/tests/test_png_paeth.c b/deps/stb/tests/test_png_paeth.c new file mode 100644 index 00000000..69ba37f0 --- /dev/null +++ b/deps/stb/tests/test_png_paeth.c @@ -0,0 +1,47 @@ +#include +#include + +// Reference Paeth filter as per PNG spec +static int ref_paeth(int a, int b, int c) +{ + int p = a + b - c; + int pa = abs(p-a); + int pb = abs(p-b); + int pc = abs(p-c); + if (pa <= pb && pa <= pc) return a; + if (pb <= pc) return b; + return c; +} + +// Optimized Paeth filter +static int opt_paeth(int a, int b, int c) +{ + int thresh = c*3 - (a + b); + int lo = a < b ? a : b; + int hi = a < b ? b : a; + int t0 = (hi <= thresh) ? lo : c; + int t1 = (thresh <= lo) ? hi : t0; + return t1; +} + +int main() +{ + // Exhaustively test the functions match for all byte inputs a, b,c in [0,255] + for (int i = 0; i < (1 << 24); ++i) { + int a = i & 0xff; + int b = (i >> 8) & 0xff; + int c = (i >> 16) & 0xff; + + int ref = ref_paeth(a, b, c); + int opt = opt_paeth(a, b, c); + if (ref != opt) { + fprintf(stderr, "mismatch at a=%3d b=%3d c=%3d: ref=%3d opt=%3d\n", a, b, c, ref, opt); + return 1; + } + } + + printf("all ok!\n"); + return 0; +} + +// vim:sw=3:sts=3:et diff --git a/deps/stb/tests/test_png_regress.c b/deps/stb/tests/test_png_regress.c new file mode 100644 index 00000000..5ba67966 --- /dev/null +++ b/deps/stb/tests/test_png_regress.c @@ -0,0 +1,75 @@ +#include +#include + +#define STBI_WINDOWS_UTF8 + +#ifdef _WIN32 +#define WIN32 // what stb.h checks +#pragma comment(lib, "advapi32.lib") +#endif + +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" + +#define STB_DEFINE +#include "deprecated/stb.h" + +static unsigned int fnv1a_hash32(const stbi_uc *bytes, size_t len) +{ + unsigned int hash = 0x811c9dc5; + unsigned int mul = 0x01000193; + size_t i; + + for (i = 0; i < len; ++i) + hash = (hash ^ bytes[i]) * mul; + + return hash; +} + +// The idea for this test is to leave pngsuite/ref_results.csv checked in, +// and then you can run this test after making PNG loader changes. If the +// ref results change (as per git diff), confirm that the change was +// intentional. If so, commit them as well; if not, undo. +int main() +{ + char **files; + FILE *csv_file; + int i; + + files = stb_readdir_recursive("pngsuite", "*.png"); + if (!files) { + fprintf(stderr, "pngsuite files not found!\n"); + return 1; + } + + // sort files by name + qsort(files, stb_arr_len(files), sizeof(char*), stb_qsort_strcmp(0)); + + csv_file = fopen("pngsuite/ref_results.csv", "w"); + if (!csv_file) { + fprintf(stderr, "error opening ref results for writing!\n"); + stb_readdir_free(files); + return 1; + } + + fprintf(csv_file, "filename,width,height,ncomp,error,hash\n"); + for (i = 0; i < stb_arr_len(files); ++i) { + char *filename = files[i]; + int width, height, ncomp; + stbi_uc *pixels = stbi_load(filename, &width, &height, &ncomp, 0); + const char *error = ""; + unsigned int hash = 0; + + if (!pixels) + error = stbi_failure_reason(); + else { + hash = fnv1a_hash32(pixels, width * height * ncomp); + stbi_image_free(pixels); + } + + fprintf(csv_file, "%s,%d,%d,%d,%s,0x%08x\n", filename, width, height, ncomp, error, hash); + } + + fclose(csv_file); + stb_readdir_free(files); +} diff --git a/deps/stb/tools/README.header.md b/deps/stb/tools/README.header.md index 03fa1c53..65e04089 100644 --- a/deps/stb/tools/README.header.md +++ b/deps/stb/tools/README.header.md @@ -3,16 +3,18 @@ stb single-file public domain (or MIT licensed) libraries for C/C++ +# This project discusses security-relevant bugs in public in Github Issues and Pull Requests, and it may take significant time for security fixes to be implemented or merged. If this poses an unreasonable risk to your project, do not use stb libraries. + Noteworthy: * image loader: [stb_image.h](stb_image.h) * image writer: [stb_image_write.h](stb_image_write.h) -* image resizer: [stb_image_resize.h](stb_image_resize.h) +* image resizer: [stb_image_resize2.h](stb_image_resize2.h) * font text rasterizer: [stb_truetype.h](stb_truetype.h) * typesafe containers: [stb_ds.h](stb_ds.h) -Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, stb_image_resize -by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts. +Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, original stb_image_resize +by Jorge L. "VinoBS" Rodriguez, and stb_image_resize2 and stb_sprintf by Jeff Roberts. diff --git a/deps/stb/tools/README.list b/deps/stb/tools/README.list index 294bf87a..e858783c 100644 --- a/deps/stb/tools/README.list +++ b/deps/stb/tools/README.list @@ -3,7 +3,7 @@ stb_hexwave.h | audio | audio waveform synthesizer stb_image.h | graphics | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC stb_truetype.h | graphics | parse, decode, and rasterize characters from truetype fonts stb_image_write.h | graphics | image writing to disk: PNG, TGA, BMP -stb_image_resize.h | graphics | resize images larger/smaller with good quality +stb_image_resize2.h | graphics | resize images larger/smaller with good quality stb_rect_pack.h | graphics | simple 2D rectangle packer with decent quality stb_perlin.h | graphics | perlin's revised simplex noise w/ different seeds stb_ds.h | utility | typesafe dynamic array and hash tables for C, will compile in C++ diff --git a/deps/zlib/.github/workflows/c-std.yml b/deps/zlib/.github/workflows/c-std.yml new file mode 100644 index 00000000..44417bfa --- /dev/null +++ b/deps/zlib/.github/workflows/c-std.yml @@ -0,0 +1,208 @@ +name: C Standard + +# Compile with as many C standards as possible. +# The worflow is setup to fail on any compilation warnings. + +on: + workflow_dispatch: + push: + pull_request: + +jobs: + + main: + name: ${{ matrix.os.name }} ${{ matrix.compiler }} ${{ matrix.arch.name }} ${{ matrix.std.name }} ${{ matrix.builder }} + runs-on: ${{ matrix.os.value }} + strategy: + fail-fast: false + matrix: + os: + - name: Linux + value: ubuntu-latest + + - name: MacOS + value: macos-latest + + - name: Windows + value: windows-latest + cmake-opt: -G Ninja + + compiler: + - gcc + - clang + + arch: + - name: 64-bit + tag: amd64 + compiler-opt: -m64 + cmake-opt: -A x64 + + - name: 32-bit + tag: i386 + compiler-opt: -m32 + cmake-opt: -A Win32 + + + builder: + - configure + - cmake + + std: + - name: c89 + value: c89 + + - name: gnu89 + value: gnu89 + + - name: c94 + value: iso9899:199409 + + - name: c99 + value: c99 + + - name: gnu99 + value: gnu99 + + - name: c11 + value: c11 + + - name: gnu11 + value: gnu11 + + - name: c17 + value: c17 + + - name: gnu17 + value: gnu17 + + - name: c2x + value: c2x + + - name: gnu2x + value: gnu2x + + exclude: + # Don't run 32-bit on MacOS + - { os: { name: MacOS }, + arch: { tag: i386 } } + + # Don't run configure on Windows + - { os: { name: Windows }, + builder: configure } + + # Don't run gcc 32-bit on Windows + - { os: { name: Windows }, + arch: { tag: i386 } } + + steps: + + - name: Checkout repository + uses: actions/checkout@v4 + with: + show-progress: 'false' + + - name: Install packages (Linux) + if: runner.os == 'Linux' && matrix.arch.tag == 'i386' + run: | + sudo apt-get update + sudo apt install gcc-multilib libc6-dev-i386-cross + + - name: Install packages (Windows) + if: runner.os == 'Windows' + run: | + choco install --no-progress ninja + + - name: Generate project files (configure) + if: matrix.builder == 'configure' + run: | + ./configure + env: + CC: ${{ matrix.compiler }} + CFLAGS: -std=${{ matrix.std.value }} ${{ matrix.arch.compiler-opt }} -Werror -Wall -Wextra + + - name: Compile source code (configure) + if: matrix.builder == 'configure' + run: make -j2 + + - name: Run test cases (configure) + if: matrix.builder == 'configure' + run: | + make test + make cover + + - name: Generate project files (cmake) + if: matrix.builder == 'cmake' + run: | + cmake -S . -B . -D CMAKE_BUILD_TYPE=Release -D ZLIB_BUILD_EXAMPLES=OFF ${{ matrix.os.cmake-opt }} + env: + CC: ${{ matrix.compiler }} + CFLAGS: -std=${{ matrix.std.value }} ${{ matrix.arch.compiler-opt }} -Werror -Wall -Wextra + + - name: Compile source code (cmake) + if: matrix.builder == 'cmake' + run: cmake --build . --config Release + + - name: Run test cases (cmake) + if: matrix.builder == 'cmake' + run: ctest -C Release --output-on-failure --max-width 120 + + + msvc: + name: ${{ matrix.os.name }} ${{ matrix.compiler }} ${{ matrix.arch.name }} ${{ matrix.std.name }} ${{ matrix.builder }} + runs-on: ${{ matrix.os.value }} + strategy: + fail-fast: false + matrix: + os: + - name: Windows + value: windows-latest + + compiler: + - cl + + arch: + - name: 32-bit + value: -A Win32 + + - name: 64-bit + value: -A x64 + + builder: + - cmake + + std: + - name: default + value: "" + + - name: C11 + value: /std:c11 + + - name: C17 + value: /std:c17 + + # not available on the runner yet + # - name: C20 + # value: /std:c20 + + - name: latest + value: /std:clatest + + steps: + + - name: Checkout repository + uses: actions/checkout@v4 + with: + show-progress: 'false' + + - name: Generate project files (cmake) + run: | + cmake -S . -B . ${{ matrix.arch.value }} -D CMAKE_BUILD_TYPE=Release + env: + CC: ${{ matrix.compiler }} + CFLAGS: /WX ${{ matrix.std.value }} + + - name: Compile source code (cmake) + run: cmake --build . --config Release -v + + - name: Run test cases (cmake) + run: ctest -C Release --output-on-failure --max-width 120 \ No newline at end of file diff --git a/deps/zlib/.github/workflows/cmake.yml b/deps/zlib/.github/workflows/cmake.yml index d15fda86..e258b64a 100644 --- a/deps/zlib/.github/workflows/cmake.yml +++ b/deps/zlib/.github/workflows/cmake.yml @@ -11,54 +11,63 @@ jobs: - name: Ubuntu GCC os: ubuntu-latest compiler: gcc + cflags: -Werror -Wall -Wextra # Test out of source builds - name: Ubuntu GCC OSB os: ubuntu-latest compiler: gcc + cflags: -Werror -Wall -Wextra build-dir: ../build src-dir: ../zlib - name: Ubuntu GCC -O3 os: ubuntu-latest compiler: gcc - cflags: -O3 + cflags: -O3 -Werror -Wall -Wextra - name: Ubuntu Clang os: ubuntu-latest compiler: clang + cflags: -Werror -Wall -Wextra - name: Ubuntu Clang Debug os: ubuntu-latest compiler: clang + cflags: -Werror -Wall -Wextra build-config: Debug - name: Windows MSVC Win32 os: windows-latest compiler: cl + cflags: /WX /W3 cmake-args: -A Win32 - name: Windows MSVC Win64 os: windows-latest compiler: cl + cflags: /WX /W3 cmake-args: -A x64 - name: Windows GCC os: windows-latest compiler: gcc + cflags: -Werror -Wall -Wextra cmake-args: -G Ninja - name: macOS Clang os: macos-latest compiler: clang + cflags: -Werror -Wall -Wextra - name: macOS GCC os: macos-latest compiler: gcc-11 + cflags: -Werror -Wall -Wextra steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install packages (Windows) if: runner.os == 'Windows' @@ -79,7 +88,7 @@ jobs: working-directory: ${{ matrix.build-dir || '.' }} - name: Upload build errors - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() with: name: ${{ matrix.name }} (cmake) diff --git a/deps/zlib/.github/workflows/configure.yml b/deps/zlib/.github/workflows/configure.yml index e7839211..0d71689c 100644 --- a/deps/zlib/.github/workflows/configure.yml +++ b/deps/zlib/.github/workflows/configure.yml @@ -95,7 +95,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install packages (Ubuntu) if: runner.os == 'Linux' && matrix.packages @@ -110,7 +110,7 @@ jobs: ${{ matrix.src-dir || '.' }}/configure ${{ matrix.configure-args }} env: CC: ${{ matrix.compiler }} - CFLAGS: ${{ matrix.cflags }} + CFLAGS: ${{ matrix.cflags }} -Werror LDFLAGS: ${{ matrix.ldflags }} CHOST: ${{ matrix.chost }} @@ -127,7 +127,7 @@ jobs: QEMU_RUN: ${{ matrix.qemu-run }} - name: Upload build errors - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() with: name: ${{ matrix.name }} (configure) diff --git a/deps/zlib/.github/workflows/fuzz.yml b/deps/zlib/.github/workflows/fuzz.yml index 48cd2b9f..ddca83c3 100644 --- a/deps/zlib/.github/workflows/fuzz.yml +++ b/deps/zlib/.github/workflows/fuzz.yml @@ -18,7 +18,7 @@ jobs: dry-run: false - name: Upload Crash - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() with: name: artifacts diff --git a/deps/zlib/CMakeLists.txt b/deps/zlib/CMakeLists.txt index ae0f8ea2..3d9b58df 100644 --- a/deps/zlib/CMakeLists.txt +++ b/deps/zlib/CMakeLists.txt @@ -3,7 +3,9 @@ set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) project(zlib C) -set(VERSION "1.3.0.1") +set(VERSION "1.3.1.1") + +option(ZLIB_BUILD_EXAMPLES "Enable Zlib Examples" ON) set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") @@ -63,7 +65,8 @@ if(MSVC) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) endif() -if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) +option(RENAME_ZCONF "Rename the zconf when building out of source" ON) +if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR AND RENAME_ZCONF) # If we're doing an out of source build and the user has a zconf.h # in their source tree... if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h) @@ -148,7 +151,13 @@ if(MINGW) endif(MINGW) add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +target_include_directories(zlib PUBLIC + $ + $) add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +target_include_directories(zlibstatic PUBLIC + $ + $) set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) set_target_properties(zlib PROPERTIES SOVERSION 1) @@ -166,7 +175,7 @@ endif() if(UNIX) # On unix-like platforms the library is almost always called libz set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z) - if(NOT APPLE) + if(NOT APPLE AND NOT(CMAKE_SYSTEM_NAME STREQUAL AIX)) set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"") endif() elseif(BUILD_SHARED_LIBS AND WIN32) @@ -193,21 +202,22 @@ endif() #============================================================================ # Example binaries #============================================================================ +if(ZLIB_BUILD_EXAMPLES) + add_executable(example test/example.c) + target_link_libraries(example zlib) + add_test(example example) -add_executable(example test/example.c) -target_link_libraries(example zlib) -add_test(example example) + add_executable(minigzip test/minigzip.c) + target_link_libraries(minigzip zlib) -add_executable(minigzip test/minigzip.c) -target_link_libraries(minigzip zlib) + if(HAVE_OFF64_T) + add_executable(example64 test/example.c) + target_link_libraries(example64 zlib) + set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") + add_test(example64 example64) -if(HAVE_OFF64_T) - add_executable(example64 test/example.c) - target_link_libraries(example64 zlib) - set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") - add_test(example64 example64) - - add_executable(minigzip64 test/minigzip.c) - target_link_libraries(minigzip64 zlib) - set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") + add_executable(minigzip64 test/minigzip.c) + target_link_libraries(minigzip64 zlib) + set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") + endif() endif() diff --git a/deps/zlib/ChangeLog b/deps/zlib/ChangeLog index dfd65246..1f83ab05 100644 --- a/deps/zlib/ChangeLog +++ b/deps/zlib/ChangeLog @@ -1,9 +1,19 @@ ChangeLog file for zlib -Changes in 1.3.0.1 (xx Aug 2023) +Changes in 1.3.1.1 (xx Jan 2024) - +Changes in 1.3.1 (22 Jan 2024) +- Reject overflows of zip header fields in minizip +- Fix bug in inflateSync() for data held in bit buffer +- Add LIT_MEM define to use more memory for a small deflate speedup +- Fix decision on the emission of Zip64 end records in minizip +- Add bounds checking to ERR_MSG() macro, used by zError() +- Neutralize zip file traversal attacks in miniunz +- Fix a bug in ZLIB_DEBUG compiles in check_match() +- Various portability and appearance improvements + Changes in 1.3 (18 Aug 2023) - Remove K&R function definitions and zlib2ansi - Fix bug in deflateBound() for level 0 and memLevel 9 diff --git a/deps/zlib/FAQ b/deps/zlib/FAQ index 55f1cdc2..f72cac63 100644 --- a/deps/zlib/FAQ +++ b/deps/zlib/FAQ @@ -14,13 +14,12 @@ The latest zlib FAQ is at http://zlib.net/zlib_faq.html 2. Where can I get a Windows DLL version? The zlib sources can be compiled without change to produce a DLL. See the - file win32/DLL_FAQ.txt in the zlib distribution. Pointers to the - precompiled DLL are found in the zlib web site at http://zlib.net/ . + file win32/DLL_FAQ.txt in the zlib distribution. 3. Where can I get a Visual Basic interface to zlib? See - * http://marknelson.us/1997/01/01/zlib-engine/ + * https://marknelson.us/posts/1997/01/01/zlib-engine.html * win32/DLL_FAQ.txt in the zlib distribution 4. compress() returns Z_BUF_ERROR. diff --git a/deps/zlib/LICENSE b/deps/zlib/LICENSE index ab8ee6f7..b517acd5 100644 --- a/deps/zlib/LICENSE +++ b/deps/zlib/LICENSE @@ -1,6 +1,6 @@ Copyright notice: - (C) 1995-2022 Jean-loup Gailly and Mark Adler + (C) 1995-2024 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/deps/zlib/Makefile.in b/deps/zlib/Makefile.in index b584073b..5b18f76e 100644 --- a/deps/zlib/Makefile.in +++ b/deps/zlib/Makefile.in @@ -1,5 +1,5 @@ # Makefile for zlib -# Copyright (C) 1995-2017 Jean-loup Gailly, Mark Adler +# Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler # For conditions of distribution and use, see copyright notice in zlib.h # To compile and test, type: @@ -22,13 +22,13 @@ CFLAGS=-O SFLAGS=-O LDFLAGS= -TEST_LDFLAGS=$(LDFLAGS) -L. libz.a +TEST_LIBS=-L. libz.a LDSHARED=$(CC) CPP=$(CC) -E STATICLIB=libz.a SHAREDLIB=libz.so -SHAREDLIBV=libz.so.1.3.0.1 +SHAREDLIBV=libz.so.1.3.1.1 SHAREDLIBM=libz.so.1 LIBS=$(STATICLIB) $(SHAREDLIBV) @@ -282,10 +282,10 @@ placebo $(SHAREDLIBV): $(PIC_OBJS) libz.a -@rmdir objs example$(EXE): example.o $(STATICLIB) - $(CC) $(CFLAGS) -o $@ example.o $(TEST_LDFLAGS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example.o $(TEST_LIBS) minigzip$(EXE): minigzip.o $(STATICLIB) - $(CC) $(CFLAGS) -o $@ minigzip.o $(TEST_LDFLAGS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip.o $(TEST_LIBS) examplesh$(EXE): example.o $(SHAREDLIBV) $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) -L. $(SHAREDLIBV) @@ -294,10 +294,10 @@ minigzipsh$(EXE): minigzip.o $(SHAREDLIBV) $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) -L. $(SHAREDLIBV) example64$(EXE): example64.o $(STATICLIB) - $(CC) $(CFLAGS) -o $@ example64.o $(TEST_LDFLAGS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example64.o $(TEST_LIBS) minigzip64$(EXE): minigzip64.o $(STATICLIB) - $(CC) $(CFLAGS) -o $@ minigzip64.o $(TEST_LDFLAGS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip64.o $(TEST_LIBS) install-libs: $(LIBS) -@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi @@ -360,7 +360,7 @@ zconf: $(SRCDIR)zconf.h.in cp -p $(SRCDIR)zconf.h.in zconf.h minizip-test: static - cd contrib/minizip && { CFLAGS="$(CFLAGS)" $(MAKE) test ; cd ../.. ; } + cd contrib/minizip && { CC="$(CC)" CFLAGS="$(CFLAGS)" $(MAKE) test ; cd ../.. ; } minizip-clean: cd contrib/minizip && { $(MAKE) clean ; cd ../.. ; } diff --git a/deps/zlib/README b/deps/zlib/README index 20f7064a..75da5205 100644 --- a/deps/zlib/README +++ b/deps/zlib/README @@ -1,6 +1,6 @@ ZLIB DATA COMPRESSION LIBRARY -zlib 1.3.0.1 is a general purpose data compression library. All the code is +zlib 1.3.1.1 is a general purpose data compression library. All the code is thread safe. The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and @@ -31,7 +31,7 @@ Mark Nelson wrote an article about zlib for the Jan. 1997 issue of Dr. Dobb's Journal; a copy of the article is available at https://marknelson.us/posts/1997/01/01/zlib-engine.html . -The changes made in version 1.3.0.1 are documented in the file ChangeLog. +The changes made in version 1.3.1.1 are documented in the file ChangeLog. Unsupported third party contributions are provided in directory contrib/ . @@ -69,8 +69,6 @@ Notes for some targets: - zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with other compilers. Use "make test" to check your compiler. -- gzdopen is not supported on RISCOS or BEOS. - - For PalmOs, see http://palmzlib.sourceforge.net/ @@ -83,7 +81,7 @@ Acknowledgments: Copyright notice: - (C) 1995-2023 Jean-loup Gailly and Mark Adler + (C) 1995-2024 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/deps/zlib/configure b/deps/zlib/configure index 7aaf5dfa..7e71a120 100644 --- a/deps/zlib/configure +++ b/deps/zlib/configure @@ -25,7 +25,7 @@ if test $SRCDIR = "."; then ZINCOUT="-I." SRCDIR="" else - ZINC='-include zconf.h' + ZINC='-I. -include zconf.h' ZINCOUT='-I. -I$(SRCDIR)' SRCDIR="$SRCDIR/" fi @@ -91,6 +91,7 @@ warn=0 debug=0 address=0 memory=0 +unknown=0 old_cc="$CC" old_cflags="$CFLAGS" OBJC='$(OBJZ) $(OBJG)' @@ -144,12 +145,12 @@ case "$1" in --sanitize) address=1; shift ;; --address) address=1; shift ;; --memory) memory=1; shift ;; - *) - echo "unknown option: $1" | tee -a configure.log - echo "$0 --help for help" | tee -a configure.log - leave 1;; + *) unknown=1; echo "unknown option ignored: $1" | tee -a configure.log; shift;; esac done +if test $unknown -eq 1; then + echo "$0 --help for help" | tee -a configure.log +fi # temporary file name test=ztest$$ @@ -258,6 +259,7 @@ if test "$gcc" -eq 1 && ($cc -c $test.c) >> configure.log 2>&1; then SHAREDLIB='libz.sl' ;; esac ;; AIX*) + LDSHARED=${LDSHARED-"$cc -shared"} LDFLAGS="${LDFLAGS} -Wl,-brtl" ;; Darwin* | darwin* | *-darwin*) shared_ext='.dylib' @@ -442,7 +444,7 @@ EOF if test $shared -eq 1; then echo Checking for shared library support... | tee -a configure.log # we must test in two steps (cc then ld), required at least on SunOS 4.x - if try $CC -w -c $SFLAGS $test.c && + if try $CC -c $SFLAGS $test.c && try $LDSHARED $SFLAGS -o $test$shared_ext $test.o; then echo Building shared library $SHAREDLIBV with $CC. | tee -a configure.log elif test -z "$old_cc" -a -z "$old_cflags"; then diff --git a/deps/zlib/contrib/ada/readme.txt b/deps/zlib/contrib/ada/readme.txt index efdd639f..dd136c84 100644 --- a/deps/zlib/contrib/ada/readme.txt +++ b/deps/zlib/contrib/ada/readme.txt @@ -2,7 +2,7 @@ Release 1.3 ZLib.Ada is a thick binding interface to the popular ZLib data -compression library, available at http://www.gzip.org/zlib/. +compression library, available at https://zlib.net/. It provides Ada-style access to the ZLib C library. diff --git a/deps/zlib/contrib/delphi/ZLib.pas b/deps/zlib/contrib/delphi/ZLib.pas index 814ffa67..a64b1a34 100644 --- a/deps/zlib/contrib/delphi/ZLib.pas +++ b/deps/zlib/contrib/delphi/ZLib.pas @@ -152,7 +152,7 @@ procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer; const OutBuf: Pointer; BufSize: Integer); const - zlib_version = '1.3.0'; + zlib_version = '1.3.1.1'; type EZlibError = class(Exception); diff --git a/deps/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs b/deps/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs index bffe6093..9b6c3907 100644 --- a/deps/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs +++ b/deps/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs @@ -34,7 +34,7 @@ namespace DotZLib } /// - /// Initializes a new instance of the checksum generator basewith a specified value + /// Initializes a new instance of the checksum generator base with a specified value /// /// The value to set the current checksum to public ChecksumGeneratorBase(uint initialValue) diff --git a/deps/zlib/contrib/dotzlib/DotZLib/UnitTests.cs b/deps/zlib/contrib/dotzlib/DotZLib/UnitTests.cs index 209c8de4..e8cf70b8 100644 --- a/deps/zlib/contrib/dotzlib/DotZLib/UnitTests.cs +++ b/deps/zlib/contrib/dotzlib/DotZLib/UnitTests.cs @@ -156,7 +156,7 @@ namespace DotZLibTests public void Info_Version() { Info info = new Info(); - Assert.AreEqual("1.3.0", Info.Version); + Assert.AreEqual("1.3.1.1", Info.Version); Assert.AreEqual(32, info.SizeOfUInt); Assert.AreEqual(32, info.SizeOfULong); Assert.AreEqual(32, info.SizeOfPointer); diff --git a/deps/zlib/contrib/gcc_gvmat64/gvmat64.S b/deps/zlib/contrib/gcc_gvmat64/gvmat64.S index 23309fa2..51a46eb7 100644 --- a/deps/zlib/contrib/gcc_gvmat64/gvmat64.S +++ b/deps/zlib/contrib/gcc_gvmat64/gvmat64.S @@ -177,7 +177,7 @@ printf("#define dsNiceMatch %u\n",(int)(((char*)&(s->nice_match))-((char*)s) ; ; gcc on macosx-linux: -; see http://www.x86-64.org/documentation/abi-0.99.pdf +; see https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf ; param 1 in rdi, param 2 in rsi ; rbx, rsp, rbp, r12 to r15 must be preserved diff --git a/deps/zlib/contrib/infback9/inftree9.c b/deps/zlib/contrib/infback9/inftree9.c index 23f30501..cbbdd2a3 100644 --- a/deps/zlib/contrib/infback9/inftree9.c +++ b/deps/zlib/contrib/infback9/inftree9.c @@ -1,5 +1,5 @@ /* inftree9.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2023 Mark Adler + * Copyright (C) 1995-2024 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -9,7 +9,7 @@ #define MAXBITS 15 const char inflate9_copyright[] = - " inflate9 1.3.0.1 Copyright 1995-2023 Mark Adler "; + " inflate9 1.3.1.1 Copyright 1995-2024 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -59,7 +59,7 @@ int inflate_table9(codetype type, unsigned short FAR *lens, unsigned codes, static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129, 130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132, - 133, 133, 133, 133, 144, 70, 200}; + 133, 133, 133, 133, 144, 73, 200}; static const unsigned short dbase[32] = { /* Distance codes 0..31 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, diff --git a/deps/zlib/contrib/iostream3/zfstream.h b/deps/zlib/contrib/iostream3/zfstream.h index 8574479a..3dabc0f9 100644 --- a/deps/zlib/contrib/iostream3/zfstream.h +++ b/deps/zlib/contrib/iostream3/zfstream.h @@ -413,7 +413,7 @@ template class gzomanip2 { public: - // Allows insertor to peek at internals + // Allows inserter to peek at internals template friend gzofstream& operator<<(gzofstream&, @@ -452,7 +452,7 @@ template : func(f), val1(v1), val2(v2) { } -// Insertor applies underlying manipulator function to stream +// Inserter applies underlying manipulator function to stream template inline gzofstream& operator<<(gzofstream& s, const gzomanip2& m) diff --git a/deps/zlib/contrib/minizip/Makefile b/deps/zlib/contrib/minizip/Makefile index aac76e07..8bf92272 100644 --- a/deps/zlib/contrib/minizip/Makefile +++ b/deps/zlib/contrib/minizip/Makefile @@ -1,5 +1,5 @@ -CC=cc -CFLAGS := $(CFLAGS) -O -I../.. +CC?=cc +CFLAGS := -O $(CFLAGS) -I../.. UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a ZIP_OBJS = minizip.o zip.o ioapi.o ../../libz.a diff --git a/deps/zlib/contrib/minizip/configure.ac b/deps/zlib/contrib/minizip/configure.ac index cdfee49c..6e3fff37 100644 --- a/deps/zlib/contrib/minizip/configure.ac +++ b/deps/zlib/contrib/minizip/configure.ac @@ -1,7 +1,7 @@ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. -AC_INIT([minizip], [1.3.0.1], [bugzilla.redhat.com]) +AC_INIT([minizip], [1.3.1.1], [bugzilla.redhat.com]) AC_CONFIG_SRCDIR([minizip.c]) AM_INIT_AUTOMAKE([foreign]) LT_INIT diff --git a/deps/zlib/contrib/minizip/iowin32.c b/deps/zlib/contrib/minizip/iowin32.c index 08536e94..49f5ba1b 100644 --- a/deps/zlib/contrib/minizip/iowin32.c +++ b/deps/zlib/contrib/minizip/iowin32.c @@ -89,7 +89,7 @@ static voidpf win32_build_iowin(HANDLE hFile) { } voidpf ZCALLBACK win32_open64_file_func(voidpf opaque, const void* filename, int mode) { - const char* mode_fopen = NULL; + (void)opaque; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; @@ -117,7 +117,7 @@ voidpf ZCALLBACK win32_open64_file_func(voidpf opaque, const void* filename, int voidpf ZCALLBACK win32_open64_file_funcA(voidpf opaque, const void* filename, int mode) { - const char* mode_fopen = NULL; + (void)opaque; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; @@ -140,7 +140,7 @@ voidpf ZCALLBACK win32_open64_file_funcA(voidpf opaque, const void* filename, in voidpf ZCALLBACK win32_open64_file_funcW(voidpf opaque, const void* filename, int mode) { - const char* mode_fopen = NULL; + (void)opaque; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; @@ -159,7 +159,7 @@ voidpf ZCALLBACK win32_open64_file_funcW(voidpf opaque, const void* filename, in voidpf ZCALLBACK win32_open_file_func(voidpf opaque, const char* filename, int mode) { - const char* mode_fopen = NULL; + (void)opaque; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; @@ -187,6 +187,7 @@ voidpf ZCALLBACK win32_open_file_func(voidpf opaque, const char* filename, int m uLong ZCALLBACK win32_read_file_func(voidpf opaque, voidpf stream, void* buf,uLong size) { + (void)opaque; uLong ret=0; HANDLE hFile = NULL; if (stream!=NULL) @@ -208,6 +209,7 @@ uLong ZCALLBACK win32_read_file_func(voidpf opaque, voidpf stream, void* buf,uLo uLong ZCALLBACK win32_write_file_func(voidpf opaque, voidpf stream, const void* buf, uLong size) { + (void)opaque; uLong ret=0; HANDLE hFile = NULL; if (stream!=NULL) @@ -247,6 +249,7 @@ static BOOL MySetFilePointerEx(HANDLE hFile, LARGE_INTEGER pos, LARGE_INTEGER *n } long ZCALLBACK win32_tell_file_func(voidpf opaque, voidpf stream) { + (void)opaque; long ret=-1; HANDLE hFile = NULL; if (stream!=NULL) @@ -269,6 +272,7 @@ long ZCALLBACK win32_tell_file_func(voidpf opaque, voidpf stream) { } ZPOS64_T ZCALLBACK win32_tell64_file_func(voidpf opaque, voidpf stream) { + (void)opaque; ZPOS64_T ret= (ZPOS64_T)-1; HANDLE hFile = NULL; if (stream!=NULL) @@ -293,6 +297,7 @@ ZPOS64_T ZCALLBACK win32_tell64_file_func(voidpf opaque, voidpf stream) { long ZCALLBACK win32_seek_file_func(voidpf opaque, voidpf stream, uLong offset, int origin) { + (void)opaque; DWORD dwMoveMethod=0xFFFFFFFF; HANDLE hFile = NULL; @@ -330,6 +335,7 @@ long ZCALLBACK win32_seek_file_func(voidpf opaque, voidpf stream, uLong offset, } long ZCALLBACK win32_seek64_file_func(voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) { + (void)opaque; DWORD dwMoveMethod=0xFFFFFFFF; HANDLE hFile = NULL; long ret=-1; @@ -368,6 +374,7 @@ long ZCALLBACK win32_seek64_file_func(voidpf opaque, voidpf stream, ZPOS64_T off } int ZCALLBACK win32_close_file_func(voidpf opaque, voidpf stream) { + (void)opaque; int ret=-1; if (stream!=NULL) @@ -385,6 +392,7 @@ int ZCALLBACK win32_close_file_func(voidpf opaque, voidpf stream) { } int ZCALLBACK win32_error_file_func(voidpf opaque, voidpf stream) { + (void)opaque; int ret=-1; if (stream!=NULL) { diff --git a/deps/zlib/contrib/minizip/make_vms.com b/deps/zlib/contrib/minizip/make_vms.com index 9ac13a98..4a0a77e5 100644 --- a/deps/zlib/contrib/minizip/make_vms.com +++ b/deps/zlib/contrib/minizip/make_vms.com @@ -2,7 +2,7 @@ $ if f$search("ioapi.h_orig") .eqs. "" then copy ioapi.h ioapi.h_orig $ open/write zdef vmsdefs.h $ copy sys$input: zdef $ deck -#define unix +#define __unix__ #define fill_zlib_filefunc64_32_def_from_filefunc32 fillzffunc64from #define Write_Zip64EndOfCentralDirectoryLocator Write_Zip64EoDLocator #define Write_Zip64EndOfCentralDirectoryRecord Write_Zip64EoDRecord diff --git a/deps/zlib/contrib/minizip/miniunz.c b/deps/zlib/contrib/minizip/miniunz.c index 8ada038d..616c3032 100644 --- a/deps/zlib/contrib/minizip/miniunz.c +++ b/deps/zlib/contrib/minizip/miniunz.c @@ -39,6 +39,9 @@ #endif +#ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS +#endif #include #include #include @@ -79,10 +82,11 @@ /* change_file_date : change the date/time of a file filename : the filename of the file where date/time must be modified - dosdate : the new date at the MSDos format (4 bytes) + dosdate : the new date at the MSDOS format (4 bytes) tmu_date : the SAME new date at the tm_unz format */ static void change_file_date(const char *filename, uLong dosdate, tm_unz tmu_date) { #ifdef _WIN32 + (void)tmu_date; HANDLE hFile; FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite; @@ -93,8 +97,7 @@ static void change_file_date(const char *filename, uLong dosdate, tm_unz tmu_dat LocalFileTimeToFileTime(&ftLocal,&ftm); SetFileTime(hFile,&ftm,&ftLastAcc,&ftm); CloseHandle(hFile); -#else -#if defined(unix) || defined(__APPLE__) +#elif defined(__unix__) || defined(__unix) || defined(__APPLE__) (void)dosdate; struct utimbuf ut; struct tm newdate; @@ -116,7 +119,6 @@ static void change_file_date(const char *filename, uLong dosdate, tm_unz tmu_dat (void)dosdate; (void)tmu_date; #endif -#endif } @@ -127,9 +129,7 @@ static int mymkdir(const char* dirname) { int ret=0; #ifdef _WIN32 ret = _mkdir(dirname); -#elif unix - ret = mkdir (dirname,0775); -#elif __APPLE__ +#elif defined(__unix__) || defined(__unix) || defined(__APPLE__) ret = mkdir (dirname,0775); #else (void)dirname; @@ -240,7 +240,7 @@ static int do_list(unzFile uf) { printf(" ------ ------ ---- ----- ---- ---- ------ ----\n"); for (i=0;i #include #include @@ -74,6 +77,7 @@ /* f: name of file to get info on, tmzip: return value: access, modification and creation times, dt: dostime */ static int filetime(const char *f, tm_zip *tmzip, uLong *dt) { + (void)tmzip; int ret = 0; { FILETIME ftLocal; @@ -91,8 +95,7 @@ static int filetime(const char *f, tm_zip *tmzip, uLong *dt) { } return ret; } -#else -#if defined(unix) || defined(__APPLE__) +#elif defined(__unix__) || defined(__unix) || defined(__APPLE__) /* f: name of file to get info on, tmzip: return value: access, modification and creation times, dt: dostime */ static int filetime(const char *f, tm_zip *tmzip, uLong *dt) { @@ -143,7 +146,6 @@ static int filetime(const char *f, tm_zip *tmzip, uLong *dt) { return 0; } #endif -#endif @@ -192,7 +194,7 @@ static int getFileCrc(const char* filenameinzip, void* buf, unsigned long size_b do { err = ZIP_OK; - size_read = fread(buf,1,size_buf,fin); + size_read = (unsigned long)fread(buf,1,size_buf,fin); if (size_read < size_buf) if (feof(fin)==0) { @@ -244,7 +246,7 @@ int main(int argc, char *argv[]) { char filename_try[MAXFILENAME+16]; int zipok; int err=0; - size_t size_buf=0; + unsigned long size_buf=0; void* buf=NULL; const char* password=NULL; @@ -306,7 +308,7 @@ int main(int argc, char *argv[]) { } else { - int i,len; + int len; int dot_found=0; zipok = 1 ; diff --git a/deps/zlib/contrib/minizip/mztools.c b/deps/zlib/contrib/minizip/mztools.c index c8d23756..f86c1e71 100644 --- a/deps/zlib/contrib/minizip/mztools.c +++ b/deps/zlib/contrib/minizip/mztools.c @@ -5,6 +5,9 @@ */ /* Code */ +#ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS +#endif #include #include #include @@ -140,28 +143,28 @@ extern int ZEXPORT unzRepair(const char* file, const char* fileOut, const char* /* Central directory entry */ { - char header[46]; + char central[46]; char* comment = ""; int comsize = (int) strlen(comment); - WRITE_32(header, 0x02014b50); - WRITE_16(header + 4, version); - WRITE_16(header + 6, version); - WRITE_16(header + 8, gpflag); - WRITE_16(header + 10, method); - WRITE_16(header + 12, filetime); - WRITE_16(header + 14, filedate); - WRITE_32(header + 16, crc); - WRITE_32(header + 20, cpsize); - WRITE_32(header + 24, uncpsize); - WRITE_16(header + 28, fnsize); - WRITE_16(header + 30, extsize); - WRITE_16(header + 32, comsize); - WRITE_16(header + 34, 0); /* disk # */ - WRITE_16(header + 36, 0); /* int attrb */ - WRITE_32(header + 38, 0); /* ext attrb */ - WRITE_32(header + 42, currentOffset); + WRITE_32(central, 0x02014b50); + WRITE_16(central + 4, version); + WRITE_16(central + 6, version); + WRITE_16(central + 8, gpflag); + WRITE_16(central + 10, method); + WRITE_16(central + 12, filetime); + WRITE_16(central + 14, filedate); + WRITE_32(central + 16, crc); + WRITE_32(central + 20, cpsize); + WRITE_32(central + 24, uncpsize); + WRITE_16(central + 28, fnsize); + WRITE_16(central + 30, extsize); + WRITE_16(central + 32, comsize); + WRITE_16(central + 34, 0); /* disk # */ + WRITE_16(central + 36, 0); /* int attrb */ + WRITE_32(central + 38, 0); /* ext attrb */ + WRITE_32(central + 42, currentOffset); /* Header */ - if (fwrite(header, 1, 46, fpOutCD) == 46) { + if (fwrite(central, 1, 46, fpOutCD) == 46) { offsetCD += 46; /* Filename */ @@ -215,23 +218,23 @@ extern int ZEXPORT unzRepair(const char* file, const char* fileOut, const char* /* Final central directory */ { int entriesZip = entries; - char header[22]; + char end[22]; char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools"; int comsize = (int) strlen(comment); if (entriesZip > 0xffff) { entriesZip = 0xffff; } - WRITE_32(header, 0x06054b50); - WRITE_16(header + 4, 0); /* disk # */ - WRITE_16(header + 6, 0); /* disk # */ - WRITE_16(header + 8, entriesZip); /* hack */ - WRITE_16(header + 10, entriesZip); /* hack */ - WRITE_32(header + 12, offsetCD); /* size of CD */ - WRITE_32(header + 16, offset); /* offset to CD */ - WRITE_16(header + 20, comsize); /* comment */ + WRITE_32(end, 0x06054b50); + WRITE_16(end + 4, 0); /* disk # */ + WRITE_16(end + 6, 0); /* disk # */ + WRITE_16(end + 8, entriesZip); /* hack */ + WRITE_16(end + 10, entriesZip); /* hack */ + WRITE_32(end + 12, offsetCD); /* size of CD */ + WRITE_32(end + 16, offset); /* offset to CD */ + WRITE_16(end + 20, comsize); /* comment */ /* Header */ - if (fwrite(header, 1, 22, fpOutCD) == 22) { + if (fwrite(end, 1, 22, fpOutCD) == 22) { /* Comment field */ if (comsize > 0) { diff --git a/deps/zlib/contrib/minizip/skipset.h b/deps/zlib/contrib/minizip/skipset.h new file mode 100644 index 00000000..381aa13a --- /dev/null +++ b/deps/zlib/contrib/minizip/skipset.h @@ -0,0 +1,360 @@ +// skipset.h -- set operations using a skiplist +// Copyright (C) 2024 Mark Adler +// See MiniZip_info.txt for the license. + +// This implements a skiplist set, i.e. just keys, no data, with ~O(log n) time +// insert and search operations. The application defines the type of a key, and +// provides a function to compare two keys. + +// This header is not definitions of functions found in another source file -- +// it creates the set functions, with the application's key type, right where +// the #include is. Before this header is #included, these must be defined: +// +// 1. A macro or typedef for set_key_t, the type of a key. +// 2. A macro or function set_cmp(a, b) to compare two keys. The return values +// are < 0 for a < b, 0 for a == b, and > 0 for a > b. +// 3. A macro or function set_drop(s, k) to release the key k's resources, if +// any, when doing a set_end() or set_clear(). s is a pointer to the set +// that key is in, for use with set_free() if desired. +// +// Example usage: +// +// typedef int set_key_t; +// #define set_cmp(a, b) ((a) < (b) ? -1 : (a) == (b) ? 0 : 1) +// #define set_drop(s, k) +// #include "skipset.h" +// +// int test(void) { // return 0: good, 1: bad, -1: out of memory +// set_t set; +// if (setjmp(set.env)) +// return -1; +// set_start(&set); +// set_insert(&set, 2); +// set_insert(&set, 1); +// set_insert(&set, 7); +// int bad = !set_found(&set, 2); +// bad = bad || set_found(&set, 5); +// set_end(&set); +// return bad; +// } +// +// Interface summary (see more details below): +// - set_t is the type of the set being operated on (a set_t pointer is passed) +// - set_start() initializes a new, empty set (initialize set.env first) +// - set_insert() inserts a new key into the set, or not if it's already there +// - set_found() determines whether or not a key is in the set +// - set_end() ends the use of the set, freeing all memory +// - set_clear() empties the set, equivalent to set_end() and then set_start() +// - set_ok() checks if set appears to be usable, i.e. started and not ended +// +// Auxiliary functions available to the application: +// - set_alloc() allocates memory with optional tracking (#define SET_TRACK) +// - set_free() deallocates memory allocated by set_alloc() +// - set_rand() returns 32 random bits (seeded by set_start()) + +#ifndef SKIPSET_H +#define SKIPSET_H + +#include // realloc(), free(), NULL, size_t +#include // jmp_buf, longjmp() +#include // ENOMEM +#include // int16_t, uint32_t, uint64_t +#include // time(), clock() +#include // assert.h + +// Structures and functions below noted as "--private--" should not be used by +// the application. set_t is partially private and partially public -- see the +// comments there. + +// There is no POSIX random() in MSVC, and rand() is awful. For portability, we +// cannot rely on a library function for random numbers. Instead we use the +// fast and effective algorithm below, invented by Melissa O'Neill. + +// *Really* minimal PCG32 code / (c) 2014 M.E. O'Neill / www.pcg-random.org +// Licensed under Apache License 2.0 (NO WARRANTY, etc. see website) +// --private-- Random number generator state. +typedef struct { + uint64_t state; // 64-bit generator state + uint64_t inc; // 63-bit sequence id +} set_rand_t; +// --private-- Initialize the state *gen using seed and seq. seed seeds the +// advancing 64-bit state. seq is a sequence selection constant. +void set_seed(set_rand_t *gen, uint64_t seed, uint64_t seq) { + gen->inc = (seq << 1) | 1; + gen->state = (seed + gen->inc) * 6364136223846793005ULL + gen->inc; +} +// Return 32 random bits, advancing the state *gen. +uint32_t set_rand(set_rand_t *gen) { + uint64_t state = gen->state; + gen->state = state * 6364136223846793005ULL + gen->inc; + uint32_t mix = (uint32_t)(((state >> 18) ^ state) >> 27); + int rot = state >> 59; + return (mix >> rot) | (mix << ((-rot) & 31)); +} +// End of PCG32 code. + +// --private-- Linked-list node. +typedef struct set_node_s set_node_t; +struct set_node_s { + set_key_t key; // the key (not used for head or path) + int16_t size; // number of allocated pointers in right[] + int16_t fill; // number of pointers in right[] filled in + set_node_t **right; // pointer for each level, each to the right +}; + +// A set. The application sets env, may use gen with set_rand(), and may read +// allocs and memory. The remaining variables are --private-- . +typedef struct set_s { + set_node_t *head; // skiplist head -- no key, just links + set_node_t *path; // right[] is path to key from set_found() + set_node_t *node; // node under construction, in case of longjmp() + int16_t depth; // maximum depth of the skiplist + uint64_t ran; // a precious trove of random bits + set_rand_t gen; // random number generator state + jmp_buf env; // setjmp() environment for allocation errors +#ifdef SET_TRACK + size_t allocs; // number of allocations + size_t memory; // total amount of allocated memory (>= requests) +#endif +} set_t; + +// Memory allocation and deallocation. set_alloc(set, ptr, size) returns a +// pointer to an allocation of size bytes if ptr is NULL, or the previous +// allocation ptr resized to size bytes. set_alloc() will never return NULL. +// set_free(set, ptr) frees an allocation created by set_alloc(). These may be +// used by the application. e.g. if allocation tracking is desired. +#ifdef SET_TRACK +// Track the number of allocations and the total backing memory size. +# if defined(_WIN32) +# include +# define SET_ALLOC_SIZE(ptr) _msize(ptr) +# elif defined(__MACH__) +# include +# define SET_ALLOC_SIZE(ptr) malloc_size(ptr) +# elif defined(__linux__) +# include +# define SET_ALLOC_SIZE(ptr) malloc_usable_size(ptr) +# elif defined(__FreeBSD__) +# include +# define SET_ALLOC_SIZE(ptr) malloc_usable_size(ptr) +# elif defined(__NetBSD__) +# include +# define SET_ALLOC_SIZE(ptr) malloc_usable_size(ptr) +# else // e.g. OpenBSD +# define SET_ALLOC_SIZE(ptr) 0 +# endif +// With tracking. +void *set_alloc(set_t *set, void *ptr, size_t size) { + size_t had = ptr == NULL ? 0 : SET_ALLOC_SIZE(ptr); + void *mem = realloc(ptr, size); + if (mem == NULL) + longjmp(set->env, ENOMEM); + set->allocs += ptr == NULL; + set->memory += SET_ALLOC_SIZE(mem) - had; + return mem; +} +void set_free(set_t *set, void *ptr) { + if (ptr != NULL) { + set->allocs--; + set->memory -= SET_ALLOC_SIZE(ptr); + free(ptr); + } +} +#else +// Without tracking. +void *set_alloc(set_t *set, void *ptr, size_t size) { + void *mem = realloc(ptr, size); + if (mem == NULL) + longjmp(set->env, ENOMEM); + return mem; +} +void set_free(set_t *set, void *ptr) { + (void)set; + free(ptr); +} +#endif + +// --private-- Grow node's array right[] as needed to be able to hold at least +// want links. If fill is true, assure that the first want links are filled in, +// setting them to set->head if not previously filled in. Otherwise it is +// assumed that the first want links are about to be filled in. +void set_grow(set_t *set, set_node_t *node, int want, int fill) { + if (node->size < want) { + int more = node->size ? node->size : 1; + while (more < want) + more <<= 1; + node->right = set_alloc(set, node->right, more * sizeof(set_node_t *)); + node->size = (int16_t)more; + } + int i; + if (fill) + for (i = node->fill; i < want; i++) + node->right[i] = set->head; + node->fill = (int16_t)want; +} + +// --private-- Return a new node. key is left uninitialized. +set_node_t *set_node(set_t *set) { + set_node_t *node = set_alloc(set, NULL, sizeof(set_node_t)); + node->size = 0; + node->fill = 0; + node->right = NULL; + return node; +} + +// --private-- Free the list linked from head, along with the keys. +void set_sweep(set_t *set) { + set_node_t *step = set->head->right[0]; + while (step != set->head) { + set_node_t *next = step->right[0]; // save link to next node + set_drop(set, step->key); + set_free(set, step->right); + set_free(set, step); + step = next; + } +} + +// Initialize a new set. set->env must be initialized using setjmp() before +// set_start() is called. A longjmp(set->env, ENOMEM) will be used to handle a +// memory allocation failure during any of the operations. (See setjmp.h and +// errno.h.) The set can still be used if this happens, assuming that it didn't +// happen during set_start(). Whether set_start() completed or not, set_end() +// can be used to free the set's memory after a longjmp(). +void set_start(set_t *set) { +#ifdef SET_TRACK + set->allocs = 0; + set->memory = 0; +#endif + set->head = set->path = set->node = NULL; // in case set_node() fails + set->path = set_node(set); + set->head = set_node(set); + set_grow(set, set->head, 1, 1); // one link back to head for an empty set + *(unsigned char *)&set->head->key = 137; // set id + set->depth = 0; + set_seed(&set->gen, ((uint64_t)(uintptr_t)set << 32) ^ + ((uint64_t)time(NULL) << 12) ^ clock(), 0); + set->ran = 1; +} + +// Return true if *set appears to be in a usable state. If *set has been zeroed +// out, then set_ok(set) will be false and set_end(set) will be safe. +int set_ok(set_t *set) { + return set->head != NULL && + set->head->right != NULL && + *(unsigned char *)&set->head->key == 137; +} + +// Empty the set. This frees the memory used for the previous set contents. +// After set_clear(), *set is ready for use, as if after a set_start(). +void set_clear(set_t *set) { + assert(set_ok(set) && "improper use"); + + // Free all the keys and their nodes. + set_sweep(set); + + // Leave the head and path allocations as is. Clear their contents, with + // head pointing to itself and setting depth to zero, for an empty set. + set->head->right[0] = set->head; + set->head->fill = 1; + set->path->fill = 0; + set->depth = 0; +} + +// Done using the set -- free all allocations. The only operation on *set +// permitted after this is set_start(). Though another set_end() would do no +// harm. This can be done at any time after a set_start(), or after a longjmp() +// on any allocation failure, including during a set_start(). +void set_end(set_t *set) { + if (set->head != NULL) { + // Empty the set and free the head node. + if (set->head->right != NULL) { + set_sweep(set); + set_free(set, set->head->right); + } + set_free(set, set->head); + set->head = NULL; + } + if (set->path != NULL) { + // Free the path work area. + set_free(set, set->path->right); + set_free(set, set->path); + set->path = NULL; + } + if (set->node != NULL) { + // Free the node that was under construction when longjmp() hit. + set_drop(set, set->node->key); + set_free(set, set->node->right); + set_free(set, set->node); + set->node = NULL; + } +} + +// Look for key. Return 1 if found or 0 if not. This also puts the path to get +// there in set->path, for use by set_insert(). +int set_found(set_t *set, set_key_t key) { + assert(set_ok(set) && "improper use"); + + // Start at depth and work down and right as determined by key comparisons. + set_node_t *head = set->head, *here = head; + int i = set->depth; + set_grow(set, set->path, i + 1, 0); + do { + while (here->right[i] != head && + set_cmp(here->right[i]->key, key) < 0) + here = here->right[i]; + set->path->right[i] = here; + } while (i--); + + // See if the key matches. + here = here->right[0]; + return here != head && set_cmp(here->key, key) == 0; +} + +// Insert the key key. Return 0 on success, or 1 if key is already in the set. +int set_insert(set_t *set, set_key_t key) { + assert(set_ok(set) && "improper use"); + + if (set_found(set, key)) + // That key is already in the set. + return 1; + + // Randomly generate a new level-- level 0 with probability 1/2, 1 with + // probability 1/4, 2 with probability 1/8, etc. + int level = 0; + for (;;) { + if (set->ran == 1) + // Ran out. Get another 32 random bits. + set->ran = set_rand(&set->gen) | (1ULL << 32); + int bit = set->ran & 1; + set->ran >>= 1; + if (bit) + break; + assert(level < 32767 && + "Overhead, without any fuss, the stars were going out."); + level++; + } + if (level > set->depth) { + // The maximum depth is now deeper. Update the structures. + set_grow(set, set->path, level + 1, 1); + set_grow(set, set->head, level + 1, 1); + set->depth = (int16_t)level; + } + + // Make a new node for the provided key, and insert it in the lists up to + // and including level. + set->node = set_node(set); + set->node->key = key; + set_grow(set, set->node, level + 1, 0); + int i; + for (i = 0; i <= level; i++) { + set->node->right[i] = set->path->right[i]->right[i]; + set->path->right[i]->right[i] = set->node; + } + set->node = NULL; + return 0; +} + +#else +#error ** another skiplist set already created here +// Would need to implement a prefix in order to support multiple sets. +#endif diff --git a/deps/zlib/contrib/minizip/unzip.c b/deps/zlib/contrib/minizip/unzip.c index ed763f89..a2ee14bd 100644 --- a/deps/zlib/contrib/minizip/unzip.c +++ b/deps/zlib/contrib/minizip/unzip.c @@ -68,10 +68,6 @@ #include #include -#ifndef NOUNCRYPT - #define NOUNCRYPT -#endif - #include "zlib.h" #include "unzip.h" @@ -92,7 +88,7 @@ #ifndef CASESENSITIVITYDEFAULT_NO -# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) +# if (!defined(__unix__) && !defined(__unix) || defined(__CYGWIN__)) && !defined(CASESENSITIVITYDEFAULT_YES) # define CASESENSITIVITYDEFAULT_NO # endif #endif @@ -117,7 +113,7 @@ const char unz_copyright[] = " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; -/* unz_file_info_interntal contain internal info about a file in zipfile*/ +/* unz_file_info64_internal contain internal info about a file in zipfile*/ typedef struct unz_file_info64_internal_s { ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */ @@ -450,7 +446,7 @@ local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) return CENTRALDIRINVALID; - /* number of the disk with the start of the zip64 end of central directory */ + /* number of the disk with the start of the zip64 end of central directory */ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) return CENTRALDIRINVALID; if (uL != 0) @@ -497,9 +493,9 @@ local unzFile unzOpenInternal(const void *path, ZPOS64_T central_pos; uLong uL; - uLong number_disk; /* number of the current dist, used for + uLong number_disk; /* number of the current disk, used for spanning ZIP, unsupported, always 0*/ - uLong number_disk_with_CD; /* number the the disk with central dir, used + uLong number_disk_with_CD; /* number the disk with central dir, used for spanning ZIP, unsupported, always 0*/ ZPOS64_T number_entry_CD; /* total number of entries in the central dir @@ -1613,7 +1609,7 @@ extern int ZEXPORT unzReadCurrentFile(unzFile file, voidp buf, unsigned len) { uInt i; for(i=0;iread_buffer[i] = - zdecode(s->keys,s->pcrc_32_tab, + (char)zdecode(s->keys,s->pcrc_32_tab, pfile_in_zip_read_info->read_buffer[i]); } # endif diff --git a/deps/zlib/contrib/minizip/unzip.h b/deps/zlib/contrib/minizip/unzip.h index 14105840..ceb614e7 100644 --- a/deps/zlib/contrib/minizip/unzip.h +++ b/deps/zlib/contrib/minizip/unzip.h @@ -306,13 +306,17 @@ extern int ZEXPORT unzGetCurrentFileInfo(unzFile file, Get Info about the current file if pfile_info!=NULL, the *pfile_info structure will contain some info about the current file - if szFileName!=NULL, the filemane string will be copied in szFileName + if szFileName!=NULL, the filename string will be copied in szFileName (fileNameBufferSize is the size of the buffer) if extraField!=NULL, the extra field information will be copied in extraField (extraFieldBufferSize is the size of the buffer). This is the Central-header version of the extra field if szComment!=NULL, the comment string of the file will be copied in szComment (commentBufferSize is the size of the buffer) + The file name and comment will be zero-terminated if there is room in the + provided buffer. Otherwise the buffer will contain as much as will fit. If at + least 65537 bytes of room is provided, then the result will always be + complete and zero-terminated. */ diff --git a/deps/zlib/contrib/minizip/zip.c b/deps/zlib/contrib/minizip/zip.c index e2e9da07..cbb25084 100644 --- a/deps/zlib/contrib/minizip/zip.c +++ b/deps/zlib/contrib/minizip/zip.c @@ -123,6 +123,19 @@ typedef struct linkedlist_data_s } linkedlist_data; +// zipAlreadyThere() set functions for a set of zero-terminated strings, and +// a block_t type for reading the central directory datablocks. +typedef char const *set_key_t; +#define set_cmp(a, b) strcmp(a, b) +#define set_drop(s, k) set_free(s, (void *)(intptr_t)(k)) +#include "skipset.h" +typedef struct { + unsigned char *next; // next byte in datablock data + size_t left; // number of bytes left in data (at least) + linkedlist_datablock_internal *node; // current datablock +} block_t; + + typedef struct { z_stream stream; /* zLib stream structure for inflate */ @@ -174,6 +187,10 @@ typedef struct char *globalcomment; #endif + // Support for zipAlreadyThere(). + set_t set; // set for detecting name collisions + block_t block; // block for reading the central directory + } zip64_internal; @@ -264,6 +281,223 @@ local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) return ZIP_OK; } +// zipAlreadyThere() operations. "set" in the zip internal structure keeps the +// set of names that are in the under-construction central directory so far. A +// skipset provides ~O(log n) time insertion and searching. Central directory +// records, stored in a linked list of allocated memory datablocks, is read +// through "block" in the zip internal structure. + +// The block_*() functions support extracting the central directory file names +// from the datablocks. They are designed to support a growing directory by +// automatically continuing once more data has been appended to the linked +// datablocks. + +// Initialize *block to the head of list. This should only be called once the +// list has at least some data in it, i.e. list->first_block is not NULL. +local void block_init(block_t *block, linkedlist_data *list) { + block->node = list->first_block; + block->next = block->node->data; + block->left = block->node->filled_in_this_block; +} + +// Mark *block as bad, with all subsequent reads returning end, even if more +// data is added to the datablocks. This is invoked if the central directory is +// invalid, so there is no longer any point in attempting to interpret it. +local void block_stop(block_t *block) { + block->left = 0; + block->next = NULL; +} + +// Return true if *block has reached the end of the data in the datablocks. +local int block_end(block_t *block) { + linkedlist_datablock_internal *node = block->node; + if (node == NULL) + // This block was previously terminated with extreme prejudice. + return 1; + if (block->next < node->data + node->filled_in_this_block) + // There are more bytes to read in the current datablock. + return 0; + while (node->next_datablock != NULL) { + if (node->filled_in_this_block != 0) + // There are some bytes in a later datablock. + return 0; + node = node->next_datablock; + } + // Reached the end of the list of datablocks. There's nothing. + return 1; +} + +// Return one byte from *block, or -1 if the end is reached. +local int block_get(block_t *block) { + while (block->left == 0) { + if (block->node == NULL) + // We've been marked bad. Return end. + return -1; + // Update left in case more was filled in since we were last here. + block->left = block->node->filled_in_this_block - + (block->next - block->node->data); + if (block->left != 0) + // There was indeed more data appended in the current datablock. + break; + if (block->node->next_datablock == NULL) + // No more data here, and there is no next datablock. At the end. + return -1; + // Try the next datablock for more data. + block->node = block->node->next_datablock; + block->next = block->node->data; + block->left = block->node->filled_in_this_block; + } + // We have a byte to return. + block->left--; + return *block->next++; +} + +// Return a 16-bit unsigned little-endian value from block, or a negative value +// if the end is reached. +local long block_get2(block_t *block) { + long got = block_get(block); + return got | ((unsigned long)block_get(block) << 8); +} + +// Read up to len bytes from block into buf. Return the number of bytes read. +local size_t block_read(block_t *block, unsigned char *buf, size_t len) { + size_t need = len; + while (need) { + if (block->left == 0) { + // Get a byte to update and step through the linked list as needed. + int got = block_get(block); + if (got == -1) + // Reached the end. + break; + *buf++ = (unsigned char)got; + need--; + continue; + } + size_t take = need > block->left ? block->left : need; + memcpy(buf, block->next, take); + block->next += take; + block->left -= take; + buf += take; + need -= take; + } + return len - need; // return the number of bytes copied +} + +// Skip n bytes in block. Return 0 on success or -1 if there are less than n +// bytes to the end. +local int block_skip(block_t *block, size_t n) { + while (n > block->left) { + n -= block->left; + block->next += block->left; + block->left = 0; + if (block_get(block) == -1) + return -1; + n--; + } + block->next += n; + block->left -= n; + return 0; +} + +// Process the next central directory record at *block. Return the allocated, +// zero-terminated file name, or NULL for end of input or invalid data. If +// invalid, *block is marked bad. This uses *set for the allocation of memory. +local char *block_central_name(block_t *block, set_t *set) { + char *name = NULL; + for (;;) { + if (block_end(block)) + // At the end of the central directory (so far). + return NULL; + + // Check for a central directory record signature. + if (block_get2(block) != (CENTRALHEADERMAGIC & 0xffff) || + block_get2(block) != (CENTRALHEADERMAGIC >> 16)) + // Incorrect signature. + break; + + // Go through the remaining fixed-length portion of the record, + // extracting the lengths of the three variable-length fields. + block_skip(block, 24); + unsigned flen = block_get2(block); // file name length + unsigned xlen = block_get2(block); // extra field length + unsigned clen = block_get2(block); // comment field length + if (block_skip(block, 12) == -1) + // Premature end of the record. + break; + + // Extract the name and skip over the extra and comment fields. + name = set_alloc(set, NULL, flen + 1); + if (block_read(block, (unsigned char *)name, flen) < flen || + block_skip(block, xlen + clen) == -1) + // Premature end of the record. + break; + + // Check for embedded nuls in the name. + if (memchr(name, 0, flen) != NULL) { + // This name can never match the zero-terminated name provided to + // zipAlreadyThere(), so we discard it and go back to get another + // name. (Who the heck is putting nuls inside their zip file entry + // names anyway?) + set_free(set, name); + continue; + } + + // All good. Return the zero-terminated file name. + name[flen] = 0; + return name; + } + + // Invalid signature or premature end of the central directory record. + // Abandon trying to process the central directory. + set_free(set, name); + block_stop(block); + return NULL; +} + +// Return 0 if name is not in the central directory so far, 1 if it is, -1 if +// the central directory is invalid, -2 if out of memory, or ZIP_PARAMERROR if +// file is NULL. +extern int ZEXPORT zipAlreadyThere(zipFile file, char const *name) { + zip64_internal *zip = file; + if (zip == NULL) + return ZIP_PARAMERROR; + if (zip->central_dir.first_block == NULL) + // No central directory yet, so no, name isn't there. + return 0; + if (setjmp(zip->set.env)) { + // Memory allocation failure. + set_end(&zip->set); + return -2; + } + if (!set_ok(&zip->set)) { + // This is the first time here with some central directory content. We + // construct this set of names only on demand. Prepare set and block. + set_start(&zip->set); + block_init(&zip->block, &zip->central_dir); + } + + // Update the set of names from the current central directory contents. + // This reads any new central directory records since the last time we were + // here. + for (;;) { + char *there = block_central_name(&zip->block, &zip->set); + if (there == NULL) { + if (zip->block.next == NULL) + // The central directory is invalid. + return -1; + break; + } + + // Add there to the set. + if (set_insert(&zip->set, there)) + // There's already a duplicate in the central directory! We'll just + // let this be and carry on. + set_free(&zip->set, there); + } + + // Return true if name is in the central directory. + return set_found(&zip->set, name); +} /****************************************************************************/ @@ -551,7 +785,7 @@ local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib for (i=(int)uReadSize-3; (i--)>0;) { - // Signature "0x07064b50" Zip64 end of central directory locater + // Signature "0x07064b50" Zip64 end of central directory locator if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) { uPosFound = uReadPos+(unsigned)i; @@ -575,7 +809,7 @@ local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) return 0; - /* number of the disk with the start of the zip64 end of central directory */ + /* number of the disk with the start of the zip64 end of central directory */ if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) return 0; if (uL != 0) @@ -843,6 +1077,7 @@ extern zipFile ZEXPORT zipOpen3(const void *pathname, int append, zipcharpc* glo ziinit.number_entry = 0; ziinit.add_position_when_writing_offset = 0; init_linkedlist(&(ziinit.central_dir)); + memset(&ziinit.set, 0, sizeof(set_t)); // make sure set appears dormant @@ -1027,7 +1262,6 @@ extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char* filename, c int err = ZIP_OK; # ifdef NOCRYPT - (crcForCrypting); if (password != NULL) return ZIP_PARAMERROR; # endif @@ -1608,7 +1842,7 @@ extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, ZPOS64_T uncompressed_si if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree) { - // we can not write more data to the buffer that we have room for. + // we cannot write more data to the buffer that we have room for. return ZIP_BADZIPFILE; } @@ -1871,6 +2105,8 @@ extern int ZEXPORT zipClose(zipFile file, const char* global_comment) { } free_linkedlist(&(zi->central_dir)); + set_end(&zi->set); // set was zeroed, so this is safe + pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; if(pos >= 0xffffffff || zi->number_entry >= 0xFFFF) { diff --git a/deps/zlib/contrib/minizip/zip.h b/deps/zlib/contrib/minizip/zip.h index 3e230d34..1f7f0b26 100644 --- a/deps/zlib/contrib/minizip/zip.h +++ b/deps/zlib/contrib/minizip/zip.h @@ -35,7 +35,7 @@ See header of zip.h -*/ + */ #ifndef _zip12_H #define _zip12_H @@ -127,12 +127,12 @@ extern zipFile ZEXPORT zipOpen64(const void *pathname, int append); If the zipfile cannot be opened, the return value is NULL. Else, the return value is a zipFile Handle, usable with other function of this zip package. -*/ + */ /* Note : there is no delete function into a zipfile. If you want delete file into a zipfile, you must open a zipfile, and create another Of course, you can use RAW reading and writing to copy the file you did not want delete -*/ + */ extern zipFile ZEXPORT zipOpen2(const char *pathname, int append, @@ -186,7 +186,7 @@ extern int ZEXPORT zipOpenNewFileInZip64(zipFile file, zip64 is set to 1 if a zip64 extended information block should be added to the local file header. this MUST be '1' if the uncompressed size is >= 0xffffffff. -*/ + */ extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, @@ -311,12 +311,12 @@ extern int ZEXPORT zipWriteInFileInZip(zipFile file, unsigned len); /* Write data in the zipfile -*/ + */ extern int ZEXPORT zipCloseFileInZip(zipFile file); /* Close the current file in the zipfile -*/ + */ extern int ZEXPORT zipCloseFileInZipRaw(zipFile file, uLong uncompressed_size, @@ -326,17 +326,23 @@ extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, ZPOS64_T uncompressed_size, uLong crc32); +extern int ZEXPORT zipAlreadyThere(zipFile file, + char const* name); +/* + See if name is already in file's central directory. + */ + /* Close the current file in the zipfile, for file opened with parameter raw=1 in zipOpenNewFileInZip2 uncompressed_size and crc32 are value for the uncompressed size -*/ + */ extern int ZEXPORT zipClose(zipFile file, const char* global_comment); /* Close the zipfile -*/ + */ extern int ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHeader); @@ -355,7 +361,7 @@ extern int ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHea Remove ZIP64 Extra information from a Local File Header extra field data zipRemoveExtraInfoBlock(pLocalHeaderExtraFieldData, &nLocalHeaderExtraFieldDataLen, 0x0001); -*/ + */ #ifdef __cplusplus } diff --git a/deps/zlib/contrib/nuget/nuget.csproj b/deps/zlib/contrib/nuget/nuget.csproj index b72cbb67..852e4503 100644 --- a/deps/zlib/contrib/nuget/nuget.csproj +++ b/deps/zlib/contrib/nuget/nuget.csproj @@ -6,8 +6,8 @@ $(PackageId).win $(PackageId).linux $(PackageId).osx - (C) 1995-2023 Jean-loup Gailly and Mark Adler - 1.3.0.1 + (C) 1995-2024 Jean-loup Gailly and Mark Adler + 1.3.1.1 NuGet Package for consuming native builds of zlib into .NET without complexity.