mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 16:00:18 +02:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8991ecb67b | ||
|
|
91edf6b333 |
No files matched your search
-109
@@ -1,109 +0,0 @@
|
||||
Language: Cpp
|
||||
BasedOnStyle: WebKit
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveAssignments: None
|
||||
AlignConsecutiveBitFields: Consecutive
|
||||
AlignConsecutiveDeclarations: None
|
||||
AlignConsecutiveMacros: None
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||
AllowShortLambdasOnASingleLine: Inline
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
AttributeMacros:
|
||||
- JEMALLOC_NOTHROW
|
||||
- FEX_ALIGNED
|
||||
- FEX_ANNOTATE
|
||||
- FEX_DEFAULT_VISIBILITY
|
||||
- FEX_NAKED
|
||||
- FEX_PACKED
|
||||
- FEXCORE_PRESERVE_ALL_ATTR
|
||||
- GLIBC_ALIAS_FUNCTION
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BitFieldColonSpacing: Both
|
||||
BreakAfterAttributes: Leave
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeInlineASMColon: OnlyMultiline # clang 16 required
|
||||
BreakBeforeTernaryOperators: false
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakInheritanceList: BeforeColon
|
||||
ColumnLimit: 140
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 2
|
||||
ContinuationIndentWidth: 2
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
EmptyLineAfterAccessModifier: Leave
|
||||
EmptyLineBeforeAccessModifier: Leave
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
IncludeBlocks: Preserve
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseBlocks: false
|
||||
IndentCaseLabels: false
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentGotoLabels: false
|
||||
IndentPPDirectives: None
|
||||
IndentRequires: false
|
||||
IndentWidth: 2
|
||||
InsertBraces: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
LambdaBodyIndentation: Signature
|
||||
LineEnding: LF # clang 16 required
|
||||
MaxEmptyLinesToKeep: 2
|
||||
NamespaceIndentation: Inner
|
||||
QualifierAlignment: Left
|
||||
PackConstructorInitializers: Never
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 2
|
||||
PenaltyBreakOpenParenthesis: 2
|
||||
PenaltyBreakString: 10
|
||||
PenaltyBreakTemplateDeclaration: 8
|
||||
PenaltyExcessCharacter: 2
|
||||
PenaltyReturnTypeOnItsOwnLine: 16
|
||||
PointerAlignment: Left
|
||||
RemoveBracesLLVM: false
|
||||
ReferenceAlignment: Left
|
||||
ReflowComments: true
|
||||
RequiresClausePosition: WithPreceding
|
||||
SeparateDefinitionBlocks: Leave
|
||||
SortIncludes: Never
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: Custom
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: true
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterFunctionDefinitionName: false
|
||||
AfterOverloadedOperator: false
|
||||
AfterRequiresInClause: true
|
||||
BeforeNonEmptyParentheses: false
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: Leave
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInParentheses: false
|
||||
Standard: c++20
|
||||
UseTab: Never
|
||||
@@ -1,9 +0,0 @@
|
||||
# This file is used to ignore files and directories from clang-format
|
||||
Source/Common/cpp-optparse/*
|
||||
|
||||
# Files with human-indented tables for readability - don't mess with these
|
||||
FEXCore/Source/Interface/Core/X86Tables/*
|
||||
|
||||
# Inline headers with list-like content that can't be processed individually
|
||||
Source/Tools/LinuxEmulation/LinuxSyscalls/x*/SyscallsNames.inl
|
||||
Source/Tools/LinuxEmulation/LinuxSyscalls/x*/Ioctl/*.inl
|
||||
@@ -1,22 +0,0 @@
|
||||
# Since version 2.23 (released in August 2019), git-blame has a feature
|
||||
# to ignore or bypass certain commits.
|
||||
#
|
||||
# This file contains a list of commits that are not likely what you
|
||||
# are looking for in a blame, such as mass reformatting or renaming.
|
||||
# You can set this file as a default ignore file for blame by running
|
||||
# the following command.
|
||||
#
|
||||
# $ git config blame.ignoreRevsFile .git-blame-ignore-revs
|
||||
|
||||
# Whole tree reformat PR#3571
|
||||
2b4ec88daebd35fefb5bf5c73d7fc2b4155771ed
|
||||
|
||||
# Second reformat to find fixed point PR#3577
|
||||
905aa935f5ce344a48ef4d5edab3c31efa8d793e
|
||||
|
||||
# Reformat of CodeEmitter inl files
|
||||
8760c593ece92d7e9fa94c40da0368fd367c9cad
|
||||
|
||||
# Whole-tree reformat with clang-format-19
|
||||
5267cde60e7642852d18f20ae8568643bb5293d5
|
||||
|
||||
@@ -37,6 +37,7 @@ If applicable, add screenshots and video to help explain your problem.
|
||||
|
||||
**Additional context**
|
||||
- Is this an x86 or x86-64 game: [x86/x86-64/Both]
|
||||
- Does this reproduce on x86-64 host with FEX: [Yes/No/Untested]
|
||||
- Does this reproduce on AArch64 with Radeon/Intel/Nvidia: [Yes/No/Untested]
|
||||
- Is this a Vulkan game: [Yes/No/Unknown]
|
||||
- If Yes, What is your Vulkan driver:
|
||||
|
||||
+66
-52
@@ -13,13 +13,15 @@ env:
|
||||
BUILD_TYPE: Release
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
FEX_FORCE32BITALLOCATOR: 1
|
||||
FEX_ENABLEAVX: 1
|
||||
|
||||
jobs:
|
||||
build_plus_test:
|
||||
build:
|
||||
runs-on: ${{ matrix.arch }}
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [[self-hosted, ARMv8.0], [self-hosted, ARMv8.2], [self-hosted, ARMv8.4]]
|
||||
arch: [[self-hosted, x64], [self-hosted, ARMv8.0], [self-hosted, ARMv8.2], [self-hosted, ARMv8.4]]
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
@@ -63,7 +65,7 @@ jobs:
|
||||
# Note the current convention is to use the -S and -B options here to specify source
|
||||
# and build directories, but this is only available with CMake 3.13 and higher.
|
||||
# The CMake binaries on the Github Actions machines are (as of this writing) 3.12
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -G Ninja -DENABLE_LTO=False -DENABLE_ASSERTIONS=True -DENABLE_X86_HOST_DEBUG=True -DBUILD_FEX_LINUX_TESTS=True -DBUILD_THUNKS=True -DCMAKE_INSTALL_PREFIX=${{runner.workspace}}/build/install
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -G Ninja -DENABLE_LTO=False -DENABLE_ASSERTIONS=True -DENABLE_X86_HOST_DEBUG=True -DENABLE_INTERPRETER=True -DBUILD_FEX_LINUX_TESTS=True -DBUILD_THUNKS=True -DCMAKE_INSTALL_PREFIX=${{runner.workspace}}/build/install
|
||||
|
||||
- name: Build
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
@@ -76,6 +78,54 @@ jobs:
|
||||
shell: bash
|
||||
run: cmake --build . --config $BUILD_TYPE --target install
|
||||
|
||||
- name: ASM Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the unit tests
|
||||
run: cmake --build . --config $BUILD_TYPE --target asm_tests
|
||||
|
||||
- name: ASM Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_ASM.log || true
|
||||
|
||||
- name: IR Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the unit tests
|
||||
run: cmake --build . --config $BUILD_TYPE --target ir_tests
|
||||
|
||||
- name: IR Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_IR.log || true
|
||||
|
||||
- name: Posix Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the posixtest
|
||||
run: cmake --build . --config $BUILD_TYPE --target posix_tests
|
||||
|
||||
- name: Posix Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_Posix.log || true
|
||||
|
||||
- name: gvisor tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the gvisor tests
|
||||
run: cmake --build . --config $BUILD_TYPE --target gvisor_tests
|
||||
|
||||
- name: GVisor Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_GVisor.log || true
|
||||
|
||||
- name: gcc target tests 64
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
@@ -100,6 +150,17 @@ jobs:
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_GCC32.log || true
|
||||
|
||||
- name: Struct verifier tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
run: cmake --build . --config $BUILD_TYPE --target struct_verifier
|
||||
|
||||
- name: Struct verifier Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_StructVerifier.log || true
|
||||
|
||||
- name: APITest tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
@@ -183,60 +244,13 @@ jobs:
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_ThunkResults.log || true
|
||||
|
||||
- name: ASM Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the unit tests
|
||||
run: cmake --build . --config $BUILD_TYPE --target asm_tests
|
||||
|
||||
- name: ASM Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_ASM.log || true
|
||||
|
||||
- name: Posix Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the posixtest
|
||||
run: cmake --build . --config $BUILD_TYPE --target posix_tests
|
||||
|
||||
- name: Posix Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_Posix.log || true
|
||||
|
||||
- name: gvisor tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the gvisor tests
|
||||
run: cmake --build . --config $BUILD_TYPE --target gvisor_tests
|
||||
|
||||
- name: GVisor Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_GVisor.log || true
|
||||
|
||||
- name: Struct verifier tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
run: cmake --build . --config $BUILD_TYPE --target struct_verifier
|
||||
|
||||
- name: Struct verifier Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_StructVerifier.log || true
|
||||
|
||||
- name: Truncate test results
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
# Cap out the log files at 20M in case something crash spins and dumps fault text
|
||||
# ASM tests get quite close to 10MB
|
||||
run: truncate --size="<20M" ${{runner.workspace}}/build/Testing/Temporary/LastTest_*.log || true
|
||||
run: truncate --size=<20M ${{runner.workspace}}/build/Testing/Temporary/LastTest_*.log || true
|
||||
|
||||
- name: Remove old SHM regions
|
||||
if: ${{ always() }}
|
||||
@@ -250,7 +264,7 @@ jobs:
|
||||
|
||||
- name: Upload results
|
||||
if: ${{ always() }}
|
||||
uses: 'actions/upload-artifact@v4'
|
||||
uses: 'actions/upload-artifact@v3'
|
||||
timeout-minutes: 1
|
||||
with:
|
||||
name: Results-${{ env.runner_name }}
|
||||
|
||||
@@ -20,13 +20,16 @@ env:
|
||||
BUILD_TYPE: Release
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
FEX_FORCE32BITALLOCATOR: 1
|
||||
FEX_ENABLEAVX: 1
|
||||
|
||||
jobs:
|
||||
glibc_fault_test:
|
||||
build:
|
||||
runs-on: ${{ matrix.arch }}
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [[self-hosted, ARM64]]
|
||||
# Run on an x86 device and any ARM runner.
|
||||
arch: [[self-hosted, x64], [self-hosted, ARM64]]
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
@@ -70,7 +73,7 @@ jobs:
|
||||
# Note the current convention is to use the -S and -B options here to specify source
|
||||
# and build directories, but this is only available with CMake 3.13 and higher.
|
||||
# The CMake binaries on the Github Actions machines are (as of this writing) 3.12
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -G Ninja -DENABLE_LTO=False -DENABLE_ASSERTIONS=True -DENABLE_X86_HOST_DEBUG=True -DBUILD_FEX_LINUX_TESTS=True -DENABLE_GLIBC_ALLOCATOR_HOOK_FAULT=True -DENABLE_JEMALLOC_GLIBC_ALLOC=False -DCMAKE_INSTALL_PREFIX=${{runner.workspace}}/build/install
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -G Ninja -DENABLE_LTO=False -DENABLE_ASSERTIONS=True -DENABLE_X86_HOST_DEBUG=True -DENABLE_INTERPRETER=True -DBUILD_FEX_LINUX_TESTS=True -DENABLE_GLIBC_ALLOCATOR_HOOK_FAULT=True -DENABLE_JEMALLOC_GLIBC_ALLOC=False -DCMAKE_INSTALL_PREFIX=${{runner.workspace}}/build/install
|
||||
|
||||
- name: Build
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
@@ -83,6 +86,42 @@ jobs:
|
||||
shell: bash
|
||||
run: cmake --build . --config $BUILD_TYPE --target install
|
||||
|
||||
- name: ASM Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the unit tests
|
||||
run: cmake --build . --config $BUILD_TYPE --target asm_tests
|
||||
|
||||
- name: ASM Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_ASM.log || true
|
||||
|
||||
- name: IR Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the unit tests
|
||||
run: cmake --build . --config $BUILD_TYPE --target ir_tests
|
||||
|
||||
- name: IR Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_IR.log || true
|
||||
|
||||
- name: Posix Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the posixtest
|
||||
run: cmake --build . --config $BUILD_TYPE --target posix_tests
|
||||
|
||||
- name: Posix Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_Posix.log || true
|
||||
|
||||
- name: gcc target tests 64
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
@@ -140,37 +179,13 @@ jobs:
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_FEXLinuxTests.log || true
|
||||
|
||||
- name: ASM Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the unit tests
|
||||
run: cmake --build . --config $BUILD_TYPE --target asm_tests
|
||||
|
||||
- name: ASM Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_ASM.log || true
|
||||
|
||||
- name: Posix Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the posixtest
|
||||
run: cmake --build . --config $BUILD_TYPE --target posix_tests
|
||||
|
||||
- name: Posix Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_Posix.log || true
|
||||
|
||||
- name: Truncate test results
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
# Cap out the log files at 20M in case something crash spins and dumps fault text
|
||||
# ASM tests get quite close to 10MB
|
||||
run: truncate --size="<20M" ${{runner.workspace}}/build/Testing/Temporary/LastTest_*.log || true
|
||||
run: truncate --size=<20M ${{runner.workspace}}/build/Testing/Temporary/LastTest_*.log || true
|
||||
|
||||
- name: Remove old SHM regions
|
||||
if: ${{ always() }}
|
||||
@@ -184,7 +199,7 @@ jobs:
|
||||
|
||||
- name: Upload results
|
||||
if: ${{ always() }}
|
||||
uses: 'actions/upload-artifact@v4'
|
||||
uses: 'actions/upload-artifact@v3'
|
||||
timeout-minutes: 1
|
||||
with:
|
||||
name: Results-${{ env.runner_name }}
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
name: Hostrunner tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
env:
|
||||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||
BUILD_TYPE: Release
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
|
||||
jobs:
|
||||
hostrunner_tests:
|
||||
runs-on: ${{ matrix.arch }}
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [[self-hosted, x64]]
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set runner label
|
||||
run: echo "runner_label=${{ matrix.arch[1] }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Set rootfs paths
|
||||
run: |
|
||||
echo "FEX_ROOTFS_MOUNT=/mnt/AutoNFS/rootfs/" >> $GITHUB_ENV
|
||||
echo "FEX_ROOTFS_PATH=$HOME/Rootfs/" >> $GITHUB_ENV
|
||||
echo "FEX_ROOTFS=$HOME/Rootfs/" >> $GITHUB_ENV
|
||||
echo "ROOTFS=$HOME/Rootfs/" >> $GITHUB_ENV
|
||||
|
||||
- name: Update RootFS cache
|
||||
# Use a bash shell so we can use the same syntax for environment variable
|
||||
# access regardless of the host operating system
|
||||
shell: bash
|
||||
run: $GITHUB_WORKSPACE/Scripts/CI_FetchRootFS.py
|
||||
|
||||
- name : submodule checkout
|
||||
# Need to update submodules
|
||||
run: |
|
||||
git submodule sync --recursive
|
||||
git submodule update --init --depth 1
|
||||
|
||||
- name: Clean Build Environment
|
||||
run: rm -Rf ${{runner.workspace}}/build
|
||||
|
||||
- name: Create Build Environment
|
||||
# Some projects don't allow in-source building, so create a separate build directory
|
||||
# We'll use this as our working directory for all subsequent commands
|
||||
run: cmake -E make_directory ${{runner.workspace}}/build
|
||||
|
||||
- name: Configure CMake
|
||||
# Use a bash shell so we can use the same syntax for environment variable
|
||||
# access regardless of the host operating system
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
# Note the current convention is to use the -S and -B options here to specify source
|
||||
# and build directories, but this is only available with CMake 3.13 and higher.
|
||||
# The CMake binaries on the Github Actions machines are (as of this writing) 3.12
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -G Ninja -DENABLE_LTO=False -DENABLE_ASSERTIONS=True -DENABLE_X86_HOST_DEBUG=True
|
||||
|
||||
- name: Build
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the build. You can specify a specific target with "--target <NAME>"
|
||||
run: cmake --build . --config $BUILD_TYPE
|
||||
|
||||
- name: ASM Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the unit tests
|
||||
run: cmake --build . --config $BUILD_TYPE --target asm_tests
|
||||
|
||||
- name: ASM Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_ASM.log || true
|
||||
|
||||
- name: Truncate test results
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
# Cap out the log files at 20M in case something crash spins and dumps fault text
|
||||
# ASM tests get quite close to 10MB
|
||||
run: truncate --size="<20M" ${{runner.workspace}}/build/Testing/Temporary/LastTest_*.log || true
|
||||
|
||||
- name: Set runner name
|
||||
if: ${{ always() }}
|
||||
run: echo "runner_name=$(hostname)" >> $GITHUB_ENV
|
||||
|
||||
- name: Upload results
|
||||
if: ${{ always() }}
|
||||
uses: 'actions/upload-artifact@v4'
|
||||
timeout-minutes: 1
|
||||
with:
|
||||
name: Results-${{ env.runner_name }}
|
||||
path: ${{runner.workspace}}/build/Testing/Temporary/LastTest_*.log
|
||||
retention-days: 3
|
||||
|
||||
@@ -13,13 +13,14 @@ env:
|
||||
BUILD_TYPE: Release
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
FEX_ENABLEAVX: 1
|
||||
|
||||
jobs:
|
||||
instcountci_tests:
|
||||
build:
|
||||
runs-on: ${{ matrix.arch }}
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [[self-hosted, x64], [self-hosted, ARM64]]
|
||||
arch: [[self-hosted, ARM64]]
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
@@ -55,16 +56,6 @@ jobs:
|
||||
# We'll use this as our working directory for all subsequent commands
|
||||
run: cmake -E make_directory ${{runner.workspace}}/build
|
||||
|
||||
- name: Set vixl_sim x86
|
||||
if: matrix.arch[1] == 'x64'
|
||||
run: |
|
||||
echo "VIXL_SIM_ENABLED=True" >> $GITHUB_ENV
|
||||
|
||||
- name: Set vixl_sim Arm64
|
||||
if: matrix.arch[1] == 'ARM64'
|
||||
run: |
|
||||
echo "VIXL_SIM_ENABLED=False" >> $GITHUB_ENV
|
||||
|
||||
- name: Configure CMake
|
||||
# Use a bash shell so we can use the same syntax for environment variable
|
||||
# access regardless of the host operating system
|
||||
@@ -73,7 +64,7 @@ jobs:
|
||||
# Note the current convention is to use the -S and -B options here to specify source
|
||||
# and build directories, but this is only available with CMake 3.13 and higher.
|
||||
# The CMake binaries on the Github Actions machines are (as of this writing) 3.12
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -G Ninja -DENABLE_VIXL_SIMULATOR=$VIXL_SIM_ENABLED -DENABLE_VIXL_DISASSEMBLER=True -DENABLE_LTO=False -DENABLE_ASSERTIONS=True -DENABLE_X86_HOST_DEBUG=True
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -G Ninja -DENABLE_VIXL_SIMULATOR=False -DENABLE_VIXL_DISASSEMBLER=True -DENABLE_LTO=False -DENABLE_ASSERTIONS=True
|
||||
|
||||
- name: Build
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
@@ -95,32 +86,13 @@ jobs:
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_InstCountCI.log || true
|
||||
|
||||
- name: Update local repo instcount
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: cmake --build . --config $BUILD_TYPE --target instcountci_update_tests
|
||||
|
||||
- name: Get instcountCI diff
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{github.workspace}}/
|
||||
run: git diff --output=${{runner.workspace}}/build/InstCountCI.diff
|
||||
|
||||
- name: Check if InstCountCI Diff exists
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{github.workspace}}/
|
||||
# Check if the file is empty
|
||||
run: sh -c "! test -s ${{runner.workspace}}/build/InstCountCI.diff"
|
||||
|
||||
- name: Truncate test results
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
# Cap out the log files at 20M in case something crash spins and dumps fault text
|
||||
# ASM tests get quite close to 10MB
|
||||
run: truncate --size="<20M" ${{runner.workspace}}/build/Testing/Temporary/LastTest_*.log || true
|
||||
run: truncate --size=<20M ${{runner.workspace}}/build/Testing/Temporary/LastTest_*.log || true
|
||||
|
||||
- name: Set runner name
|
||||
if: ${{ always() }}
|
||||
@@ -128,19 +100,10 @@ jobs:
|
||||
|
||||
- name: Upload results
|
||||
if: ${{ always() }}
|
||||
uses: 'actions/upload-artifact@v4'
|
||||
uses: 'actions/upload-artifact@v3'
|
||||
timeout-minutes: 1
|
||||
with:
|
||||
name: Results-${{ env.runner_name }}
|
||||
path: ${{runner.workspace}}/build/Testing/Temporary/LastTest_*.log
|
||||
retention-days: 3
|
||||
|
||||
- name: Upload results InstCountCI
|
||||
if: ${{ always() }}
|
||||
uses: 'actions/upload-artifact@v4'
|
||||
timeout-minutes: 1
|
||||
with:
|
||||
name: Results-${{ env.runner_name }}-instcountci
|
||||
path: ${{runner.workspace}}/build/InstCountCI.diff
|
||||
retention-days: 3
|
||||
|
||||
@@ -10,13 +10,14 @@ on:
|
||||
|
||||
env:
|
||||
BUILD_TYPE: Debug
|
||||
FEX_ENABLEAVX: 1
|
||||
|
||||
jobs:
|
||||
mingw_build:
|
||||
build:
|
||||
runs-on: ${{ matrix.arch }}
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [[self-hosted, ARM64, mingw], [self-hosted, ARM64EC, mingw, ARM64]]
|
||||
arch: [[self-hosted, x64, mingw], [self-hosted, ARM64, mingw]]
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
@@ -38,11 +39,6 @@ jobs:
|
||||
run: |
|
||||
echo "MINGW_TRIPLE=aarch64-w64-mingw32" >> $GITHUB_ENV
|
||||
|
||||
- name: Set CC Arm64EC
|
||||
if: matrix.arch[1] == 'ARM64EC'
|
||||
run: |
|
||||
echo "MINGW_TRIPLE=arm64ec-w64-mingw32" >> $GITHUB_ENV
|
||||
|
||||
- name: Set rootfs paths
|
||||
run: |
|
||||
echo "FEX_ROOTFS_MOUNT=/mnt/AutoNFS/rootfs/" >> $GITHUB_ENV
|
||||
@@ -78,7 +74,7 @@ jobs:
|
||||
# Note the current convention is to use the -S and -B options here to specify source
|
||||
# and build directories, but this is only available with CMake 3.13 and higher.
|
||||
# The CMake binaries on the Github Actions machines are (as of this writing) 3.12
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_TOOLCHAIN_FILE=$GITHUB_WORKSPACE/Data/CMake/toolchain_mingw.cmake -DMINGW_TRIPLE=$MINGW_TRIPLE -G Ninja -DENABLE_LTO=False -DENABLE_ASSERTIONS=True -DENABLE_X86_HOST_DEBUG=True -DBUILD_TESTS=False -DCMAKE_INSTALL_PREFIX=${{runner.workspace}}/build/install
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_TOOLCHAIN_FILE=$GITHUB_WORKSPACE/toolchain_mingw.cmake -DMINGW_TRIPLE=$MINGW_TRIPLE -G Ninja -DENABLE_LTO=False -DENABLE_ASSERTIONS=True -DENABLE_X86_HOST_DEBUG=True -DENABLE_INTERPRETER=False -DBUILD_TESTS=False -DENABLE_JEMALLOC=False -DENABLE_JEMALLOC_GLIBC_ALLOC=False -DCMAKE_INSTALL_PREFIX=${{runner.workspace}}/build/install
|
||||
|
||||
- name: Build
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
@@ -92,7 +88,7 @@ jobs:
|
||||
|
||||
- name: Upload results
|
||||
if: ${{ always() }}
|
||||
uses: 'actions/upload-artifact@v4'
|
||||
uses: 'actions/upload-artifact@v3'
|
||||
timeout-minutes: 1
|
||||
with:
|
||||
name: Results-${{ env.runner_name }}
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
# Inspired by LLVM's pr-code-format.yml at
|
||||
# https://github.com/llvm/llvm-project/blob/main/.github/workflows/pr-code-format.yml
|
||||
|
||||
name: "Check code formatting"
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
code_formatter:
|
||||
runs-on: [self-hosted, X64]
|
||||
if: github.repository == 'FEX-Emu/FEX'
|
||||
|
||||
steps:
|
||||
- name: Fetch FEX sources
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
- name: Checkout through merge base
|
||||
uses: rmacklin/fetch-through-merge-base@v0
|
||||
timeout-minutes: 3
|
||||
with:
|
||||
base_ref: ${{ github.event.pull_request.base.ref }}
|
||||
head_ref: ${{ github.event.pull_request.head.sha }}
|
||||
deepen_length: 500
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: step-security/changed-files@3dbe17c78367e7d60f00d78ae6781a35be47b4a1 # v45.0.1
|
||||
with:
|
||||
separator: ","
|
||||
skip_initial_fetch: true
|
||||
|
||||
- name: "Listed files"
|
||||
env:
|
||||
CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
|
||||
run: |
|
||||
echo "Formatting files:"
|
||||
echo "$CHANGED_FILES"
|
||||
|
||||
- name: Check git-clang-format-19 exists
|
||||
run: which git-clang-format-19
|
||||
|
||||
- name: Setup Python env
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.11'
|
||||
cache: 'pip'
|
||||
cache-dependency-path: './External/code-format-helper/requirements_formatting.txt'
|
||||
|
||||
- name: Install python dependencies
|
||||
run: pip install -r ./External/code-format-helper/requirements_formatting.txt
|
||||
|
||||
- name: Run code formatter
|
||||
env:
|
||||
CLANG_FORMAT_PATH: 'git-clang-format-19'
|
||||
GITHUB_PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
START_REV: ${{ github.event.pull_request.base.sha }}
|
||||
END_REV: ${{ github.event.pull_request.head.sha }}
|
||||
CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
|
||||
# Using --diff_from_common_commit option available in clang-format-19
|
||||
run: |
|
||||
python ./External/code-format-helper/code-format-helper.py \
|
||||
--repo "FEX-emu/FEX" \
|
||||
--issue-number $GITHUB_PR_NUMBER \
|
||||
--start-rev $START_REV \
|
||||
--end-rev $END_REV \
|
||||
--changed-files "$CHANGED_FILES"
|
||||
@@ -13,9 +13,10 @@ env:
|
||||
BUILD_TYPE: Release
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
FEX_ENABLEAVX: 1
|
||||
|
||||
jobs:
|
||||
vixl_simulator:
|
||||
build:
|
||||
runs-on: ${{ matrix.arch }}
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -72,22 +73,23 @@ jobs:
|
||||
# Execute the build. You can specify a specific target with "--target <NAME>"
|
||||
run: cmake --build . --config $BUILD_TYPE
|
||||
|
||||
- name: ASM Tests - SVE256
|
||||
- name: ASM Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the unit tests
|
||||
run: cmake --build . --config $BUILD_TYPE --target asm_tests
|
||||
|
||||
- name: ASM Test SVE256 Results move
|
||||
- name: ASM Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_ASM_SVE256Bit.log || true
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_ASM.log || true
|
||||
|
||||
- name: ASM Tests - SVE128
|
||||
- name: ASM Tests 128-bit
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
env:
|
||||
FEX_HOSTFEATURES: "disableavx"
|
||||
FEX_FORCESVEWIDTH: "128"
|
||||
# Execute the unit tests
|
||||
run: cmake --build . --config $BUILD_TYPE --target asm_tests
|
||||
@@ -96,21 +98,19 @@ jobs:
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_ASM_SVE128Bit.log || true
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_ASM128bit.log || true
|
||||
|
||||
- name: ASM Tests - ASIMD
|
||||
- name: IR Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
env:
|
||||
FEX_HOSTFEATURES: "disablesve"
|
||||
# Execute the unit tests
|
||||
run: cmake --build . --config $BUILD_TYPE --target asm_tests
|
||||
run: cmake --build . --config $BUILD_TYPE --target ir_tests
|
||||
|
||||
- name: ASM Test ASIMD Results move
|
||||
- name: IR Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_ASM_ASIMD.log || true
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_IR.log || true
|
||||
|
||||
- name: Truncate test results
|
||||
if: ${{ always() }}
|
||||
@@ -118,7 +118,7 @@ jobs:
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
# Cap out the log files at 20M in case something crash spins and dumps fault text
|
||||
# ASM tests get quite close to 10MB
|
||||
run: truncate --size="<20M" ${{runner.workspace}}/build/Testing/Temporary/LastTest_*.log || true
|
||||
run: truncate --size=<20M ${{runner.workspace}}/build/Testing/Temporary/LastTest_*.log || true
|
||||
|
||||
- name: Set runner name
|
||||
if: ${{ always() }}
|
||||
@@ -126,7 +126,7 @@ jobs:
|
||||
|
||||
- name: Upload results
|
||||
if: ${{ always() }}
|
||||
uses: 'actions/upload-artifact@v4'
|
||||
uses: 'actions/upload-artifact@v3'
|
||||
timeout-minutes: 1
|
||||
with:
|
||||
name: Results-${{ env.runner_name }}
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
name: Wine DLL artifacts
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
env:
|
||||
BUILD_TYPE: Release
|
||||
|
||||
jobs:
|
||||
wine_dll_artifacts:
|
||||
runs-on: ${{ matrix.arch }}
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [[self-hosted, ARM64, mingw]]
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Add MingGW to PATH
|
||||
run: echo "$HOME/llvm-mingw/build/bin/" >> $GITHUB_PATH
|
||||
|
||||
- name : submodule checkout
|
||||
# Need to update submodules
|
||||
run: |
|
||||
git submodule sync --recursive
|
||||
git submodule update --init --depth 1
|
||||
|
||||
- name: Clean install directory
|
||||
run: |
|
||||
rm -Rf ${{runner.workspace}}/build_install
|
||||
mkdir ${{runner.workspace}}/build_install
|
||||
|
||||
- name: Clean Build Environment
|
||||
run: |
|
||||
rm -Rf ${{runner.workspace}}/build_arm64ec
|
||||
rm -Rf ${{runner.workspace}}/build_wow64
|
||||
|
||||
- name: Create Build Environment arm64ec
|
||||
run: |
|
||||
cmake -E make_directory ${{runner.workspace}}/build_arm64ec
|
||||
cmake -E make_directory ${{runner.workspace}}/build_wow64
|
||||
|
||||
- name: Configure CMake arm64ec
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build_arm64ec
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_TOOLCHAIN_FILE=$GITHUB_WORKSPACE/Data/CMake/toolchain_mingw.cmake -DMINGW_TRIPLE=arm64ec-w64-mingw32 -DCMAKE_INSTALL_LIBDIR=/usr/lib/wine/aarch64-windows -G Ninja -DENABLE_LTO=False -DENABLE_ASSERTIONS=False -DENABLE_JEMALLOC_GLIBC_ALLOC=False -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_TESTS=False -DCMAKE_INSTALL_PREFIX=/usr
|
||||
|
||||
- name: Configure CMake wow64
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build_wow64
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_TOOLCHAIN_FILE=$GITHUB_WORKSPACE/Data/CMake/toolchain_mingw.cmake -DMINGW_TRIPLE=aarch64-w64-mingw32 -DCMAKE_INSTALL_LIBDIR=/usr/lib/wine/aarch64-windows -G Ninja -DENABLE_LTO=False -DENABLE_ASSERTIONS=False -DENABLE_JEMALLOC_GLIBC_ALLOC=False -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_TESTS=False -DCMAKE_INSTALL_PREFIX=/usr
|
||||
|
||||
- name: Build arm64ec
|
||||
working-directory: ${{runner.workspace}}/build_arm64ec
|
||||
shell: bash
|
||||
run: cmake --build . --config $BUILD_TYPE
|
||||
|
||||
- name: install arm64ec
|
||||
working-directory: ${{runner.workspace}}/build_arm64ec
|
||||
shell: bash
|
||||
env:
|
||||
DESTDIR: ${{runner.workspace}}/build_install
|
||||
run: cmake --build . --config $BUILD_TYPE -t install
|
||||
|
||||
- name: Build wow64
|
||||
working-directory: ${{runner.workspace}}/build_wow64
|
||||
shell: bash
|
||||
run: cmake --build . --config $BUILD_TYPE
|
||||
|
||||
- name: install wow64
|
||||
working-directory: ${{runner.workspace}}/build_wow64
|
||||
shell: bash
|
||||
env:
|
||||
DESTDIR: ${{runner.workspace}}/build_install
|
||||
run: cmake --build . --config $BUILD_TYPE -t install
|
||||
|
||||
- name: Upload libraries
|
||||
uses: 'actions/upload-artifact@v4'
|
||||
timeout-minutes: 1
|
||||
with:
|
||||
overwrite: true
|
||||
name: wine_dll_artifacts
|
||||
path: ${{runner.workspace}}/build_install/usr/lib/wine/aarch64-windows/lib*.dll
|
||||
retention-days: 60
|
||||
compression-level: 9
|
||||
+1
-1
@@ -4,7 +4,7 @@ compile_commands.json
|
||||
vim_rc
|
||||
Config.json
|
||||
|
||||
[Bb]uild*
|
||||
[Bb]uild*/
|
||||
[Bb]in/
|
||||
out/
|
||||
.vscode/
|
||||
|
||||
+17
-7
@@ -5,16 +5,29 @@
|
||||
[submodule "External/cpp-optparse"]
|
||||
path = Source/Common/cpp-optparse
|
||||
url = https://github.com/Sonicadvance1/cpp-optparse
|
||||
[submodule "External/imgui"]
|
||||
path = External/imgui
|
||||
url = https://github.com/Sonicadvance1/imgui.git
|
||||
[submodule "External/json-maker"]
|
||||
path = External/json-maker
|
||||
url = https://github.com/Sonicadvance1/json-maker.git
|
||||
[submodule "External/tiny-json"]
|
||||
path = External/tiny-json
|
||||
url = https://github.com/Sonicadvance1/tiny-json.git
|
||||
[submodule "External/xbyak"]
|
||||
shallow = true
|
||||
path = External/xbyak
|
||||
url = https://github.com/FEX-Emu/xbyak.git
|
||||
[submodule "External/fex-posixtest-bins"]
|
||||
shallow = true
|
||||
shallow = true
|
||||
path = External/fex-posixtest-bins
|
||||
url = https://github.com/FEX-Emu/fex-posixtest-bins.git
|
||||
[submodule "External/fex-gvisor-tests-bins"]
|
||||
shallow = true
|
||||
shallow = true
|
||||
path = External/fex-gvisor-tests-bins
|
||||
url = https://github.com/FEX-Emu/fex-gvisor-tests-bins.git
|
||||
[submodule "External/fex-gcc-target-tests-bins"]
|
||||
shallow = true
|
||||
shallow = true
|
||||
path = External/fex-gcc-target-tests-bins
|
||||
url = https://github.com/FEX-Emu/fex-gcc-target-tests-bins.git
|
||||
[submodule "External/jemalloc"]
|
||||
@@ -28,7 +41,7 @@
|
||||
url = https://github.com/FEX-Emu/drm-headers.git
|
||||
[submodule "External/xxhash"]
|
||||
path = External/xxhash
|
||||
url = https://github.com/Cyan4973/xxHash.git
|
||||
url = https://github.com/FEX-Emu/xxHash.git
|
||||
[submodule "External/Catch2"]
|
||||
path = External/Catch2
|
||||
url = https://github.com/catchorg/Catch2.git
|
||||
@@ -43,6 +56,3 @@
|
||||
[submodule "External/jemalloc_glibc"]
|
||||
path = External/jemalloc_glibc
|
||||
url = https://github.com/FEX-Emu/jemalloc.git
|
||||
[submodule "External/tracy"]
|
||||
path = External/tracy
|
||||
url = https://github.com/wolfpld/tracy
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+135
-182
@@ -1,5 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(FEX C CXX ASM)
|
||||
project(FEX)
|
||||
|
||||
INCLUDE (CheckIncludeFiles)
|
||||
CHECK_INCLUDE_FILES ("gdb/jit-reader.h" HAVE_GDB_JIT_READER_H)
|
||||
@@ -7,16 +7,15 @@ CHECK_INCLUDE_FILES ("gdb/jit-reader.h" HAVE_GDB_JIT_READER_H)
|
||||
option(BUILD_TESTS "Build unit tests to ensure sanity" TRUE)
|
||||
option(BUILD_FEX_LINUX_TESTS "Build FEXLinuxTests, requires x86 compiler" FALSE)
|
||||
option(BUILD_THUNKS "Build thunks" FALSE)
|
||||
option(BUILD_FEXCONFIG "Build FEXConfig" TRUE)
|
||||
option(ENABLE_CLANG_THUNKS "Build thunks with clang" TRUE)
|
||||
option(BUILD_FEXCONFIG "Build FEXConfig, requires SDL2 and X11" TRUE)
|
||||
option(ENABLE_CLANG_THUNKS "Build thunks with clang" FALSE)
|
||||
option(ENABLE_CLANG_FORMAT "Run clang format over the source" FALSE)
|
||||
option(ENABLE_IWYU "Enables include what you use program" FALSE)
|
||||
option(ENABLE_LTO "Enable LTO with compilation" TRUE)
|
||||
option(ENABLE_XRAY "Enable building with LLVM X-Ray" FALSE)
|
||||
set(USE_LINKER "" CACHE STRING "Allow overriding the linker path directly")
|
||||
option(ENABLE_UBSAN "Enables Clang UBSAN" FALSE)
|
||||
option(ENABLE_ASAN "Enables Clang ASAN" FALSE)
|
||||
option(ENABLE_TSAN "Enables Clang TSAN" FALSE)
|
||||
option(ENABLE_COVERAGE "Enables Coverage" FALSE)
|
||||
option(ENABLE_ASSERTIONS "Enables assertions in build" FALSE)
|
||||
option(ENABLE_GDB_SYMBOLS "Enables GDBSymbols integration support" ${HAVE_GDB_JIT_READER_H})
|
||||
option(ENABLE_STRICT_WERROR "Enables stricter -Werror for CI" FALSE)
|
||||
@@ -26,43 +25,25 @@ option(ENABLE_JEMALLOC_GLIBC_ALLOC "Enables jemalloc glibc allocator" TRUE)
|
||||
option(ENABLE_OFFLINE_TELEMETRY "Enables FEX offline telemetry" TRUE)
|
||||
option(ENABLE_COMPILE_TIME_TRACE "Enables time trace compile option" FALSE)
|
||||
option(ENABLE_LIBCXX "Enables LLVM libc++" FALSE)
|
||||
option(ENABLE_INTERPRETER "Enables FEX's Interpreter" FALSE)
|
||||
option(ENABLE_CCACHE "Enables ccache for compile caching" TRUE)
|
||||
option(ENABLE_VIXL_SIMULATOR "Enable use of VIXL simulator for emulation (only useful for CI testing)" FALSE)
|
||||
option(ENABLE_TERMUX_BUILD "Forces building for Termux on a non-Termux build machine" FALSE)
|
||||
option(ENABLE_VIXL_SIMULATOR "Forces the FEX JIT to use the VIXL simulator" FALSE)
|
||||
option(ENABLE_VIXL_DISASSEMBLER "Enables debug disassembler output with VIXL" FALSE)
|
||||
option(USE_LEGACY_BINFMTMISC "Uses legacy method of setting up binfmt_misc" FALSE)
|
||||
option(COMPILE_VIXL_DISASSEMBLER "Compiles the vixl disassembler in to vixl" FALSE)
|
||||
option(ENABLE_FEXCORE_PROFILER "Enables use of the FEXCore timeline profiling capabilities" FALSE)
|
||||
set (FEXCORE_PROFILER_BACKEND "gpuvis" CACHE STRING "Set which backend to use for the FEXCore profiler (gpuvis, tracy)")
|
||||
set (FEXCORE_PROFILER_BACKEND "gpuvis" CACHE STRING "Set which backend you want to use for the FEXCore profiler")
|
||||
option(ENABLE_GLIBC_ALLOCATOR_HOOK_FAULT "Enables glibc memory allocation hooking with fault for CI testing")
|
||||
option(USE_PDB_DEBUGINFO "Builds debug info in PDB format" FALSE)
|
||||
|
||||
set (X86_32_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/Data/CMake/toolchain_x86_32.cmake" CACHE FILEPATH "Toolchain file for the (cross-)compiler targeting i686")
|
||||
set (X86_64_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/Data/CMake/toolchain_x86_64.cmake" CACHE FILEPATH "Toolchain file for the (cross-)compiler targeting x86_64")
|
||||
set (X86_DEV_ROOTFS "/" CACHE FILEPATH "Path to the sysroot used for cross-compiling for i686 and x86_64")
|
||||
set (DATA_DIRECTORY "" CACHE PATH "Global data directory (override)")
|
||||
set (HOSTLIBS_DATA_DIRECTORY "" CACHE PATH "Global data directory (override)")
|
||||
if (NOT DATA_DIRECTORY)
|
||||
set (DATA_DIRECTORY "${CMAKE_INSTALL_PREFIX}/share/fex-emu")
|
||||
endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
if (NOT HOSTLIBS_DATA_DIRECTORY)
|
||||
set(HOSTLIBS_DATA_DIRECTORY "${CMAKE_INSTALL_FULL_LIBDIR}/fex-emu")
|
||||
endif()
|
||||
set (X86_32_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/toolchain_x86_32.cmake" CACHE FILEPATH "Toolchain file for the (cross-)compiler targeting i686")
|
||||
set (X86_64_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/toolchain_x86_64.cmake" CACHE FILEPATH "Toolchain file for the (cross-)compiler targeting x86_64")
|
||||
set (DATA_DIRECTORY "${CMAKE_INSTALL_PREFIX}/share/fex-emu" CACHE PATH "global data directory")
|
||||
|
||||
string(FIND ${CMAKE_BASE_NAME} mingw CONTAINS_MINGW)
|
||||
if (NOT CONTAINS_MINGW EQUAL -1)
|
||||
message (STATUS "Mingw build")
|
||||
set (MINGW_BUILD TRUE)
|
||||
set (ENABLE_JEMALLOC TRUE)
|
||||
set (ENABLE_JEMALLOC_GLIBC_ALLOC FALSE)
|
||||
endif()
|
||||
|
||||
if (NOT MINGW_BUILD)
|
||||
message (STATUS "Clang version ${CMAKE_CXX_COMPILER_VERSION}")
|
||||
set (CLANG_MINIMUM_VERSION 13.0)
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${CLANG_MINIMUM_VERSION})
|
||||
message (FATAL_ERROR "Clang version too old for FEX. Need at least ${CLANG_MINIMUM_VERSION} but has ${CMAKE_CXX_COMPILER_VERSION}")
|
||||
endif()
|
||||
set (ENABLE_JEMALLOC FALSE)
|
||||
endif()
|
||||
|
||||
if (ENABLE_FEXCORE_PROFILER)
|
||||
@@ -71,22 +52,6 @@ if (ENABLE_FEXCORE_PROFILER)
|
||||
|
||||
if (FEXCORE_PROFILER_BACKEND STREQUAL "GPUVIS")
|
||||
add_definitions(-DFEXCORE_PROFILER_BACKEND=1)
|
||||
elseif (FEXCORE_PROFILER_BACKEND STREQUAL "TRACY")
|
||||
add_definitions(-DFEXCORE_PROFILER_BACKEND=2)
|
||||
add_definitions(-DTRACY_ENABLE=1)
|
||||
# Required so that Tracy will only start in the selected guest application
|
||||
add_definitions(-DTRACY_MANUAL_LIFETIME=1)
|
||||
add_definitions(-DTRACY_DELAYED_INIT=1)
|
||||
# This interferes with FEX's signal handling
|
||||
add_definitions(-DTRACY_NO_CRASH_HANDLER=1)
|
||||
# Tracy can gather call stack samples in regular intervals, but this
|
||||
# isn't useful for us since it would usually sample opaque JIT code
|
||||
add_definitions(-DTRACY_NO_SAMPLING=1)
|
||||
# This pulls in libbacktrace which allocators in global constructors (before FEX can set up its allocator hooks)
|
||||
add_definitions(-DTRACY_NO_CALLSTACK=1)
|
||||
if (MINGW_BUILD)
|
||||
message(FATAL_ERROR "Tracy profiler not supported")
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Unknown FEXCore profiler backend ${FEXCORE_PROFILER_BACKEND}")
|
||||
endif()
|
||||
@@ -103,7 +68,7 @@ endif()
|
||||
# uninstall target
|
||||
if(NOT TARGET uninstall)
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Data/CMake/cmake_uninstall.cmake.in"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/CMakeFiles/cmake_uninstall.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/cmake_uninstall.cmake"
|
||||
IMMEDIATE @ONLY)
|
||||
|
||||
@@ -132,6 +97,11 @@ if (ENABLE_GDB_SYMBOLS)
|
||||
endif()
|
||||
|
||||
|
||||
if (ENABLE_INTERPRETER)
|
||||
message(STATUS "Interpreter enabled")
|
||||
add_definitions(-DINTERPRETER_ENABLED=1)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Bin)
|
||||
@@ -151,8 +121,10 @@ if (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
|
||||
option(ENABLE_X86_HOST_DEBUG "Enables compiling on x86_64 host" FALSE)
|
||||
if (NOT ENABLE_X86_HOST_DEBUG)
|
||||
message(FATAL_ERROR
|
||||
" FEX-Emu doesn't support compiling for x86-64 hosts!"
|
||||
" This is /only/ a supported configuration for FEX CI and nothing else!")
|
||||
" Be warned: FEX isn't optimized for x86_64 hosts!\n"
|
||||
" Support for x86_64 hosts is only for debugging and convenience!\n"
|
||||
" Don't expect amazing performance or optimal code generation!\n"
|
||||
" Pass -DENABLE_X86_HOST_DEBUG=True to bypass this message!")
|
||||
endif()
|
||||
set(_M_X86_64 1)
|
||||
add_definitions(-D_M_X86_64=1)
|
||||
@@ -164,44 +136,6 @@ if (CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64|^arm64|^armv8\.*")
|
||||
add_definitions(-D_M_ARM_64=1)
|
||||
endif()
|
||||
|
||||
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^arm64ec")
|
||||
set(_M_ARM_64EC 1)
|
||||
add_definitions(-D_M_ARM_64EC=1)
|
||||
endif()
|
||||
|
||||
include(CheckCXXSourceCompiles)
|
||||
set(CMAKE_REQUIRED_FLAGS "-std=c++11 -Wattributes -Werror=attributes")
|
||||
check_cxx_source_compiles(
|
||||
"
|
||||
__attribute__((preserve_all))
|
||||
int Testy(int a, int b, int c, int d, int e, int f) {
|
||||
return a + b + c + d + e + f;
|
||||
}
|
||||
int main() {
|
||||
return Testy(0, 1, 2, 3, 4, 5);
|
||||
}"
|
||||
HAS_CLANG_PRESERVE_ALL)
|
||||
unset(CMAKE_REQUIRED_FLAGS)
|
||||
if (HAS_CLANG_PRESERVE_ALL)
|
||||
if (MINGW_BUILD)
|
||||
message(STATUS "Ignoring broken clang::preserve_all support")
|
||||
set(HAS_CLANG_PRESERVE_ALL FALSE)
|
||||
else()
|
||||
message(STATUS "Has clang::preserve_all")
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
if (_M_ARM_64 AND HAS_CLANG_PRESERVE_ALL)
|
||||
add_definitions("-DFEX_PRESERVE_ALL_ATTR=__attribute__((preserve_all))" "-DFEX_HAS_PRESERVE_ALL_ATTR=1")
|
||||
else()
|
||||
add_definitions("-DFEX_PRESERVE_ALL_ATTR=" "-DFEX_HAS_PRESERVE_ALL_ATTR=0")
|
||||
endif()
|
||||
|
||||
if (ENABLE_VIXL_SIMULATOR)
|
||||
# We can run the simulator on both x86-64 or AArch64 hosts
|
||||
add_definitions(-DVIXL_SIMULATOR=1 -DVIXL_INCLUDE_SIMULATOR_AARCH64=1)
|
||||
endif()
|
||||
|
||||
if (ENABLE_CCACHE)
|
||||
find_program(CCACHE_PROGRAM ccache)
|
||||
if(CCACHE_PROGRAM)
|
||||
@@ -238,17 +172,16 @@ if (NOT ENABLE_OFFLINE_TELEMETRY)
|
||||
add_definitions(-DFEX_DISABLE_TELEMETRY=1)
|
||||
endif()
|
||||
|
||||
if (ENABLE_UBSAN)
|
||||
# See https://github.com/FEX-Emu/FEX/pull/4494#issuecomment-2800608944
|
||||
# and related discussion for the use of -fno-sanitize=alignment -fno-sanitize=function
|
||||
# with UBSAN.
|
||||
# alignment: we don't follow a strict alignment policy, for example IR uses packed structs
|
||||
# that are regularly access unaligned.
|
||||
# function: syscalls cast function pointers to void (*)(unsigned long...), causing warnings
|
||||
# related to this access.
|
||||
add_definitions(-DENABLE_UBSAN=1)
|
||||
add_compile_options(-fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize=alignment -fno-sanitize=function -fno-sanitize-recover=undefined)
|
||||
link_libraries(-fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize=alignment -fno-sanitize=function -fno-sanitize-recover=undefined)
|
||||
if(DEFINED ENV{TERMUX_VERSION} OR ENABLE_TERMUX_BUILD)
|
||||
add_definitions(-DTERMUX_BUILD=1)
|
||||
set(TERMUX_BUILD 1)
|
||||
|
||||
# Termux doesn't support Jemalloc due to bad interactions between emutls, jemalloc, and scudo
|
||||
set(ENABLE_JEMALLOC FALSE)
|
||||
|
||||
# Termux builds can't rely on X11 packages
|
||||
# SDL2 isn't even compiled with GL support so our GUIs wouldn't even work
|
||||
set(BUILD_FEXCONFIG FALSE)
|
||||
endif()
|
||||
|
||||
if (ENABLE_ASAN)
|
||||
@@ -262,17 +195,13 @@ if (ENABLE_TSAN)
|
||||
link_libraries(-fno-omit-frame-pointer -fsanitize=thread)
|
||||
endif()
|
||||
|
||||
if (ENABLE_COVERAGE)
|
||||
add_compile_options(-fprofile-instr-generate -fcoverage-mapping)
|
||||
link_libraries(-fprofile-instr-generate -fcoverage-mapping)
|
||||
endif()
|
||||
|
||||
if (ENABLE_JEMALLOC_GLIBC_ALLOC)
|
||||
# The glibc jemalloc subproject which hooks the glibc allocator.
|
||||
# Required for thunks to work.
|
||||
# All host native libraries will use this allocator, while *most* other FEX internal allocations will use the other jemalloc allocator.
|
||||
add_definitions(-DENABLE_JEMALLOC_GLIBC=1)
|
||||
add_subdirectory(External/jemalloc_glibc/)
|
||||
elseif (NOT MINGW_BUILD)
|
||||
else()
|
||||
message (STATUS
|
||||
" jemalloc glibc allocator disabled!\n"
|
||||
" This is not a recommended configuration!\n"
|
||||
@@ -282,8 +211,10 @@ endif()
|
||||
|
||||
if (ENABLE_JEMALLOC)
|
||||
# The jemalloc subproject that all FEXCore fextl objects allocate through.
|
||||
add_definitions(-DENABLE_JEMALLOC=1)
|
||||
add_subdirectory(External/jemalloc/)
|
||||
elseif (NOT MINGW_BUILD)
|
||||
include_directories(External/jemalloc/pregen/include/)
|
||||
else()
|
||||
message (STATUS
|
||||
" jemalloc disabled!\n"
|
||||
" This is not a recommended configuration!\n"
|
||||
@@ -291,11 +222,6 @@ elseif (NOT MINGW_BUILD)
|
||||
" Use at your own risk!")
|
||||
endif()
|
||||
|
||||
if (USE_PDB_DEBUGINFO)
|
||||
add_compile_options(-g -gcodeview)
|
||||
add_link_options(-g -Wl,--pdb=)
|
||||
endif()
|
||||
|
||||
set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fno-omit-frame-pointer")
|
||||
set (CMAKE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_LINKER_FLAGS_RELWITHDEBINFO} -fno-omit-frame-pointer")
|
||||
|
||||
@@ -304,14 +230,13 @@ set (CMAKE_LINKER_FLAGS_RELEASE "${CMAKE_LINKER_FLAGS_RELEASE} -fomit-frame-poin
|
||||
|
||||
include_directories(External/robin-map/include/)
|
||||
|
||||
if (BUILD_TESTS OR ENABLE_VIXL_DISASSEMBLER OR ENABLE_VIXL_SIMULATOR)
|
||||
add_subdirectory(External/vixl/)
|
||||
include_directories(SYSTEM External/vixl/src/)
|
||||
if (BUILD_TESTS)
|
||||
# Enable vixl disassembler if tests are enabled.
|
||||
set(COMPILE_VIXL_DISASSEMBLER TRUE)
|
||||
endif()
|
||||
|
||||
if (ENABLE_FEXCORE_PROFILER AND FEXCORE_PROFILER_BACKEND STREQUAL "TRACY")
|
||||
add_subdirectory(External/tracy)
|
||||
endif()
|
||||
add_subdirectory(External/vixl/)
|
||||
include_directories(SYSTEM External/vixl/src/)
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
# This means we were attempted to get compiled with GCC
|
||||
@@ -321,42 +246,37 @@ endif()
|
||||
find_package(PkgConfig REQUIRED)
|
||||
find_package(Python 3.0 REQUIRED COMPONENTS Interpreter)
|
||||
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
|
||||
pkg_search_module(xxhash IMPORTED_TARGET xxhash libxxhash)
|
||||
if (TARGET PkgConfig::xxhash AND NOT CMAKE_CROSSCOMPILING)
|
||||
add_library(xxHash::xxhash ALIAS PkgConfig::xxhash)
|
||||
else()
|
||||
set(XXHASH_BUNDLED_MODE TRUE)
|
||||
set(XXHASH_BUILD_XXHSUM FALSE)
|
||||
add_subdirectory(External/xxhash/cmake_unofficial/)
|
||||
endif()
|
||||
add_subdirectory(External/xxhash/)
|
||||
include_directories(External/xxhash/)
|
||||
|
||||
add_definitions(-Wno-trigraphs)
|
||||
add_definitions(-DGLOBAL_DATA_DIRECTORY="${DATA_DIRECTORY}/")
|
||||
|
||||
if (BUILD_TESTS)
|
||||
find_package(Catch2 3 QUIET)
|
||||
if (NOT Catch2_FOUND)
|
||||
add_subdirectory(External/Catch2/)
|
||||
|
||||
# Pull in catch_discover_tests definition
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/External/Catch2/contrib/")
|
||||
endif()
|
||||
option(CATCH_BUILD_STATIC_LIBRARY "" ON)
|
||||
set(CATCH_BUILD_STATIC_LIBRARY ON)
|
||||
add_subdirectory(External/Catch2/)
|
||||
|
||||
# Pull in catch_discover_tests definition
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/External/Catch2/contrib/")
|
||||
include(Catch)
|
||||
endif()
|
||||
|
||||
find_package(fmt QUIET)
|
||||
if (NOT fmt_FOUND)
|
||||
# Disable fmt install
|
||||
set(FMT_INSTALL OFF)
|
||||
add_subdirectory(External/fmt/)
|
||||
endif()
|
||||
# Disable fmt install
|
||||
set(FMT_INSTALL OFF)
|
||||
add_subdirectory(External/fmt/)
|
||||
|
||||
add_subdirectory(External/imgui/)
|
||||
include_directories(External/imgui/)
|
||||
|
||||
add_subdirectory(External/json-maker/)
|
||||
include_directories(External/json-maker/)
|
||||
|
||||
add_subdirectory(External/tiny-json/)
|
||||
include_directories(External/tiny-json/)
|
||||
|
||||
include_directories(External/xbyak/)
|
||||
|
||||
include_directories(Source/)
|
||||
include_directories("${CMAKE_BINARY_DIR}/Source/")
|
||||
|
||||
@@ -387,11 +307,10 @@ if(ENABLE_WERROR OR ENABLE_STRICT_WERROR)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(FEX_TUNE_COMPILE_FLAGS)
|
||||
if (NOT TUNE_ARCH STREQUAL "generic")
|
||||
check_cxx_compiler_flag("-march=${TUNE_ARCH}" COMPILER_SUPPORTS_ARCH_TYPE)
|
||||
if(COMPILER_SUPPORTS_ARCH_TYPE)
|
||||
list(APPEND FEX_TUNE_COMPILE_FLAGS "-march=${TUNE_ARCH}")
|
||||
add_compile_options("-march=${TUNE_ARCH}")
|
||||
else()
|
||||
message(FATAL_ERROR "Trying to compile arch type '${TUNE_ARCH}' but the compiler doesn't support this")
|
||||
endif()
|
||||
@@ -404,36 +323,33 @@ if (TUNE_CPU STREQUAL "native")
|
||||
# Clang can not currently check for native Apple M1 type in hypervisor. Currently disabled
|
||||
check_cxx_compiler_flag("-mcpu=native" COMPILER_SUPPORTS_CPU_TYPE)
|
||||
if(COMPILER_SUPPORTS_CPU_TYPE)
|
||||
list(APPEND FEX_TUNE_COMPILE_FLAGS "-mcpu=native")
|
||||
add_compile_options("-mcpu=native")
|
||||
endif()
|
||||
else()
|
||||
# Due to an oversight in llvm, it declares any reasonably new Kryo CPU to only be ARMv8.0
|
||||
# Manually detect newer CPU revisions until clang and llvm fixes their bug
|
||||
# This script will either provide a supported CPU or 'native'
|
||||
# Additionally -march doesn't work under AArch64+Clang, so you have to use -mcpu or -mtune
|
||||
execute_process(COMMAND python3 "${PROJECT_SOURCE_DIR}/Scripts/aarch64_fit_native.py" "/proc/cpuinfo" "${CMAKE_CXX_COMPILER_VERSION}"
|
||||
OUTPUT_VARIABLE AARCH64_CPU)
|
||||
|
||||
string(STRIP ${AARCH64_CPU} AARCH64_CPU)
|
||||
|
||||
execute_process(COMMAND python3 "${PROJECT_SOURCE_DIR}/Scripts/NeedDisabledSVE.py"
|
||||
RESULT_VARIABLE NEEDS_SVE_DISABLED)
|
||||
if (NEEDS_SVE_DISABLED)
|
||||
message(STATUS "Platform has bugged SVE. Disabling")
|
||||
set(AARCH64_CPU "cortex-a78")
|
||||
endif()
|
||||
|
||||
check_cxx_compiler_flag("-mcpu=${AARCH64_CPU}" COMPILER_SUPPORTS_CPU_TYPE)
|
||||
if(COMPILER_SUPPORTS_CPU_TYPE)
|
||||
list(APPEND FEX_TUNE_COMPILE_FLAGS "-mcpu=${AARCH64_CPU}")
|
||||
add_compile_options("-mcpu=${AARCH64_CPU}")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
check_cxx_compiler_flag("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE)
|
||||
if(COMPILER_SUPPORTS_MARCH_NATIVE)
|
||||
list(APPEND FEX_TUNE_COMPILE_FLAGS "-march=native")
|
||||
add_compile_options("-march=native")
|
||||
endif()
|
||||
endif()
|
||||
elseif (NOT TUNE_CPU STREQUAL "none")
|
||||
else()
|
||||
check_cxx_compiler_flag("-mcpu=${TUNE_CPU}" COMPILER_SUPPORTS_CPU_TYPE)
|
||||
if(COMPILER_SUPPORTS_CPU_TYPE)
|
||||
list(APPEND FEX_TUNE_COMPILE_FLAGS "-mcpu=${TUNE_CPU}")
|
||||
add_compile_options("-mcpu=${TUNE_CPU}")
|
||||
else()
|
||||
message(FATAL_ERROR "Trying to compile cpu type '${TUNE_CPU}' but the compiler doesn't support this")
|
||||
endif()
|
||||
@@ -447,35 +363,74 @@ if (ENABLE_IWYU)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (ENABLE_CLANG_FORMAT)
|
||||
find_program(CLANG_TIDY_EXE "clang-tidy")
|
||||
if (NOT CLANG_TIDY_EXE)
|
||||
message(FATAL_ERROR "Couldn't find clang-tidy")
|
||||
endif()
|
||||
|
||||
set(CLANG_TIDY_FLAGS
|
||||
"-checks=*"
|
||||
"-fuchsia*"
|
||||
"-bugprone-macro-parentheses"
|
||||
"-clang-analyzer-core.*"
|
||||
"-cppcoreguidelines-pro-type-*"
|
||||
"-cppcoreguidelines-pro-bounds-array-to-pointer-decay"
|
||||
"-cppcoreguidelines-pro-bounds-pointer-arithmetic"
|
||||
"-cppcoreguidelines-avoid-c-arrays"
|
||||
"-cppcoreguidelines-avoid-magic-numbers"
|
||||
"-cppcoreguidelines-pro-bounds-constant-array-index"
|
||||
"-cppcoreguidelines-no-malloc"
|
||||
"-cppcoreguidelines-special-member-functions"
|
||||
"-cppcoreguidelines-owning-memory"
|
||||
"-cppcoreguidelines-macro-usage"
|
||||
"-cppcoreguidelines-avoid-goto"
|
||||
"-google-readability-function-size"
|
||||
"-google-readability-namespace-comments"
|
||||
"-google-readability-braces-around-statements"
|
||||
"-google-build-using-namespace"
|
||||
"-hicpp-*"
|
||||
"-llvm-namespace-comment"
|
||||
"-llvm-include-order" # Messes up with case sensitivity
|
||||
"-llvmlibc-*"
|
||||
"-misc-unused-parameters"
|
||||
"-modernize-loop-convert"
|
||||
"-modernize-use-auto"
|
||||
"-modernize-avoid-c-arrays"
|
||||
"-modernize-use-nodiscard"
|
||||
"readability-*"
|
||||
"-readability-function-size"
|
||||
"-readability-implicit-bool-conversion"
|
||||
"-readability-braces-around-statements"
|
||||
"-readability-else-after-return"
|
||||
"-readability-magic-numbers"
|
||||
"-readability-named-parameter"
|
||||
"-readability-uppercase-literal-suffix"
|
||||
"-cert-err34-c"
|
||||
"-cert-err58-cpp"
|
||||
"-bugprone-exception-escape"
|
||||
)
|
||||
string(REPLACE ";" "," CLANG_TIDY_FLAGS "${CLANG_TIDY_FLAGS}")
|
||||
set(CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY_EXE} "${CLANG_TIDY_FLAGS}")
|
||||
endif()
|
||||
|
||||
add_compile_options(-Wall)
|
||||
|
||||
include(CTest)
|
||||
if (BUILD_TESTS)
|
||||
message(STATUS "Unit tests are enabled")
|
||||
if (NOT BUILD_TESTING)
|
||||
# CMake checks this variable before generating CTestTestfile.cmake
|
||||
message(SEND_ERROR "Unit tests require BUILD_TESTING to be enabled")
|
||||
endif()
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/Config.h.in
|
||||
${CMAKE_BINARY_DIR}/generated/ConfigDefines.h)
|
||||
|
||||
set (TEST_JOB_COUNT "" CACHE STRING "Override number of parallel jobs to use while running tests")
|
||||
if (TEST_JOB_COUNT)
|
||||
message(STATUS "Running tests with ${TEST_JOB_COUNT} jobs")
|
||||
elseif(CMAKE_VERSION VERSION_LESS "3.29")
|
||||
execute_process(COMMAND "nproc" OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE TEST_JOB_COUNT)
|
||||
endif()
|
||||
set(TEST_JOB_FLAG "-j${TEST_JOB_COUNT}")
|
||||
if (BUILD_TESTS)
|
||||
include(CTest)
|
||||
enable_testing()
|
||||
message(STATUS "Unit tests are enabled")
|
||||
endif()
|
||||
|
||||
add_subdirectory(External/SoftFloat-3e/)
|
||||
add_subdirectory(External/cephes/)
|
||||
add_subdirectory(FEXHeaderUtils/)
|
||||
add_subdirectory(CodeEmitter/)
|
||||
add_subdirectory(FEXCore/)
|
||||
|
||||
if (_M_ARM_64 AND NOT MINGW_BUILD)
|
||||
# Binfmt_misc files must be installed prior to Source/ installs
|
||||
add_subdirectory(Data/binfmts/)
|
||||
endif()
|
||||
# Binfmt_misc files must be installed prior to Source/ installs
|
||||
add_subdirectory(Data/binfmts/)
|
||||
|
||||
add_subdirectory(Source/)
|
||||
add_subdirectory(Data/AppConfig/)
|
||||
@@ -512,13 +467,12 @@ if (BUILD_THUNKS)
|
||||
CMAKE_ARGS
|
||||
"-DBITNESS=64"
|
||||
"-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
|
||||
"-DBUILD_FEX_LINUX_TESTS=${BUILD_FEX_LINUX_TESTS}"
|
||||
"-DENABLE_CLANG_THUNKS=${ENABLE_CLANG_THUNKS}"
|
||||
"-DCMAKE_TOOLCHAIN_FILE:FILEPATH=${X86_64_TOOLCHAIN_FILE}"
|
||||
"-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}"
|
||||
"-DSTRUCT_VERIFIER=${CMAKE_SOURCE_DIR}/Scripts/StructPackVerifier.py"
|
||||
"-DFEX_PROJECT_SOURCE_DIR=${FEX_PROJECT_SOURCE_DIR}"
|
||||
"-DGENERATOR_EXE=$<TARGET_FILE:thunkgen>"
|
||||
"-DX86_DEV_ROOTFS=${X86_DEV_ROOTFS}"
|
||||
INSTALL_COMMAND ""
|
||||
BUILD_ALWAYS ON
|
||||
DEPENDS thunkgen
|
||||
@@ -531,13 +485,12 @@ if (BUILD_THUNKS)
|
||||
CMAKE_ARGS
|
||||
"-DBITNESS=32"
|
||||
"-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
|
||||
"-DBUILD_FEX_LINUX_TESTS=${BUILD_FEX_LINUX_TESTS}"
|
||||
"-DENABLE_CLANG_THUNKS=${ENABLE_CLANG_THUNKS}"
|
||||
"-DCMAKE_TOOLCHAIN_FILE:FILEPATH=${X86_32_TOOLCHAIN_FILE}"
|
||||
"-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}"
|
||||
"-DSTRUCT_VERIFIER=${CMAKE_SOURCE_DIR}/Scripts/StructPackVerifier.py"
|
||||
"-DFEX_PROJECT_SOURCE_DIR=${FEX_PROJECT_SOURCE_DIR}"
|
||||
"-DGENERATOR_EXE=$<TARGET_FILE:thunkgen>"
|
||||
"-DX86_DEV_ROOTFS=${X86_DEV_ROOTFS}"
|
||||
INSTALL_COMMAND ""
|
||||
BUILD_ALWAYS ON
|
||||
DEPENDS thunkgen
|
||||
@@ -631,12 +584,12 @@ set (CPACK_PACKAGE_CONTACT "FEX-Emu Maintainers <team@fex-emu.com>")
|
||||
set (CPACK_PACKAGE_VERSION_MAJOR "${FEX_VERSION_MAJOR}")
|
||||
set (CPACK_PACKAGE_VERSION_MINOR "${FEX_VERSION_MINOR}")
|
||||
set (CPACK_PACKAGE_VERSION_PATCH "${FEX_VERSION_PATCH}")
|
||||
set (CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/Data/CMake/CPack/Description.txt")
|
||||
set (CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/CPack/Description.txt")
|
||||
|
||||
# Debian defines
|
||||
set (CPACK_DEBIAN_PACKAGE_DEPENDS "libc6, libstdc++6, libepoxy0, libsdl2-2.0-0, libegl1, libx11-6, squashfuse")
|
||||
set (CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Data/CMake/CPack/postinst;${CMAKE_CURRENT_SOURCE_DIR}/Data/CMake/CPack/prerm;${CMAKE_CURRENT_SOURCE_DIR}/Data/CMake/CPack/triggers")
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/CPack/postinst;${CMAKE_CURRENT_SOURCE_DIR}/CPack/prerm;${CMAKE_CURRENT_SOURCE_DIR}/CPack/triggers")
|
||||
if (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
|
||||
# binfmt_misc conflicts with qemu-user-static
|
||||
# We also only install binfmt_misc on aarch64 hosts
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
x86 and x86-64 Linux emulator
|
||||
|
||||
FEX is very much work in progress, so expect things to change.
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,2 +0,0 @@
|
||||
add_library(CodeEmitter INTERFACE)
|
||||
target_include_directories(CodeEmitter INTERFACE .)
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,327 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/* Branch instruction emitters.
|
||||
*
|
||||
* Most of these instructions will use `BackwardLabel`, `ForwardLabel`, or `BiDirectionLabel` to determine where a branch targets.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef INCLUDED_BY_EMITTER
|
||||
#include <CodeEmitter/Emitter.h>
|
||||
namespace ARMEmitter {
|
||||
struct EmitterOps : Emitter {
|
||||
#endif
|
||||
|
||||
public:
|
||||
// Branches, Exception Generating and System instructions
|
||||
public:
|
||||
// Conditional branch immediate
|
||||
///< Branch conditional
|
||||
void b(ARMEmitter::Condition Cond, uint32_t Imm) {
|
||||
constexpr uint32_t Op = 0b0101'010 << 25;
|
||||
Branch_Conditional(Op, 0, 0, Cond, Imm);
|
||||
}
|
||||
void b(ARMEmitter::Condition Cond, const BackwardLabel* Label) {
|
||||
int32_t Imm = static_cast<int32_t>(Label->Location - GetCursorAddress<uint8_t*>());
|
||||
LOGMAN_THROW_A_FMT(Imm >= -1048576 && Imm <= 1048575 && ((Imm & 0b11) == 0), "Unscaled offset too large");
|
||||
constexpr uint32_t Op = 0b0101'010 << 25;
|
||||
Branch_Conditional(Op, 0, 0, Cond, Imm >> 2);
|
||||
}
|
||||
void b(ARMEmitter::Condition Cond, ForwardLabel* Label) {
|
||||
AddLocationToLabel(Label, ForwardLabel::Reference {.Location = GetCursorAddress<uint8_t*>(), .Type = ForwardLabel::InstType::BC});
|
||||
constexpr uint32_t Op = 0b0101'010 << 25;
|
||||
Branch_Conditional(Op, 0, 0, Cond, 0);
|
||||
}
|
||||
|
||||
void b(ARMEmitter::Condition Cond, BiDirectionalLabel* Label) {
|
||||
if (Label->Backward.Location) {
|
||||
b(Cond, &Label->Backward);
|
||||
} else {
|
||||
b(Cond, &Label->Forward);
|
||||
}
|
||||
}
|
||||
|
||||
///< Branch consistent conditional
|
||||
void bc(ARMEmitter::Condition Cond, uint32_t Imm) {
|
||||
constexpr uint32_t Op = 0b0101'010 << 25;
|
||||
Branch_Conditional(Op, 0, 1, Cond, Imm);
|
||||
}
|
||||
void bc(ARMEmitter::Condition Cond, const BackwardLabel* Label) {
|
||||
int32_t Imm = static_cast<int32_t>(Label->Location - GetCursorAddress<uint8_t*>());
|
||||
LOGMAN_THROW_A_FMT(Imm >= -1048576 && Imm <= 1048575 && ((Imm & 0b11) == 0), "Unscaled offset too large");
|
||||
constexpr uint32_t Op = 0b0101'010 << 25;
|
||||
Branch_Conditional(Op, 0, 1, Cond, Imm >> 2);
|
||||
}
|
||||
|
||||
void bc(ARMEmitter::Condition Cond, ForwardLabel* Label) {
|
||||
AddLocationToLabel(Label, ForwardLabel::Reference {.Location = GetCursorAddress<uint8_t*>(), .Type = ForwardLabel::InstType::BC});
|
||||
constexpr uint32_t Op = 0b0101'010 << 25;
|
||||
Branch_Conditional(Op, 0, 1, Cond, 0);
|
||||
}
|
||||
|
||||
void bc(ARMEmitter::Condition Cond, BiDirectionalLabel* Label) {
|
||||
if (Label->Backward.Location) {
|
||||
bc(Cond, &Label->Backward);
|
||||
} else {
|
||||
bc(Cond, &Label->Forward);
|
||||
}
|
||||
}
|
||||
|
||||
// Unconditional branch register
|
||||
void br(ARMEmitter::Register rn) {
|
||||
constexpr uint32_t Op = 0b1101011 << 25 | 0b0'000 << 21 | // opc
|
||||
0b1'1111 << 16 | // op2
|
||||
0b0000'00 << 10 | // op3
|
||||
0b0'0000; // op4
|
||||
|
||||
UnconditionalBranch(Op, rn);
|
||||
}
|
||||
void blr(ARMEmitter::Register rn) {
|
||||
constexpr uint32_t Op = 0b1101011 << 25 | 0b0'001 << 21 | // opc
|
||||
0b1'1111 << 16 | // op2
|
||||
0b0000'00 << 10 | // op3
|
||||
0b0'0000; // op4
|
||||
|
||||
UnconditionalBranch(Op, rn);
|
||||
}
|
||||
void ret(ARMEmitter::Register rn = ARMEmitter::Reg::r30) {
|
||||
constexpr uint32_t Op = 0b1101011 << 25 | 0b0'010 << 21 | // opc
|
||||
0b1'1111 << 16 | // op2
|
||||
0b0000'00 << 10 | // op3
|
||||
0b0'0000; // op4
|
||||
|
||||
UnconditionalBranch(Op, rn);
|
||||
}
|
||||
|
||||
// Unconditional branch immediate
|
||||
void b(uint32_t Imm) {
|
||||
constexpr uint32_t Op = 0b0001'01 << 26;
|
||||
|
||||
UnconditionalBranch(Op, Imm);
|
||||
}
|
||||
void b(const BackwardLabel* Label) {
|
||||
int32_t Imm = static_cast<int32_t>(Label->Location - GetCursorAddress<uint8_t*>());
|
||||
LOGMAN_THROW_A_FMT(Imm >= -134217728 && Imm <= 134217724 && ((Imm & 0b11) == 0), "Unscaled offset too large");
|
||||
constexpr uint32_t Op = 0b0001'01 << 26;
|
||||
|
||||
UnconditionalBranch(Op, Imm >> 2);
|
||||
}
|
||||
void b(ForwardLabel* Label) {
|
||||
AddLocationToLabel(Label, ForwardLabel::Reference {.Location = GetCursorAddress<uint8_t*>(), .Type = ForwardLabel::InstType::B});
|
||||
constexpr uint32_t Op = 0b0001'01 << 26;
|
||||
|
||||
UnconditionalBranch(Op, 0);
|
||||
}
|
||||
|
||||
void b(BiDirectionalLabel* Label) {
|
||||
if (Label->Backward.Location) {
|
||||
b(&Label->Backward);
|
||||
} else {
|
||||
b(&Label->Forward);
|
||||
}
|
||||
}
|
||||
|
||||
void bl(uint32_t Imm) {
|
||||
constexpr uint32_t Op = 0b1001'01 << 26;
|
||||
|
||||
UnconditionalBranch(Op, Imm);
|
||||
}
|
||||
|
||||
void bl(const BackwardLabel* Label) {
|
||||
int32_t Imm = static_cast<int32_t>(Label->Location - GetCursorAddress<uint8_t*>());
|
||||
LOGMAN_THROW_A_FMT(Imm >= -134217728 && Imm <= 134217724 && ((Imm & 0b11) == 0), "Unscaled offset too large");
|
||||
constexpr uint32_t Op = 0b1001'01 << 26;
|
||||
|
||||
UnconditionalBranch(Op, Imm >> 2);
|
||||
}
|
||||
void bl(ForwardLabel* Label) {
|
||||
AddLocationToLabel(Label, ForwardLabel::Reference {.Location = GetCursorAddress<uint8_t*>(), .Type = ForwardLabel::InstType::B});
|
||||
constexpr uint32_t Op = 0b1001'01 << 26;
|
||||
|
||||
UnconditionalBranch(Op, 0);
|
||||
}
|
||||
|
||||
void bl(BiDirectionalLabel* Label) {
|
||||
if (Label->Backward.Location) {
|
||||
bl(&Label->Backward);
|
||||
} else {
|
||||
bl(&Label->Forward);
|
||||
}
|
||||
}
|
||||
|
||||
// Compare and branch
|
||||
void cbz(ARMEmitter::Size s, ARMEmitter::Register rt, uint32_t Imm) {
|
||||
constexpr uint32_t Op = 0b0011'0100 << 24;
|
||||
|
||||
CompareAndBranch(Op, s, rt, Imm);
|
||||
}
|
||||
|
||||
void cbz(ARMEmitter::Size s, ARMEmitter::Register rt, const BackwardLabel* Label) {
|
||||
int32_t Imm = static_cast<int32_t>(Label->Location - GetCursorAddress<uint8_t*>());
|
||||
LOGMAN_THROW_A_FMT(Imm >= -1048576 && Imm <= 1048575 && ((Imm & 0b11) == 0), "Unscaled offset too large");
|
||||
|
||||
constexpr uint32_t Op = 0b0011'0100 << 24;
|
||||
|
||||
CompareAndBranch(Op, s, rt, Imm >> 2);
|
||||
}
|
||||
|
||||
void cbz(ARMEmitter::Size s, ARMEmitter::Register rt, ForwardLabel* Label) {
|
||||
AddLocationToLabel(Label, ForwardLabel::Reference {.Location = GetCursorAddress<uint8_t*>(), .Type = ForwardLabel::InstType::BC});
|
||||
|
||||
constexpr uint32_t Op = 0b0011'0100 << 24;
|
||||
|
||||
CompareAndBranch(Op, s, rt, 0);
|
||||
}
|
||||
|
||||
void cbz(ARMEmitter::Size s, ARMEmitter::Register rt, BiDirectionalLabel* Label) {
|
||||
if (Label->Backward.Location) {
|
||||
cbz(s, rt, &Label->Backward);
|
||||
} else {
|
||||
cbz(s, rt, &Label->Forward);
|
||||
}
|
||||
}
|
||||
|
||||
void cbnz(ARMEmitter::Size s, ARMEmitter::Register rt, uint32_t Imm) {
|
||||
constexpr uint32_t Op = 0b0011'0101 << 24;
|
||||
|
||||
CompareAndBranch(Op, s, rt, Imm);
|
||||
}
|
||||
|
||||
void cbnz(ARMEmitter::Size s, ARMEmitter::Register rt, const BackwardLabel* Label) {
|
||||
int32_t Imm = static_cast<int32_t>(Label->Location - GetCursorAddress<uint8_t*>());
|
||||
LOGMAN_THROW_A_FMT(Imm >= -1048576 && Imm <= 1048575 && ((Imm & 0b11) == 0), "Unscaled offset too large");
|
||||
|
||||
constexpr uint32_t Op = 0b0011'0101 << 24;
|
||||
|
||||
CompareAndBranch(Op, s, rt, Imm >> 2);
|
||||
}
|
||||
|
||||
void cbnz(ARMEmitter::Size s, ARMEmitter::Register rt, ForwardLabel* Label) {
|
||||
AddLocationToLabel(Label, ForwardLabel::Reference {.Location = GetCursorAddress<uint8_t*>(), .Type = ForwardLabel::InstType::BC});
|
||||
|
||||
constexpr uint32_t Op = 0b0011'0101 << 24;
|
||||
|
||||
CompareAndBranch(Op, s, rt, 0);
|
||||
}
|
||||
|
||||
void cbnz(ARMEmitter::Size s, ARMEmitter::Register rt, BiDirectionalLabel* Label) {
|
||||
if (Label->Backward.Location) {
|
||||
cbnz(s, rt, &Label->Backward);
|
||||
} else {
|
||||
cbnz(s, rt, &Label->Forward);
|
||||
}
|
||||
}
|
||||
|
||||
// Test and branch immediate
|
||||
void tbz(ARMEmitter::Register rt, uint32_t Bit, uint32_t Imm) {
|
||||
constexpr uint32_t Op = 0b0011'0110 << 24;
|
||||
|
||||
TestAndBranch(Op, rt, Bit, Imm);
|
||||
}
|
||||
void tbz(ARMEmitter::Register rt, uint32_t Bit, const BackwardLabel* Label) {
|
||||
int32_t Imm = static_cast<int32_t>(Label->Location - GetCursorAddress<uint8_t*>());
|
||||
LOGMAN_THROW_A_FMT(Imm >= -32768 && Imm <= 32764 && ((Imm & 0b11) == 0), "Unscaled offset too large");
|
||||
|
||||
constexpr uint32_t Op = 0b0011'0110 << 24;
|
||||
|
||||
TestAndBranch(Op, rt, Bit, Imm >> 2);
|
||||
}
|
||||
|
||||
void tbz(ARMEmitter::Register rt, uint32_t Bit, ForwardLabel* Label) {
|
||||
AddLocationToLabel(Label, ForwardLabel::Reference {.Location = GetCursorAddress<uint8_t*>(), .Type = ForwardLabel::InstType::TEST_BRANCH});
|
||||
|
||||
constexpr uint32_t Op = 0b0011'0110 << 24;
|
||||
|
||||
TestAndBranch(Op, rt, Bit, 0);
|
||||
}
|
||||
|
||||
void tbz(ARMEmitter::Register rt, uint32_t Bit, BiDirectionalLabel* Label) {
|
||||
if (Label->Backward.Location) {
|
||||
tbz(rt, Bit, &Label->Backward);
|
||||
} else {
|
||||
tbz(rt, Bit, &Label->Forward);
|
||||
}
|
||||
}
|
||||
|
||||
void tbnz(ARMEmitter::Register rt, uint32_t Bit, uint32_t Imm) {
|
||||
constexpr uint32_t Op = 0b0011'0111 << 24;
|
||||
|
||||
TestAndBranch(Op, rt, Bit, Imm);
|
||||
}
|
||||
void tbnz(ARMEmitter::Register rt, uint32_t Bit, const BackwardLabel* Label) {
|
||||
int32_t Imm = static_cast<int32_t>(Label->Location - GetCursorAddress<uint8_t*>());
|
||||
LOGMAN_THROW_A_FMT(Imm >= -32768 && Imm <= 32764 && ((Imm & 0b11) == 0), "Unscaled offset too large");
|
||||
|
||||
constexpr uint32_t Op = 0b0011'0111 << 24;
|
||||
|
||||
TestAndBranch(Op, rt, Bit, Imm >> 2);
|
||||
}
|
||||
|
||||
void tbnz(ARMEmitter::Register rt, uint32_t Bit, ForwardLabel* Label) {
|
||||
AddLocationToLabel(Label, ForwardLabel::Reference {.Location = GetCursorAddress<uint8_t*>(), .Type = ForwardLabel::InstType::TEST_BRANCH});
|
||||
constexpr uint32_t Op = 0b0011'0111 << 24;
|
||||
|
||||
TestAndBranch(Op, rt, Bit, 0);
|
||||
}
|
||||
|
||||
void tbnz(ARMEmitter::Register rt, uint32_t Bit, BiDirectionalLabel* Label) {
|
||||
if (Label->Backward.Location) {
|
||||
tbnz(rt, Bit, &Label->Backward);
|
||||
} else {
|
||||
tbnz(rt, Bit, &Label->Forward);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// Conditional branch immediate
|
||||
void Branch_Conditional(uint32_t Op, uint32_t Op1, uint32_t Op0, ARMEmitter::Condition Cond, uint32_t Imm) {
|
||||
uint32_t Instr = Op;
|
||||
|
||||
Instr |= Op1 << 24;
|
||||
Instr |= (Imm & 0x7'FFFF) << 5;
|
||||
Instr |= Op0 << 4;
|
||||
Instr |= FEXCore::ToUnderlying(Cond);
|
||||
|
||||
dc32(Instr);
|
||||
}
|
||||
|
||||
// Unconditional branch register
|
||||
void UnconditionalBranch(uint32_t Op, ARMEmitter::Register rn) {
|
||||
uint32_t Instr = Op;
|
||||
Instr |= Encode_rn(rn);
|
||||
dc32(Instr);
|
||||
}
|
||||
|
||||
// Unconditional branch - immediate
|
||||
void UnconditionalBranch(uint32_t Op, uint32_t Imm) {
|
||||
uint32_t Instr = Op;
|
||||
Instr |= Imm & 0x3FF'FFFF;
|
||||
dc32(Instr);
|
||||
}
|
||||
|
||||
// Compare and branch
|
||||
void CompareAndBranch(uint32_t Op, ARMEmitter::Size s, ARMEmitter::Register rt, uint32_t Imm) {
|
||||
const uint32_t SF = s == ARMEmitter::Size::i64Bit ? (1U << 31) : 0;
|
||||
|
||||
uint32_t Instr = Op;
|
||||
|
||||
Instr |= SF;
|
||||
Instr |= (Imm & 0x7'FFFF) << 5;
|
||||
Instr |= Encode_rt(rt);
|
||||
dc32(Instr);
|
||||
}
|
||||
|
||||
// Test and branch - immediate
|
||||
void TestAndBranch(uint32_t Op, ARMEmitter::Register rt, uint32_t Bit, uint32_t Imm) {
|
||||
uint32_t Instr = Op;
|
||||
|
||||
Instr |= (Bit >> 5) << 31;
|
||||
Instr |= (Bit & 0b1'1111) << 19;
|
||||
Instr |= (Imm & 0x3FFF) << 5;
|
||||
Instr |= Encode_rt(rt);
|
||||
dc32(Instr);
|
||||
}
|
||||
|
||||
#ifndef INCLUDED_BY_EMITTER
|
||||
}; // struct LoadstoreEmitterOps
|
||||
} // namespace ARMEmitter
|
||||
#endif
|
||||
@@ -1,99 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
|
||||
namespace ARMEmitter {
|
||||
class Buffer {
|
||||
public:
|
||||
Buffer() {
|
||||
SetBuffer(nullptr, 0);
|
||||
}
|
||||
|
||||
Buffer(uint8_t* Base, uint64_t BaseSize) {
|
||||
SetBuffer(Base, BaseSize);
|
||||
}
|
||||
|
||||
void SetBuffer(uint8_t* Base, uint64_t BaseSize) {
|
||||
BufferBase = Base;
|
||||
CurrentOffset = BufferBase;
|
||||
Size = BaseSize;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
requires (std::is_trivially_copyable_v<T>)
|
||||
void dcn(const T& Data) {
|
||||
std::memcpy(CurrentOffset, &Data, sizeof(Data));
|
||||
CurrentOffset += sizeof(Data);
|
||||
}
|
||||
void dc8(uint8_t Data) {
|
||||
dcn(Data);
|
||||
}
|
||||
void dc16(uint16_t Data) {
|
||||
dcn(Data);
|
||||
}
|
||||
void dc32(uint32_t Data) {
|
||||
dcn(Data);
|
||||
}
|
||||
void dc64(uint64_t Data) {
|
||||
dcn(Data);
|
||||
}
|
||||
|
||||
void EmitString(const char* String) {
|
||||
const auto StringLength = strlen(String);
|
||||
memcpy(CurrentOffset, String, StringLength);
|
||||
CurrentOffset += StringLength;
|
||||
}
|
||||
|
||||
void Align(size_t Size = 4) {
|
||||
// Align the buffer to provided size.
|
||||
auto CurrentAlignment = reinterpret_cast<uint64_t>(CurrentOffset) & (Size - 1);
|
||||
if (!CurrentAlignment) {
|
||||
return;
|
||||
}
|
||||
CurrentOffset += Size - CurrentAlignment;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T GetCursorAddress() const {
|
||||
return reinterpret_cast<T>(CurrentOffset);
|
||||
}
|
||||
|
||||
static void ClearICache(void* Begin, std::size_t Length) {
|
||||
__builtin___clear_cache(static_cast<char*>(Begin), static_cast<char*>(Begin) + Length);
|
||||
}
|
||||
|
||||
size_t GetCursorOffset() const {
|
||||
return static_cast<size_t>(CurrentOffset - BufferBase);
|
||||
}
|
||||
|
||||
uint8_t* GetBufferBase() const {
|
||||
return BufferBase;
|
||||
}
|
||||
|
||||
void CursorIncrement(size_t Size) {
|
||||
CurrentOffset += Size;
|
||||
}
|
||||
|
||||
void SetCursorOffset(size_t Offset) {
|
||||
CurrentOffset = BufferBase + Offset;
|
||||
}
|
||||
|
||||
uint64_t GetBufferSize() const {
|
||||
return Size;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
size_t GetCursorOffsetFromAddress(const T* Address) const {
|
||||
return static_cast<size_t>(reinterpret_cast<const uint8_t*>(Address) - BufferBase);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
uint8_t* BufferBase;
|
||||
uint8_t* CurrentOffset;
|
||||
uint64_t Size;
|
||||
};
|
||||
} // namespace ARMEmitter
|
||||
@@ -1,856 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include <FEXCore/Utils/CompilerDefs.h>
|
||||
#include <FEXCore/Utils/EnumUtils.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/Utils/MathUtils.h>
|
||||
#include <FEXCore/fextl/vector.h>
|
||||
|
||||
#include <FEXHeaderUtils/BitUtils.h>
|
||||
#include <CodeEmitter/Buffer.h>
|
||||
#include <CodeEmitter/Registers.h>
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
/*
|
||||
* Welcome to FEX-Emu's custom AArch64 emitter.
|
||||
* This was written specifically to avoid the performance cost of the vixl emitter.
|
||||
*
|
||||
* There are some specific design constraints in this design to target a couple features:
|
||||
* - High performance
|
||||
* - Low CPU cache performance hit
|
||||
* - Significantly reduced code footprint
|
||||
* - Low number of branches
|
||||
*
|
||||
* These requirements are mostly achieved by removing a bunch of developer conveniences
|
||||
* that vixl provides. The developer needs to take a lot of care to not shoot themselves in the foot.
|
||||
*
|
||||
* Misc design decisions:
|
||||
* - Registers are encoded as basic uint32_t enums.
|
||||
* - Converting between different registers is zero-cost.
|
||||
* - Passing around as arguments are as cheap as registers
|
||||
* - Contrast to vixl where every register requires living on the stack.
|
||||
* - Registers can get encoded in to instructions with a simple `BFM` instruction.
|
||||
*
|
||||
* - Instructions are very simply emitted, allowing direct inlining most of the time.
|
||||
* - These are simple enough that multiple back-to-back instructions get optimized to 128-bit load-store operations.
|
||||
* - Contrast to vixl where pretty much no instruction emitter gets inlined.
|
||||
*
|
||||
* - Instruction emitters are /mostly/ unsized. Most instructions take a size argument first, which gets encoded
|
||||
* directly in to the instruction.
|
||||
* - Contrast to vixl where the register arguments are how the instructions determine operating size.
|
||||
* - Size argument allows FEX to use `CSEL` to select a size at runtime, instead of branching.
|
||||
* - Some instructions are explicitly sized based on register type. Read comments in the respective `inl` files to
|
||||
* see why.
|
||||
* Some scalar/vector operations are an example of this.
|
||||
*
|
||||
* - Almost zero helper functions.
|
||||
* - Primary exception to this rule is load-store operations. These will use a helper to make
|
||||
* it easier to select the correct load-store instruction. Mostly because these are a nightmare selecting
|
||||
* the right instruction.
|
||||
*/
|
||||
namespace ARMEmitter {
|
||||
/*
|
||||
* This `Size` enum is used for most ALU operations.
|
||||
* These follow the AArch64 encoding style in most cases.
|
||||
*/
|
||||
enum class Size : uint32_t {
|
||||
i32Bit = 0,
|
||||
i64Bit,
|
||||
};
|
||||
|
||||
// This allows us to get the `Size` enum in bits.
|
||||
[[nodiscard]]
|
||||
constexpr size_t RegSizeInBits(Size size) {
|
||||
return size_t {32} << FEXCore::ToUnderlying(size);
|
||||
}
|
||||
|
||||
/* This `SubRegSize` enum is used for most ASIMD operations.
|
||||
* These follow the AArch64 encoding style in most cases.
|
||||
*/
|
||||
enum class SubRegSize : uint32_t {
|
||||
i8Bit = 0b00,
|
||||
i16Bit = 0b01,
|
||||
i32Bit = 0b10,
|
||||
i64Bit = 0b11,
|
||||
i128Bit = 0b100,
|
||||
};
|
||||
|
||||
// This allows us to get the `SubRegSize` in bits.
|
||||
[[nodiscard]]
|
||||
constexpr size_t SubRegSizeInBits(SubRegSize size) {
|
||||
return size_t {8} << FEXCore::ToUnderlying(size);
|
||||
}
|
||||
|
||||
// Many floating point operations constrain their element sizes to the
|
||||
// main three float sizes half, single, and double precision. This just
|
||||
// combines all the checks together for brevity.
|
||||
[[nodiscard]]
|
||||
constexpr bool IsStandardFloatSize(SubRegSize size) {
|
||||
return size == SubRegSize::i16Bit || size == SubRegSize::i32Bit || size == SubRegSize::i64Bit;
|
||||
}
|
||||
|
||||
/* This `ScalarRegSize` enum is used for most scalar float
|
||||
* operations.
|
||||
*
|
||||
* This is specifically duplicated from `SubRegSize` to have strongly
|
||||
* typed functions.
|
||||
*
|
||||
* `ScalarRegSize` specifically doesn't have `i128Bit` because scalar operations
|
||||
* can't operate at 128-bit.
|
||||
*/
|
||||
enum class ScalarRegSize : uint32_t {
|
||||
i8Bit = 0b00,
|
||||
i16Bit = 0b01,
|
||||
i32Bit = 0b10,
|
||||
i64Bit = 0b11,
|
||||
};
|
||||
|
||||
// This allows us to get the `ScalarRegSize` in bits.
|
||||
[[nodiscard]]
|
||||
constexpr size_t ScalarRegSizeInBits(ScalarRegSize size) {
|
||||
return size_t {8} << FEXCore::ToUnderlying(size);
|
||||
}
|
||||
|
||||
/* This `VectorRegSizePair` union allows us to have an overlapping type
|
||||
* to select a scalar operation or a vector depending on which operation
|
||||
* we pass in.
|
||||
* Useful in FEX's vector operations that behave as scalar or vector
|
||||
* depending on various factors. But since the operation will have the sa,e
|
||||
* element size, we want to choose the operation more easily
|
||||
*/
|
||||
union VectorRegSizePair {
|
||||
ScalarRegSize Scalar;
|
||||
SubRegSize Vector;
|
||||
};
|
||||
|
||||
// This allows us to create a `VectorRegSizePair` union.
|
||||
[[nodiscard]]
|
||||
constexpr VectorRegSizePair ToVectorSizePair(SubRegSize size) {
|
||||
return VectorRegSizePair {.Vector = size};
|
||||
}
|
||||
[[nodiscard]]
|
||||
constexpr VectorRegSizePair ToVectorSizePair(ScalarRegSize size) {
|
||||
return VectorRegSizePair {.Scalar = size};
|
||||
}
|
||||
|
||||
// This `ShiftType` enum is used for ALU shift-register encoded instructions.
|
||||
enum class ShiftType : uint32_t {
|
||||
LSL = 0,
|
||||
LSR,
|
||||
ASR,
|
||||
ROR,
|
||||
};
|
||||
|
||||
// This `ExtendedType` enum is used for ALU extended-register encoded instructions.
|
||||
enum class ExtendedType : uint32_t {
|
||||
UXTB = 0b000,
|
||||
UXTH = 0b001,
|
||||
UXTW = 0b010,
|
||||
UXTX = 0b011,
|
||||
SXTB = 0b100,
|
||||
SXTH = 0b101,
|
||||
SXTW = 0b110,
|
||||
SXTX = 0b111,
|
||||
LSL_32 = UXTW,
|
||||
LSL_64 = UXTX,
|
||||
};
|
||||
|
||||
// This `Condition` enum is used for various conditional instructions.
|
||||
enum class Condition : uint32_t {
|
||||
// Meaning: Int - Float
|
||||
CC_EQ = 0, // Equal - Equal
|
||||
CC_NE, // Not Eq - Not Eq or unordered
|
||||
CC_CS, // Carry set - Greater than, equal, or unordered
|
||||
CC_CC, // Carry clear - Less than
|
||||
CC_MI, // Minus/Negative - Less than
|
||||
CC_PL, // Plus, positive or zero - GT, equal, or unordered
|
||||
CC_VS, // Overflow - Unordered
|
||||
CC_VC, // No Overflow - Ordered
|
||||
CC_HI, // Unsigned higher - GT, or unordered
|
||||
CC_LS, // Unsigned lower or same - LT or EQ
|
||||
CC_GE, // Signed GT or EQ - GT or EQ
|
||||
CC_LT, // Signed LT - LT or Unordered
|
||||
CC_GT, // Signed GT - GT
|
||||
CC_LE, // Signed LT or EQ - LT, EQ, or Unordered
|
||||
CC_AL, // Always - Always
|
||||
CC_NV, // Always - Always
|
||||
|
||||
// Aliases
|
||||
CC_HS = CC_CS,
|
||||
CC_LO = CC_CC,
|
||||
};
|
||||
|
||||
/*
|
||||
* This `StatusFlags` enum is used for conditional compare encoded instructions.
|
||||
* These directly encode to the `nzcv` flags.
|
||||
*/
|
||||
enum class StatusFlags : uint32_t {
|
||||
None = 0,
|
||||
Flag_V = 0b0001,
|
||||
Flag_C = 0b0010,
|
||||
Flag_Z = 0b0100,
|
||||
Flag_N = 0b1000,
|
||||
|
||||
Flag_NZCV = Flag_N | Flag_Z | Flag_C | Flag_V,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This `IndexType` enum is used for load-store instructions.
|
||||
* Not all load-store instructions use this, so the user needs to be careful.
|
||||
*/
|
||||
enum class IndexType {
|
||||
POST,
|
||||
OFFSET,
|
||||
PRE,
|
||||
|
||||
UNPRIVILEGED,
|
||||
};
|
||||
|
||||
// Used with adr and scalar + vector load/store variants to denote
|
||||
// a modifier operation.
|
||||
enum class SVEModType : uint8_t {
|
||||
MOD_UXTW,
|
||||
MOD_SXTW,
|
||||
MOD_LSL,
|
||||
MOD_NONE,
|
||||
};
|
||||
|
||||
/* This `SVEMemOperand` class is used for the helper SVE load-store instructions.
|
||||
* Load-store instructions are quite expressive, so having a helper that handles these differences is worth it.
|
||||
*/
|
||||
class SVEMemOperand final {
|
||||
public:
|
||||
enum class Type {
|
||||
ScalarPlusScalar,
|
||||
ScalarPlusImm,
|
||||
ScalarPlusVector,
|
||||
VectorPlusImm,
|
||||
};
|
||||
|
||||
SVEMemOperand(XRegister rn, XRegister rm = XReg::zr)
|
||||
: rn {rn}
|
||||
, MemType {Type::ScalarPlusScalar}
|
||||
, MetaType {.ScalarScalarType {
|
||||
.rm = rm,
|
||||
}} {}
|
||||
SVEMemOperand(XRegister rn, int32_t imm = 0)
|
||||
: rn {rn}
|
||||
, MemType {Type::ScalarPlusImm}
|
||||
, MetaType {.ScalarImmType {
|
||||
.Imm = imm,
|
||||
}} {}
|
||||
SVEMemOperand(XRegister rn, ZRegister zm, SVEModType mod = SVEModType::MOD_NONE, uint8_t scale = 0)
|
||||
: rn {rn}
|
||||
, MemType {Type::ScalarPlusVector}
|
||||
, MetaType {.ScalarVectorType {
|
||||
.zm = zm,
|
||||
.mod = mod,
|
||||
.scale = scale,
|
||||
}} {}
|
||||
SVEMemOperand(ZRegister zn, uint32_t imm)
|
||||
: rn {Register {zn.Idx()}}
|
||||
, MemType {Type::VectorPlusImm}
|
||||
, MetaType {.VectorImmType {
|
||||
.Imm = imm,
|
||||
}} {}
|
||||
|
||||
[[nodiscard]]
|
||||
bool IsScalarPlusScalar() const {
|
||||
return MemType == Type::ScalarPlusScalar;
|
||||
}
|
||||
[[nodiscard]]
|
||||
bool IsScalarPlusImm() const {
|
||||
return MemType == Type::ScalarPlusImm;
|
||||
}
|
||||
[[nodiscard]]
|
||||
bool IsScalarPlusVector() const {
|
||||
return MemType == Type::ScalarPlusVector;
|
||||
}
|
||||
[[nodiscard]]
|
||||
bool IsVectorPlusImm() const {
|
||||
return MemType == Type::VectorPlusImm;
|
||||
}
|
||||
|
||||
union Data {
|
||||
struct {
|
||||
Register rm;
|
||||
} ScalarScalarType;
|
||||
|
||||
struct {
|
||||
int32_t Imm;
|
||||
} ScalarImmType;
|
||||
|
||||
struct {
|
||||
ZRegister zm;
|
||||
SVEModType mod;
|
||||
uint8_t scale;
|
||||
} ScalarVectorType;
|
||||
|
||||
struct {
|
||||
// rn will be a ZRegister
|
||||
uint32_t Imm;
|
||||
} VectorImmType;
|
||||
};
|
||||
|
||||
Register rn;
|
||||
Type MemType;
|
||||
Data MetaType;
|
||||
};
|
||||
|
||||
/* This `ExtendedMemOperand` class is used for the helper load-store instructions.
|
||||
* Load-store instructions are quite expressive, so having a helper that handles these differences is worth it.
|
||||
*/
|
||||
class ExtendedMemOperand final {
|
||||
public:
|
||||
ExtendedMemOperand(XRegister rn, XRegister rm = XReg::zr, ExtendedType Option = ExtendedType::LSL_64, uint32_t Shift = 0)
|
||||
: rn {rn}
|
||||
, MetaType {.ExtendedType {
|
||||
.Header = {.MemType = TYPE_EXTENDED},
|
||||
.rm = rm,
|
||||
.Option = Option,
|
||||
.Shift = Shift,
|
||||
}} {}
|
||||
ExtendedMemOperand(XRegister rn, IndexType Index = IndexType::OFFSET, int32_t Imm = 0)
|
||||
: rn {rn}
|
||||
, MetaType {.ImmType {
|
||||
.Header = {.MemType = TYPE_IMM},
|
||||
.Index = Index,
|
||||
.Imm = Imm,
|
||||
}} {}
|
||||
|
||||
Register rn;
|
||||
enum Type {
|
||||
TYPE_EXTENDED,
|
||||
TYPE_IMM,
|
||||
};
|
||||
struct HeaderStruct {
|
||||
Type MemType;
|
||||
};
|
||||
union {
|
||||
HeaderStruct Header;
|
||||
struct {
|
||||
HeaderStruct Header;
|
||||
Register rm;
|
||||
ExtendedType Option;
|
||||
uint32_t Shift;
|
||||
} ExtendedType;
|
||||
struct {
|
||||
HeaderStruct Header;
|
||||
IndexType Index;
|
||||
int32_t Imm;
|
||||
} ImmType;
|
||||
} MetaType;
|
||||
};
|
||||
|
||||
template<uint32_t op0, uint32_t op1, uint32_t CRn, uint32_t CRm, uint32_t op2>
|
||||
inline constexpr uint32_t GenSystemReg = op0 << 19 | op1 << 16 | CRn << 12 | CRm << 8 | op2 << 5;
|
||||
|
||||
// This `SystemRegister` enum is used for the mrs/msr instructions.
|
||||
enum class SystemRegister : uint32_t {
|
||||
CTR_EL0 = GenSystemReg<0b11, 0b011, 0b0000, 0b0000, 0b001>,
|
||||
DCZID_EL0 = GenSystemReg<0b11, 0b011, 0b0000, 0b0000, 0b111>,
|
||||
TPIDR_EL0 = GenSystemReg<0b11, 0b011, 0b1101, 0b0000, 0b010>,
|
||||
RNDR = GenSystemReg<0b11, 0b011, 0b0010, 0b0100, 0b000>,
|
||||
RNDRRS = GenSystemReg<0b11, 0b011, 0b0010, 0b0100, 0b001>,
|
||||
NZCV = GenSystemReg<0b11, 0b011, 0b0100, 0b0010, 0b000>,
|
||||
FPCR = GenSystemReg<0b11, 0b011, 0b0100, 0b0100, 0b000>,
|
||||
TPIDRRO_EL0 = GenSystemReg<0b11, 0b011, 0b1101, 0b0000, 0b011>,
|
||||
CNTFRQ_EL0 = GenSystemReg<0b11, 0b011, 0b1110, 0b0000, 0b000>,
|
||||
CNTVCT_EL0 = GenSystemReg<0b11, 0b011, 0b1110, 0b0000, 0b010>,
|
||||
CNTVCTSS_EL0 = GenSystemReg<0b11, 0b011, 0b1110, 0b0000, 0b110>,
|
||||
};
|
||||
|
||||
template<uint32_t op1, uint32_t CRm, uint32_t op2>
|
||||
inline constexpr uint32_t GenDCReg = op1 << 16 | CRm << 8 | op2 << 5;
|
||||
|
||||
// This `DataCacheOperation` enum is used for the dc instruction.
|
||||
enum class DataCacheOperation : uint32_t {
|
||||
IVAC = GenDCReg<0b000, 0b0110, 0b001>,
|
||||
ISW = GenDCReg<0b000, 0b0110, 0b010>,
|
||||
CSW = GenDCReg<0b000, 0b1010, 0b010>,
|
||||
CISW = GenDCReg<0b000, 0b1110, 0b010>,
|
||||
ZVA = GenDCReg<0b011, 0b0100, 0b001>,
|
||||
CVAC = GenDCReg<0b011, 0b1010, 0b001>,
|
||||
CVAU = GenDCReg<0b011, 0b1011, 0b001>,
|
||||
CIVAC = GenDCReg<0b011, 0b1110, 0b001>,
|
||||
|
||||
// MTE2
|
||||
IGVAC = GenDCReg<0b000, 0b0110, 0b011>,
|
||||
IGSW = GenDCReg<0b000, 0b0110, 0b100>,
|
||||
IGDVAC = GenDCReg<0b000, 0b0110, 0b101>,
|
||||
IGDSW = GenDCReg<0b000, 0b0110, 0b110>,
|
||||
CGSW = GenDCReg<0b000, 0b1010, 0b100>,
|
||||
CGDSW = GenDCReg<0b000, 0b1010, 0b110>,
|
||||
CIGSW = GenDCReg<0b000, 0b1110, 0b100>,
|
||||
CIGDSW = GenDCReg<0b000, 0b1110, 0b110>,
|
||||
|
||||
// MTE
|
||||
GVA = GenDCReg<0b011, 0b0100, 0b011>,
|
||||
GZVA = GenDCReg<0b011, 0b0100, 0b100>,
|
||||
CGVAC = GenDCReg<0b011, 0b1010, 0b011>,
|
||||
CGDVAC = GenDCReg<0b011, 0b1010, 0b101>,
|
||||
CGVAP = GenDCReg<0b011, 0b1100, 0b011>,
|
||||
CGDVAP = GenDCReg<0b011, 0b1100, 0b101>,
|
||||
CGVADP = GenDCReg<0b011, 0b1101, 0b011>,
|
||||
CGDVADP = GenDCReg<0b011, 0b1101, 0b101>,
|
||||
CIGVAC = GenDCReg<0b011, 0b1110, 0b011>,
|
||||
CIGDVAC = GenDCReg<0b011, 0b1110, 0b101>,
|
||||
|
||||
// DPB
|
||||
CVAP = GenDCReg<0b011, 0b1100, 0b001>,
|
||||
|
||||
// DPB2
|
||||
CVADP = GenDCReg<0b011, 0b1101, 0b001>,
|
||||
};
|
||||
|
||||
template<uint32_t CRm, uint32_t op2>
|
||||
inline constexpr uint32_t GenHintBarrierReg = CRm << 8 | op2 << 5;
|
||||
|
||||
// This `HintRegister` enum is used for the hint instruction.
|
||||
enum class HintRegister : uint32_t {
|
||||
NOP = GenHintBarrierReg<0b0000, 0b000>,
|
||||
YIELD = GenHintBarrierReg<0b0000, 0b001>,
|
||||
WFE = GenHintBarrierReg<0b0000, 0b010>,
|
||||
WFI = GenHintBarrierReg<0b0000, 0b011>,
|
||||
SEV = GenHintBarrierReg<0b0000, 0b100>,
|
||||
SEVL = GenHintBarrierReg<0b0000, 0b101>,
|
||||
DGH = GenHintBarrierReg<0b0000, 0b110>,
|
||||
CSDB = GenHintBarrierReg<0b0010, 0b100>,
|
||||
};
|
||||
|
||||
// This `BarrierRegister` enum is used for the various barrier instructions.
|
||||
enum class BarrierRegister : uint32_t {
|
||||
CLREX = GenHintBarrierReg<0b0000, 0b010>,
|
||||
TCOMMIT = GenHintBarrierReg<0b0000, 0b011>,
|
||||
DSB = GenHintBarrierReg<0b0000, 0b100>,
|
||||
DMB = GenHintBarrierReg<0b0000, 0b101>,
|
||||
ISB = GenHintBarrierReg<0b0000, 0b110>,
|
||||
SB = GenHintBarrierReg<0b0000, 0b111>,
|
||||
};
|
||||
|
||||
// This `BarrierScope` enum is used for the dsb/dmb instructions.
|
||||
enum class BarrierScope : uint32_t {
|
||||
// Outer shareable
|
||||
OSHLD = 0b0001,
|
||||
OSHST = 0b0010,
|
||||
OSH = 0b0011,
|
||||
// Non shareable
|
||||
NSHLD = 0b0101,
|
||||
NSHST = 0b0110,
|
||||
NSH = 0b0111,
|
||||
// Inner shareable
|
||||
ISHLD = 0b1001,
|
||||
ISHST = 0b1010,
|
||||
ISH = 0b1011,
|
||||
// Full System visibility
|
||||
LD = 0b1101,
|
||||
ST = 0b1110,
|
||||
SY = 0b1111,
|
||||
};
|
||||
|
||||
// This `Prefetch` enum is used for prefetch instructions.
|
||||
enum class Prefetch : uint32_t {
|
||||
// Prefetch for load
|
||||
PLDL1KEEP = 0b00000,
|
||||
PLDL1STRM = 0b00001,
|
||||
PLDL2KEEP = 0b00010,
|
||||
PLDL2STRM = 0b00011,
|
||||
PLDL3KEEP = 0b00100,
|
||||
PLDL3STRM = 0b00101,
|
||||
|
||||
// Preload instructions
|
||||
PLIL1KEEP = 0b01000,
|
||||
PLIL1STRM = 0b01001,
|
||||
PLIL2KEEP = 0b01010,
|
||||
PLIL2STRM = 0b01011,
|
||||
PLIL3KEEP = 0b01100,
|
||||
PLIL3STRM = 0b01101,
|
||||
|
||||
// Preload for store
|
||||
PSTL1KEEP = 0b10000,
|
||||
PSTL1STRM = 0b10001,
|
||||
PSTL2KEEP = 0b10010,
|
||||
PSTL2STRM = 0b10011,
|
||||
PSTL3KEEP = 0b10100,
|
||||
PSTL3STRM = 0b10101,
|
||||
};
|
||||
|
||||
// This `PredicatePattern` enun is used for some SVE instructions.
|
||||
enum class PredicatePattern : uint32_t {
|
||||
SVE_POW2 = 0b00000,
|
||||
SVE_VL1 = 0b00001,
|
||||
SVE_VL2 = 0b00010,
|
||||
SVE_VL3 = 0b00011,
|
||||
SVE_VL4 = 0b00100,
|
||||
SVE_VL5 = 0b00101,
|
||||
SVE_VL6 = 0b00110,
|
||||
SVE_VL7 = 0b00111,
|
||||
SVE_VL8 = 0b01000,
|
||||
SVE_VL16 = 0b01001,
|
||||
SVE_VL32 = 0b01010,
|
||||
SVE_VL64 = 0b01011,
|
||||
SVE_VL128 = 0b01100,
|
||||
SVE_VL256 = 0b01101,
|
||||
SVE_MUL4 = 0b11101,
|
||||
SVE_MUL3 = 0b11110,
|
||||
SVE_ALL = 0b11111,
|
||||
};
|
||||
|
||||
// Used with SVE FP immediate arithmetic instructions
|
||||
enum class SVEFAddSubImm : uint32_t {
|
||||
_0_5,
|
||||
_1_0,
|
||||
};
|
||||
enum class SVEFMulImm : uint32_t {
|
||||
_0_5,
|
||||
_2_0,
|
||||
};
|
||||
enum class SVEFMaxMinImm : uint32_t {
|
||||
_0_0,
|
||||
_1_0,
|
||||
};
|
||||
|
||||
/* This `BackwardLabel` struct is used for retaining a location for PC-Relative instructions.
|
||||
* This is specifically a label for a target that is logically `below` an instruction that uses it.
|
||||
* Which means that a branch would jump backwards.
|
||||
*/
|
||||
struct BackwardLabel {
|
||||
uint8_t* Location {};
|
||||
};
|
||||
|
||||
/* This `ForwardLabel` struct is used for retaining a location for PC-Relative instructions.
|
||||
* This is specifically a label for a target that is logically `above` an instruction that uses it.
|
||||
* Which means that a branch would jump forwards.
|
||||
*/
|
||||
struct ForwardLabel {
|
||||
enum class InstType {
|
||||
UNKNOWN,
|
||||
ADR,
|
||||
ADRP,
|
||||
B,
|
||||
BC,
|
||||
TEST_BRANCH,
|
||||
RELATIVE_LOAD,
|
||||
LONG_ADDRESS_GEN,
|
||||
};
|
||||
|
||||
struct Reference {
|
||||
uint8_t* Location {};
|
||||
InstType Type = InstType::UNKNOWN;
|
||||
};
|
||||
|
||||
// The first element is stored separately to avoid allocations for simple cases
|
||||
Reference FirstInst;
|
||||
|
||||
fextl::vector<Reference> Insts;
|
||||
};
|
||||
|
||||
/* This `BiDirectionalLabel` struct used for retaining a location for PC-Relative instructions.
|
||||
* This is specifically a label for a target that is in either direction of an instruction that uses it.
|
||||
* Which means a branch could jump backwards or forwards depending on situation.
|
||||
*/
|
||||
struct BiDirectionalLabel {
|
||||
BackwardLabel Backward;
|
||||
ForwardLabel Forward;
|
||||
};
|
||||
|
||||
static inline void AddLocationToLabel(ForwardLabel* Label, ForwardLabel::Reference&& Location) {
|
||||
if (Label->FirstInst.Location == nullptr) {
|
||||
Label->FirstInst = Location;
|
||||
} else {
|
||||
Label->Insts.push_back(Location);
|
||||
}
|
||||
}
|
||||
|
||||
// Some FCMA ASIMD instructions support a rotation argument.
|
||||
enum class Rotation : uint32_t {
|
||||
ROTATE_0 = 0b00,
|
||||
ROTATE_90 = 0b01,
|
||||
ROTATE_180 = 0b10,
|
||||
ROTATE_270 = 0b11,
|
||||
};
|
||||
|
||||
// Concept for contraining some instructions to accept only an XRegister or WRegister.
|
||||
// Particularly for operations that differ encodings depending on which one is used.
|
||||
template<typename T>
|
||||
concept IsXOrWRegister = std::is_same_v<T, XRegister> || std::is_same_v<T, WRegister>;
|
||||
|
||||
// Concept for contraining some instructions to accept only a QRegister or DRegister.
|
||||
template<typename T>
|
||||
concept IsQOrDRegister = std::is_same_v<T, QRegister> || std::is_same_v<T, DRegister>;
|
||||
|
||||
// Whether or not a given set of vector registers are sequential
|
||||
// in increasing order as far as the register file is concerned (modulo its size)
|
||||
//
|
||||
// For example, a set of registers like:
|
||||
//
|
||||
// v1, v2, v3 and
|
||||
// v31, v0, v1
|
||||
//
|
||||
// would both be considered sequential sequences, and some instructions in particular
|
||||
// limit register lists to these kind of sequences.
|
||||
//
|
||||
template<typename T, typename... Args>
|
||||
constexpr bool AreVectorsSequential(T first, const Args&... args) {
|
||||
// Ensure we always have a pair of registers to compare against.
|
||||
static_assert(sizeof...(args) >= 1, "Number of arguments must be greater than 1");
|
||||
|
||||
const auto fn = [](auto& lhs, const auto& rhs) {
|
||||
const auto result = ((lhs.Idx() + 1) % 32) == rhs.Idx();
|
||||
lhs = rhs;
|
||||
return result;
|
||||
};
|
||||
|
||||
return (fn(first, args) && ...);
|
||||
}
|
||||
|
||||
// Returns if the immediate can fit in to add/sub immediate instruction encodings.
|
||||
constexpr bool IsImmAddSub(uint64_t imm) {
|
||||
constexpr uint64_t U12Mask = 0xFFF;
|
||||
auto FitsWithin12Bits = [](uint64_t imm) {
|
||||
return (imm & ~U12Mask) == 0;
|
||||
};
|
||||
// Can fit in to the instruction encoding:
|
||||
// - if only bits [11:0] are set.
|
||||
// - if only bits [23:12] are set.
|
||||
return FitsWithin12Bits(imm) || (FitsWithin12Bits(imm >> 12) && (imm & U12Mask) == 0);
|
||||
}
|
||||
|
||||
// This is an emitter that is designed around the smallest code bloat as possible.
|
||||
// Eschewing most developer convenience in order to keep code as small as possible.
|
||||
|
||||
// Choices:
|
||||
// - Size of ops passed as an argument rather than template to let the compiler use csel instead of branching.
|
||||
// - Registers are unsized so they can be passed in a GPR and not need conversion operations
|
||||
class Emitter : public ARMEmitter::Buffer {
|
||||
public:
|
||||
Emitter() = default;
|
||||
|
||||
Emitter(uint8_t* Base, uint64_t BaseSize)
|
||||
: Buffer(Base, BaseSize) {}
|
||||
|
||||
// Bind a backward label to an address.
|
||||
// Address that is bound is the current emitter location.
|
||||
void Bind(BackwardLabel* Label) {
|
||||
LOGMAN_THROW_A_FMT(Label->Location == nullptr, "Trying to bind a label twice");
|
||||
Label->Location = GetCursorAddress<uint8_t*>();
|
||||
}
|
||||
|
||||
void Bind(const ForwardLabel::Reference* Label) {
|
||||
uint8_t* CurrentAddress = GetCursorAddress<uint8_t*>();
|
||||
// Patch up the instructions
|
||||
switch (Label->Type) {
|
||||
case ForwardLabel::InstType::ADR: {
|
||||
uint32_t* Instruction = reinterpret_cast<uint32_t*>(Label->Location);
|
||||
int64_t Imm = reinterpret_cast<int64_t>(CurrentAddress) - reinterpret_cast<int64_t>(Instruction);
|
||||
LOGMAN_THROW_A_FMT(IsADRRange(Imm), "Unscaled offset too large");
|
||||
uint32_t InstMask = 0b11 << 29 | 0b1111'1111'1111'1111'111 << 5;
|
||||
uint32_t Offset = static_cast<uint32_t>(Imm) & 0x3F'FFFF;
|
||||
uint32_t Inst = *Instruction & ~InstMask;
|
||||
Inst |= (Offset & 0b11) << 29;
|
||||
Inst |= (Offset >> 2) << 5;
|
||||
*Instruction = Inst;
|
||||
break;
|
||||
}
|
||||
case ForwardLabel::InstType::ADRP: {
|
||||
uint32_t* Instruction = reinterpret_cast<uint32_t*>(Label->Location);
|
||||
int64_t Imm = reinterpret_cast<int64_t>(CurrentAddress) - reinterpret_cast<int64_t>(Instruction);
|
||||
LOGMAN_THROW_A_FMT(IsADRPRange(Imm) && IsADRPAligned(Imm), "Unscaled offset too large");
|
||||
Imm >>= 12;
|
||||
uint32_t InstMask = 0b11 << 29 | 0b1111'1111'1111'1111'111 << 5;
|
||||
uint32_t Offset = static_cast<uint32_t>(Imm) & 0x3F'FFFF;
|
||||
uint32_t Inst = *Instruction & ~InstMask;
|
||||
Inst |= (Offset & 0b11) << 29;
|
||||
Inst |= (Offset >> 2) << 5;
|
||||
*Instruction = Inst;
|
||||
break;
|
||||
}
|
||||
|
||||
case ForwardLabel::InstType::B: {
|
||||
uint32_t* Instruction = reinterpret_cast<uint32_t*>(Label->Location);
|
||||
int64_t Imm = reinterpret_cast<int64_t>(CurrentAddress) - reinterpret_cast<int64_t>(Instruction);
|
||||
LOGMAN_THROW_A_FMT(Imm >= -134217728 && Imm <= 134217724 && ((Imm & 0b11) == 0), "Unscaled offset too large");
|
||||
Imm >>= 2;
|
||||
uint32_t InstMask = 0x3FF'FFFF;
|
||||
uint32_t Offset = static_cast<uint32_t>(Imm) & InstMask;
|
||||
uint32_t Inst = *Instruction & ~InstMask;
|
||||
Inst |= Offset;
|
||||
*Instruction = Inst;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ForwardLabel::InstType::TEST_BRANCH: {
|
||||
uint32_t* Instruction = reinterpret_cast<uint32_t*>(Label->Location);
|
||||
int64_t Imm = reinterpret_cast<int64_t>(CurrentAddress) - reinterpret_cast<int64_t>(Instruction);
|
||||
LOGMAN_THROW_A_FMT(Imm >= -32768 && Imm <= 32764 && ((Imm & 0b11) == 0), "Unscaled offset too large");
|
||||
Imm >>= 2;
|
||||
uint32_t InstMask = 0x3FFF;
|
||||
uint32_t Offset = static_cast<uint32_t>(Imm) & InstMask;
|
||||
uint32_t Inst = *Instruction & ~(InstMask << 5);
|
||||
Inst |= Offset << 5;
|
||||
*Instruction = Inst;
|
||||
|
||||
break;
|
||||
}
|
||||
case ForwardLabel::InstType::BC:
|
||||
case ForwardLabel::InstType::RELATIVE_LOAD: {
|
||||
uint32_t* Instruction = reinterpret_cast<uint32_t*>(Label->Location);
|
||||
int64_t Imm = reinterpret_cast<int64_t>(CurrentAddress) - reinterpret_cast<int64_t>(Instruction);
|
||||
LOGMAN_THROW_A_FMT(Imm >= -1048576 && Imm <= 1048575 && ((Imm & 0b11) == 0), "Unscaled offset too large");
|
||||
Imm >>= 2;
|
||||
uint32_t InstMask = 0x7'FFFF;
|
||||
uint32_t Offset = static_cast<uint32_t>(Imm) & InstMask;
|
||||
uint32_t Inst = *Instruction & ~(InstMask << 5);
|
||||
Inst |= Offset << 5;
|
||||
*Instruction = Inst;
|
||||
break;
|
||||
}
|
||||
case ForwardLabel::InstType::LONG_ADDRESS_GEN: {
|
||||
uint32_t* Instructions = reinterpret_cast<uint32_t*>(Label->Location);
|
||||
int64_t ImmInstOne = reinterpret_cast<int64_t>(CurrentAddress) - reinterpret_cast<int64_t>(&Instructions[0]);
|
||||
int64_t ImmInstTwo = reinterpret_cast<int64_t>(CurrentAddress) - reinterpret_cast<int64_t>(&Instructions[1]);
|
||||
auto OriginalOffset = GetCursorOffset();
|
||||
|
||||
auto InstOffset = GetCursorOffsetFromAddress(Instructions);
|
||||
SetCursorOffset(InstOffset);
|
||||
|
||||
// We encoded the destination register in to the first instruction space.
|
||||
// Read it back.
|
||||
ARMEmitter::Register DestReg(Instructions[0]);
|
||||
|
||||
if (IsADRRange(ImmInstTwo)) {
|
||||
// If within ADR range from the second instruction, then we can emit NOP+ADR
|
||||
nop();
|
||||
adr(DestReg, static_cast<uint32_t>(ImmInstTwo) & 0x7FFF);
|
||||
} else if (IsADRPRange(ImmInstOne)) {
|
||||
|
||||
// If within ADRP range from the first instruction, then we are /definitely/ in range for the second instruction.
|
||||
// First check if we are in non-offset range for second instruction.
|
||||
if (IsADRPAligned(reinterpret_cast<uint64_t>(CurrentAddress))) {
|
||||
// We can emit nop + adrp
|
||||
nop();
|
||||
adrp(DestReg, static_cast<uint32_t>(ImmInstTwo >> 12) & 0x7FFF);
|
||||
} else {
|
||||
// Not aligned, need adrp + add
|
||||
adrp(DestReg, static_cast<uint32_t>(ImmInstOne >> 12) & 0x7FFF);
|
||||
add(ARMEmitter::Size::i64Bit, DestReg, DestReg, ImmInstOne & 0xFFF);
|
||||
}
|
||||
} else {
|
||||
LOGMAN_MSG_A_FMT("Unscaled offset is too large");
|
||||
FEX_UNREACHABLE;
|
||||
}
|
||||
|
||||
SetCursorOffset(OriginalOffset);
|
||||
break;
|
||||
}
|
||||
default: LOGMAN_MSG_A_FMT("Unexpected inst type in label fixup");
|
||||
}
|
||||
}
|
||||
|
||||
// Bind a forward label to a location.
|
||||
// This walks all the instructions in the label's vector.
|
||||
// Then backpatching all instructions that have used the label.
|
||||
void Bind(ForwardLabel* Label) {
|
||||
if (Label->FirstInst.Location) {
|
||||
Bind(&Label->FirstInst);
|
||||
}
|
||||
for (auto& Inst : Label->Insts) {
|
||||
Bind(&Inst);
|
||||
}
|
||||
}
|
||||
|
||||
// Bind a bidirectional location to a location.
|
||||
// Binds both forwards and backwards depending on how the label was used.
|
||||
void Bind(BiDirectionalLabel* Label) {
|
||||
if (!Label->Backward.Location) {
|
||||
Bind(&Label->Backward);
|
||||
}
|
||||
Bind(&Label->Forward);
|
||||
}
|
||||
|
||||
#include <CodeEmitter/VixlUtils.inl>
|
||||
|
||||
public:
|
||||
|
||||
// This symbol is used to allow external tooling (IDEs, clang-format, ...) to process the included files individually:
|
||||
// If defined, the files will inject member functions into this class.
|
||||
// If not, the files will wrap the member functions in a class so that tooling will process them properly.
|
||||
#define INCLUDED_BY_EMITTER
|
||||
|
||||
// TODO: Implement SME when it matters.
|
||||
#include <CodeEmitter/ALUOps.inl>
|
||||
#include <CodeEmitter/BranchOps.inl>
|
||||
#include <CodeEmitter/LoadstoreOps.inl>
|
||||
#include <CodeEmitter/SystemOps.inl>
|
||||
#include <CodeEmitter/ScalarOps.inl>
|
||||
#include <CodeEmitter/ASIMDOps.inl>
|
||||
#include <CodeEmitter/SVEOps.inl>
|
||||
|
||||
#undef INCLUDED_BY_EMITTER
|
||||
|
||||
protected:
|
||||
template<typename T>
|
||||
uint32_t Encode_ra(T Reg) const {
|
||||
return Reg.Idx() << 10;
|
||||
}
|
||||
uint32_t Encode_ra(uint32_t Reg) const {
|
||||
return Reg << 10;
|
||||
}
|
||||
template<typename T>
|
||||
uint32_t Encode_rt2(T Reg) const {
|
||||
return Reg.Idx() << 10;
|
||||
}
|
||||
uint32_t Encode_rt2(uint32_t Reg) const {
|
||||
return Reg << 10;
|
||||
}
|
||||
template<typename T>
|
||||
uint32_t Encode_rm(T Reg) const {
|
||||
return Reg.Idx() << 16;
|
||||
}
|
||||
uint32_t Encode_rm(uint32_t Reg) const {
|
||||
return Reg << 16;
|
||||
}
|
||||
template<typename T>
|
||||
uint32_t Encode_rs(T Reg) const {
|
||||
return Reg.Idx() << 16;
|
||||
}
|
||||
uint32_t Encode_rs(uint32_t Reg) const {
|
||||
return Reg << 16;
|
||||
}
|
||||
template<typename T>
|
||||
uint32_t Encode_rn(T Reg) const {
|
||||
return Reg.Idx() << 5;
|
||||
}
|
||||
uint32_t Encode_rn(uint32_t Reg) const {
|
||||
return Reg << 5;
|
||||
}
|
||||
template<typename T>
|
||||
uint32_t Encode_rd(T Reg) const {
|
||||
return Reg.Idx();
|
||||
}
|
||||
uint32_t Encode_rd(uint32_t Reg) const {
|
||||
return Reg;
|
||||
}
|
||||
template<typename T>
|
||||
uint32_t Encode_rt(T Reg) const {
|
||||
return Reg.Idx();
|
||||
}
|
||||
uint32_t Encode_rt(Prefetch Reg) const {
|
||||
return FEXCore::ToUnderlying(Reg);
|
||||
}
|
||||
uint32_t Encode_rt(uint32_t Reg) const {
|
||||
return Reg;
|
||||
}
|
||||
template<typename T>
|
||||
uint32_t Encode_pd(T Reg) const {
|
||||
return FEXCore::ToUnderlying(Reg);
|
||||
}
|
||||
};
|
||||
} // namespace ARMEmitter
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,194 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/* System instruction emitters.
|
||||
*
|
||||
* This is mostly a mashup of various instruction types.
|
||||
* Nothing follows an explicit pattern since they are mostly different.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef INCLUDED_BY_EMITTER
|
||||
#include <CodeEmitter/Emitter.h>
|
||||
namespace ARMEmitter {
|
||||
struct EmitterOps : Emitter {
|
||||
#endif
|
||||
|
||||
public:
|
||||
// Reserved
|
||||
void udf(uint32_t Imm) {
|
||||
LOGMAN_THROW_A_FMT(Imm < 0x1'0000, "Immediate needs to be 16-bit");
|
||||
dc32(Imm);
|
||||
}
|
||||
|
||||
// System with result
|
||||
// TODO: SYSL
|
||||
// System Instruction
|
||||
// TODO: AT
|
||||
// TODO: CFP
|
||||
// TODO: CPP
|
||||
void dc(ARMEmitter::DataCacheOperation DCOp, ARMEmitter::Register rt) {
|
||||
constexpr uint32_t Op = 0b1101'0101'0000'1000'0111 << 12;
|
||||
SystemInstruction(Op, 0, FEXCore::ToUnderlying(DCOp), rt);
|
||||
}
|
||||
// TODO: DVP
|
||||
// TODO: IC
|
||||
// TODO: TLBI
|
||||
|
||||
// Exception generation
|
||||
void svc(uint32_t Imm) {
|
||||
ExceptionGeneration(0b000, 0b000, 0b01, Imm);
|
||||
}
|
||||
void hvc(uint32_t Imm) {
|
||||
ExceptionGeneration(0b000, 0b000, 0b10, Imm);
|
||||
}
|
||||
void smc(uint32_t Imm) {
|
||||
ExceptionGeneration(0b000, 0b000, 0b11, Imm);
|
||||
}
|
||||
void brk(uint32_t Imm) {
|
||||
ExceptionGeneration(0b001, 0b000, 0b00, Imm);
|
||||
}
|
||||
void hlt(uint32_t Imm) {
|
||||
ExceptionGeneration(0b010, 0b000, 0b00, Imm);
|
||||
}
|
||||
void tcancel(uint32_t Imm) {
|
||||
ExceptionGeneration(0b011, 0b000, 0b00, Imm);
|
||||
}
|
||||
void dcps1(uint32_t Imm) {
|
||||
ExceptionGeneration(0b101, 0b000, 0b01, Imm);
|
||||
}
|
||||
void dcps2(uint32_t Imm) {
|
||||
ExceptionGeneration(0b101, 0b000, 0b10, Imm);
|
||||
}
|
||||
void dcps3(uint32_t Imm) {
|
||||
ExceptionGeneration(0b101, 0b000, 0b11, Imm);
|
||||
}
|
||||
// System instructions with register argument
|
||||
void wfet(ARMEmitter::Register rt) {
|
||||
SystemInstructionWithReg(0b0000, 0b000, rt);
|
||||
}
|
||||
void wfit(ARMEmitter::Register rt) {
|
||||
SystemInstructionWithReg(0b0000, 0b001, rt);
|
||||
}
|
||||
|
||||
// Hints
|
||||
void nop() {
|
||||
Hint(ARMEmitter::HintRegister::NOP);
|
||||
}
|
||||
void yield() {
|
||||
Hint(ARMEmitter::HintRegister::YIELD);
|
||||
}
|
||||
void wfe() {
|
||||
Hint(ARMEmitter::HintRegister::WFE);
|
||||
}
|
||||
void wfi() {
|
||||
Hint(ARMEmitter::HintRegister::WFI);
|
||||
}
|
||||
void sev() {
|
||||
Hint(ARMEmitter::HintRegister::SEV);
|
||||
}
|
||||
void sevl() {
|
||||
Hint(ARMEmitter::HintRegister::SEVL);
|
||||
}
|
||||
void dgh() {
|
||||
Hint(ARMEmitter::HintRegister::DGH);
|
||||
}
|
||||
void csdb() {
|
||||
Hint(ARMEmitter::HintRegister::CSDB);
|
||||
}
|
||||
|
||||
// Barriers
|
||||
void clrex(uint32_t imm = 15) {
|
||||
LOGMAN_THROW_A_FMT(imm < 16, "Immediate out of range");
|
||||
Barrier(ARMEmitter::BarrierRegister::CLREX, imm);
|
||||
}
|
||||
void dsb(ARMEmitter::BarrierScope Scope) {
|
||||
Barrier(ARMEmitter::BarrierRegister::DSB, FEXCore::ToUnderlying(Scope));
|
||||
}
|
||||
void dmb(ARMEmitter::BarrierScope Scope) {
|
||||
Barrier(ARMEmitter::BarrierRegister::DMB, FEXCore::ToUnderlying(Scope));
|
||||
}
|
||||
void isb() {
|
||||
Barrier(ARMEmitter::BarrierRegister::ISB, FEXCore::ToUnderlying(ARMEmitter::BarrierScope::SY));
|
||||
}
|
||||
void sb() {
|
||||
Barrier(ARMEmitter::BarrierRegister::SB, 0);
|
||||
}
|
||||
void tcommit() {
|
||||
Barrier(ARMEmitter::BarrierRegister::TCOMMIT, 0);
|
||||
}
|
||||
|
||||
// System register move
|
||||
void msr(ARMEmitter::SystemRegister reg, ARMEmitter::Register rt) {
|
||||
constexpr uint32_t Op = 0b1101'0101'0001 << 20;
|
||||
SystemRegisterMove(Op, rt, reg);
|
||||
}
|
||||
|
||||
void mrs(ARMEmitter::Register rd, ARMEmitter::SystemRegister reg) {
|
||||
constexpr uint32_t Op = 0b1101'0101'0011 << 20;
|
||||
SystemRegisterMove(Op, rd, reg);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Exception Generation
|
||||
void ExceptionGeneration(uint32_t opc, uint32_t op2, uint32_t LL, uint32_t Imm) {
|
||||
LOGMAN_THROW_A_FMT((Imm & 0xFFFF'0000) == 0, "Imm amount too large");
|
||||
|
||||
uint32_t Instr = 0b1101'0100 << 24;
|
||||
|
||||
Instr |= opc << 21;
|
||||
Instr |= Imm << 5;
|
||||
Instr |= op2 << 2;
|
||||
Instr |= LL;
|
||||
|
||||
dc32(Instr);
|
||||
}
|
||||
|
||||
// System instructions with register argument
|
||||
void SystemInstructionWithReg(uint32_t CRm, uint32_t op2, ARMEmitter::Register rt) {
|
||||
uint32_t Instr = 0b1101'0101'0000'0011'0001 << 12;
|
||||
|
||||
Instr |= CRm << 8;
|
||||
Instr |= op2 << 5;
|
||||
Instr |= Encode_rt(rt);
|
||||
dc32(Instr);
|
||||
}
|
||||
|
||||
// Hints
|
||||
void Hint(ARMEmitter::HintRegister Reg) {
|
||||
uint32_t Instr = 0b1101'0101'0000'0011'0010'0000'0001'1111U;
|
||||
Instr |= FEXCore::ToUnderlying(Reg);
|
||||
dc32(Instr);
|
||||
}
|
||||
// Barriers
|
||||
void Barrier(ARMEmitter::BarrierRegister Reg, uint32_t CRm) {
|
||||
uint32_t Instr = 0b1101'0101'0000'0011'0011'0000'0001'1111U;
|
||||
Instr |= CRm << 8;
|
||||
Instr |= FEXCore::ToUnderlying(Reg);
|
||||
dc32(Instr);
|
||||
}
|
||||
|
||||
// System Instruction
|
||||
void SystemInstruction(uint32_t Op, uint32_t L, uint32_t SubOp, ARMEmitter::Register rt) {
|
||||
uint32_t Instr = Op;
|
||||
|
||||
Instr |= L << 21;
|
||||
Instr |= SubOp;
|
||||
Instr |= Encode_rt(rt);
|
||||
|
||||
dc32(Instr);
|
||||
}
|
||||
|
||||
// System register move
|
||||
void SystemRegisterMove(uint32_t Op, ARMEmitter::Register rt, ARMEmitter::SystemRegister reg) {
|
||||
uint32_t Instr = Op;
|
||||
|
||||
Instr |= FEXCore::ToUnderlying(reg);
|
||||
Instr |= Encode_rt(rt);
|
||||
|
||||
dc32(Instr);
|
||||
}
|
||||
|
||||
#ifndef INCLUDED_BY_EMITTER
|
||||
}; // struct LoadstoreEmitterOps
|
||||
} // namespace ARMEmitter
|
||||
#endif
|
||||
@@ -1,351 +0,0 @@
|
||||
// Collection of utilities from vixl.
|
||||
// Following is the vixl license.
|
||||
// Copyright 2015, VIXL authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither the name of ARM Limited nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// Test if a given value can be encoded in the immediate field of a logical
|
||||
// instruction.
|
||||
// If it can be encoded, the function returns true, and values pointed to by n,
|
||||
// imm_s and imm_r are updated with immediates encoded in the format required
|
||||
// by the corresponding fields in the logical instruction.
|
||||
// If it can not be encoded, the function returns false, and the values pointed
|
||||
// to by n, imm_s and imm_r are undefined.
|
||||
static bool IsImmLogical(uint64_t value, unsigned width, unsigned* n = nullptr, unsigned* imm_s = nullptr, unsigned* imm_r = nullptr) {
|
||||
[[maybe_unused]] constexpr auto kBRegSize = 8;
|
||||
[[maybe_unused]] constexpr auto kHRegSize = 16;
|
||||
[[maybe_unused]] constexpr auto kSRegSize = 32;
|
||||
[[maybe_unused]] constexpr auto kDRegSize = 64;
|
||||
|
||||
constexpr auto kWRegSize = 32;
|
||||
constexpr auto kXRegSize = 64;
|
||||
|
||||
LOGMAN_THROW_A_FMT((width == kBRegSize) || (width == kHRegSize) || (width == kSRegSize) || (width == kDRegSize), "Unexpected imm size");
|
||||
|
||||
bool negate = false;
|
||||
|
||||
// Logical immediates are encoded using parameters n, imm_s and imm_r using
|
||||
// the following table:
|
||||
//
|
||||
// N imms immr size S R
|
||||
// 1 ssssss rrrrrr 64 UInt(ssssss) UInt(rrrrrr)
|
||||
// 0 0sssss xrrrrr 32 UInt(sssss) UInt(rrrrr)
|
||||
// 0 10ssss xxrrrr 16 UInt(ssss) UInt(rrrr)
|
||||
// 0 110sss xxxrrr 8 UInt(sss) UInt(rrr)
|
||||
// 0 1110ss xxxxrr 4 UInt(ss) UInt(rr)
|
||||
// 0 11110s xxxxxr 2 UInt(s) UInt(r)
|
||||
// (s bits must not be all set)
|
||||
//
|
||||
// A pattern is constructed of size bits, where the least significant S+1 bits
|
||||
// are set. The pattern is rotated right by R, and repeated across a 32 or
|
||||
// 64-bit value, depending on destination register width.
|
||||
//
|
||||
// Put another way: the basic format of a logical immediate is a single
|
||||
// contiguous stretch of 1 bits, repeated across the whole word at intervals
|
||||
// given by a power of 2. To identify them quickly, we first locate the
|
||||
// lowest stretch of 1 bits, then the next 1 bit above that; that combination
|
||||
// is different for every logical immediate, so it gives us all the
|
||||
// information we need to identify the only logical immediate that our input
|
||||
// could be, and then we simply check if that's the value we actually have.
|
||||
//
|
||||
// (The rotation parameter does give the possibility of the stretch of 1 bits
|
||||
// going 'round the end' of the word. To deal with that, we observe that in
|
||||
// any situation where that happens the bitwise NOT of the value is also a
|
||||
// valid logical immediate. So we simply invert the input whenever its low bit
|
||||
// is set, and then we know that the rotated case can't arise.)
|
||||
|
||||
if (value & 1) {
|
||||
// If the low bit is 1, negate the value, and set a flag to remember that we
|
||||
// did (so that we can adjust the return values appropriately).
|
||||
negate = true;
|
||||
value = ~value;
|
||||
}
|
||||
|
||||
if (width <= kWRegSize) {
|
||||
// To handle 8/16/32-bit logical immediates, the very easiest thing is to repeat
|
||||
// the input value to fill a 64-bit word. The correct encoding of that as a
|
||||
// logical immediate will also be the correct encoding of the value.
|
||||
|
||||
// Avoid making the assumption that the most-significant 56/48/32 bits are zero by
|
||||
// shifting the value left and duplicating it.
|
||||
for (unsigned bits = width; bits <= kWRegSize; bits *= 2) {
|
||||
value <<= bits;
|
||||
uint64_t mask = (UINT64_C(1) << bits) - 1;
|
||||
value |= ((value >> bits) & mask);
|
||||
}
|
||||
}
|
||||
|
||||
// The basic analysis idea: imagine our input word looks like this.
|
||||
//
|
||||
// 0011111000111110001111100011111000111110001111100011111000111110
|
||||
// c b a
|
||||
// |<--d-->|
|
||||
//
|
||||
// We find the lowest set bit (as an actual power-of-2 value, not its index)
|
||||
// and call it a. Then we add a to our original number, which wipes out the
|
||||
// bottommost stretch of set bits and replaces it with a 1 carried into the
|
||||
// next zero bit. Then we look for the new lowest set bit, which is in
|
||||
// position b, and subtract it, so now our number is just like the original
|
||||
// but with the lowest stretch of set bits completely gone. Now we find the
|
||||
// lowest set bit again, which is position c in the diagram above. Then we'll
|
||||
// measure the distance d between bit positions a and c (using CLZ), and that
|
||||
// tells us that the only valid logical immediate that could possibly be equal
|
||||
// to this number is the one in which a stretch of bits running from a to just
|
||||
// below b is replicated every d bits.
|
||||
uint64_t a = LowestSetBit(value);
|
||||
uint64_t value_plus_a = value + a;
|
||||
uint64_t b = LowestSetBit(value_plus_a);
|
||||
uint64_t value_plus_a_minus_b = value_plus_a - b;
|
||||
uint64_t c = LowestSetBit(value_plus_a_minus_b);
|
||||
|
||||
int d, clz_a, out_n;
|
||||
uint64_t mask;
|
||||
|
||||
if (c != 0) {
|
||||
// The general case, in which there is more than one stretch of set bits.
|
||||
// Compute the repeat distance d, and set up a bitmask covering the basic
|
||||
// unit of repetition (i.e. a word with the bottom d bits set). Also, in all
|
||||
// of these cases the N bit of the output will be zero.
|
||||
clz_a = CountLeadingZeros(a, kXRegSize);
|
||||
int clz_c = CountLeadingZeros(c, kXRegSize);
|
||||
d = clz_a - clz_c;
|
||||
mask = ((UINT64_C(1) << d) - 1);
|
||||
out_n = 0;
|
||||
} else {
|
||||
// Handle degenerate cases.
|
||||
//
|
||||
// If any of those 'find lowest set bit' operations didn't find a set bit at
|
||||
// all, then the word will have been zero thereafter, so in particular the
|
||||
// last lowest_set_bit operation will have returned zero. So we can test for
|
||||
// all the special case conditions in one go by seeing if c is zero.
|
||||
if (a == 0) {
|
||||
// The input was zero (or all 1 bits, which will come to here too after we
|
||||
// inverted it at the start of the function), for which we just return
|
||||
// false.
|
||||
return false;
|
||||
} else {
|
||||
// Otherwise, if c was zero but a was not, then there's just one stretch
|
||||
// of set bits in our word, meaning that we have the trivial case of
|
||||
// d == 64 and only one 'repetition'. Set up all the same variables as in
|
||||
// the general case above, and set the N bit in the output.
|
||||
clz_a = CountLeadingZeros(a, kXRegSize);
|
||||
d = 64;
|
||||
mask = ~UINT64_C(0);
|
||||
out_n = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// If the repeat period d is not a power of two, it can't be encoded.
|
||||
if (!IsPowerOf2(d)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (((b - a) & ~mask) != 0) {
|
||||
// If the bit stretch (b - a) does not fit within the mask derived from the
|
||||
// repeat period, then fail.
|
||||
return false;
|
||||
}
|
||||
|
||||
// The only possible option is b - a repeated every d bits. Now we're going to
|
||||
// actually construct the valid logical immediate derived from that
|
||||
// specification, and see if it equals our original input.
|
||||
//
|
||||
// To repeat a value every d bits, we multiply it by a number of the form
|
||||
// (1 + 2^d + 2^(2d) + ...), i.e. 0x0001000100010001 or similar. These can
|
||||
// be derived using a table lookup on CLZ(d).
|
||||
static const uint64_t multipliers[] = {
|
||||
0x0000000000000001UL, 0x0000000100000001UL, 0x0001000100010001UL, 0x0101010101010101UL, 0x1111111111111111UL, 0x5555555555555555UL,
|
||||
};
|
||||
uint64_t multiplier = multipliers[CountLeadingZeros(d, kXRegSize) - 57];
|
||||
uint64_t candidate = (b - a) * multiplier;
|
||||
|
||||
if (value != candidate) {
|
||||
// The candidate pattern doesn't match our input value, so fail.
|
||||
return false;
|
||||
}
|
||||
|
||||
// We have a match! This is a valid logical immediate, so now we have to
|
||||
// construct the bits and pieces of the instruction encoding that generates
|
||||
// it.
|
||||
|
||||
// Count the set bits in our basic stretch. The special case of clz(0) == -1
|
||||
// makes the answer come out right for stretches that reach the very top of
|
||||
// the word (e.g. numbers like 0xffffc00000000000).
|
||||
int clz_b = (b == 0) ? -1 : CountLeadingZeros(b, kXRegSize);
|
||||
int s = clz_a - clz_b;
|
||||
|
||||
// Decide how many bits to rotate right by, to put the low bit of that basic
|
||||
// stretch in position a.
|
||||
int r;
|
||||
if (negate) {
|
||||
// If we inverted the input right at the start of this function, here's
|
||||
// where we compensate: the number of set bits becomes the number of clear
|
||||
// bits, and the rotation count is based on position b rather than position
|
||||
// a (since b is the location of the 'lowest' 1 bit after inversion).
|
||||
s = d - s;
|
||||
r = (clz_b + 1) & (d - 1);
|
||||
} else {
|
||||
r = (clz_a + 1) & (d - 1);
|
||||
}
|
||||
|
||||
// Now we're done, except for having to encode the S output in such a way that
|
||||
// it gives both the number of set bits and the length of the repeated
|
||||
// segment. The s field is encoded like this:
|
||||
//
|
||||
// imms size S
|
||||
// ssssss 64 UInt(ssssss)
|
||||
// 0sssss 32 UInt(sssss)
|
||||
// 10ssss 16 UInt(ssss)
|
||||
// 110sss 8 UInt(sss)
|
||||
// 1110ss 4 UInt(ss)
|
||||
// 11110s 2 UInt(s)
|
||||
//
|
||||
// So we 'or' (2 * -d) with our computed s to form imms.
|
||||
if (n != nullptr) {
|
||||
*n = out_n;
|
||||
}
|
||||
if (imm_s != nullptr) {
|
||||
*imm_s = ((2 * -d) | (s - 1)) & 0x3f;
|
||||
}
|
||||
if (imm_r != nullptr) {
|
||||
*imm_r = r;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool IsIntN(unsigned n, int64_t x) {
|
||||
if (n == 64) {
|
||||
return true;
|
||||
}
|
||||
int64_t limit = INT64_C(1) << (n - 1);
|
||||
return (-limit <= x) && (x < limit);
|
||||
}
|
||||
|
||||
static inline bool IsUintN(unsigned n, int64_t x) {
|
||||
// Convert to an unsigned integer to avoid implementation-defined behavior.
|
||||
return !(static_cast<uint64_t>(x) >> n);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
#define INT_1_TO_32_LIST(V) \
|
||||
V(1) V(2) V(3) V(4) V(5) V(6) V(7) V(8) \
|
||||
V(9) V(10) V(11) V(12) V(13) V(14) V(15) V(16) \
|
||||
V(17) V(18) V(19) V(20) V(21) V(22) V(23) V(24) \
|
||||
V(25) V(26) V(27) V(28) V(29) V(30) V(31) V(32)
|
||||
|
||||
#define INT_33_TO_63_LIST(V) \
|
||||
V(33) V(34) V(35) V(36) V(37) V(38) V(39) V(40) \
|
||||
V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48) \
|
||||
V(49) V(50) V(51) V(52) V(53) V(54) V(55) V(56) \
|
||||
V(57) V(58) V(59) V(60) V(61) V(62) V(63)
|
||||
|
||||
#define INT_1_TO_63_LIST(V) INT_1_TO_32_LIST(V) INT_33_TO_63_LIST(V)
|
||||
|
||||
// clang-format on
|
||||
|
||||
#define DECLARE_IS_INT_N(N) \
|
||||
static inline bool IsInt##N(int64_t x) { \
|
||||
return IsIntN(N, x); \
|
||||
}
|
||||
|
||||
#define DECLARE_IS_UINT_N(N) \
|
||||
static inline bool IsUint##N(int64_t x) { \
|
||||
return IsUintN(N, x); \
|
||||
}
|
||||
|
||||
INT_1_TO_63_LIST(DECLARE_IS_INT_N)
|
||||
INT_1_TO_63_LIST(DECLARE_IS_UINT_N)
|
||||
|
||||
#undef DECLARE_IS_INT_N
|
||||
#undef DECLARE_IS_UINT_N
|
||||
|
||||
private:
|
||||
|
||||
template<typename V>
|
||||
static inline bool IsPowerOf2(V value) {
|
||||
return (value != 0) && ((value & (value - 1)) == 0);
|
||||
}
|
||||
|
||||
// Some compilers dislike negating unsigned integers,
|
||||
// so we provide an equivalent.
|
||||
template<typename T>
|
||||
static inline T UnsignedNegate(T value) {
|
||||
static_assert(std::is_unsigned<T>::value);
|
||||
return ~value + 1;
|
||||
}
|
||||
|
||||
static inline uint64_t LowestSetBit(uint64_t value) {
|
||||
return value & UnsignedNegate(value);
|
||||
}
|
||||
|
||||
template<typename V>
|
||||
static inline int CountLeadingZeros(V value, int width = (sizeof(V) * 8)) {
|
||||
#if COMPILER_HAS_BUILTIN_CLZ
|
||||
if (width == 32) {
|
||||
return (value == 0) ? 32 : __builtin_clz(static_cast<unsigned>(value));
|
||||
} else if (width == 64) {
|
||||
return (value == 0) ? 64 : __builtin_clzll(value);
|
||||
}
|
||||
#endif
|
||||
return CountLeadingZerosFallBack(value, width);
|
||||
}
|
||||
|
||||
static inline int CountLeadingZerosFallBack(uint64_t value, int width) {
|
||||
LOGMAN_THROW_A_FMT(IsPowerOf2(width) && (width <= 64), "Invalid width");
|
||||
if (value == 0) {
|
||||
return width;
|
||||
}
|
||||
int count = 0;
|
||||
value = value << (64 - width);
|
||||
if ((value & UINT64_C(0xffffffff00000000)) == 0) {
|
||||
count += 32;
|
||||
value = value << 32;
|
||||
}
|
||||
if ((value & UINT64_C(0xffff000000000000)) == 0) {
|
||||
count += 16;
|
||||
value = value << 16;
|
||||
}
|
||||
if ((value & UINT64_C(0xff00000000000000)) == 0) {
|
||||
count += 8;
|
||||
value = value << 8;
|
||||
}
|
||||
if ((value & UINT64_C(0xf000000000000000)) == 0) {
|
||||
count += 4;
|
||||
value = value << 4;
|
||||
}
|
||||
if ((value & UINT64_C(0xc000000000000000)) == 0) {
|
||||
count += 2;
|
||||
value = value << 2;
|
||||
}
|
||||
if ((value & UINT64_C(0x8000000000000000)) == 0) {
|
||||
count += 1;
|
||||
}
|
||||
count += (value == 0);
|
||||
return count;
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"Config": {
|
||||
"Env": "STEAM_GAME_LAUNCH_SHELL=@CMAKE_INSTALL_PREFIX@/bin/FEXBash"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"Comment": "Bypasses libGL's glX and instead sends GLX requests directly via xcb",
|
||||
"ThunksDB": {
|
||||
"GL": 0
|
||||
"Config": {
|
||||
"AdditionalArguments": "--no-sandbox"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"ThunksDB": {
|
||||
"fex_thunk_test": 1
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
x86 and x86-64 Linux emulator
|
||||
|
||||
FEX allows you to run x86 applications on ARM64 Linux devices. It offers broad compatibility with both 32-bit and 64-bit binaries, and it can be used alongside Wine/Proton to play Windows games.
|
||||
@@ -1,35 +0,0 @@
|
||||
# This is a reference AArch64 cross compile script
|
||||
# Pass in to cmake when building:
|
||||
# eg: cmake --toolchain ../Data/CMake/toolchain_aarch64.cmake ..
|
||||
if (NOT DEFINED ENV{SYSROOT})
|
||||
message(FATAL_ERROR "Need to have SYSROOT environment variable set")
|
||||
endif()
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(CMAKE_SYSTEM_PROCESSOR aarch64)
|
||||
set(CMAKE_CROSSCOMPILING TRUE)
|
||||
|
||||
# Target triple needs to match the binutils exactly
|
||||
set(TARGET_TRIPLE aarch64-linux-gnu)
|
||||
set(CMAKE_C_COMPILER "clang")
|
||||
set(CMAKE_CXX_COMPILER "clang++")
|
||||
set(CMAKE_C_COMPILER_AR "llvm-ar")
|
||||
set(CMAKE_CXX_COMPILER_AR "llvm-ar")
|
||||
set(CMAKE_C_COMPILER_RANLIB "llvm-ranlib")
|
||||
set(CMAKE_CXX_COMPILER_RANLIB "llvm-ranlib")
|
||||
set(CMAKE_LINKER "ld.lld")
|
||||
|
||||
set(CMAKE_C_COMPILER_TARGET ${TARGET_TRIPLE})
|
||||
set(CMAKE_CXX_COMPILER_TARGET ${TARGET_TRIPLE})
|
||||
|
||||
# Set the environment variable SYSROOT to the aarch64 rootfs
|
||||
set(CMAKE_FIND_ROOT_PATH "$ENV{SYSROOT}")
|
||||
set(CMAKE_SYSROOT "$ENV{SYSROOT}")
|
||||
|
||||
list(APPEND CMAKE_PREFIX_PATH "$ENV{SYSROOT}/usr/lib/${TARGET_TRIPLE}/cmake/")
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
@@ -1,31 +0,0 @@
|
||||
# --- Stage 1: Builder ---
|
||||
FROM ubuntu:22.04 as builder
|
||||
|
||||
RUN DEBIAN_FRONTEND="noninteractive" apt-get update
|
||||
RUN DEBIAN_FRONTEND="noninteractive" apt install -y cmake \
|
||||
clang-13 llvm-13 nasm ninja-build pkg-config \
|
||||
libcap-dev libglfw3-dev libepoxy-dev python3-dev libsdl2-dev \
|
||||
python3 linux-headers-generic \
|
||||
git qtbase5-dev qtdeclarative5-dev lld
|
||||
|
||||
RUN git clone --recurse-submodules https://github.com/FEX-Emu/FEX.git
|
||||
WORKDIR /FEX
|
||||
RUN mkdir build
|
||||
|
||||
ARG CC=clang-13
|
||||
ARG CXX=clang++-13
|
||||
RUN cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DUSE_LINKER=lld -DENABLE_LTO=True -DBUILD_TESTS=False -DENABLE_ASSERTIONS=False -G Ninja .
|
||||
RUN ninja
|
||||
|
||||
WORKDIR /FEX/build
|
||||
|
||||
# --- Stage 2: Runner ---
|
||||
FROM builder as runner
|
||||
|
||||
RUN DEBIAN_FRONTEND="noninteractive" apt-get update
|
||||
RUN DEBIAN_FRONTEND="noninteractive" apt install -y \
|
||||
libcap-dev libglfw3-dev libepoxy-dev
|
||||
|
||||
COPY --from=builder /FEX/Bin/* /usr/bin/
|
||||
|
||||
WORKDIR /
|
||||
+142
-4
@@ -2,6 +2,9 @@
|
||||
"DB": {
|
||||
"GL": {
|
||||
"Library" : "libGL-guest.so",
|
||||
"Depends": [
|
||||
"X11"
|
||||
],
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/libGL.so",
|
||||
"@PREFIX_LIB@/libGL.so.1",
|
||||
@@ -9,12 +12,120 @@
|
||||
"@PREFIX_LIB@/libGL.so.1.7.0"
|
||||
]
|
||||
},
|
||||
"GLESv2": {
|
||||
"Library": "libGLESv2-guest.so",
|
||||
"Depends": [
|
||||
"X11"
|
||||
],
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/libGLESv2.so",
|
||||
"@PREFIX_LIB@/libGLESv2.so.2",
|
||||
"@PREFIX_LIB@/libGLESv2.so.2.0.0"
|
||||
]
|
||||
},
|
||||
"X11": {
|
||||
"Library": "libX11-guest.so",
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/libX11.so",
|
||||
"@PREFIX_LIB@/libX11.so.6",
|
||||
"@PREFIX_LIB@/libX11.so.6.4.0"
|
||||
]
|
||||
},
|
||||
"Vulkan": {
|
||||
"Library": "libvulkan-guest.so",
|
||||
"Depends": [
|
||||
"xcb"
|
||||
],
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/libvulkan.so",
|
||||
"@PREFIX_LIB@/libvulkan.so.1",
|
||||
"@HOME@/.local/share/Steam/ubuntu12_32/steam-runtime/pinned_libs_64/libvulkan.so.1"
|
||||
],
|
||||
"Comment": [
|
||||
"Vulkan library relies on xcb, otherwise it crashes with jemalloc"
|
||||
]
|
||||
},
|
||||
"xcb": {
|
||||
"Depends": [
|
||||
"X11"
|
||||
],
|
||||
"Library": "libxcb-guest.so",
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/libxcb.so",
|
||||
"@PREFIX_LIB@/libxcb.so.1",
|
||||
"@PREFIX_LIB@/libxcb.so.1.1.0"
|
||||
]
|
||||
},
|
||||
"xcb-dri2": {
|
||||
"Library": "libxcb-dri2-guest.so",
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/libxcb-dri2.so",
|
||||
"@PREFIX_LIB@/libxcb-dri2.so.0",
|
||||
"@PREFIX_LIB@/libxcb-dri2.so.0.0.0"
|
||||
]
|
||||
},
|
||||
"xcb-dri3": {
|
||||
"Library": "libxcb-dri3-guest.so",
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/libxcb-dri3.so",
|
||||
"@PREFIX_LIB@/libxcb-dri3.so.0",
|
||||
"@PREFIX_LIB@/libxcb-dri3.so.0.0.0"
|
||||
]
|
||||
},
|
||||
"xcb-xfixes": {
|
||||
"Library": "libxcb-xfixes-guest.so",
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/libxcb-xfixes.so",
|
||||
"@PREFIX_LIB@/libxcb-xfixes.so.0",
|
||||
"@PREFIX_LIB@/libxcb-xfixes.so.0.0.0"
|
||||
]
|
||||
},
|
||||
"xcb-shm": {
|
||||
"Library": "libxcb-shm-guest.so",
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/libxcb-shm.so",
|
||||
"@PREFIX_LIB@/libxcb-shm.so.0",
|
||||
"@PREFIX_LIB@/libxcb-shm.so.0.0.0"
|
||||
]
|
||||
},
|
||||
"xcb-sync": {
|
||||
"Library": "libxcb-sync-guest.so",
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/libxcb-sync.so",
|
||||
"@PREFIX_LIB@/libxcb-sync.so.1",
|
||||
"@PREFIX_LIB@/libxcb-sync.so.1.0.0"
|
||||
]
|
||||
},
|
||||
"xcb-randr": {
|
||||
"Library": "libxcb-randr-guest.so",
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/libxcb-randr.so",
|
||||
"@PREFIX_LIB@/libxcb-randr.so.0",
|
||||
"@PREFIX_LIB@/libxcb-randr.so.0.1.0"
|
||||
]
|
||||
},
|
||||
"xcb-present": {
|
||||
"Library": "libxcb-present-guest.so",
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/libxcb-present.so",
|
||||
"@PREFIX_LIB@/libxcb-present.so.0",
|
||||
"@PREFIX_LIB@/libxcb-present.so.0.0.0"
|
||||
]
|
||||
},
|
||||
"xcb-glx": {
|
||||
"Library": "libxcb-glx-guest.so",
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/libxcb-glx.so",
|
||||
"@PREFIX_LIB@/libxcb-glx.so.0",
|
||||
"@PREFIX_LIB@/libxcb-glx.so.0.0.0"
|
||||
]
|
||||
},
|
||||
"xshmfence": {
|
||||
"Library": "libxshmfence-guest.so",
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/libxshmfence.so",
|
||||
"@PREFIX_LIB@/libxshmfence.so.1",
|
||||
"@PREFIX_LIB@/libxshmfence.so.1.0.0"
|
||||
]
|
||||
},
|
||||
"drm": {
|
||||
@@ -33,10 +144,36 @@
|
||||
"@PREFIX_LIB@/libasound.so.2.0.0"
|
||||
]
|
||||
},
|
||||
"fex_thunk_test": {
|
||||
"Library": "libfex_thunk_test-guest.so",
|
||||
"Xrender": {
|
||||
"Library": "libXrender-guest.so",
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/libfex_thunk_test.so"
|
||||
"@PREFIX_LIB@/libXrender.so",
|
||||
"@PREFIX_LIB@/libXrender.so.1",
|
||||
"@PREFIX_LIB@/libXrender.so.1.3.0"
|
||||
]
|
||||
},
|
||||
"Xext": {
|
||||
"Library": "libXext-guest.so",
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/libXext.so",
|
||||
"@PREFIX_LIB@/libXext.so.6",
|
||||
"@PREFIX_LIB@/libXext.so.6.4.0"
|
||||
]
|
||||
},
|
||||
"Xfixes": {
|
||||
"Library": "libXfixes-guest.so",
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/libXfixes.so",
|
||||
"@PREFIX_LIB@/libXfixes.so.3",
|
||||
"@PREFIX_LIB@/libXfixes.so.3.1.0"
|
||||
]
|
||||
},
|
||||
"OpenCL": {
|
||||
"Library" : "libOpenCL-guest.so",
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/libOpenCL.so",
|
||||
"@PREFIX_LIB@/libOpenCL.so.1",
|
||||
"@PREFIX_LIB@/libOpenCL.so.1.0.0"
|
||||
]
|
||||
},
|
||||
"WaylandClient": {
|
||||
@@ -46,6 +183,7 @@
|
||||
"@PREFIX_LIB@/libwayland-client.so.0",
|
||||
"@PREFIX_LIB@/libwayland-client.so.0.20.0"
|
||||
]
|
||||
}
|
||||
},
|
||||
"":{}
|
||||
}
|
||||
}
|
||||
@@ -13,14 +13,5 @@ function(GenBinFmt Name)
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/binfmts/)
|
||||
endfunction()
|
||||
|
||||
if (NOT USE_LEGACY_BINFMTMISC)
|
||||
configure_file(FEX-x86.conf.in ${CMAKE_BINARY_DIR}/Data/binfmts/FEX-x86.conf)
|
||||
configure_file(FEX-x86_64.conf.in ${CMAKE_BINARY_DIR}/Data/binfmts/FEX-x86_64.conf)
|
||||
|
||||
install(
|
||||
FILES ${CMAKE_BINARY_DIR}/Data/binfmts/FEX-x86.conf ${CMAKE_BINARY_DIR}/Data/binfmts/FEX-x86_64.conf
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/binfmt.d/)
|
||||
else()
|
||||
GenBinFmt(FEX-x86.in)
|
||||
GenBinFmt(FEX-x86_64.in)
|
||||
endif()
|
||||
GenBinFmt(FEX-x86.in)
|
||||
GenBinFmt(FEX-x86_64.in)
|
||||
@@ -1 +0,0 @@
|
||||
:FEX-x86:M:0:\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00:\xff\xff\xff\xff\xff\xfe\xfe\x00\x00\x00\x00\xff\xff\xff\xff\xff\xfe\xff\xff\xff:@CMAKE_INSTALL_PREFIX@/bin/FEXInterpreter:POCF
|
||||
@@ -6,3 +6,4 @@ mask \xff\xff\xff\xff\xff\xfe\xfe\x00\x00\x00\x00\xff\xff\xff\xff\xff\xfe\xff\xf
|
||||
credentials yes
|
||||
fix_binary yes
|
||||
preserve yes
|
||||
expose_interpreter optional
|
||||
@@ -1 +0,0 @@
|
||||
:FEX-x86_64:M:0:\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00:\xff\xff\xff\xff\xff\xfe\xfe\x00\x00\x00\x00\xff\xff\xff\xff\xff\xfe\xff\xff\xff:@CMAKE_INSTALL_PREFIX@/bin/FEXInterpreter:POCF
|
||||
@@ -6,3 +6,4 @@ mask \xff\xff\xff\xff\xff\xfe\xfe\x00\x00\x00\x00\xff\xff\xff\xff\xff\xfe\xff\xf
|
||||
credentials yes
|
||||
fix_binary yes
|
||||
preserve yes
|
||||
expose_interpreter optional
|
||||
@@ -1,35 +0,0 @@
|
||||
{ pkgs ? import <nixpkgs> { } }:
|
||||
|
||||
let
|
||||
pkgsCross32 = pkgs.pkgsCross.gnu32;
|
||||
pkgsCross64 = pkgs.pkgsCross.gnu64;
|
||||
|
||||
gcc32 = pkgs.writeText "toolchain_nix_gcc_x86_32.txt" ''
|
||||
set(CMAKE_SYSTEM_PROCESSOR i686)
|
||||
set(CMAKE_C_COMPILER ${pkgsCross32.buildPackages.gcc}/bin/i686-unknown-linux-gnu-gcc)
|
||||
set(CMAKE_CXX_COMPILER ${pkgsCross32.buildPackages.gcc}/bin/i686-unknown-linux-gnu-g++)
|
||||
'';
|
||||
|
||||
gcc64 = pkgs.writeText "toolchain_nix_gcc_x86_64.txt" ''
|
||||
set(CMAKE_SYSTEM_PROCESSOR x86_64)
|
||||
set(CMAKE_C_COMPILER ${pkgsCross64.buildPackages.gcc}/bin/x86_64-unknown-linux-gnu-gcc)
|
||||
set(CMAKE_CXX_COMPILER ${pkgsCross64.buildPackages.gcc}/bin/x86_64-unknown-linux-gnu-g++)
|
||||
'';
|
||||
in
|
||||
pkgs.mkShell {
|
||||
buildInputs = [
|
||||
pkgsCross64.buildPackages.clang
|
||||
pkgsCross32.buildPackages.clang
|
||||
];
|
||||
|
||||
shellHook = ''
|
||||
if [[ $- == *i* ]]; then
|
||||
echo "toolchain32: ${gcc32}"
|
||||
echo "toolchain64: ${gcc64}"
|
||||
echo ""
|
||||
echo "Use \$FEX_CMAKE_TOOLCHAINS to configure CMake."
|
||||
fi
|
||||
'';
|
||||
|
||||
FEX_CMAKE_TOOLCHAINS = "-DX86_32_TOOLCHAIN_FILE=${gcc32} -DX86_64_TOOLCHAIN_FILE=${gcc64}";
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
{ pkgs ? import <nixpkgs> { } }:
|
||||
|
||||
let
|
||||
pkgsCross32 = pkgs.pkgsCross.gnu32;
|
||||
pkgsCross64 = pkgs.pkgsCross.gnu64;
|
||||
|
||||
devRootFS = pkgs.buildEnv {
|
||||
name = "fex-dev-rootfs";
|
||||
paths = [
|
||||
pkgsCross64.stdenv.cc.libc_dev
|
||||
pkgsCross32.stdenv.cc.libc_dev
|
||||
pkgsCross64.stdenv.cc.cc
|
||||
pkgsCross32.stdenv.cc.cc
|
||||
|
||||
pkgs.alsa-lib.dev
|
||||
pkgs.libdrm.dev
|
||||
pkgs.libGL.dev
|
||||
pkgs.wayland.dev
|
||||
pkgs.xorg.libX11.dev
|
||||
pkgs.xorg.libxcb.dev
|
||||
pkgs.xorg.libXrandr.dev
|
||||
pkgs.xorg.libXrender.dev
|
||||
pkgs.xorg.xorgproto
|
||||
];
|
||||
ignoreCollisions = true;
|
||||
pathsToLink = [
|
||||
"/include"
|
||||
"/lib"
|
||||
];
|
||||
|
||||
postBuild = ''
|
||||
mkdir -p $out/usr
|
||||
ln -s $out/include $out/usr/
|
||||
'';
|
||||
};
|
||||
|
||||
toolchain32 = pkgs.writeText "toolchain_nix_x86_32.txt" ''
|
||||
set(CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=lld")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_INIT "-fuse-ld=lld")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=lld")
|
||||
set(CMAKE_SYSTEM_PROCESSOR i686)
|
||||
set(CMAKE_C_COMPILER clang)
|
||||
set(CMAKE_CXX_COMPILER clang++)
|
||||
set(CMAKE_C_COMPILER ${pkgsCross32.buildPackages.clang}/bin/i686-unknown-linux-gnu-clang)
|
||||
set(CMAKE_CXX_COMPILER ${pkgsCross32.buildPackages.clang}/bin/i686-unknown-linux-gnu-clang++)
|
||||
set(CLANG_FLAGS "-nodefaultlibs -nostartfiles -lstdc++ -target i686-linux-gnu -msse2 -mfpmath=sse --sysroot=${devRootFS} -iwithsysroot/include")
|
||||
set(CMAKE_C_FLAGS "''${CMAKE_C_FLAGS} ''${CLANG_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "''${CMAKE_CXX_FLAGS} ''${CLANG_FLAGS}")
|
||||
'';
|
||||
|
||||
toolchain64 = pkgs.writeText "toolchain_nix_x86_64.txt" ''
|
||||
set(CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=lld")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_INIT "-fuse-ld=lld")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=lld")
|
||||
set(CMAKE_SYSTEM_PROCESSOR x86_64)
|
||||
set(CMAKE_C_COMPILER clang)
|
||||
set(CMAKE_CXX_COMPILER clang++)
|
||||
set(CMAKE_C_COMPILER ${pkgsCross64.buildPackages.clang}/bin/x86_64-unknown-linux-gnu-clang)
|
||||
set(CMAKE_CXX_COMPILER ${pkgsCross64.buildPackages.clang}/bin/x86_64-unknown-linux-gnu-clang++)
|
||||
set(CLANG_FLAGS "-nodefaultlibs -nostartfiles -lstdc++ -target x86_64-linux-gnu --sysroot=${devRootFS} -iwithsysroot/usr/include")
|
||||
set(CMAKE_C_FLAGS "''${CMAKE_C_FLAGS} ''${CLANG_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "''${CMAKE_CXX_FLAGS} ''${CLANG_FLAGS}")
|
||||
'';
|
||||
in
|
||||
pkgs.mkShell {
|
||||
buildInputs = [
|
||||
pkgsCross64.buildPackages.clang
|
||||
pkgsCross32.buildPackages.clang
|
||||
];
|
||||
|
||||
shellHook = ''
|
||||
if [[ $- == *i* ]]; then
|
||||
echo "Set up dev RootFS at ${devRootFS}"
|
||||
echo "toolchain32: ${toolchain32}"
|
||||
echo "toolchain64: ${toolchain64}"
|
||||
echo ""
|
||||
echo "Use \$FEX_CMAKE_TOOLCHAINS to configure CMake."
|
||||
fi
|
||||
'';
|
||||
|
||||
FEX_CMAKE_TOOLCHAINS = "-DX86_32_TOOLCHAIN_FILE=${toolchain32} -DX86_64_TOOLCHAIN_FILE=${toolchain64} -DX86_DEV_ROOTFS=${devRootFS}";
|
||||
ROOTFS = "${devRootFS}";
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
{ pkgs ? import <nixpkgs> { } }:
|
||||
|
||||
let
|
||||
toolchain = pkgs.fetchzip {
|
||||
url = "https://github.com/bylaws/llvm-mingw/releases/download/20250305/llvm-mingw-20250305-ucrt-ubuntu-20.04-aarch64.tar.xz";
|
||||
sha256 = "sha256-cA03/ab9O61eO9+S2JzIXD4V0HzTXK5/AYyxW2d73Po=";
|
||||
};
|
||||
|
||||
cmakeToolchainFile = pkgs.substitute {
|
||||
# Use absolute paths that are discoverable outside of the nix shell
|
||||
src = ../../CMake/toolchain_mingw.cmake;
|
||||
substitutions = ["--replace-fail" "\${MINGW_TRIPLE}-" "${toolchain}/bin/\${MINGW_TRIPLE}-"];
|
||||
};
|
||||
|
||||
mesonCrossFile = pkgs.writeText "crossfile_llvm_mingw.txt" ''
|
||||
[binaries]
|
||||
ar = '${toolchain}/bin/arm64ec-w64-mingw32-ar'
|
||||
c = '${toolchain}/bin/arm64ec-w64-mingw32-gcc'
|
||||
cpp = '${toolchain}/bin/arm64ec-w64-mingw32-g++'
|
||||
ld = '${toolchain}/bin/arm64ec-w64-mingw32-ld'
|
||||
windres = '${toolchain}/bin/arm64ec-w64-mingw32-windres'
|
||||
strip = '${toolchain}/bin/strip'
|
||||
widl = '${toolchain}/bin/arm64ec-w64-mingw32-widl'
|
||||
pkgconfig = 'aarch64-linux-gnu-pkg-config'
|
||||
[host_machine]
|
||||
system = 'windows'
|
||||
cpu_family = 'aarch64'
|
||||
cpu = 'aarch64'
|
||||
endian = 'little'
|
||||
'';
|
||||
in
|
||||
pkgs.mkShell {
|
||||
buildInputs = [
|
||||
toolchain
|
||||
];
|
||||
|
||||
shellHook = ''
|
||||
if [[ $- == *i* ]]; then
|
||||
echo "llvm-mingw set up at ${toolchain}."
|
||||
echo ""
|
||||
echo "To configure DXVK/vkd3d-proton: meson setup \$FEX_MESON_CROSSFILE"
|
||||
echo ""
|
||||
echo "To configure 32-bit FEX build: cmake \$FEX_CMAKE_TOOLCHAIN_WOW64"
|
||||
echo "To configure 64-bit FEX build: cmake \$FEX_CMAKE_TOOLCHAIN_ARM64EC"
|
||||
fi
|
||||
'';
|
||||
|
||||
# E.g. cmake $FEX_CMAKE_TOOLCHAIN_ARM64EC -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DENABLE_LTO=False -DBUILD_TESTS=False
|
||||
FEX_CMAKE_TOOLCHAIN_ARM64EC = "--toolchain ${cmakeToolchainFile} -DMINGW_TRIPLE=arm64ec-w64-mingw32 -DCMAKE_INSTALL_LIBDIR=/usr/lib/wine/aarch64-windows";
|
||||
FEX_CMAKE_TOOLCHAIN_WOW64 = "--toolchain ${cmakeToolchainFile} -DMINGW_TRIPLE=aarch64-w64-mingw32 -DCMAKE_INSTALL_LIBDIR=/usr/lib/wine/aarch64-windows";
|
||||
FEX_MESON_CROSSFILE = "--cross-file ${mesonCrossFile}";
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#! /usr/bin/env nix-shell
|
||||
#! nix-shell -i bash WineOnArm/shell.nix
|
||||
|
||||
# Helper script to configure CMake for building FEX as library for emulation
|
||||
# of 32-bit applications in Wine/Proton.
|
||||
# The required cross-toolchains will be set up and managed by nix.
|
||||
|
||||
if [ $# -eq 0 ]
|
||||
then
|
||||
echo "Expected CMake argument list"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -f CMakeCache.txt ]
|
||||
then
|
||||
echo "Expected empty build folder"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -o xtrace
|
||||
cmake $FEX_CMAKE_TOOLCHAIN_WOW64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DENABLE_LTO=False -DBUILD_TESTS=False $@
|
||||
@@ -1,21 +0,0 @@
|
||||
#! /usr/bin/env nix-shell
|
||||
#! nix-shell -i bash WineOnArm/shell.nix
|
||||
|
||||
# Helper script to configure CMake for building FEX as library for emulation
|
||||
# of 64-bit applications in Wine/Proton
|
||||
# Nix is used to install and manage the required cross-toolchains.
|
||||
|
||||
if [ $# -eq 0 ]
|
||||
then
|
||||
echo "Expected CMake argument list"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -f CMakeCache.txt ]
|
||||
then
|
||||
echo "Expected empty build folder"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -o xtrace
|
||||
cmake $FEX_CMAKE_TOOLCHAIN_ARM64EC -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DENABLE_LTO=False -DBUILD_TESTS=False $@
|
||||
@@ -1,17 +0,0 @@
|
||||
#! /usr/bin/env nix-shell
|
||||
#! nix-shell -i bash FEXLinuxTests/shell.nix
|
||||
|
||||
# Helper script to configure CMake for building FEXLinuxTests.
|
||||
# Nix is used to install and manage the required cross-toolchains.
|
||||
|
||||
if [ ! -f CMakeCache.txt ]
|
||||
then
|
||||
echo "Must be run from a pre-configured CMake build folder"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Remove previous build to ensure the new toolchain is applied
|
||||
rm -rf unittests/FEXLinuxTests
|
||||
|
||||
set -o xtrace
|
||||
cmake . $FEX_CMAKE_TOOLCHAINS -DBUILD_TESTS=ON -DBUILD_FEX_LINUX_TESTS=ON
|
||||
@@ -1,22 +0,0 @@
|
||||
# Helper script to configure CMake for library forwarding in FEX.
|
||||
# Nix is used to install and manage the required cross-toolchains.
|
||||
|
||||
if [ ! -f CMakeCache.txt ]
|
||||
then
|
||||
echo "Must be run from a pre-configured CMake build folder"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Remove previous build to ensure the new toolchain is applied
|
||||
rm -rf guest-libs guest-libs-32 Guest Guest_32
|
||||
|
||||
# Set clang executable path manually since the one from the nix store
|
||||
# will be picked up otherwise
|
||||
CLANG_EXEC_PATH=""
|
||||
if ! grep -q CLANG_EXEC_PATH CMakeCache.txt
|
||||
then
|
||||
CLANG_EXEC_PATH="-DCLANG_EXEC_PATH=`which clang`"
|
||||
fi
|
||||
|
||||
nix-shell `dirname -- "$0"`/LibraryForwarding/shell.nix \
|
||||
--run "set -o xtrace; cmake . \$FEX_CMAKE_TOOLCHAINS -DBUILD_THUNKS=ON $CLANG_EXEC_PATH; set +o xtrace"
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
# --- Stage 1: Builder ---
|
||||
FROM ubuntu:20.04 as builder
|
||||
|
||||
RUN DEBIAN_FRONTEND="noninteractive" apt-get update
|
||||
RUN DEBIAN_FRONTEND="noninteractive" apt install -y cmake \
|
||||
clang-10 llvm-10 nasm ninja-build \
|
||||
libcap-dev libglfw3-dev libepoxy-dev python3-dev \
|
||||
python3 linux-headers-generic
|
||||
|
||||
COPY . /opt/FEX
|
||||
|
||||
CMD [ "mkdir /opt/FEX/build" ]
|
||||
|
||||
WORKDIR /opt/FEX/build
|
||||
|
||||
ARG CC=clang-10
|
||||
ARG CXX=clang++-10
|
||||
RUN cmake -G Ninja .. -DCMAKE_BUILD_TYPE=Release
|
||||
RUN ninja
|
||||
|
||||
# --- Stage 2: Runner ---
|
||||
FROM ubuntu:20.04
|
||||
|
||||
RUN DEBIAN_FRONTEND="noninteractive" apt-get update
|
||||
RUN DEBIAN_FRONTEND="noninteractive" apt install -y \
|
||||
libcap-dev libglfw3-dev libepoxy-dev
|
||||
|
||||
COPY --from=builder /opt/FEX/build/Bin/* /usr/bin/
|
||||
|
||||
WORKDIR /root
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
DisableFormat: true
|
||||
Vendored
+1
-1
Submodule External/Catch2 updated: 8ac8190e49...d4b0b34561.
Vendored
-98
@@ -1,98 +0,0 @@
|
||||
|
||||
set (SRCS
|
||||
# F80 support
|
||||
src/extF80_add.c
|
||||
src/extF80_div.c
|
||||
src/extF80_sub.c
|
||||
src/extF80_mul.c
|
||||
src/extF80_rem.c
|
||||
src/extF80_sqrt.c
|
||||
src/extF80_le.c
|
||||
src/extF80_to_i32.c
|
||||
src/extF80_to_i64.c
|
||||
src/extF80_to_ui64.c
|
||||
src/extF80_to_f32.c
|
||||
src/extF80_to_f64.c
|
||||
src/i32_to_extF80.c
|
||||
src/ui64_to_extF80.c
|
||||
src/extF80_to_f128.c
|
||||
src/f128_to_extF80.c
|
||||
|
||||
# F128 support
|
||||
src/f128_add.c
|
||||
src/f128_div.c
|
||||
src/f128_eq.c
|
||||
src/f128_eq_signaling.c
|
||||
src/f128_isSignalingNaN.c
|
||||
src/f128_le.c
|
||||
src/f128_le_quiet.c
|
||||
src/f128_lt.c
|
||||
src/f128_lt_quiet.c
|
||||
src/f128_mulAdd.c
|
||||
src/f128_mul.c
|
||||
src/f128_rem.c
|
||||
src/f128_sqrt.c
|
||||
src/f128_sub.c
|
||||
src/f128_to_f16.c
|
||||
src/f128_to_f32.c
|
||||
src/f128_to_f64.c
|
||||
src/f128_to_i32.c
|
||||
src/f128_to_i64.c
|
||||
src/f128_to_ui32.c
|
||||
src/f128_to_ui64.c
|
||||
src/s_addMagsF128.c
|
||||
src/s_subMagsF128.c
|
||||
src/s_normRoundPackToF128.c
|
||||
src/s_roundPackToF128.c
|
||||
src/s_propagateNaNF128UI.c
|
||||
|
||||
# Conversion
|
||||
src/f32_to_f128.c
|
||||
src/i32_to_f128.c
|
||||
|
||||
src/s_roundToUI64.c
|
||||
src/s_f128UIToCommonNaN.c
|
||||
src/s_commonNaNToF128UI.c
|
||||
src/s_normSubnormalF128Sig.c
|
||||
src/s_roundToI32.c
|
||||
src/s_roundToI64.c
|
||||
src/s_roundPackToF32.c
|
||||
src/s_addMagsExtF80.c
|
||||
src/s_extF80UIToCommonNaN.c
|
||||
src/s_commonNaNToF32UI.c
|
||||
src/s_commonNaNToF64UI.c
|
||||
src/s_roundPackToF64.c
|
||||
src/s_propagateNaNExtF80UI.c
|
||||
src/s_roundPackToExtF80.c
|
||||
src/s_normSubnormalExtF80Sig.c
|
||||
src/s_subMagsExtF80.c
|
||||
src/s_shiftRightJam128.c
|
||||
src/s_shiftRightJam128Extra.c
|
||||
src/s_normRoundPackToExtF80.c
|
||||
src/s_approxRecip_1Ks.c
|
||||
src/s_approxRecipSqrt32_1.c
|
||||
src/s_approxRecipSqrt_1Ks.c
|
||||
src/softfloat_raiseFlags.c
|
||||
src/f64_to_extF80.c
|
||||
src/s_commonNaNToExtF80UI.c
|
||||
src/s_normSubnormalF64Sig.c
|
||||
src/s_f64UIToCommonNaN.c
|
||||
src/extF80_roundToInt.c
|
||||
src/extF80_eq.c
|
||||
src/extF80_lt.c
|
||||
src/f32_to_extF80.c
|
||||
src/s_normSubnormalF32Sig.c
|
||||
src/s_f32UIToCommonNaN.c)
|
||||
|
||||
if (_M_ARM_64 AND HAS_CLANG_PRESERVE_ALL)
|
||||
list(APPEND DEFINES "-DFEXCORE_PRESERVE_ALL_ATTR=__attribute__((preserve_all));-DFEXCORE_HAS_PRESERVE_ALL_ATTR=1")
|
||||
else()
|
||||
list(APPEND DEFINES "-DFEXCORE_PRESERVE_ALL_ATTR=;-DFEXCORE_HAS_PRESERVE_ALL_ATTR=0")
|
||||
endif()
|
||||
|
||||
list(APPEND DEFINES "-DSOFTFLOAT_BUILTIN_CLZ=1;-DINLINE=static inline;-DINLINE_LEVEL=4;-DSOFTFLOAT_FAST_INT64=1;-DSOFTFLOAT_FAST_DIV32TO16=1;-DSOFTFLOAT_FAST_DIV64TO32=1")
|
||||
|
||||
add_library(softfloat_3e STATIC ${SRCS})
|
||||
target_include_directories(softfloat_3e PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/)
|
||||
target_include_directories(softfloat_3e PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/SoftFloat-3e/)
|
||||
target_compile_definitions(softfloat_3e PUBLIC ${DEFINES})
|
||||
-73
@@ -1,73 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
bool extF80_le( struct softfloat_state *state, extFloat80_t a, extFloat80_t b )
|
||||
{
|
||||
union { struct extFloat80M s; extFloat80_t f; } uA;
|
||||
uint_fast16_t uiA64;
|
||||
uint_fast64_t uiA0;
|
||||
union { struct extFloat80M s; extFloat80_t f; } uB;
|
||||
uint_fast16_t uiB64;
|
||||
uint_fast64_t uiB0;
|
||||
bool signA, signB;
|
||||
|
||||
uA.f = a;
|
||||
uiA64 = uA.s.signExp;
|
||||
uiA0 = uA.s.signif;
|
||||
uB.f = b;
|
||||
uiB64 = uB.s.signExp;
|
||||
uiB0 = uB.s.signif;
|
||||
if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) {
|
||||
softfloat_raiseFlags( state, softfloat_flag_invalid );
|
||||
return false;
|
||||
}
|
||||
signA = signExtF80UI64( uiA64 );
|
||||
signB = signExtF80UI64( uiB64 );
|
||||
return
|
||||
(signA != signB)
|
||||
? signA || ! (((uiA64 | uiB64) & 0x7FFF) | uiA0 | uiB0)
|
||||
: ((uiA64 == uiB64) && (uiA0 == uiB0))
|
||||
|| (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
|
||||
|
||||
}
|
||||
|
||||
Vendored
-78
@@ -1,78 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
float128_t f128_add( struct softfloat_state *state, float128_t a, float128_t b )
|
||||
{
|
||||
union ui128_f128 uA;
|
||||
uint_fast64_t uiA64, uiA0;
|
||||
bool signA;
|
||||
union ui128_f128 uB;
|
||||
uint_fast64_t uiB64, uiB0;
|
||||
bool signB;
|
||||
#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2)
|
||||
float128_t
|
||||
(*magsFuncPtr)(
|
||||
uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool );
|
||||
#endif
|
||||
|
||||
uA.f = a;
|
||||
uiA64 = uA.ui.v64;
|
||||
uiA0 = uA.ui.v0;
|
||||
signA = signF128UI64( uiA64 );
|
||||
uB.f = b;
|
||||
uiB64 = uB.ui.v64;
|
||||
uiB0 = uB.ui.v0;
|
||||
signB = signF128UI64( uiB64 );
|
||||
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
||||
if ( signA == signB ) {
|
||||
return softfloat_addMagsF128( state, uiA64, uiA0, uiB64, uiB0, signA );
|
||||
} else {
|
||||
return softfloat_subMagsF128( state, uiA64, uiA0, uiB64, uiB0, signA );
|
||||
}
|
||||
#else
|
||||
magsFuncPtr =
|
||||
(signA == signB) ? softfloat_addMagsF128 : softfloat_subMagsF128;
|
||||
return (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
Vendored
-199
@@ -1,199 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
float128_t f128_div( struct softfloat_state *state, float128_t a, float128_t b )
|
||||
{
|
||||
union ui128_f128 uA;
|
||||
uint_fast64_t uiA64, uiA0;
|
||||
bool signA;
|
||||
int_fast32_t expA;
|
||||
struct uint128 sigA;
|
||||
union ui128_f128 uB;
|
||||
uint_fast64_t uiB64, uiB0;
|
||||
bool signB;
|
||||
int_fast32_t expB;
|
||||
struct uint128 sigB;
|
||||
bool signZ;
|
||||
struct exp32_sig128 normExpSig;
|
||||
int_fast32_t expZ;
|
||||
struct uint128 rem;
|
||||
uint_fast32_t recip32;
|
||||
int ix;
|
||||
uint_fast64_t q64;
|
||||
uint_fast32_t q;
|
||||
struct uint128 term;
|
||||
uint_fast32_t qs[3];
|
||||
uint_fast64_t sigZExtra;
|
||||
struct uint128 sigZ, uiZ;
|
||||
union ui128_f128 uZ;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
uA.f = a;
|
||||
uiA64 = uA.ui.v64;
|
||||
uiA0 = uA.ui.v0;
|
||||
signA = signF128UI64( uiA64 );
|
||||
expA = expF128UI64( uiA64 );
|
||||
sigA.v64 = fracF128UI64( uiA64 );
|
||||
sigA.v0 = uiA0;
|
||||
uB.f = b;
|
||||
uiB64 = uB.ui.v64;
|
||||
uiB0 = uB.ui.v0;
|
||||
signB = signF128UI64( uiB64 );
|
||||
expB = expF128UI64( uiB64 );
|
||||
sigB.v64 = fracF128UI64( uiB64 );
|
||||
sigB.v0 = uiB0;
|
||||
signZ = signA ^ signB;
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
if ( expA == 0x7FFF ) {
|
||||
if ( sigA.v64 | sigA.v0 ) goto propagateNaN;
|
||||
if ( expB == 0x7FFF ) {
|
||||
if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
|
||||
goto invalid;
|
||||
}
|
||||
goto infinity;
|
||||
}
|
||||
if ( expB == 0x7FFF ) {
|
||||
if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
|
||||
goto zero;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
if ( ! expB ) {
|
||||
if ( ! (sigB.v64 | sigB.v0) ) {
|
||||
if ( ! (expA | sigA.v64 | sigA.v0) ) goto invalid;
|
||||
softfloat_raiseFlags( state, softfloat_flag_infinite );
|
||||
goto infinity;
|
||||
}
|
||||
normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 );
|
||||
expB = normExpSig.exp;
|
||||
sigB = normExpSig.sig;
|
||||
}
|
||||
if ( ! expA ) {
|
||||
if ( ! (sigA.v64 | sigA.v0) ) goto zero;
|
||||
normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
|
||||
expA = normExpSig.exp;
|
||||
sigA = normExpSig.sig;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
expZ = expA - expB + 0x3FFE;
|
||||
sigA.v64 |= UINT64_C( 0x0001000000000000 );
|
||||
sigB.v64 |= UINT64_C( 0x0001000000000000 );
|
||||
rem = sigA;
|
||||
if ( softfloat_lt128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 ) ) {
|
||||
--expZ;
|
||||
rem = softfloat_add128( sigA.v64, sigA.v0, sigA.v64, sigA.v0 );
|
||||
}
|
||||
recip32 = softfloat_approxRecip32_1( sigB.v64>>17 );
|
||||
ix = 3;
|
||||
for (;;) {
|
||||
q64 = (uint_fast64_t) (uint32_t) (rem.v64>>19) * recip32;
|
||||
q = (q64 + 0x80000000)>>32;
|
||||
--ix;
|
||||
if ( ix < 0 ) break;
|
||||
rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
|
||||
term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
|
||||
rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
|
||||
if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
|
||||
--q;
|
||||
rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
|
||||
}
|
||||
qs[ix] = q;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
if ( ((q + 1) & 7) < 2 ) {
|
||||
rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
|
||||
term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
|
||||
rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
|
||||
if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
|
||||
--q;
|
||||
rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
|
||||
} else if ( softfloat_le128( sigB.v64, sigB.v0, rem.v64, rem.v0 ) ) {
|
||||
++q;
|
||||
rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
|
||||
}
|
||||
if ( rem.v64 | rem.v0 ) q |= 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
sigZExtra = (uint64_t) ((uint_fast64_t) q<<60);
|
||||
term = softfloat_shortShiftLeft128( 0, qs[1], 54 );
|
||||
sigZ =
|
||||
softfloat_add128(
|
||||
(uint_fast64_t) qs[2]<<19, ((uint_fast64_t) qs[0]<<25) + (q>>4),
|
||||
term.v64, term.v0
|
||||
);
|
||||
return
|
||||
softfloat_roundPackToF128( state, signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra );
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
propagateNaN:
|
||||
uiZ = softfloat_propagateNaNF128UI( state, uiA64, uiA0, uiB64, uiB0 );
|
||||
goto uiZ;
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
invalid:
|
||||
softfloat_raiseFlags( state, softfloat_flag_invalid );
|
||||
uiZ.v64 = defaultNaNF128UI64;
|
||||
uiZ.v0 = defaultNaNF128UI0;
|
||||
goto uiZ;
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
infinity:
|
||||
uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 );
|
||||
goto uiZ0;
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
zero:
|
||||
uiZ.v64 = packToF128UI64( signZ, 0, 0 );
|
||||
uiZ0:
|
||||
uiZ.v0 = 0;
|
||||
uiZ:
|
||||
uZ.ui = uiZ;
|
||||
return uZ.f;
|
||||
|
||||
}
|
||||
|
||||
Vendored
-73
@@ -1,73 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
bool f128_eq( struct softfloat_state *state, float128_t a, float128_t b )
|
||||
{
|
||||
union ui128_f128 uA;
|
||||
uint_fast64_t uiA64, uiA0;
|
||||
union ui128_f128 uB;
|
||||
uint_fast64_t uiB64, uiB0;
|
||||
|
||||
uA.f = a;
|
||||
uiA64 = uA.ui.v64;
|
||||
uiA0 = uA.ui.v0;
|
||||
uB.f = b;
|
||||
uiB64 = uB.ui.v64;
|
||||
uiB0 = uB.ui.v0;
|
||||
if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
|
||||
if (
|
||||
softfloat_isSigNaNF128UI( uiA64, uiA0 )
|
||||
|| softfloat_isSigNaNF128UI( uiB64, uiB0 )
|
||||
) {
|
||||
softfloat_raiseFlags( state, softfloat_flag_invalid );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return
|
||||
(uiA0 == uiB0)
|
||||
&& ( (uiA64 == uiB64)
|
||||
|| (! uiA0 && ! ((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF )))
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
-67
@@ -1,67 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
bool f128_eq_signaling( struct softfloat_state *state, float128_t a, float128_t b )
|
||||
{
|
||||
union ui128_f128 uA;
|
||||
uint_fast64_t uiA64, uiA0;
|
||||
union ui128_f128 uB;
|
||||
uint_fast64_t uiB64, uiB0;
|
||||
|
||||
uA.f = a;
|
||||
uiA64 = uA.ui.v64;
|
||||
uiA0 = uA.ui.v0;
|
||||
uB.f = b;
|
||||
uiB64 = uB.ui.v64;
|
||||
uiB0 = uB.ui.v0;
|
||||
if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
|
||||
softfloat_raiseFlags( state, softfloat_flag_invalid );
|
||||
return false;
|
||||
}
|
||||
return
|
||||
(uiA0 == uiB0)
|
||||
&& ( (uiA64 == uiB64)
|
||||
|| (! uiA0 && ! ((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF )))
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
Vendored
-72
@@ -1,72 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
bool f128_le( struct softfloat_state *state, float128_t a, float128_t b )
|
||||
{
|
||||
union ui128_f128 uA;
|
||||
uint_fast64_t uiA64, uiA0;
|
||||
union ui128_f128 uB;
|
||||
uint_fast64_t uiB64, uiB0;
|
||||
bool signA, signB;
|
||||
|
||||
uA.f = a;
|
||||
uiA64 = uA.ui.v64;
|
||||
uiA0 = uA.ui.v0;
|
||||
uB.f = b;
|
||||
uiB64 = uB.ui.v64;
|
||||
uiB0 = uB.ui.v0;
|
||||
if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
|
||||
softfloat_raiseFlags( state, softfloat_flag_invalid );
|
||||
return false;
|
||||
}
|
||||
signA = signF128UI64( uiA64 );
|
||||
signB = signF128UI64( uiB64 );
|
||||
return
|
||||
(signA != signB)
|
||||
? signA
|
||||
|| ! (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
|
||||
| uiA0 | uiB0)
|
||||
: ((uiA64 == uiB64) && (uiA0 == uiB0))
|
||||
|| (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
|
||||
|
||||
}
|
||||
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
bool f128_le_quiet( struct softfloat_state *state, float128_t a, float128_t b )
|
||||
{
|
||||
union ui128_f128 uA;
|
||||
uint_fast64_t uiA64, uiA0;
|
||||
union ui128_f128 uB;
|
||||
uint_fast64_t uiB64, uiB0;
|
||||
bool signA, signB;
|
||||
|
||||
uA.f = a;
|
||||
uiA64 = uA.ui.v64;
|
||||
uiA0 = uA.ui.v0;
|
||||
uB.f = b;
|
||||
uiB64 = uB.ui.v64;
|
||||
uiB0 = uB.ui.v0;
|
||||
if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
|
||||
if (
|
||||
softfloat_isSigNaNF128UI( uiA64, uiA0 )
|
||||
|| softfloat_isSigNaNF128UI( uiB64, uiB0 )
|
||||
) {
|
||||
softfloat_raiseFlags( state, softfloat_flag_invalid );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
signA = signF128UI64( uiA64 );
|
||||
signB = signF128UI64( uiB64 );
|
||||
return
|
||||
(signA != signB)
|
||||
? signA
|
||||
|| ! (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
|
||||
| uiA0 | uiB0)
|
||||
: ((uiA64 == uiB64) && (uiA0 == uiB0))
|
||||
|| (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
|
||||
|
||||
}
|
||||
|
||||
Vendored
-72
@@ -1,72 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
bool f128_lt( struct softfloat_state *state, float128_t a, float128_t b )
|
||||
{
|
||||
union ui128_f128 uA;
|
||||
uint_fast64_t uiA64, uiA0;
|
||||
union ui128_f128 uB;
|
||||
uint_fast64_t uiB64, uiB0;
|
||||
bool signA, signB;
|
||||
|
||||
uA.f = a;
|
||||
uiA64 = uA.ui.v64;
|
||||
uiA0 = uA.ui.v0;
|
||||
uB.f = b;
|
||||
uiB64 = uB.ui.v64;
|
||||
uiB0 = uB.ui.v0;
|
||||
if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
|
||||
softfloat_raiseFlags( state, softfloat_flag_invalid );
|
||||
return false;
|
||||
}
|
||||
signA = signF128UI64( uiA64 );
|
||||
signB = signF128UI64( uiB64 );
|
||||
return
|
||||
(signA != signB)
|
||||
? signA
|
||||
&& (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
|
||||
| uiA0 | uiB0)
|
||||
: ((uiA64 != uiB64) || (uiA0 != uiB0))
|
||||
&& (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
|
||||
|
||||
}
|
||||
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
bool f128_lt_quiet( struct softfloat_state *state, float128_t a, float128_t b )
|
||||
{
|
||||
union ui128_f128 uA;
|
||||
uint_fast64_t uiA64, uiA0;
|
||||
union ui128_f128 uB;
|
||||
uint_fast64_t uiB64, uiB0;
|
||||
bool signA, signB;
|
||||
|
||||
uA.f = a;
|
||||
uiA64 = uA.ui.v64;
|
||||
uiA0 = uA.ui.v0;
|
||||
uB.f = b;
|
||||
uiB64 = uB.ui.v64;
|
||||
uiB0 = uB.ui.v0;
|
||||
if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
|
||||
if (
|
||||
softfloat_isSigNaNF128UI( uiA64, uiA0 )
|
||||
|| softfloat_isSigNaNF128UI( uiB64, uiB0 )
|
||||
) {
|
||||
softfloat_raiseFlags( state, softfloat_flag_invalid );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
signA = signF128UI64( uiA64 );
|
||||
signB = signF128UI64( uiB64 );
|
||||
return
|
||||
(signA != signB)
|
||||
? signA
|
||||
&& (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
|
||||
| uiA0 | uiB0)
|
||||
: ((uiA64 != uiB64) || (uiA0 != uiB0))
|
||||
&& (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
|
||||
|
||||
}
|
||||
|
||||
Vendored
-163
@@ -1,163 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
float128_t f128_mul( struct softfloat_state *state, float128_t a, float128_t b )
|
||||
{
|
||||
union ui128_f128 uA;
|
||||
uint_fast64_t uiA64, uiA0;
|
||||
bool signA;
|
||||
int_fast32_t expA;
|
||||
struct uint128 sigA;
|
||||
union ui128_f128 uB;
|
||||
uint_fast64_t uiB64, uiB0;
|
||||
bool signB;
|
||||
int_fast32_t expB;
|
||||
struct uint128 sigB;
|
||||
bool signZ;
|
||||
uint_fast64_t magBits;
|
||||
struct exp32_sig128 normExpSig;
|
||||
int_fast32_t expZ;
|
||||
uint64_t sig256Z[4];
|
||||
uint_fast64_t sigZExtra;
|
||||
struct uint128 sigZ;
|
||||
struct uint128_extra sig128Extra;
|
||||
struct uint128 uiZ;
|
||||
union ui128_f128 uZ;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
uA.f = a;
|
||||
uiA64 = uA.ui.v64;
|
||||
uiA0 = uA.ui.v0;
|
||||
signA = signF128UI64( uiA64 );
|
||||
expA = expF128UI64( uiA64 );
|
||||
sigA.v64 = fracF128UI64( uiA64 );
|
||||
sigA.v0 = uiA0;
|
||||
uB.f = b;
|
||||
uiB64 = uB.ui.v64;
|
||||
uiB0 = uB.ui.v0;
|
||||
signB = signF128UI64( uiB64 );
|
||||
expB = expF128UI64( uiB64 );
|
||||
sigB.v64 = fracF128UI64( uiB64 );
|
||||
sigB.v0 = uiB0;
|
||||
signZ = signA ^ signB;
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
if ( expA == 0x7FFF ) {
|
||||
if (
|
||||
(sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0))
|
||||
) {
|
||||
goto propagateNaN;
|
||||
}
|
||||
magBits = expB | sigB.v64 | sigB.v0;
|
||||
goto infArg;
|
||||
}
|
||||
if ( expB == 0x7FFF ) {
|
||||
if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
|
||||
magBits = expA | sigA.v64 | sigA.v0;
|
||||
goto infArg;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
if ( ! expA ) {
|
||||
if ( ! (sigA.v64 | sigA.v0) ) goto zero;
|
||||
normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
|
||||
expA = normExpSig.exp;
|
||||
sigA = normExpSig.sig;
|
||||
}
|
||||
if ( ! expB ) {
|
||||
if ( ! (sigB.v64 | sigB.v0) ) goto zero;
|
||||
normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 );
|
||||
expB = normExpSig.exp;
|
||||
sigB = normExpSig.sig;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
expZ = expA + expB - 0x4000;
|
||||
sigA.v64 |= UINT64_C( 0x0001000000000000 );
|
||||
sigB = softfloat_shortShiftLeft128( sigB.v64, sigB.v0, 16 );
|
||||
softfloat_mul128To256M( sigA.v64, sigA.v0, sigB.v64, sigB.v0, sig256Z );
|
||||
sigZExtra = sig256Z[indexWord( 4, 1 )] | (sig256Z[indexWord( 4, 0 )] != 0);
|
||||
sigZ =
|
||||
softfloat_add128(
|
||||
sig256Z[indexWord( 4, 3 )], sig256Z[indexWord( 4, 2 )],
|
||||
sigA.v64, sigA.v0
|
||||
);
|
||||
if ( UINT64_C( 0x0002000000000000 ) <= sigZ.v64 ) {
|
||||
++expZ;
|
||||
sig128Extra =
|
||||
softfloat_shortShiftRightJam128Extra(
|
||||
sigZ.v64, sigZ.v0, sigZExtra, 1 );
|
||||
sigZ = sig128Extra.v;
|
||||
sigZExtra = sig128Extra.extra;
|
||||
}
|
||||
return
|
||||
softfloat_roundPackToF128( state, signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra );
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
propagateNaN:
|
||||
uiZ = softfloat_propagateNaNF128UI( state, uiA64, uiA0, uiB64, uiB0 );
|
||||
goto uiZ;
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
infArg:
|
||||
if ( ! magBits ) {
|
||||
softfloat_raiseFlags( state, softfloat_flag_invalid );
|
||||
uiZ.v64 = defaultNaNF128UI64;
|
||||
uiZ.v0 = defaultNaNF128UI0;
|
||||
goto uiZ;
|
||||
}
|
||||
uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 );
|
||||
goto uiZ0;
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
zero:
|
||||
uiZ.v64 = packToF128UI64( signZ, 0, 0 );
|
||||
uiZ0:
|
||||
uiZ.v0 = 0;
|
||||
uiZ:
|
||||
uZ.ui = uiZ;
|
||||
return uZ.f;
|
||||
|
||||
}
|
||||
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
float128_t f128_mulAdd( struct softfloat_state *state, float128_t a, float128_t b, float128_t c )
|
||||
{
|
||||
union ui128_f128 uA;
|
||||
uint_fast64_t uiA64, uiA0;
|
||||
union ui128_f128 uB;
|
||||
uint_fast64_t uiB64, uiB0;
|
||||
union ui128_f128 uC;
|
||||
uint_fast64_t uiC64, uiC0;
|
||||
|
||||
uA.f = a;
|
||||
uiA64 = uA.ui.v64;
|
||||
uiA0 = uA.ui.v0;
|
||||
uB.f = b;
|
||||
uiB64 = uB.ui.v64;
|
||||
uiB0 = uB.ui.v0;
|
||||
uC.f = c;
|
||||
uiC64 = uC.ui.v64;
|
||||
uiC0 = uC.ui.v0;
|
||||
return softfloat_mulAddF128( uiA64, uiA0, uiB64, uiB0, uiC64, uiC0, 0 );
|
||||
|
||||
}
|
||||
|
||||
Vendored
-190
@@ -1,190 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
|
||||
California. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
float128_t f128_rem( struct softfloat_state *state, float128_t a, float128_t b )
|
||||
{
|
||||
union ui128_f128 uA;
|
||||
uint_fast64_t uiA64, uiA0;
|
||||
bool signA;
|
||||
int_fast32_t expA;
|
||||
struct uint128 sigA;
|
||||
union ui128_f128 uB;
|
||||
uint_fast64_t uiB64, uiB0;
|
||||
int_fast32_t expB;
|
||||
struct uint128 sigB;
|
||||
struct exp32_sig128 normExpSig;
|
||||
struct uint128 rem;
|
||||
int_fast32_t expDiff;
|
||||
uint_fast32_t q, recip32;
|
||||
uint_fast64_t q64;
|
||||
struct uint128 term, altRem, meanRem;
|
||||
bool signRem;
|
||||
struct uint128 uiZ;
|
||||
union ui128_f128 uZ;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
uA.f = a;
|
||||
uiA64 = uA.ui.v64;
|
||||
uiA0 = uA.ui.v0;
|
||||
signA = signF128UI64( uiA64 );
|
||||
expA = expF128UI64( uiA64 );
|
||||
sigA.v64 = fracF128UI64( uiA64 );
|
||||
sigA.v0 = uiA0;
|
||||
uB.f = b;
|
||||
uiB64 = uB.ui.v64;
|
||||
uiB0 = uB.ui.v0;
|
||||
expB = expF128UI64( uiB64 );
|
||||
sigB.v64 = fracF128UI64( uiB64 );
|
||||
sigB.v0 = uiB0;
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
if ( expA == 0x7FFF ) {
|
||||
if (
|
||||
(sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0))
|
||||
) {
|
||||
goto propagateNaN;
|
||||
}
|
||||
goto invalid;
|
||||
}
|
||||
if ( expB == 0x7FFF ) {
|
||||
if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
|
||||
return a;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
if ( ! expB ) {
|
||||
if ( ! (sigB.v64 | sigB.v0) ) goto invalid;
|
||||
normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 );
|
||||
expB = normExpSig.exp;
|
||||
sigB = normExpSig.sig;
|
||||
}
|
||||
if ( ! expA ) {
|
||||
if ( ! (sigA.v64 | sigA.v0) ) return a;
|
||||
normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
|
||||
expA = normExpSig.exp;
|
||||
sigA = normExpSig.sig;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
sigA.v64 |= UINT64_C( 0x0001000000000000 );
|
||||
sigB.v64 |= UINT64_C( 0x0001000000000000 );
|
||||
rem = sigA;
|
||||
expDiff = expA - expB;
|
||||
if ( expDiff < 1 ) {
|
||||
if ( expDiff < -1 ) return a;
|
||||
if ( expDiff ) {
|
||||
--expB;
|
||||
sigB = softfloat_add128( sigB.v64, sigB.v0, sigB.v64, sigB.v0 );
|
||||
q = 0;
|
||||
} else {
|
||||
q = softfloat_le128( sigB.v64, sigB.v0, rem.v64, rem.v0 );
|
||||
if ( q ) {
|
||||
rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
recip32 = softfloat_approxRecip32_1( sigB.v64>>17 );
|
||||
expDiff -= 30;
|
||||
for (;;) {
|
||||
q64 = (uint_fast64_t) (uint32_t) (rem.v64>>19) * recip32;
|
||||
if ( expDiff < 0 ) break;
|
||||
q = (q64 + 0x80000000)>>32;
|
||||
rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
|
||||
term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
|
||||
rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
|
||||
if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
|
||||
rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
|
||||
}
|
||||
expDiff -= 29;
|
||||
}
|
||||
/*--------------------------------------------------------------------
|
||||
| (`expDiff' cannot be less than -29 here.)
|
||||
*--------------------------------------------------------------------*/
|
||||
q = (uint32_t) (q64>>32)>>(~expDiff & 31);
|
||||
rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, expDiff + 30 );
|
||||
term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
|
||||
rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
|
||||
if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
|
||||
altRem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
|
||||
goto selectRem;
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
do {
|
||||
altRem = rem;
|
||||
++q;
|
||||
rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
|
||||
} while ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) );
|
||||
selectRem:
|
||||
meanRem = softfloat_add128( rem.v64, rem.v0, altRem.v64, altRem.v0 );
|
||||
if (
|
||||
(meanRem.v64 & UINT64_C( 0x8000000000000000 ))
|
||||
|| (! (meanRem.v64 | meanRem.v0) && (q & 1))
|
||||
) {
|
||||
rem = altRem;
|
||||
}
|
||||
signRem = signA;
|
||||
if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
|
||||
signRem = ! signRem;
|
||||
rem = softfloat_sub128( 0, 0, rem.v64, rem.v0 );
|
||||
}
|
||||
return softfloat_normRoundPackToF128( state, signRem, expB - 1, rem.v64, rem.v0 );
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
propagateNaN:
|
||||
uiZ = softfloat_propagateNaNF128UI( state, uiA64, uiA0, uiB64, uiB0 );
|
||||
goto uiZ;
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
invalid:
|
||||
softfloat_raiseFlags( state, softfloat_flag_invalid );
|
||||
uiZ.v64 = defaultNaNF128UI64;
|
||||
uiZ.v0 = defaultNaNF128UI0;
|
||||
uiZ:
|
||||
uZ.ui = uiZ;
|
||||
return uZ.f;
|
||||
|
||||
}
|
||||
|
||||
-201
@@ -1,201 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
|
||||
University of California. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
float128_t f128_sqrt( struct softfloat_state *state, float128_t a )
|
||||
{
|
||||
union ui128_f128 uA;
|
||||
uint_fast64_t uiA64, uiA0;
|
||||
bool signA;
|
||||
int_fast32_t expA;
|
||||
struct uint128 sigA, uiZ;
|
||||
struct exp32_sig128 normExpSig;
|
||||
int_fast32_t expZ;
|
||||
uint_fast32_t sig32A, recipSqrt32, sig32Z;
|
||||
struct uint128 rem;
|
||||
uint32_t qs[3];
|
||||
uint_fast32_t q;
|
||||
uint_fast64_t x64, sig64Z;
|
||||
struct uint128 y, term;
|
||||
uint_fast64_t sigZExtra;
|
||||
struct uint128 sigZ;
|
||||
union ui128_f128 uZ;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
uA.f = a;
|
||||
uiA64 = uA.ui.v64;
|
||||
uiA0 = uA.ui.v0;
|
||||
signA = signF128UI64( uiA64 );
|
||||
expA = expF128UI64( uiA64 );
|
||||
sigA.v64 = fracF128UI64( uiA64 );
|
||||
sigA.v0 = uiA0;
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
if ( expA == 0x7FFF ) {
|
||||
if ( sigA.v64 | sigA.v0 ) {
|
||||
uiZ = softfloat_propagateNaNF128UI( state, uiA64, uiA0, 0, 0 );
|
||||
goto uiZ;
|
||||
}
|
||||
if ( ! signA ) return a;
|
||||
goto invalid;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
if ( signA ) {
|
||||
if ( ! (expA | sigA.v64 | sigA.v0) ) return a;
|
||||
goto invalid;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
if ( ! expA ) {
|
||||
if ( ! (sigA.v64 | sigA.v0) ) return a;
|
||||
normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
|
||||
expA = normExpSig.exp;
|
||||
sigA = normExpSig.sig;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
| (`sig32Z' is guaranteed to be a lower bound on the square root of
|
||||
| `sig32A', which makes `sig32Z' also a lower bound on the square root of
|
||||
| `sigA'.)
|
||||
*------------------------------------------------------------------------*/
|
||||
expZ = ((expA - 0x3FFF)>>1) + 0x3FFE;
|
||||
expA &= 1;
|
||||
sigA.v64 |= UINT64_C( 0x0001000000000000 );
|
||||
sig32A = sigA.v64>>17;
|
||||
recipSqrt32 = softfloat_approxRecipSqrt32_1( expA, sig32A );
|
||||
sig32Z = ((uint_fast64_t) sig32A * recipSqrt32)>>32;
|
||||
if ( expA ) {
|
||||
sig32Z >>= 1;
|
||||
rem = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 12 );
|
||||
} else {
|
||||
rem = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 13 );
|
||||
}
|
||||
qs[2] = sig32Z;
|
||||
rem.v64 -= (uint_fast64_t) sig32Z * sig32Z;
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
q = ((uint32_t) (rem.v64>>2) * (uint_fast64_t) recipSqrt32)>>32;
|
||||
x64 = (uint_fast64_t) sig32Z<<32;
|
||||
sig64Z = x64 + ((uint_fast64_t) q<<3);
|
||||
y = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
|
||||
/*------------------------------------------------------------------------
|
||||
| (Repeating this loop is a rare occurrence.)
|
||||
*------------------------------------------------------------------------*/
|
||||
for (;;) {
|
||||
term = softfloat_mul64ByShifted32To128( x64 + sig64Z, q );
|
||||
rem = softfloat_sub128( y.v64, y.v0, term.v64, term.v0 );
|
||||
if ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) ) break;
|
||||
--q;
|
||||
sig64Z -= 1<<3;
|
||||
}
|
||||
qs[1] = q;
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
q = ((rem.v64>>2) * recipSqrt32)>>32;
|
||||
y = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
|
||||
sig64Z <<= 1;
|
||||
/*------------------------------------------------------------------------
|
||||
| (Repeating this loop is a rare occurrence.)
|
||||
*------------------------------------------------------------------------*/
|
||||
for (;;) {
|
||||
term = softfloat_shortShiftLeft128( 0, sig64Z, 32 );
|
||||
term = softfloat_add128( term.v64, term.v0, 0, (uint_fast64_t) q<<6 );
|
||||
term = softfloat_mul128By32( term.v64, term.v0, q );
|
||||
rem = softfloat_sub128( y.v64, y.v0, term.v64, term.v0 );
|
||||
if ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) ) break;
|
||||
--q;
|
||||
}
|
||||
qs[0] = q;
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
q = (((rem.v64>>2) * recipSqrt32)>>32) + 2;
|
||||
sigZExtra = (uint64_t) ((uint_fast64_t) q<<59);
|
||||
term = softfloat_shortShiftLeft128( 0, qs[1], 53 );
|
||||
sigZ =
|
||||
softfloat_add128(
|
||||
(uint_fast64_t) qs[2]<<18, ((uint_fast64_t) qs[0]<<24) + (q>>5),
|
||||
term.v64, term.v0
|
||||
);
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
if ( (q & 0xF) <= 2 ) {
|
||||
q &= ~3;
|
||||
sigZExtra = (uint64_t) ((uint_fast64_t) q<<59);
|
||||
y = softfloat_shortShiftLeft128( sigZ.v64, sigZ.v0, 6 );
|
||||
y.v0 |= sigZExtra>>58;
|
||||
term = softfloat_sub128( y.v64, y.v0, 0, q );
|
||||
y = softfloat_mul64ByShifted32To128( term.v0, q );
|
||||
term = softfloat_mul64ByShifted32To128( term.v64, q );
|
||||
term = softfloat_add128( term.v64, term.v0, 0, y.v64 );
|
||||
rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 20 );
|
||||
term = softfloat_sub128( term.v64, term.v0, rem.v64, rem.v0 );
|
||||
/*--------------------------------------------------------------------
|
||||
| The concatenation of `term' and `y.v0' is now the negative remainder
|
||||
| (3 words altogether).
|
||||
*--------------------------------------------------------------------*/
|
||||
if ( term.v64 & UINT64_C( 0x8000000000000000 ) ) {
|
||||
sigZExtra |= 1;
|
||||
} else {
|
||||
if ( term.v64 | term.v0 | y.v0 ) {
|
||||
if ( sigZExtra ) {
|
||||
--sigZExtra;
|
||||
} else {
|
||||
sigZ = softfloat_sub128( sigZ.v64, sigZ.v0, 0, 1 );
|
||||
sigZExtra = ~0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return softfloat_roundPackToF128( state, 0, expZ, sigZ.v64, sigZ.v0, sigZExtra );
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
invalid:
|
||||
softfloat_raiseFlags( state, softfloat_flag_invalid );
|
||||
uiZ.v64 = defaultNaNF128UI64;
|
||||
uiZ.v0 = defaultNaNF128UI0;
|
||||
uiZ:
|
||||
uZ.ui = uiZ;
|
||||
return uZ.f;
|
||||
|
||||
}
|
||||
|
||||
Vendored
-78
@@ -1,78 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
float128_t f128_sub( struct softfloat_state *state, float128_t a, float128_t b )
|
||||
{
|
||||
union ui128_f128 uA;
|
||||
uint_fast64_t uiA64, uiA0;
|
||||
bool signA;
|
||||
union ui128_f128 uB;
|
||||
uint_fast64_t uiB64, uiB0;
|
||||
bool signB;
|
||||
#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2)
|
||||
float128_t
|
||||
(*magsFuncPtr)(
|
||||
uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool );
|
||||
#endif
|
||||
|
||||
uA.f = a;
|
||||
uiA64 = uA.ui.v64;
|
||||
uiA0 = uA.ui.v0;
|
||||
signA = signF128UI64( uiA64 );
|
||||
uB.f = b;
|
||||
uiB64 = uB.ui.v64;
|
||||
uiB0 = uB.ui.v0;
|
||||
signB = signF128UI64( uiB64 );
|
||||
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
|
||||
if ( signA == signB ) {
|
||||
return softfloat_subMagsF128( state, uiA64, uiA0, uiB64, uiB0, signA );
|
||||
} else {
|
||||
return softfloat_addMagsF128( state, uiA64, uiA0, uiB64, uiB0, signA );
|
||||
}
|
||||
#else
|
||||
magsFuncPtr =
|
||||
(signA == signB) ? softfloat_subMagsF128 : softfloat_addMagsF128;
|
||||
return (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
-95
@@ -1,95 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
|
||||
California. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
float16_t f128_to_f16( struct softfloat_state *state, float128_t a )
|
||||
{
|
||||
union ui128_f128 uA;
|
||||
uint_fast64_t uiA64, uiA0;
|
||||
bool sign;
|
||||
int_fast32_t exp;
|
||||
uint_fast64_t frac64;
|
||||
struct commonNaN commonNaN;
|
||||
uint_fast16_t uiZ, frac16;
|
||||
union ui16_f16 uZ;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
uA.f = a;
|
||||
uiA64 = uA.ui.v64;
|
||||
uiA0 = uA.ui.v0;
|
||||
sign = signF128UI64( uiA64 );
|
||||
exp = expF128UI64( uiA64 );
|
||||
frac64 = fracF128UI64( uiA64 ) | (uiA0 != 0);
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
if ( exp == 0x7FFF ) {
|
||||
if ( frac64 ) {
|
||||
softfloat_f128UIToCommonNaN( state, uiA64, uiA0, &commonNaN );
|
||||
uiZ = softfloat_commonNaNToF16UI( &commonNaN );
|
||||
} else {
|
||||
uiZ = packToF16UI( sign, 0x1F, 0 );
|
||||
}
|
||||
goto uiZ;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
frac16 = softfloat_shortShiftRightJam64( frac64, 34 );
|
||||
if ( ! (exp | frac16) ) {
|
||||
uiZ = packToF16UI( sign, 0, 0 );
|
||||
goto uiZ;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
exp -= 0x3FF1;
|
||||
if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) {
|
||||
if ( exp < -0x40 ) exp = -0x40;
|
||||
}
|
||||
return softfloat_roundPackToF16( sign, exp, frac16 | 0x4000 );
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
uiZ:
|
||||
uZ.ui = uiZ;
|
||||
return uZ.f;
|
||||
|
||||
}
|
||||
|
||||
-95
@@ -1,95 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
|
||||
California. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
float32_t f128_to_f32( struct softfloat_state *state, float128_t a )
|
||||
{
|
||||
union ui128_f128 uA;
|
||||
uint_fast64_t uiA64, uiA0;
|
||||
bool sign;
|
||||
int_fast32_t exp;
|
||||
uint_fast64_t frac64;
|
||||
struct commonNaN commonNaN;
|
||||
uint_fast32_t uiZ, frac32;
|
||||
union ui32_f32 uZ;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
uA.f = a;
|
||||
uiA64 = uA.ui.v64;
|
||||
uiA0 = uA.ui.v0;
|
||||
sign = signF128UI64( uiA64 );
|
||||
exp = expF128UI64( uiA64 );
|
||||
frac64 = fracF128UI64( uiA64 ) | (uiA0 != 0);
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
if ( exp == 0x7FFF ) {
|
||||
if ( frac64 ) {
|
||||
softfloat_f128UIToCommonNaN( state, uiA64, uiA0, &commonNaN );
|
||||
uiZ = softfloat_commonNaNToF32UI( &commonNaN );
|
||||
} else {
|
||||
uiZ = packToF32UI( sign, 0xFF, 0 );
|
||||
}
|
||||
goto uiZ;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
frac32 = softfloat_shortShiftRightJam64( frac64, 18 );
|
||||
if ( ! (exp | frac32) ) {
|
||||
uiZ = packToF32UI( sign, 0, 0 );
|
||||
goto uiZ;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
exp -= 0x3F81;
|
||||
if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) {
|
||||
if ( exp < -0x1000 ) exp = -0x1000;
|
||||
}
|
||||
return softfloat_roundPackToF32( state, sign, exp, frac32 | 0x40000000 );
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
uiZ:
|
||||
uZ.ui = uiZ;
|
||||
return uZ.f;
|
||||
|
||||
}
|
||||
|
||||
-100
@@ -1,100 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
|
||||
California. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
float64_t f128_to_f64( struct softfloat_state *state, float128_t a )
|
||||
{
|
||||
union ui128_f128 uA;
|
||||
uint_fast64_t uiA64, uiA0;
|
||||
bool sign;
|
||||
int_fast32_t exp;
|
||||
uint_fast64_t frac64, frac0;
|
||||
struct commonNaN commonNaN;
|
||||
uint_fast64_t uiZ;
|
||||
struct uint128 frac128;
|
||||
union ui64_f64 uZ;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
uA.f = a;
|
||||
uiA64 = uA.ui.v64;
|
||||
uiA0 = uA.ui.v0;
|
||||
sign = signF128UI64( uiA64 );
|
||||
exp = expF128UI64( uiA64 );
|
||||
frac64 = fracF128UI64( uiA64 );
|
||||
frac0 = uiA0;
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
if ( exp == 0x7FFF ) {
|
||||
if ( frac64 | frac0 ) {
|
||||
softfloat_f128UIToCommonNaN( state, uiA64, uiA0, &commonNaN );
|
||||
uiZ = softfloat_commonNaNToF64UI( &commonNaN );
|
||||
} else {
|
||||
uiZ = packToF64UI( sign, 0x7FF, 0 );
|
||||
}
|
||||
goto uiZ;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
frac128 = softfloat_shortShiftLeft128( frac64, frac0, 14 );
|
||||
frac64 = frac128.v64 | (frac128.v0 != 0);
|
||||
if ( ! (exp | frac64) ) {
|
||||
uiZ = packToF64UI( sign, 0, 0 );
|
||||
goto uiZ;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
exp -= 0x3C01;
|
||||
if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) {
|
||||
if ( exp < -0x1000 ) exp = -0x1000;
|
||||
}
|
||||
return
|
||||
softfloat_roundPackToF64(
|
||||
state, sign, exp, frac64 | UINT64_C( 0x4000000000000000 ) );
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
uiZ:
|
||||
uZ.ui = uiZ;
|
||||
return uZ.f;
|
||||
|
||||
}
|
||||
|
||||
-85
@@ -1,85 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
|
||||
University of California. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
int_fast32_t f128_to_i32( struct softfloat_state *state, float128_t a, uint_fast8_t roundingMode, bool exact )
|
||||
{
|
||||
union ui128_f128 uA;
|
||||
uint_fast64_t uiA64, uiA0;
|
||||
bool sign;
|
||||
int_fast32_t exp;
|
||||
uint_fast64_t sig64, sig0;
|
||||
int_fast32_t shiftDist;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
uA.f = a;
|
||||
uiA64 = uA.ui.v64;
|
||||
uiA0 = uA.ui.v0;
|
||||
sign = signF128UI64( uiA64 );
|
||||
exp = expF128UI64( uiA64 );
|
||||
sig64 = fracF128UI64( uiA64 );
|
||||
sig0 = uiA0;
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow)
|
||||
if ( (exp == 0x7FFF) && (sig64 | sig0) ) {
|
||||
#if (i32_fromNaN == i32_fromPosOverflow)
|
||||
sign = 0;
|
||||
#elif (i32_fromNaN == i32_fromNegOverflow)
|
||||
sign = 1;
|
||||
#else
|
||||
softfloat_raiseFlags( softfloat_flag_invalid );
|
||||
return i32_fromNaN;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 );
|
||||
sig64 |= (sig0 != 0);
|
||||
shiftDist = 0x4023 - exp;
|
||||
if ( 0 < shiftDist ) sig64 = softfloat_shiftRightJam64( sig64, shiftDist );
|
||||
return softfloat_roundToI32( state, sign, sig64, roundingMode, exact );
|
||||
|
||||
}
|
||||
|
||||
-95
@@ -1,95 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
|
||||
University of California. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
int_fast64_t f128_to_i64( struct softfloat_state *state, float128_t a, uint_fast8_t roundingMode, bool exact )
|
||||
{
|
||||
union ui128_f128 uA;
|
||||
uint_fast64_t uiA64, uiA0;
|
||||
bool sign;
|
||||
int_fast32_t exp;
|
||||
uint_fast64_t sig64, sig0;
|
||||
int_fast32_t shiftDist;
|
||||
struct uint128 sig128;
|
||||
struct uint64_extra sigExtra;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
uA.f = a;
|
||||
uiA64 = uA.ui.v64;
|
||||
uiA0 = uA.ui.v0;
|
||||
sign = signF128UI64( uiA64 );
|
||||
exp = expF128UI64( uiA64 );
|
||||
sig64 = fracF128UI64( uiA64 );
|
||||
sig0 = uiA0;
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
shiftDist = 0x402F - exp;
|
||||
if ( shiftDist <= 0 ) {
|
||||
/*--------------------------------------------------------------------
|
||||
*--------------------------------------------------------------------*/
|
||||
if ( shiftDist < -15 ) {
|
||||
softfloat_raiseFlags( state, softfloat_flag_invalid );
|
||||
return
|
||||
(exp == 0x7FFF) && (sig64 | sig0) ? i64_fromNaN
|
||||
: sign ? i64_fromNegOverflow : i64_fromPosOverflow;
|
||||
}
|
||||
/*--------------------------------------------------------------------
|
||||
*--------------------------------------------------------------------*/
|
||||
sig64 |= UINT64_C( 0x0001000000000000 );
|
||||
if ( shiftDist ) {
|
||||
sig128 = softfloat_shortShiftLeft128( sig64, sig0, -shiftDist );
|
||||
sig64 = sig128.v64;
|
||||
sig0 = sig128.v0;
|
||||
}
|
||||
} else {
|
||||
/*--------------------------------------------------------------------
|
||||
*--------------------------------------------------------------------*/
|
||||
if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 );
|
||||
sigExtra = softfloat_shiftRightJam64Extra( sig64, sig0, shiftDist );
|
||||
sig64 = sigExtra.v;
|
||||
sig0 = sigExtra.extra;
|
||||
}
|
||||
return softfloat_roundToI64( state, sign, sig64, sig0, roundingMode, exact );
|
||||
|
||||
}
|
||||
|
||||
-86
@@ -1,86 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
|
||||
University of California. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
uint_fast32_t
|
||||
f128_to_ui32( struct softfloat_state *state, float128_t a, uint_fast8_t roundingMode, bool exact )
|
||||
{
|
||||
union ui128_f128 uA;
|
||||
uint_fast64_t uiA64, uiA0;
|
||||
bool sign;
|
||||
int_fast32_t exp;
|
||||
uint_fast64_t sig64;
|
||||
int_fast32_t shiftDist;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
uA.f = a;
|
||||
uiA64 = uA.ui.v64;
|
||||
uiA0 = uA.ui.v0;
|
||||
sign = signF128UI64( uiA64 );
|
||||
exp = expF128UI64( uiA64 );
|
||||
sig64 = fracF128UI64( uiA64 ) | (uiA0 != 0);
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow)
|
||||
if ( (exp == 0x7FFF) && sig64 ) {
|
||||
#if (ui32_fromNaN == ui32_fromPosOverflow)
|
||||
sign = 0;
|
||||
#elif (ui32_fromNaN == ui32_fromNegOverflow)
|
||||
sign = 1;
|
||||
#else
|
||||
softfloat_raiseFlags( softfloat_flag_invalid );
|
||||
return ui32_fromNaN;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 );
|
||||
shiftDist = 0x4023 - exp;
|
||||
if ( 0 < shiftDist ) {
|
||||
sig64 = softfloat_shiftRightJam64( sig64, shiftDist );
|
||||
}
|
||||
return softfloat_roundToUI32( sign, sig64, roundingMode, exact );
|
||||
|
||||
}
|
||||
|
||||
-96
@@ -1,96 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
|
||||
University of California. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
uint_fast64_t
|
||||
f128_to_ui64( struct softfloat_state *state, float128_t a, uint_fast8_t roundingMode, bool exact )
|
||||
{
|
||||
union ui128_f128 uA;
|
||||
uint_fast64_t uiA64, uiA0;
|
||||
bool sign;
|
||||
int_fast32_t exp;
|
||||
uint_fast64_t sig64, sig0;
|
||||
int_fast32_t shiftDist;
|
||||
struct uint128 sig128;
|
||||
struct uint64_extra sigExtra;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
uA.f = a;
|
||||
uiA64 = uA.ui.v64;
|
||||
uiA0 = uA.ui.v0;
|
||||
sign = signF128UI64( uiA64 );
|
||||
exp = expF128UI64( uiA64 );
|
||||
sig64 = fracF128UI64( uiA64 );
|
||||
sig0 = uiA0;
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
shiftDist = 0x402F - exp;
|
||||
if ( shiftDist <= 0 ) {
|
||||
/*--------------------------------------------------------------------
|
||||
*--------------------------------------------------------------------*/
|
||||
if ( shiftDist < -15 ) {
|
||||
softfloat_raiseFlags( state, softfloat_flag_invalid );
|
||||
return
|
||||
(exp == 0x7FFF) && (sig64 | sig0) ? ui64_fromNaN
|
||||
: sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
|
||||
}
|
||||
/*--------------------------------------------------------------------
|
||||
*--------------------------------------------------------------------*/
|
||||
sig64 |= UINT64_C( 0x0001000000000000 );
|
||||
if ( shiftDist ) {
|
||||
sig128 = softfloat_shortShiftLeft128( sig64, sig0, -shiftDist );
|
||||
sig64 = sig128.v64;
|
||||
sig0 = sig128.v0;
|
||||
}
|
||||
} else {
|
||||
/*--------------------------------------------------------------------
|
||||
*--------------------------------------------------------------------*/
|
||||
if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 );
|
||||
sigExtra = softfloat_shiftRightJam64Extra( sig64, sig0, shiftDist );
|
||||
sig64 = sigExtra.v;
|
||||
sig0 = sigExtra.extra;
|
||||
}
|
||||
return softfloat_roundToUI64( state, sign, sig64, sig0, roundingMode, exact );
|
||||
|
||||
}
|
||||
|
||||
-96
@@ -1,96 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
|
||||
California. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
float128_t f32_to_f128( struct softfloat_state *state, float32_t a )
|
||||
{
|
||||
union ui32_f32 uA;
|
||||
uint_fast32_t uiA;
|
||||
bool sign;
|
||||
int_fast16_t exp;
|
||||
uint_fast32_t frac;
|
||||
struct commonNaN commonNaN;
|
||||
struct uint128 uiZ;
|
||||
struct exp16_sig32 normExpSig;
|
||||
union ui128_f128 uZ;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
uA.f = a;
|
||||
uiA = uA.ui;
|
||||
sign = signF32UI( uiA );
|
||||
exp = expF32UI( uiA );
|
||||
frac = fracF32UI( uiA );
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
if ( exp == 0xFF ) {
|
||||
if ( frac ) {
|
||||
softfloat_f32UIToCommonNaN( state, uiA, &commonNaN );
|
||||
uiZ = softfloat_commonNaNToF128UI( &commonNaN );
|
||||
} else {
|
||||
uiZ.v64 = packToF128UI64( sign, 0x7FFF, 0 );
|
||||
uiZ.v0 = 0;
|
||||
}
|
||||
goto uiZ;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
if ( ! exp ) {
|
||||
if ( ! frac ) {
|
||||
uiZ.v64 = packToF128UI64( sign, 0, 0 );
|
||||
uiZ.v0 = 0;
|
||||
goto uiZ;
|
||||
}
|
||||
normExpSig = softfloat_normSubnormalF32Sig( frac );
|
||||
exp = normExpSig.exp - 1;
|
||||
frac = normExpSig.sig;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
uiZ.v64 = packToF128UI64( sign, exp + 0x3F80, (uint_fast64_t) frac<<25 );
|
||||
uiZ.v0 = 0;
|
||||
uiZ:
|
||||
uZ.ui = uiZ;
|
||||
return uZ.f;
|
||||
|
||||
}
|
||||
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
|
||||
California. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
float128_t i32_to_f128( int32_t a )
|
||||
{
|
||||
uint_fast64_t uiZ64;
|
||||
bool sign;
|
||||
uint_fast32_t absA;
|
||||
int_fast8_t shiftDist;
|
||||
union ui128_f128 uZ;
|
||||
|
||||
uiZ64 = 0;
|
||||
if ( a ) {
|
||||
sign = (a < 0);
|
||||
absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a;
|
||||
shiftDist = softfloat_countLeadingZeros32( absA ) + 17;
|
||||
uiZ64 =
|
||||
packToF128UI64(
|
||||
sign, 0x402E - shiftDist, (uint_fast64_t) absA<<shiftDist );
|
||||
}
|
||||
uZ.ui.v64 = uiZ64;
|
||||
uZ.ui.v0 = 0;
|
||||
return uZ.f;
|
||||
|
||||
}
|
||||
|
||||
-155
@@ -1,155 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
|
||||
float128_t
|
||||
softfloat_addMagsF128(
|
||||
struct softfloat_state *state,
|
||||
uint_fast64_t uiA64,
|
||||
uint_fast64_t uiA0,
|
||||
uint_fast64_t uiB64,
|
||||
uint_fast64_t uiB0,
|
||||
bool signZ
|
||||
)
|
||||
{
|
||||
int_fast32_t expA;
|
||||
struct uint128 sigA;
|
||||
int_fast32_t expB;
|
||||
struct uint128 sigB;
|
||||
int_fast32_t expDiff;
|
||||
struct uint128 uiZ, sigZ;
|
||||
int_fast32_t expZ;
|
||||
uint_fast64_t sigZExtra;
|
||||
struct uint128_extra sig128Extra;
|
||||
union ui128_f128 uZ;
|
||||
|
||||
expA = expF128UI64( uiA64 );
|
||||
sigA.v64 = fracF128UI64( uiA64 );
|
||||
sigA.v0 = uiA0;
|
||||
expB = expF128UI64( uiB64 );
|
||||
sigB.v64 = fracF128UI64( uiB64 );
|
||||
sigB.v0 = uiB0;
|
||||
expDiff = expA - expB;
|
||||
if ( ! expDiff ) {
|
||||
if ( expA == 0x7FFF ) {
|
||||
if ( sigA.v64 | sigA.v0 | sigB.v64 | sigB.v0 ) goto propagateNaN;
|
||||
uiZ.v64 = uiA64;
|
||||
uiZ.v0 = uiA0;
|
||||
goto uiZ;
|
||||
}
|
||||
sigZ = softfloat_add128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 );
|
||||
if ( ! expA ) {
|
||||
uiZ.v64 = packToF128UI64( signZ, 0, sigZ.v64 );
|
||||
uiZ.v0 = sigZ.v0;
|
||||
goto uiZ;
|
||||
}
|
||||
expZ = expA;
|
||||
sigZ.v64 |= UINT64_C( 0x0002000000000000 );
|
||||
sigZExtra = 0;
|
||||
goto shiftRight1;
|
||||
}
|
||||
if ( expDiff < 0 ) {
|
||||
if ( expB == 0x7FFF ) {
|
||||
if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
|
||||
uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 );
|
||||
uiZ.v0 = 0;
|
||||
goto uiZ;
|
||||
}
|
||||
expZ = expB;
|
||||
if ( expA ) {
|
||||
sigA.v64 |= UINT64_C( 0x0001000000000000 );
|
||||
} else {
|
||||
++expDiff;
|
||||
sigZExtra = 0;
|
||||
if ( ! expDiff ) goto newlyAligned;
|
||||
}
|
||||
sig128Extra =
|
||||
softfloat_shiftRightJam128Extra( sigA.v64, sigA.v0, 0, -expDiff );
|
||||
sigA = sig128Extra.v;
|
||||
sigZExtra = sig128Extra.extra;
|
||||
} else {
|
||||
if ( expA == 0x7FFF ) {
|
||||
if ( sigA.v64 | sigA.v0 ) goto propagateNaN;
|
||||
uiZ.v64 = uiA64;
|
||||
uiZ.v0 = uiA0;
|
||||
goto uiZ;
|
||||
}
|
||||
expZ = expA;
|
||||
if ( expB ) {
|
||||
sigB.v64 |= UINT64_C( 0x0001000000000000 );
|
||||
} else {
|
||||
--expDiff;
|
||||
sigZExtra = 0;
|
||||
if ( ! expDiff ) goto newlyAligned;
|
||||
}
|
||||
sig128Extra =
|
||||
softfloat_shiftRightJam128Extra( sigB.v64, sigB.v0, 0, expDiff );
|
||||
sigB = sig128Extra.v;
|
||||
sigZExtra = sig128Extra.extra;
|
||||
}
|
||||
newlyAligned:
|
||||
sigZ =
|
||||
softfloat_add128(
|
||||
sigA.v64 | UINT64_C( 0x0001000000000000 ),
|
||||
sigA.v0,
|
||||
sigB.v64,
|
||||
sigB.v0
|
||||
);
|
||||
--expZ;
|
||||
if ( sigZ.v64 < UINT64_C( 0x0002000000000000 ) ) goto roundAndPack;
|
||||
++expZ;
|
||||
shiftRight1:
|
||||
sig128Extra =
|
||||
softfloat_shortShiftRightJam128Extra(
|
||||
sigZ.v64, sigZ.v0, sigZExtra, 1 );
|
||||
sigZ = sig128Extra.v;
|
||||
sigZExtra = sig128Extra.extra;
|
||||
roundAndPack:
|
||||
return
|
||||
softfloat_roundPackToF128( state, signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra );
|
||||
propagateNaN:
|
||||
uiZ = softfloat_propagateNaNF128UI( state, uiA64, uiA0, uiB64, uiB0 );
|
||||
uiZ:
|
||||
uZ.ui = uiZ;
|
||||
return uZ.f;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
|
||||
California. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
|
||||
float128_t
|
||||
softfloat_normRoundPackToF128(
|
||||
struct softfloat_state *state,
|
||||
bool sign, int_fast32_t exp, uint_fast64_t sig64, uint_fast64_t sig0 )
|
||||
{
|
||||
int_fast8_t shiftDist;
|
||||
struct uint128 sig128;
|
||||
union ui128_f128 uZ;
|
||||
uint_fast64_t sigExtra;
|
||||
struct uint128_extra sig128Extra;
|
||||
|
||||
if ( ! sig64 ) {
|
||||
exp -= 64;
|
||||
sig64 = sig0;
|
||||
sig0 = 0;
|
||||
}
|
||||
shiftDist = softfloat_countLeadingZeros64( sig64 ) - 15;
|
||||
exp -= shiftDist;
|
||||
if ( 0 <= shiftDist ) {
|
||||
if ( shiftDist ) {
|
||||
sig128 = softfloat_shortShiftLeft128( sig64, sig0, shiftDist );
|
||||
sig64 = sig128.v64;
|
||||
sig0 = sig128.v0;
|
||||
}
|
||||
if ( (uint32_t) exp < 0x7FFD ) {
|
||||
uZ.ui.v64 = packToF128UI64( sign, sig64 | sig0 ? exp : 0, sig64 );
|
||||
uZ.ui.v0 = sig0;
|
||||
return uZ.f;
|
||||
}
|
||||
sigExtra = 0;
|
||||
} else {
|
||||
sig128Extra =
|
||||
softfloat_shortShiftRightJam128Extra( sig64, sig0, 0, -shiftDist );
|
||||
sig64 = sig128Extra.v.v64;
|
||||
sig0 = sig128Extra.v.v0;
|
||||
sigExtra = sig128Extra.extra;
|
||||
}
|
||||
return softfloat_roundPackToF128( state, sign, exp, sig64, sig0, sigExtra );
|
||||
|
||||
}
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Interpreting the unsigned integer formed from concatenating `uiA64' and
|
||||
| `uiA0' as a 128-bit floating-point value, and likewise interpreting the
|
||||
| unsigned integer formed from concatenating `uiB64' and `uiB0' as another
|
||||
| 128-bit floating-point value, and assuming at least on of these floating-
|
||||
| point values is a NaN, returns the bit pattern of the combined NaN result.
|
||||
| If either original floating-point value is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
struct uint128
|
||||
softfloat_propagateNaNF128UI(
|
||||
struct softfloat_state *state,
|
||||
uint_fast64_t uiA64,
|
||||
uint_fast64_t uiA0,
|
||||
uint_fast64_t uiB64,
|
||||
uint_fast64_t uiB0
|
||||
)
|
||||
{
|
||||
bool isSigNaNA;
|
||||
struct uint128 uiZ;
|
||||
|
||||
isSigNaNA = softfloat_isSigNaNF128UI( uiA64, uiA0 );
|
||||
if ( isSigNaNA || softfloat_isSigNaNF128UI( uiB64, uiB0 ) ) {
|
||||
softfloat_raiseFlags( state, softfloat_flag_invalid );
|
||||
if ( isSigNaNA ) goto returnNonsigA;
|
||||
}
|
||||
if ( isNaNF128UI( uiA64, uiA0 ) ) {
|
||||
returnNonsigA:
|
||||
uiZ.v64 = uiA64;
|
||||
uiZ.v0 = uiA0;
|
||||
} else {
|
||||
uiZ.v64 = uiB64;
|
||||
uiZ.v0 = uiB0;
|
||||
}
|
||||
uiZ.v64 |= UINT64_C( 0x0000800000000000 );
|
||||
return uiZ;
|
||||
|
||||
}
|
||||
|
||||
-171
@@ -1,171 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
|
||||
California. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
float128_t
|
||||
softfloat_roundPackToF128(
|
||||
struct softfloat_state *state,
|
||||
bool sign,
|
||||
int_fast32_t exp,
|
||||
uint_fast64_t sig64,
|
||||
uint_fast64_t sig0,
|
||||
uint_fast64_t sigExtra
|
||||
)
|
||||
{
|
||||
uint_fast8_t roundingMode;
|
||||
bool roundNearEven, doIncrement, isTiny;
|
||||
struct uint128_extra sig128Extra;
|
||||
uint_fast64_t uiZ64, uiZ0;
|
||||
struct uint128 sig128;
|
||||
union ui128_f128 uZ;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
roundingMode = state->roundingMode;
|
||||
roundNearEven = (roundingMode == softfloat_round_near_even);
|
||||
doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra);
|
||||
if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
|
||||
doIncrement =
|
||||
(roundingMode
|
||||
== (sign ? softfloat_round_min : softfloat_round_max))
|
||||
&& sigExtra;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
if ( 0x7FFD <= (uint32_t) exp ) {
|
||||
if ( exp < 0 ) {
|
||||
/*----------------------------------------------------------------
|
||||
*----------------------------------------------------------------*/
|
||||
isTiny =
|
||||
(state->detectTininess
|
||||
== softfloat_tininess_beforeRounding)
|
||||
|| (exp < -1)
|
||||
|| ! doIncrement
|
||||
|| softfloat_lt128(
|
||||
sig64,
|
||||
sig0,
|
||||
UINT64_C( 0x0001FFFFFFFFFFFF ),
|
||||
UINT64_C( 0xFFFFFFFFFFFFFFFF )
|
||||
);
|
||||
sig128Extra =
|
||||
softfloat_shiftRightJam128Extra( sig64, sig0, sigExtra, -exp );
|
||||
sig64 = sig128Extra.v.v64;
|
||||
sig0 = sig128Extra.v.v0;
|
||||
sigExtra = sig128Extra.extra;
|
||||
exp = 0;
|
||||
if ( isTiny && sigExtra ) {
|
||||
softfloat_raiseFlags( state, softfloat_flag_underflow );
|
||||
}
|
||||
doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra);
|
||||
if (
|
||||
! roundNearEven
|
||||
&& (roundingMode != softfloat_round_near_maxMag)
|
||||
) {
|
||||
doIncrement =
|
||||
(roundingMode
|
||||
== (sign ? softfloat_round_min : softfloat_round_max))
|
||||
&& sigExtra;
|
||||
}
|
||||
} else if (
|
||||
(0x7FFD < exp)
|
||||
|| ((exp == 0x7FFD)
|
||||
&& softfloat_eq128(
|
||||
sig64,
|
||||
sig0,
|
||||
UINT64_C( 0x0001FFFFFFFFFFFF ),
|
||||
UINT64_C( 0xFFFFFFFFFFFFFFFF )
|
||||
)
|
||||
&& doIncrement)
|
||||
) {
|
||||
/*----------------------------------------------------------------
|
||||
*----------------------------------------------------------------*/
|
||||
softfloat_raiseFlags(
|
||||
state, softfloat_flag_overflow | softfloat_flag_inexact );
|
||||
if (
|
||||
roundNearEven
|
||||
|| (roundingMode == softfloat_round_near_maxMag)
|
||||
|| (roundingMode
|
||||
== (sign ? softfloat_round_min : softfloat_round_max))
|
||||
) {
|
||||
uiZ64 = packToF128UI64( sign, 0x7FFF, 0 );
|
||||
uiZ0 = 0;
|
||||
} else {
|
||||
uiZ64 =
|
||||
packToF128UI64(
|
||||
sign, 0x7FFE, UINT64_C( 0x0000FFFFFFFFFFFF ) );
|
||||
uiZ0 = UINT64_C( 0xFFFFFFFFFFFFFFFF );
|
||||
}
|
||||
goto uiZ;
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
if ( sigExtra ) {
|
||||
state->exceptionFlags |= softfloat_flag_inexact;
|
||||
#ifdef SOFTFLOAT_ROUND_ODD
|
||||
if ( roundingMode == softfloat_round_odd ) {
|
||||
sig0 |= 1;
|
||||
goto packReturn;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if ( doIncrement ) {
|
||||
sig128 = softfloat_add128( sig64, sig0, 0, 1 );
|
||||
sig64 = sig128.v64;
|
||||
sig0 =
|
||||
sig128.v0
|
||||
& ~(uint64_t)
|
||||
(! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
|
||||
& roundNearEven);
|
||||
} else {
|
||||
if ( ! (sig64 | sig0) ) exp = 0;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
*------------------------------------------------------------------------*/
|
||||
uiZ64 = packToF128UI64( sign, exp, sig64 );
|
||||
uiZ0 = sig0;
|
||||
uiZ:
|
||||
uZ.ui.v64 = uiZ64;
|
||||
uZ.ui.v0 = uiZ0;
|
||||
return uZ.f;
|
||||
|
||||
}
|
||||
|
||||
-140
@@ -1,140 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
|
||||
Package, Release 3e, by John R. Hauser.
|
||||
|
||||
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
|
||||
California. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions, and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the University nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
float128_t
|
||||
softfloat_subMagsF128(
|
||||
struct softfloat_state *state,
|
||||
uint_fast64_t uiA64,
|
||||
uint_fast64_t uiA0,
|
||||
uint_fast64_t uiB64,
|
||||
uint_fast64_t uiB0,
|
||||
bool signZ
|
||||
)
|
||||
{
|
||||
int_fast32_t expA;
|
||||
struct uint128 sigA;
|
||||
int_fast32_t expB;
|
||||
struct uint128 sigB, sigZ;
|
||||
int_fast32_t expDiff, expZ;
|
||||
struct uint128 uiZ;
|
||||
union ui128_f128 uZ;
|
||||
|
||||
expA = expF128UI64( uiA64 );
|
||||
sigA.v64 = fracF128UI64( uiA64 );
|
||||
sigA.v0 = uiA0;
|
||||
expB = expF128UI64( uiB64 );
|
||||
sigB.v64 = fracF128UI64( uiB64 );
|
||||
sigB.v0 = uiB0;
|
||||
sigA = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 4 );
|
||||
sigB = softfloat_shortShiftLeft128( sigB.v64, sigB.v0, 4 );
|
||||
expDiff = expA - expB;
|
||||
if ( 0 < expDiff ) goto expABigger;
|
||||
if ( expDiff < 0 ) goto expBBigger;
|
||||
if ( expA == 0x7FFF ) {
|
||||
if ( sigA.v64 | sigA.v0 | sigB.v64 | sigB.v0 ) goto propagateNaN;
|
||||
softfloat_raiseFlags( state, softfloat_flag_invalid );
|
||||
uiZ.v64 = defaultNaNF128UI64;
|
||||
uiZ.v0 = defaultNaNF128UI0;
|
||||
goto uiZ;
|
||||
}
|
||||
expZ = expA;
|
||||
if ( ! expZ ) expZ = 1;
|
||||
if ( sigB.v64 < sigA.v64 ) goto aBigger;
|
||||
if ( sigA.v64 < sigB.v64 ) goto bBigger;
|
||||
if ( sigB.v0 < sigA.v0 ) goto aBigger;
|
||||
if ( sigA.v0 < sigB.v0 ) goto bBigger;
|
||||
uiZ.v64 =
|
||||
packToF128UI64(
|
||||
(state->roundingMode == softfloat_round_min), 0, 0 );
|
||||
uiZ.v0 = 0;
|
||||
goto uiZ;
|
||||
expBBigger:
|
||||
if ( expB == 0x7FFF ) {
|
||||
if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
|
||||
uiZ.v64 = packToF128UI64( signZ ^ 1, 0x7FFF, 0 );
|
||||
uiZ.v0 = 0;
|
||||
goto uiZ;
|
||||
}
|
||||
if ( expA ) {
|
||||
sigA.v64 |= UINT64_C( 0x0010000000000000 );
|
||||
} else {
|
||||
++expDiff;
|
||||
if ( ! expDiff ) goto newlyAlignedBBigger;
|
||||
}
|
||||
sigA = softfloat_shiftRightJam128( sigA.v64, sigA.v0, -expDiff );
|
||||
newlyAlignedBBigger:
|
||||
expZ = expB;
|
||||
sigB.v64 |= UINT64_C( 0x0010000000000000 );
|
||||
bBigger:
|
||||
signZ = ! signZ;
|
||||
sigZ = softfloat_sub128( sigB.v64, sigB.v0, sigA.v64, sigA.v0 );
|
||||
goto normRoundPack;
|
||||
expABigger:
|
||||
if ( expA == 0x7FFF ) {
|
||||
if ( sigA.v64 | sigA.v0 ) goto propagateNaN;
|
||||
uiZ.v64 = uiA64;
|
||||
uiZ.v0 = uiA0;
|
||||
goto uiZ;
|
||||
}
|
||||
if ( expB ) {
|
||||
sigB.v64 |= UINT64_C( 0x0010000000000000 );
|
||||
} else {
|
||||
--expDiff;
|
||||
if ( ! expDiff ) goto newlyAlignedABigger;
|
||||
}
|
||||
sigB = softfloat_shiftRightJam128( sigB.v64, sigB.v0, expDiff );
|
||||
newlyAlignedABigger:
|
||||
expZ = expA;
|
||||
sigA.v64 |= UINT64_C( 0x0010000000000000 );
|
||||
aBigger:
|
||||
sigZ = softfloat_sub128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 );
|
||||
normRoundPack:
|
||||
return softfloat_normRoundPackToF128( state, signZ, expZ - 5, sigZ.v64, sigZ.v0 );
|
||||
propagateNaN:
|
||||
uiZ = softfloat_propagateNaNF128UI( state, uiA64, uiA0, uiB64, uiB0 );
|
||||
uiZ:
|
||||
uZ.ui = uiZ;
|
||||
return uZ.f;
|
||||
|
||||
}
|
||||
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2018 Ryan Houdek <Sonicadvance1@gmail.com>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
Vendored
+1
-1
Submodule External/Vulkan-Headers updated: cacef3039d...98f440ce68.
Vendored
-17
@@ -1,17 +0,0 @@
|
||||
set(SRCS_128BIT
|
||||
src/128bit/Impl.cpp
|
||||
src/128bit/atanll.c
|
||||
src/128bit/constll.c
|
||||
src/128bit/exp2ll.c
|
||||
src/128bit/floorll.c
|
||||
src/128bit/log2ll.c
|
||||
src/128bit/mtherr.c
|
||||
src/128bit/polevll.c
|
||||
src/128bit/sinll.c
|
||||
src/128bit/tanll.c)
|
||||
|
||||
# 128-bit library
|
||||
add_library(cephes_128bit STATIC ${SRCS_128BIT})
|
||||
target_link_libraries(cephes_128bit softfloat_3e)
|
||||
target_include_directories(cephes_128bit PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/)
|
||||
target_compile_options(cephes_128bit PRIVATE -fno-builtin)
|
||||
Vendored
-118
@@ -1,118 +0,0 @@
|
||||
The cephes math library is BSD licensed.
|
||||
The source can be accessed from https://www.netlib.org/cephes/
|
||||
|
||||
Original license from https://www.netlib.org/cephes/readme :
|
||||
> Some software in this archive may be from the book _Methods and
|
||||
> Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
|
||||
> International, 1989) or from the Cephes Mathematical Library, a
|
||||
> commercial product. In either event, it is copyrighted by the author.
|
||||
> What you see here may be used freely but it comes with no support or
|
||||
> guarantee.
|
||||
>
|
||||
> The two known misprints in the book are repaired here in the
|
||||
> source listings for the gamma function and the incomplete beta
|
||||
> integral.
|
||||
>
|
||||
>
|
||||
> Stephen L. Moshier
|
||||
> moshier@na-net.ornl.gov
|
||||
|
||||
The author was e-mailed and they allowed it to be relicensed under BSD.
|
||||
Resources:
|
||||
https://bugs.gentoo.org/687276
|
||||
https://lists.debian.org/debian-legal/2004/12/msg00295.html
|
||||
https://github.com/deepmind/torch-cephes/blob/master/LICENSE.txt
|
||||
https://github.com/nearform/node-cephes/blob/master/LICENSE
|
||||
|
||||
E-mail snippit from torch-cephes source:
|
||||
|
||||
Return-Path: <steve@moshier.net>
|
||||
X-Original-To: julien@cornebise.com
|
||||
Delivered-To: julien@cornebise.com
|
||||
Received: from atl4mhob11.myregisteredsite.com (atl4mhob11.myregisteredsite.com [209.17.115.49])
|
||||
by cornebise.com (Postfix) with ESMTP id D47B139FC0
|
||||
for <julien@cornebise.com>; Fri, 25 Oct 2013 16:32:40 +0200 (CEST)
|
||||
Received: from mailpod1.hostingplatform.com ([10.30.71.116])
|
||||
by atl4mhob11.myregisteredsite.com (8.14.4/8.14.4) with ESMTP id r9PEWcwQ003543
|
||||
for <julien@cornebise.com>; Fri, 25 Oct 2013 10:32:38 -0400
|
||||
Received: (qmail 11948 invoked by uid 0); 25 Oct 2013 12:36:20 -0000
|
||||
X-TCPREMOTEIP: 76.24.25.74
|
||||
X-Authenticated-UID: steve@moshier.net
|
||||
Received: from unknown (HELO d510.local) (steve@moshier.net@76.24.25.74)
|
||||
by 0 with ESMTPA; 25 Oct 2013 12:36:20 -0000
|
||||
Date: Fri, 25 Oct 2013 08:36:19 -0400 (EDT)
|
||||
From: Stephen Moshier <steve@moshier.net>
|
||||
X-X-Sender: steve@d510
|
||||
To: Julien Cornebise <julien@cornebise.com>
|
||||
Subject: Re: Cephes: permission to wrap+distribute for Lua
|
||||
In-Reply-To: <52653AD3.1010004@cornebise.com>
|
||||
Message-ID: <alpine.DEB.2.02.1310250827040.17646@d510>
|
||||
References: <52653AD3.1010004@cornebise.com>
|
||||
User-Agent: Alpine 2.02 (DEB 1266 2009-07-14)
|
||||
MIME-Version: 1.0
|
||||
Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed
|
||||
|
||||
|
||||
Julien, thank you for writing.
|
||||
BSD license is fine, modification is OK.
|
||||
There are more build scripts available in the web site distributions than
|
||||
there are on the Netlib. I think there is an update to Planck's radiation
|
||||
function that I haven't sent to Netlib yet. But Netlib is a more stable
|
||||
site, so it is better to cite that as a reference.
|
||||
|
||||
|
||||
On Mon, 21 Oct 2013, Julien Cornebise wrote:
|
||||
|
||||
> -----BEGIN PGP SIGNED MESSAGE-----
|
||||
> Hash: SHA1
|
||||
>
|
||||
> Dear Mr Moshier
|
||||
>
|
||||
> I am a researcher in mathematics and machine learning in London, and
|
||||
> am writing about your awesome Cephes library, whom I found at the
|
||||
> heart of Scipy.
|
||||
>
|
||||
> It is so useful that, with your permission, I would like to wrap it
|
||||
> for Lua and Torch (a machine learning overlay to Lua, specialized in
|
||||
> neural nets, see http://www.torch.ch). I would like to distribute it
|
||||
> as a package for Torch, including your source code along the wrapping
|
||||
> code.
|
||||
> This wouldbe a public package, distributed under BSD License. I have
|
||||
> put a first draft on github:
|
||||
> https://github.com/jucor/torch-cephes
|
||||
>
|
||||
> Hence my three questions, please:
|
||||
>
|
||||
> 1/ How would you like to be acknowledged, beyond the comments that are
|
||||
> already in your code? Do you have any standard header/disclaimer that
|
||||
> I could add to the documentation?
|
||||
>
|
||||
> 2/ At the moment, your code is left untouched. However, if I ever need
|
||||
> to modify bits of the code, what are the conditions/restrictions?
|
||||
> Nothing huge -- I definitely do not want to mess with it: I was
|
||||
> planning to use the natural completion of some functions on the
|
||||
> completed real line (e.g. CDF returing 1 when called with "infinity",
|
||||
> or quantiles returning -Infinity when called with 0), either natively
|
||||
> if supported, or by setting a specific flag via mtherr().
|
||||
>
|
||||
> 3/ I am currently using the source from Netlib. Do you recommend using
|
||||
> the source from your website instead ?
|
||||
>
|
||||
> Thank you very much for your attention,
|
||||
> and, more importantly, for the time and effort your poured into Cephes.
|
||||
>
|
||||
> Best regards,
|
||||
>
|
||||
> Julien Cornebise, Ph.D.
|
||||
> London, UK
|
||||
> http://www.cornebise.com/julien
|
||||
> -----BEGIN PGP SIGNATURE-----
|
||||
> Version: GnuPG v1.4.14 (Darwin)
|
||||
> Comment: GPGTools - http://gpgtools.org
|
||||
> Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/
|
||||
>
|
||||
> iEYEARECAAYFAlJlOtEACgkQKYR3gC0rw/gIpQCfZKu6+iDh9ghhm6QfsLXnldKN
|
||||
> BuIAn2zZHu1c/IrRAevhjM7N7xGg0LHO
|
||||
> =WeP5
|
||||
> -----END PGP SIGNATURE-----
|
||||
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
extern "C" {
|
||||
#include "SoftFloat-3e/platform.h"
|
||||
#include "SoftFloat-3e/softfloat.h"
|
||||
}
|
||||
|
||||
namespace FEXCore::cephes_128bit {
|
||||
float128_t atan2l(float128_t y, float128_t x);
|
||||
float128_t cosl(float128_t x);
|
||||
float128_t exp2l(float128_t x);
|
||||
float128_t log2l(float128_t x);
|
||||
float128_t sinl(float128_t x);
|
||||
float128_t tanl(float128_t x);
|
||||
}
|
||||
Vendored
-32
@@ -1,32 +0,0 @@
|
||||
#include "cephes_128bit.h"
|
||||
|
||||
extern "C" {
|
||||
// cephes_128bit functions
|
||||
float128_t cephes_f128_atan2l(float128_t y, float128_t x);
|
||||
float128_t cephes_f128_cosl(float128_t x);
|
||||
float128_t cephes_f128_exp2l(float128_t x);
|
||||
float128_t cephes_f128_log2l(float128_t x);
|
||||
float128_t cephes_f128_sinl(float128_t x);
|
||||
float128_t cephes_f128_tanl(float128_t x);
|
||||
}
|
||||
|
||||
namespace FEXCore::cephes_128bit {
|
||||
float128_t atan2l(float128_t y, float128_t x) {
|
||||
return cephes_f128_atan2l(y, x);
|
||||
}
|
||||
float128_t cosl(float128_t x) {
|
||||
return cephes_f128_cosl(x);
|
||||
}
|
||||
float128_t exp2l(float128_t x) {
|
||||
return cephes_f128_exp2l(x);
|
||||
}
|
||||
float128_t log2l(float128_t x) {
|
||||
return cephes_f128_log2l(x);
|
||||
}
|
||||
float128_t sinl(float128_t x) {
|
||||
return cephes_f128_sinl(x);
|
||||
}
|
||||
float128_t tanl(float128_t x) {
|
||||
return cephes_f128_tanl(x);
|
||||
}
|
||||
}
|
||||
Vendored
-221
@@ -1,221 +0,0 @@
|
||||
/* atanl.c
|
||||
*
|
||||
* Inverse circular tangent, 128-bit float128_t precision
|
||||
* (arctangent)
|
||||
*
|
||||
*
|
||||
*
|
||||
* SYNOPSIS:
|
||||
*
|
||||
* float128_t x, y, atanl();
|
||||
*
|
||||
* y = atanl( x );
|
||||
*
|
||||
*
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* Returns radian angle between -pi/2 and +pi/2 whose tangent
|
||||
* is x.
|
||||
*
|
||||
* Range reduction is from four intervals into the interval
|
||||
* from zero to tan( pi/8 ). The approximant uses a rational
|
||||
* function of degree 3/4 of the form x + x**3 P(x)/Q(x).
|
||||
*
|
||||
*
|
||||
*
|
||||
* ACCURACY:
|
||||
*
|
||||
* Relative error:
|
||||
* arithmetic domain # trials peak rms
|
||||
* IEEE -10, 10 100,000 2.6e-34 6.5e-35
|
||||
*
|
||||
*/
|
||||
/* atan2l()
|
||||
*
|
||||
* Quadrant correct inverse circular tangent,
|
||||
* float128_t precision
|
||||
*
|
||||
*
|
||||
*
|
||||
* SYNOPSIS:
|
||||
*
|
||||
* float128_t x, y, z, atan2l();
|
||||
*
|
||||
* z = atan2l( y, x );
|
||||
*
|
||||
*
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* Returns radian angle whose tangent is y/x.
|
||||
* Define compile time symbol ANSIC = 1 for ANSI standard,
|
||||
* range -PI < z <= +PI, args (y,x); else ANSIC = 0 for range
|
||||
* 0 to 2PI, args (x,y).
|
||||
*
|
||||
*
|
||||
*
|
||||
* ACCURACY:
|
||||
*
|
||||
* Relative error:
|
||||
* arithmetic domain # trials peak rms
|
||||
* IEEE -10, 10 100,000 3.2e-34 5.9e-35
|
||||
* See atan.c.
|
||||
*
|
||||
*/
|
||||
|
||||
/* atan.c */
|
||||
|
||||
|
||||
/*
|
||||
Cephes Math Library Release 2.2: December, 1990
|
||||
Copyright 1984, 1990 by Stephen L. Moshier
|
||||
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
|
||||
*/
|
||||
|
||||
#include "mconf.h"
|
||||
|
||||
/* arctan(x) = x + x^3 P(x^2)
|
||||
* Theoretical peak relative error = 3.0e-36
|
||||
* relative peak error spread = 6.6e-8
|
||||
*/
|
||||
static float128_t P[9] = {
|
||||
{0xf3f0105b1dae46bfULL, 0xbff45be85838aa26ULL}, // -6.635810778635296712545011270011752799963E-4L,
|
||||
{0x529a2bf25f15874bULL, 0xbffec0f17ae68a18ULL}, // -8.768423468036849091777415076702113400070E-1L,
|
||||
{0x3054a2e7144e265cULL, 0xc00397b0dc1f4d10ULL}, // -2.548067867495502632615671450650071218995E1L,
|
||||
{0x1e19d6b8c5cd9e65ULL, 0xc006f38d4e47779aULL}, // -2.497759878476618348858065206895055957104E2L,
|
||||
{0x69dcb1e41a413bddULL, 0xc0091f0a8586c642ULL}, // -1.148164399808514330375280133523543970854E3L,
|
||||
{0x501d0f5157516744ULL, 0xc00a5d08ba650145ULL}, // -2.792272753241044941703278827346430350236E3L,
|
||||
{0x16f18bf3f5b4b987ULL, 0xc00ace087656cfbeULL}, // -3.696264445691821235400930243493001671932E3L,
|
||||
{0x2966de608cbf9696ULL, 0xc00a3a5a8d629fc7ULL}, // -2.514829758941713674909996882101723647996E3L,
|
||||
{0xeb77db69572ecd22ULL, 0xc0085807a6c98431ULL}, // -6.880597774405940432145577545328795037141E2L
|
||||
};
|
||||
static float128_t Q[8] = {
|
||||
/* 1.000000000000000000000000000000000000000E0L, */
|
||||
{0x0cc994a760137543ULL, 0x40041d4c974b22bcULL}, // 3.566239794444800849656497338030115886153E1L,
|
||||
{0xa5b186c10b6a065eULL, 0x4007aed5b7e20c37ULL}, // 4.308348370818927353321556740027020068897E2L,
|
||||
{0x8711ebf202296129ULL, 0x400a37d5c6fdd0cdULL}, // 2.494680540950601626662048893678584497900E3L,
|
||||
{0x02d59339ee4eee21ULL, 0x400bef892855649eULL}, // 7.928572347062145288093560392463784743935E3L,
|
||||
{0xd9b903b0950fefb3ULL, 0x400cc7c8d1c45b09ULL}, // 1.458510242529987155225086911411015961174E4L,
|
||||
{0x174d6e0dae833752ULL, 0x400ce38f8ba0a897ULL}, // 1.547394317752562611786521896296215170819E4L,
|
||||
{0xfcbdd5dddcf7c68cULL, 0x400c1277f99a3d1aULL}, // 8.782996876218210302516194604424986107121E3L,
|
||||
{0x7099e48f01631a53ULL, 0x400a0205bd172325ULL}, // 2.064179332321782129643673263598686441900E3L
|
||||
};
|
||||
|
||||
/* tan( 3*pi/8 ) */
|
||||
static float128_t T3P8 = {0x6484597d89b3754bULL, 0x40003504f333f9deULL};
|
||||
|
||||
/* tan( pi/8 ) */
|
||||
static float128_t TP8 = {0x2422cbec4d9baa56ULL, 0x3ffda827999fcef3ULL};
|
||||
|
||||
static const float128_t zero = {0, 0};
|
||||
static const float128_t one = {0, 0x3fff000000000000ULL};
|
||||
__attribute__((unused)) static const float128_t f_2_p0 = {0x0000000000000000ULL, 0x4000000000000000ULL};
|
||||
__attribute__((unused)) static const float128_t f_3_p0 = {0x0000000000000000ULL, 0x4000800000000000ULL};
|
||||
|
||||
float128_t cephes_f128_atanl(float128_t x)
|
||||
{
|
||||
struct softfloat_state state = {};
|
||||
float128_t y, z;
|
||||
short sign;
|
||||
|
||||
/* make argument positive and save the sign */
|
||||
sign = 1;
|
||||
if( f128_lt(&state, x, zero) )
|
||||
{
|
||||
sign = -1;
|
||||
x = f128_complement_sign(x);
|
||||
}
|
||||
|
||||
/* range reduction */
|
||||
// if( x > T3P8 )
|
||||
|
||||
if( f128_lt(&state, T3P8, x) )
|
||||
{
|
||||
y = F128_PIO2L;
|
||||
x = f128_complement_sign( f128_div(&state, one, x));
|
||||
}
|
||||
|
||||
else if( f128_lt(&state, TP8, x) )
|
||||
{
|
||||
y = F128_PIO4L;
|
||||
x = f128_div(&state, f128_sub(&state, x, one), f128_add(&state, x, one));
|
||||
}
|
||||
else
|
||||
y = zero;
|
||||
|
||||
/* rational form in x**2 */
|
||||
z = f128_mul(&state, x, x);
|
||||
y = f128_add(&state, f128_add(&state, y, f128_mul(&state, f128_mul(&state, f128_div(&state, cephes_f128_polevll( z, P, 8 ), cephes_f128_p1evll( z, Q, 8 ) ), z), x)), x);
|
||||
|
||||
if( sign < 0 )
|
||||
y = f128_complement_sign(y);
|
||||
|
||||
return(y);
|
||||
}
|
||||
|
||||
/* atan2 */
|
||||
|
||||
|
||||
|
||||
#if ANSIC
|
||||
float128_t cephes_f128_atan2l( float128_t y, float128_t x )
|
||||
#else
|
||||
float128_t cephes_f128_atan2l( float128_t x, float128_t y )
|
||||
#endif
|
||||
{
|
||||
struct softfloat_state state = {};
|
||||
float128_t z, w;
|
||||
short code;
|
||||
|
||||
|
||||
code = 0;
|
||||
w = zero;
|
||||
|
||||
if( f128_lt(&state, x, zero) )
|
||||
code = 2;
|
||||
if( f128_lt(&state, y, zero) )
|
||||
code |= 1;
|
||||
|
||||
if( f128_eq(&state, x, zero) )
|
||||
{
|
||||
if( code & 1 )
|
||||
{
|
||||
#if ANSIC
|
||||
return( f128_complement_sign(F128_PIO2L) );
|
||||
#else
|
||||
return( f128_mul(&state, f_3_p0, F128_PIO2L) );
|
||||
#endif
|
||||
}
|
||||
if( f128_eq(&state, y, zero) )
|
||||
return zero;
|
||||
return( F128_PIO2L );
|
||||
}
|
||||
|
||||
if( f128_eq(&state, y, zero) )
|
||||
{
|
||||
if( code & 2 )
|
||||
return( F128_PIL );
|
||||
return zero;
|
||||
}
|
||||
|
||||
|
||||
switch( code )
|
||||
{
|
||||
#if ANSIC
|
||||
case 0:
|
||||
case 1: w = zero; break;
|
||||
case 2: w = F128_PIL; break;
|
||||
case 3: w = f128_complement_sign(F128_PIL); break;
|
||||
#else
|
||||
case 0: w = zero; break;
|
||||
case 1: w = f128_mul(&state, f_2_p0, F128_PIL); break;
|
||||
case 2:
|
||||
case 3: w = F128_PIL; break;
|
||||
#endif
|
||||
}
|
||||
|
||||
z = cephes_f128_atanl( f128_div(&state, y, x) );
|
||||
|
||||
return f128_add(&state, w, z );
|
||||
}
|
||||
Vendored
-34
@@ -1,34 +0,0 @@
|
||||
#include "mconf.h"
|
||||
|
||||
/* (1 - 2^-113) 2^16384 */
|
||||
float128_t F128_MAXNUML = {0xffffffffffffffffULL, 0x7ffeffffffffffffULL}; //1.189731495357231765085759326628007016196469e4932L;
|
||||
|
||||
/* 2^-113 */
|
||||
float128_t F128_MACHEPL = {0x0000000000000000ULL, 0x3f8e000000000000ULL}; // 9.629649721936179265279889712924636592690508e-35L;
|
||||
|
||||
/* (1 + 2^-112) 2^-16382 */
|
||||
float128_t F128_UFTHRESHL = {0x0000000000000001ULL, 0x0001000000000000ULL}; // 3.362103143112093506262677817321753250115591e-4932L;
|
||||
|
||||
/* 2^-16494 */
|
||||
float128_t F128_MINNUML = {0x0000000000000001ULL, 0x0000000000000000ULL}; // 6.475175119438025110924438958227646552499569e-4966L;
|
||||
|
||||
/* ln(MAXNUM) */
|
||||
float128_t F128_MAXLOGL = {0xf35793c7673007e6ULL, 0x400c62e42fefa39eULL}; // 1.1356523406294143949491931077970764891253E4L;
|
||||
|
||||
/* ln(MINNUM) */
|
||||
float128_t F128_MINLOGL = {0x2c89d24d65e96274ULL, 0xc00c654628220780ULL}; // -1.143276959615573793352782661133116431383730e4L;
|
||||
|
||||
/* ln(UFTHRESH) */
|
||||
/* float128_t F128_MINLOGL = -1.135513711193302405887309661372784853802025e4L; */
|
||||
|
||||
float128_t F128_PIL = {0x8469898cc51701b8ULL, 0x4000921fb54442d1ULL}; // 3.141592653589793238462643383279502884197169L;
|
||||
|
||||
float128_t F128_PIO2L = {0x8469898cc51701b8ULL, 0x3fff921fb54442d1ULL}; // 1.570796326794896619231321691639751442098585L;
|
||||
|
||||
float128_t F128_PIO4L = {0x8469898cc51701b8ULL, 0x3ffe921fb54442d1ULL}; // 0.7853981633974483096156608458198757210492923L;
|
||||
|
||||
float128_t F128_LOGE2L = {0xf35793c7673007e6ULL, 0x3ffe62e42fefa39eULL}; // 0.6931471805599453094172321214581765680755001L;
|
||||
|
||||
float128_t F128_LOG2EL = {0xe1777d0ffda0d23aULL, 0x3fff71547652b82fULL}; // 1.442695040888963407359924681001892137426646L;
|
||||
|
||||
float128_t F128_INFINITYL = {0x0000000000000000ULL, 0x7fff000000000000ULL}; // 1.0L / 0.0L;
|
||||
Vendored
-122
@@ -1,122 +0,0 @@
|
||||
/* exp2l.c
|
||||
*
|
||||
* Base 2 exponential function, 128-bit float128_t precision
|
||||
*
|
||||
*
|
||||
*
|
||||
* SYNOPSIS:
|
||||
*
|
||||
* float128_t x, y, exp2l();
|
||||
*
|
||||
* y = exp2l( x );
|
||||
*
|
||||
*
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* Returns 2 raised to the x power.
|
||||
*
|
||||
* Range reduction is accomplished by separating the argument
|
||||
* into an integer k and fraction f such that
|
||||
* x k f
|
||||
* 2 = 2 2.
|
||||
*
|
||||
* A Pade' form
|
||||
*
|
||||
* 1 + 2x P(x**2) / (Q(x**2) - x P(x**2) )
|
||||
*
|
||||
* approximates 2**x in the basic range [-0.5, 0.5].
|
||||
*
|
||||
*
|
||||
* ACCURACY:
|
||||
*
|
||||
* Relative error:
|
||||
* arithmetic domain # trials peak rms
|
||||
* IEEE +-16300 100,000 2.0e-34 4.8e-35
|
||||
*
|
||||
*
|
||||
* See exp.c for comments on error amplification.
|
||||
*
|
||||
*
|
||||
* ERROR MESSAGES:
|
||||
*
|
||||
* message condition value returned
|
||||
* exp2l underflow x < -16382 0.0
|
||||
* exp2l overflow x >= 16384 MAXNUM
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Cephes Math Library Release 2.2: January, 1991
|
||||
Copyright 1984, 1991 by Stephen L. Moshier
|
||||
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
|
||||
*/
|
||||
|
||||
#include "mconf.h"
|
||||
static char fname[] = {"exp2l"};
|
||||
|
||||
/* Pade' coefficients for 2^x - 1
|
||||
Theoretical peak relative error = 1.4e-40,
|
||||
relative peak error spread = 6.8e-14
|
||||
*/
|
||||
static float128_t P[5] = {
|
||||
{0x3008ca100ca13471ULL, 0x40063d6f2f556577ULL}, // 1.587171580015525194694938306936721666031E2L,
|
||||
{0x9fac10fe43d72769ULL, 0x40122e00e88b4606ULL}, // 6.185032670011643762127954396427045467506E5L,
|
||||
{0x4c22cf0c6c7a8fc7ULL, 0x401c0eb996d98ba4ULL}, // 5.677513871931844661829755443994214173883E8L,
|
||||
{0x4acd9b1339dda08aULL, 0x40241d19e728a6beULL}, // 1.530625323728429161131811299626419117557E11L,
|
||||
{0xae406b996488ba7aULL, 0x402a0840400c1c84ULL}, // 9.079594442980146270952372234833529694788E12L
|
||||
};
|
||||
static float128_t Q[5] = {
|
||||
/* 1.000000000000000000000000000000000000000E0L, */
|
||||
{0xcf48c9db239c2189ULL, 0x400c827029417a6aULL}, // 1.236602014442099053716561665053645270207E4L,
|
||||
{0xb20f61f9a3c778b9ULL, 0x40174d9860120d5dULL}, // 2.186249607051644894762167991800811827835E7L,
|
||||
{0x9f361a3e85f209ceULL, 0x4020457bc8296e4eULL}, // 1.092141473886177435056423606755843616331E10L,
|
||||
{0x2dcf78c66f0a65ddULL, 0x40275b0c5bcbd7a7ULL}, // 1.490560994263653042761789432690793026977E12L,
|
||||
{0x4e4a9905cf9c9235ULL, 0x402b7d3bcb89794eULL}, // 2.619817175234089411411070339065679229869E13L
|
||||
};
|
||||
|
||||
static const float128_t MAXL2 = {0x0000000000000000ULL, 0x400d000000000000ULL};
|
||||
static const float128_t MINL2 = {0x0000000000000000ULL, 0xc00cfff000000000ULL};
|
||||
static const float128_t zero = {0, 0};
|
||||
static const float128_t f_0_p5 = {0, 0x3ffe000000000000ULL};
|
||||
static const float128_t one = {0, 0x3fff000000000000ULL};
|
||||
|
||||
extern float128_t F128_MAXNUML;
|
||||
|
||||
float128_t cephes_f128_exp2l(float128_t x) {
|
||||
struct softfloat_state state = {};
|
||||
float128_t px, xx;
|
||||
int n;
|
||||
|
||||
if( f128_le(&state, MAXL2, x))
|
||||
{
|
||||
mtherr( fname, OVERFLOW );
|
||||
return( F128_MAXNUML );
|
||||
}
|
||||
|
||||
if(f128_lt(&state, x, MINL2) )
|
||||
{
|
||||
mtherr( fname, UNDERFLOW );
|
||||
return zero;
|
||||
}
|
||||
|
||||
xx = x; /* save x */
|
||||
/* separate into integer and fractional parts */
|
||||
px = cephes_f128_floorl(f128_add(&state, x, f_0_p5));
|
||||
n = f128_to_i32(&state, px, softfloat_round_near_even, true);
|
||||
x = f128_sub(&state, x, px);
|
||||
|
||||
/* rational approximation
|
||||
* exp2(x) = 1.0 + 2xP(xx)/(Q(xx) - P(xx))
|
||||
* where xx = x**2
|
||||
*/
|
||||
xx = f128_mul(&state, x, x);
|
||||
px = f128_mul(&state, x, cephes_f128_polevll( xx, P, 4 ));
|
||||
x = f128_div(&state, px, f128_sub(&state, cephes_f128_p1evll( xx, Q, 5 ), px));
|
||||
x = f128_add(&state, one, cephes_f128_ldexpl( x, 1 ));
|
||||
|
||||
/* scale by power of 2 */
|
||||
x = cephes_f128_ldexpl( x, n );
|
||||
return(x);
|
||||
}
|
||||
Vendored
-475
@@ -1,475 +0,0 @@
|
||||
/* ceill()
|
||||
* floorl()
|
||||
* frexpl()
|
||||
* ldexpl()
|
||||
* fabsl()
|
||||
* signbitl()
|
||||
* isnanl()
|
||||
* isfinitel()
|
||||
*
|
||||
* Floating point numeric utilities
|
||||
*
|
||||
*
|
||||
*
|
||||
* SYNOPSIS:
|
||||
*
|
||||
* float128_t x, y;
|
||||
* float128_t ceill(), floorl(), frexpl(), ldexpl(), fabsl();
|
||||
* int signbitl(), isnanl(), isfinitel();
|
||||
* int expnt, n;
|
||||
*
|
||||
* y = floorl(x);
|
||||
* y = ceill(x);
|
||||
* y = frexpl( x, &expnt );
|
||||
* y = ldexpl( x, n );
|
||||
* y = fabsl( x );
|
||||
*
|
||||
*
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* All four routines return a float128_t precision floating point
|
||||
* result.
|
||||
*
|
||||
* floorl() returns the largest integer less than or equal to x.
|
||||
* It truncates toward minus infinity.
|
||||
*
|
||||
* ceill() returns the smallest integer greater than or equal
|
||||
* to x. It truncates toward plus infinity.
|
||||
*
|
||||
* frexpl() extracts the exponent from x. It returns an integer
|
||||
* power of two to expnt and the significand between 0.5 and 1
|
||||
* to y. Thus x = y * 2**expn.
|
||||
*
|
||||
* ldexpl() multiplies x by 2**n.
|
||||
*
|
||||
* fabsl() returns the absolute value of its argument.
|
||||
*
|
||||
* signbitl(x) returns 1 if the sign bit of x is 1, else 0.
|
||||
*
|
||||
* These functions are part of the standard C run time library
|
||||
* for some but not all C compilers. The ones supplied are
|
||||
* written in C for IEEE arithmetic. They should
|
||||
* be used only if your compiler library does not already have
|
||||
* them.
|
||||
*
|
||||
* The IEEE versions assume that denormal numbers are implemented
|
||||
* in the arithmetic. Some modifications will be required if
|
||||
* the arithmetic has abrupt rather than gradual underflow.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Cephes Math Library Release 2.2: July, 1992
|
||||
Copyright 1984, 1987, 1988, 1992 by Stephen L. Moshier
|
||||
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
|
||||
*/
|
||||
|
||||
#include "mconf.h"
|
||||
#define DENORMAL 1
|
||||
|
||||
#ifdef UNK
|
||||
char *unkmsg = "ceill(), floorl(), frexpl(), ldexpl() must be rewritten!\n";
|
||||
#undef UNK
|
||||
#define MIEEE 1
|
||||
#define EXPOFS 0
|
||||
#endif
|
||||
|
||||
#ifdef IBMPC
|
||||
#define NBITS 113
|
||||
#define EXPOFS 7
|
||||
#endif
|
||||
|
||||
#ifdef MIEEE
|
||||
#define NBITS 113
|
||||
#define EXPOFS 0
|
||||
#endif
|
||||
|
||||
extern float128_t F128_MAXNUML;
|
||||
|
||||
|
||||
static const float128_t zero = {0, 0};
|
||||
static const float128_t f_0_p5 = {0, 0x3ffe000000000000ULL};
|
||||
static const float128_t one = {0, 0x3fff000000000000ULL};
|
||||
static const float128_t neg_one = {0, 0xbfff000000000000ULL};
|
||||
static const float128_t f_2_p0 = {0, 0x4000000000000000ULL};
|
||||
|
||||
float128_t cephes_f128_fabsl(float128_t x)
|
||||
{
|
||||
struct softfloat_state state = {};
|
||||
|
||||
if( f128_lt(&state, x, zero) )
|
||||
return f128_sub(&state, zero, x );
|
||||
else
|
||||
return( x );
|
||||
}
|
||||
|
||||
|
||||
|
||||
float128_t cephes_f128_ceill(float128_t x)
|
||||
{
|
||||
float128_t y;
|
||||
|
||||
#ifdef UNK
|
||||
mtherr( "ceill", DOMAIN );
|
||||
return(0.0L);
|
||||
#endif
|
||||
|
||||
struct softfloat_state state = {};
|
||||
y = cephes_f128_floorl(x);
|
||||
if( f128_lt(&state, y, x) )
|
||||
y = f128_add(&state, y, one);
|
||||
return(y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Bit clearing masks: */
|
||||
|
||||
static unsigned short bmask[] = {
|
||||
0xffff,
|
||||
0xfffe,
|
||||
0xfffc,
|
||||
0xfff8,
|
||||
0xfff0,
|
||||
0xffe0,
|
||||
0xffc0,
|
||||
0xff80,
|
||||
0xff00,
|
||||
0xfe00,
|
||||
0xfc00,
|
||||
0xf800,
|
||||
0xf000,
|
||||
0xe000,
|
||||
0xc000,
|
||||
0x8000,
|
||||
0x0000,
|
||||
};
|
||||
|
||||
|
||||
|
||||
float128_t cephes_f128_floorl(float128_t x)
|
||||
{
|
||||
union
|
||||
{
|
||||
float128_t y;
|
||||
unsigned short sh[8];
|
||||
} u;
|
||||
int e, j;
|
||||
|
||||
#ifdef UNK
|
||||
mtherr( "floor", DOMAIN );
|
||||
return(0.0L);
|
||||
#endif
|
||||
|
||||
struct softfloat_state state = {};
|
||||
u.y = x;
|
||||
/* find the exponent (power of 2) */
|
||||
e = (u.sh[EXPOFS] & 0x7fff) - 0x3fff;
|
||||
|
||||
if( e < 0 )
|
||||
{
|
||||
if( f128_lt(&state, u.y, zero) )
|
||||
return neg_one;
|
||||
else
|
||||
return zero;
|
||||
}
|
||||
|
||||
#ifdef IBMPC
|
||||
j = 0;
|
||||
#endif
|
||||
|
||||
#ifdef MIEEE
|
||||
j = 7;
|
||||
#endif
|
||||
|
||||
e = (NBITS - 1) - e;
|
||||
/* clean out 16 bits at a time */
|
||||
while( e >= 16 )
|
||||
{
|
||||
#ifdef IBMPC
|
||||
u.sh[j++] = 0;
|
||||
#endif
|
||||
|
||||
#ifdef MIEEE
|
||||
u.sh[j--] = 0;
|
||||
#endif
|
||||
e -= 16;
|
||||
}
|
||||
|
||||
/* clear the remaining bits */
|
||||
if( e > 0 )
|
||||
u.sh[j] &= bmask[e];
|
||||
|
||||
if( f128_lt(&state, x, zero) && !f128_eq(&state, u.y, x) )
|
||||
u.y = f128_sub(&state, u.y, one);;
|
||||
|
||||
return(u.y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
float128_t cephes_f128_frexpl( float128_t x, int *pw2 )
|
||||
{
|
||||
union
|
||||
{
|
||||
float128_t y;
|
||||
unsigned short sh[8];
|
||||
} u;
|
||||
int i, k;
|
||||
|
||||
struct softfloat_state state = {};
|
||||
u.y = x;
|
||||
|
||||
#ifdef UNK
|
||||
mtherr( "frexp", DOMAIN );
|
||||
return(0.0L);
|
||||
#endif
|
||||
|
||||
/* find the exponent (power of 2) */
|
||||
i = u.sh[EXPOFS] & 0x7fff;
|
||||
|
||||
if( i == 0 )
|
||||
{
|
||||
if( f128_eq(&state, u.y, zero))
|
||||
{
|
||||
*pw2 = 0;
|
||||
return zero;
|
||||
}
|
||||
/* Number is denormal or zero */
|
||||
#if DENORMAL
|
||||
/* Handle denormal number. */
|
||||
do
|
||||
{
|
||||
u.y = f128_mul(&state, u.y, f_2_p0);
|
||||
i -= 1;
|
||||
k = u.sh[EXPOFS] & 0x7fff;
|
||||
}
|
||||
while( (k == 0) && (i > -115) );
|
||||
i = i + k;
|
||||
#else
|
||||
*pw2 = 0;
|
||||
return(0.0L);
|
||||
#endif /* DENORMAL */
|
||||
}
|
||||
|
||||
*pw2 = i - 0x3ffe;
|
||||
u.sh[EXPOFS] = 0x3ffe;
|
||||
return( u.y );
|
||||
}
|
||||
|
||||
|
||||
float128_t cephes_f128_ldexpl( float128_t x, int pw2 )
|
||||
{
|
||||
union
|
||||
{
|
||||
float128_t y;
|
||||
unsigned short sh[8];
|
||||
} u;
|
||||
long e;
|
||||
|
||||
#ifdef UNK
|
||||
mtherr( "ldexp", DOMAIN );
|
||||
return zero;
|
||||
#endif
|
||||
|
||||
struct softfloat_state state = {};
|
||||
u.y = x;
|
||||
while( (e = (u.sh[EXPOFS] & 0x7fffL)) == 0 )
|
||||
{
|
||||
#if DENORMAL
|
||||
if( f128_eq(&state, u.y, zero))
|
||||
{
|
||||
return zero;
|
||||
}
|
||||
/* Input is denormal. */
|
||||
if( pw2 > 0 )
|
||||
{
|
||||
u.y = f128_mul(&state, u.y, f_2_p0);
|
||||
pw2 -= 1;
|
||||
}
|
||||
if( pw2 < 0 )
|
||||
{
|
||||
if( pw2 < -113 )
|
||||
return zero;
|
||||
u.y = f128_sub(&state, u.y, f_0_p5);
|
||||
pw2 += 1;
|
||||
}
|
||||
if( pw2 == 0 )
|
||||
return(u.y);
|
||||
#else
|
||||
return zero;
|
||||
#endif
|
||||
}
|
||||
|
||||
e = e + pw2;
|
||||
|
||||
/* Handle overflow */
|
||||
if( e > 0x7ffeL )
|
||||
{
|
||||
e = u.sh[EXPOFS];
|
||||
u.y = zero;
|
||||
u.sh[EXPOFS] = e | 0x7fff;
|
||||
return( u.y );
|
||||
}
|
||||
u.sh[EXPOFS] &= 0x8000;
|
||||
/* Handle denormalized results */
|
||||
if( e < 1 )
|
||||
{
|
||||
#if DENORMAL
|
||||
if( e < -113 )
|
||||
return zero;
|
||||
u.sh[EXPOFS] |= 1;
|
||||
while( e < 1 )
|
||||
{
|
||||
u.y = f128_sub(&state, u.y, f_0_p5);
|
||||
e += 1;
|
||||
}
|
||||
e = 0;
|
||||
#else
|
||||
return zero;
|
||||
#endif
|
||||
}
|
||||
|
||||
u.sh[EXPOFS] |= e & 0x7fff;
|
||||
return(u.y);
|
||||
}
|
||||
|
||||
/* Return 1 if x is a number that is Not a Number, else return 0. */
|
||||
|
||||
int cephes_f128_isnanl(float128_t x)
|
||||
{
|
||||
#ifdef NANS
|
||||
union
|
||||
{
|
||||
float128_t d;
|
||||
unsigned short s[8];
|
||||
unsigned int i[4];
|
||||
} u;
|
||||
|
||||
u.d = x;
|
||||
|
||||
if( sizeof(int) == 4 )
|
||||
{
|
||||
#ifdef IBMPC
|
||||
if( ((u.s[7] & 0x7fff) == 0x7fff)
|
||||
&& ((u.i[3] & 0x7fff) | u.i[2] | u.i[1] | u.i[0]))
|
||||
return 1;
|
||||
#endif
|
||||
#ifdef MIEEE
|
||||
if( ((u.i[0] & 0x7fff0000) == 0x7fff0000)
|
||||
&& ((u.i[0] & 0x7fff) | u.i[1] | u.i[2] | u.i[3]))
|
||||
return 1;
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
{ /* size int not 4 */
|
||||
#ifdef IBMPC
|
||||
if( (u.s[7] & 0x7fff) == 0x7fff)
|
||||
{
|
||||
if((u.s[6] & 0x7fff) | u.s[5] | u.s[4] | u.s[3] | u.s[2] | u.s[1] | u.s[0])
|
||||
return(1);
|
||||
}
|
||||
#endif
|
||||
#ifdef MIEEE
|
||||
if( (u.s[0] & 0x7fff) == 0x7fff)
|
||||
{
|
||||
if((u.s[1] & 0x7fff) | (u.s[2] & 0x7fff) | u.s[3] | u.s[4] | u.s[5] | u.s[6] | u.s[7])
|
||||
return(1);
|
||||
}
|
||||
#endif
|
||||
return(0);
|
||||
} /* size int not 4 */
|
||||
|
||||
#else
|
||||
/* No NANS. */
|
||||
return(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Return 1 if x is not infinite and is not a NaN. */
|
||||
|
||||
int cephes_f128_isfinitel(float128_t x)
|
||||
{
|
||||
#ifdef INFINITIES
|
||||
union
|
||||
{
|
||||
float128_t d;
|
||||
unsigned short s[8];
|
||||
unsigned int i[4];
|
||||
} u;
|
||||
|
||||
u.d = x;
|
||||
|
||||
if( sizeof(int) == 4 )
|
||||
{
|
||||
#ifdef IBMPC
|
||||
if( (u.s[7] & 0x7fff) != 0x7fff)
|
||||
return 1;
|
||||
#endif
|
||||
#ifdef MIEEE
|
||||
if( (u.i[0] & 0x7fff0000) != 0x7fff0000)
|
||||
return 1;
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef IBMPC
|
||||
if( (u.s[7] & 0x7fff) != 0x7fff)
|
||||
return 1;
|
||||
#endif
|
||||
#ifdef MIEEE
|
||||
if( (u.s[0] & 0x7fff) != 0x7fff)
|
||||
return 1;
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
#else
|
||||
/* No INFINITY. */
|
||||
return(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Return 1 if the sign bit of x is 1, else 0. */
|
||||
|
||||
int cephes_f128_signbitl(float128_t x)
|
||||
{
|
||||
union
|
||||
{
|
||||
float128_t d;
|
||||
short s[8];
|
||||
int i[4];
|
||||
} u;
|
||||
|
||||
u.d = x;
|
||||
|
||||
if( sizeof(int) == 4 )
|
||||
{
|
||||
#ifdef IBMPC
|
||||
return( u.s[7] < 0 );
|
||||
#endif
|
||||
#ifdef DEC
|
||||
error no such DEC format
|
||||
#endif
|
||||
#ifdef MIEEE
|
||||
return( u.i[0] < 0 );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef IBMPC
|
||||
return( u.s[7] < 0 );
|
||||
#endif
|
||||
#ifdef DEC
|
||||
error no such DEC format
|
||||
#endif
|
||||
#ifdef MIEEE
|
||||
return( u.s[0] < 0 );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
Vendored
-209
@@ -1,209 +0,0 @@
|
||||
/* cephes_f128_log2l.c
|
||||
*
|
||||
* Base 2 logarithm, float128_t precision
|
||||
*
|
||||
*
|
||||
*
|
||||
* SYNOPSIS:
|
||||
*
|
||||
* float128_t x, y, cephes_f128_log2l();
|
||||
*
|
||||
* y = cephes_f128_log2l( x );
|
||||
*
|
||||
*
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* Returns the base 2 logarithm of x.
|
||||
*
|
||||
* The argument is separated into its exponent and fractional
|
||||
* parts. If the exponent is between -1 and +1, the (natural)
|
||||
* logarithm of the fraction is approximated by
|
||||
*
|
||||
* log(1+x) = x - 0.5 x**2 + x**3 P(x)/Q(x).
|
||||
*
|
||||
* Otherwise, setting z = 2(x-1)/x+1),
|
||||
*
|
||||
* log(x) = z + z**3 P(z)/Q(z).
|
||||
*
|
||||
*
|
||||
*
|
||||
* ACCURACY:
|
||||
*
|
||||
* Relative error:
|
||||
* arithmetic domain # trials peak rms
|
||||
* IEEE 0.5, 2.0 100,000 1.3e-34 4.5e-35
|
||||
* IEEE exp(+-10000) 100,000 9.6e-35 4.0e-35
|
||||
*
|
||||
* In the tests over the interval exp(+-10000), the logarithms
|
||||
* of the random arguments were uniformly distributed over
|
||||
* [-10000, +10000].
|
||||
*
|
||||
* ERROR MESSAGES:
|
||||
*
|
||||
* log singularity: x = 0; returns MINLOG
|
||||
* log domain: x < 0; returns MINLOG
|
||||
*/
|
||||
|
||||
/*
|
||||
Cephes Math Library Release 2.2: January, 1991
|
||||
Copyright 1984, 1991 by Stephen L. Moshier
|
||||
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
|
||||
*/
|
||||
|
||||
#include "mconf.h"
|
||||
static char fname[] = {"cephes_f128_log2l"};
|
||||
|
||||
/* Coefficients for ln(1+x) = x - x**2/2 + x**3 P(x)/Q(x)
|
||||
* 1/sqrt(2) <= x < sqrt(2)
|
||||
* Theoretical peak relative error = 5.3e-37,
|
||||
* relative peak error spread = 2.3e-14
|
||||
*/
|
||||
static float128_t P[13] = {
|
||||
{0x95434922008560fcULL, 0x3feb9d04a0d6ed82ULL}, // 1.538612243596254322971797716843006400388E-6L
|
||||
{0x2e9cb5e91a8c2fa0ULL, 0x3ffdffd7e21347ccULL}, // 4.998469661968096229986658302195402690910E-1L
|
||||
{0x674c43ea62a592e7ULL, 0x400373615178fe96ULL}, // 2.321125933898420063925789532045674660756E1L
|
||||
{0xfa539715d5fd0560ULL, 0x40079b73a8639c28ULL}, // 4.114517881637811823002128927449878962058E2L
|
||||
{0x5ec5c60d38b7fa2aULL, 0x400ade1e79b3ae12ULL}, // 3.824952356185897735160588078446136783779E3L
|
||||
{0x6369f0cada64eeecULL, 0x400d4ca24f0550cfULL}, // 2.128857716871515081352991964243375186031E4L
|
||||
{0x115104b644c1f464ULL, 0x400f28a791822d40ULL}, // 7.594356839258970405033155585486712125861E4L
|
||||
{0x95ec43488121aff8ULL, 0x40105f196a49f171ULL}, // 1.797628303815655343403735250238293741397E5L
|
||||
{0xa2484b7171ab5034ULL, 0x401116caba9f2757ULL}, // 2.854829159639697837788887080758954924001E5L
|
||||
{0xe49b2bf8646a8a1eULL, 0x401125a72eb05ba7ULL}, // 3.007007295140399532324943111654767187848E5L
|
||||
{0x17ac5c737d1b8ad4ULL, 0x4010897ca319418dULL}, // 2.014652742082537582487669938141683759923E5L
|
||||
{0x9ff15925da76d408ULL, 0x400f2f8f8bfbf9a1ULL}, // 7.771154681358524243729929227226708890930E4L
|
||||
{0xe740b8544d79077cULL, 0x400c9a7dcad5d0efULL}, // 1.313572404063446165910279910527789794488E4L
|
||||
};
|
||||
static float128_t Q[12] = {
|
||||
/* 1.000000000000000000000000000000000000000E0L, */
|
||||
{0x4a2113daac8d7fa5ULL,0x40048322fbda4d3fULL}, // 4.839208193348159620282142911143429644326E1L,
|
||||
{0x9efb2fe2c778f56fULL,0x4008c73f14777e56ULL}, // 9.104928120962988414618126155557301584078E2L,
|
||||
{0xf23a98d434d3a705ULL,0x400c1dd933ea5565ULL}, // 9.147150349299596453976674231612674085381E3L,
|
||||
{0x4b44059a3b76f461ULL,0x400eb5f4d77aed02ULL}, // 5.605842085972455027590989944010492125825E4L,
|
||||
{0x2962234d48fff0bcULL,0x4010b71bb67f5effULL}, // 2.248234257620569139969141618556349415120E5L,
|
||||
{0xe673c713bcf24ee3ULL,0x40122b6c5ddac3b8ULL}, // 6.132189329546557743179177159925690841200E5L,
|
||||
{0x34d8d36e8de37c71ULL,0x40131ab83fa3b03bULL}, // 1.158019977462989115839826904108208787040E6L,
|
||||
{0x061338bb0e95b314ULL,0x401371d8273f762aULL}, // 1.514882452993549494932585972882995548426E6L,
|
||||
{0xe379b5d8e7071d74ULL,0x401348fbe89d38e2ULL}, // 1.347518538384329112529391120390701166528E6L,
|
||||
{0x412eafafea233277ULL,0x40127bc5211688c1ULL}, // 7.777690340007566932935753241556479363645E5L,
|
||||
{0x16378fd2514ba129ULL,0x40110088814003eaULL}, // 2.626900195321832660448791748036714883242E5L,
|
||||
{0xed708a3f3a1ac5caULL,0x400e33de58205cb3ULL}, // 3.940717212190338497730839731583397586124E4L
|
||||
};
|
||||
|
||||
/* Coefficients for log(x) = z + z^3 P(z^2)/Q(z^2),
|
||||
* where z = 2(x-1)/(x+1)
|
||||
* 1/sqrt(2) <= x < sqrt(2)
|
||||
* Theoretical peak relative error = 1.1e-35,
|
||||
* relative peak error spread 1.1e-9
|
||||
*/
|
||||
static float128_t R[6] = {
|
||||
{0x68479d54e4ced708ULL, 0xbffec40a1c874f5aULL}, // -8.828896441624934385266096344596648080902E-1L,
|
||||
{0x565b5611a30df628ULL, 0x40054247b533971eULL}, // 8.057002716646055371965756206836056074715E1L,
|
||||
{0xb690eddd457e03b0ULL, 0xc009fa1350a9210eULL}, // -2.024301798136027039250415126250455056397E3L,
|
||||
{0xea1230d4dc2a41c8ULL, 0x400d4020cbb3c4edULL}, // 2.048819892795278657810231591630928516206E4L,
|
||||
{0x388e5d3ae806c32aULL, 0xc00f5eac94780e23ULL}, // -8.977257995689735303686582344659576526998E4L,
|
||||
{0x6802a6fb3250b4fdULL, 0x401014fab5e2e8c1ULL}, // 1.418134209872192732479751274970992665513E5L
|
||||
};
|
||||
static float128_t S[6] = {
|
||||
/* 1.000000000000000000000000000000000000000E0L, */
|
||||
{0x2575cd7cadd52c63ULL, 0xc005da8b34108b63ULL}, // -1.186359407982897997337150403816839480438E2L,
|
||||
{0x9022bf51e9d20aecULL, 0x400af3d0db24df08ULL}, // 3.998526750980007367835804959888064681098E3L,
|
||||
{0xeb27fc1032bb267dULL, 0xc00ec11ad77cc51cULL}, // -5.748542087379434595104154610899551484314E4L,
|
||||
{0xaeec5bd6a5211cbdULL, 0x401186c6f13df72eULL}, // 4.001557694070773974936904547424676279307E5L,
|
||||
{0xee9e91e4b3020178ULL, 0xc013455371e04bc5ULL}, // -1.332535117259762928288745111081235577029E6L,
|
||||
{0x1c03fa78cb791730ULL, 0x40139f7810d45d22ULL}, // 1.701761051846631278975701529965589676574E6L
|
||||
};
|
||||
/* log2(e) - 1 */
|
||||
static const float128_t LOG2EA = {0x85ddf43ff68348eaULL, 0x3ffdc551d94ae0bfULL};
|
||||
|
||||
static const float128_t SQRTH = {0xc908b2fb1366ea95ULL, 0x3ffe6a09e667f3bcULL};
|
||||
static const float128_t zero = {0, 0};
|
||||
static const float128_t f_0_p5 = {0, 0x3ffe000000000000ULL};
|
||||
static const float128_t one = {0, 0x3fff000000000000ULL};
|
||||
|
||||
static const float128_t indeterminate = {0x0000000000000000ULL, 0xc00d000000000000ULL};
|
||||
|
||||
float128_t cephes_f128_log2l(float128_t x) {
|
||||
VOLATILE float128_t z;
|
||||
float128_t y;
|
||||
int e;
|
||||
|
||||
struct softfloat_state state = {};
|
||||
|
||||
/* Test for domain */
|
||||
if( f128_le(&state, x, zero) )
|
||||
{
|
||||
if( f128_eq(&state, x, zero) )
|
||||
mtherr( fname, SING );
|
||||
else
|
||||
mtherr( fname, DOMAIN );
|
||||
return indeterminate;
|
||||
}
|
||||
|
||||
/* separate mantissa from exponent */
|
||||
|
||||
/* Note, frexp is used so that denormal numbers
|
||||
* will be handled properly.
|
||||
*/
|
||||
x = cephes_f128_frexpl( x, &e );
|
||||
|
||||
|
||||
/* logarithm using log(x) = z + z**3 P(z)/Q(z),
|
||||
* where z = 2(x-1)/x+1)
|
||||
*/
|
||||
if( (e > 2) || (e < -2) )
|
||||
{
|
||||
if( f128_lt(&state, x, SQRTH) )
|
||||
{ /* 2( 2x-1 )/( 2x+1 ) */
|
||||
e -= 1;
|
||||
z = f128_sub(&state, x, f_0_p5);
|
||||
y = f128_add(&state, f128_mul(&state, f_0_p5, z), f_0_p5);
|
||||
}
|
||||
else
|
||||
{ /* 2 (x-1)/(x+1) */
|
||||
z = f128_sub(&state, x, f_0_p5);
|
||||
z = f128_sub(&state, z, f_0_p5);
|
||||
y = f128_add(&state, f128_mul(&state, f_0_p5, x), f_0_p5);
|
||||
}
|
||||
x = f128_div(&state, z, y);
|
||||
z = f128_mul(&state, x, x);
|
||||
y = f128_mul(&state, x,
|
||||
f128_div(&state, f128_mul(&state, z, cephes_f128_polevll( z, R, 5 )), cephes_f128_p1evll( z, S, 6 ) ));
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
/* logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) */
|
||||
|
||||
if( f128_lt(&state, x, SQRTH) )
|
||||
{
|
||||
e -= 1;
|
||||
x = f128_sub(&state, cephes_f128_ldexpl( x, 1 ), one); /* 2x - 1 */
|
||||
}
|
||||
else
|
||||
{
|
||||
x = f128_sub(&state, x, one);
|
||||
}
|
||||
z = f128_mul(&state, x, x);
|
||||
y = f128_mul(&state, x,
|
||||
f128_div(&state, f128_mul(&state, z, cephes_f128_polevll( x, P, 12 )), cephes_f128_p1evll( x, Q, 12 )));
|
||||
y = f128_sub(&state, y, cephes_f128_ldexpl( z, -1 )); /* -0.5x^2 + ... */
|
||||
|
||||
done:
|
||||
|
||||
/* Multiply log of fraction by log2(e)
|
||||
* and base 2 exponent by 1
|
||||
*
|
||||
* ***CAUTION***
|
||||
*
|
||||
* This sequence of operations is critical and it may
|
||||
* be horribly defeated by some compiler optimizers.
|
||||
*/
|
||||
z = f128_mul(&state, y, LOG2EA);
|
||||
z = f128_add(&state, z, f128_mul(&state, x, LOG2EA));
|
||||
z = f128_add(&state, z, y);
|
||||
z = f128_add(&state, z, x);
|
||||
z = f128_add(&state, z, i32_to_f128(e));
|
||||
return( z );
|
||||
}
|
||||
|
||||
Vendored
-200
@@ -1,200 +0,0 @@
|
||||
/* mconf.h
|
||||
*
|
||||
* Common include file for math routines
|
||||
*
|
||||
*
|
||||
*
|
||||
* SYNOPSIS:
|
||||
*
|
||||
* #include "mconf.h"
|
||||
*
|
||||
*
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* This file contains definitions for error codes that are
|
||||
* passed to the common error handling routine mtherr()
|
||||
* (which see).
|
||||
*
|
||||
* The file also includes a conditional assembly definition
|
||||
* for the type of computer arithmetic (IEEE, DEC, Motorola
|
||||
* IEEE, or UNKnown).
|
||||
*
|
||||
* For Digital Equipment PDP-11 and VAX computers, certain
|
||||
* IBM systems, and others that use numbers with a 56-bit
|
||||
* significand, the symbol DEC should be defined. In this
|
||||
* mode, most floating point constants are given as arrays
|
||||
* of octal integers to eliminate decimal to binary conversion
|
||||
* errors that might be introduced by the compiler.
|
||||
*
|
||||
* For little-endian computers, such as IBM PC, that follow the
|
||||
* IEEE Standard for Binary Floating Point Arithmetic (ANSI/IEEE
|
||||
* Std 754-1985), the symbol IBMPC should be defined. These
|
||||
* numbers have 53-bit significands. In this mode, constants
|
||||
* are provided as arrays of hexadecimal 16 bit integers.
|
||||
*
|
||||
* Big-endian IEEE format is denoted MIEEE. On some RISC
|
||||
* systems such as Sun SPARC, double precision constants
|
||||
* must be stored on 8-byte address boundaries. Since integer
|
||||
* arrays may be aligned differently, the MIEEE configuration
|
||||
* may fail on such machines.
|
||||
*
|
||||
* To accommodate other types of computer arithmetic, all
|
||||
* constants are also provided in a normal decimal radix
|
||||
* which one can hope are correctly converted to a suitable
|
||||
* format by the available C language compiler. To invoke
|
||||
* this mode, define the symbol UNK.
|
||||
*
|
||||
* An important difference among these modes is a predefined
|
||||
* set of machine arithmetic constants for each. The numbers
|
||||
* MACHEP (the machine roundoff error), MAXNUM (largest number
|
||||
* represented), and several other parameters are preset by
|
||||
* the configuration symbol. Check the file const.c to
|
||||
* ensure that these values are correct for your computer.
|
||||
*
|
||||
* Configurations NANS, INFINITIES, MINUSZERO, and DENORMAL
|
||||
* may fail on many systems. Verify that they are supposed
|
||||
* to work on your computer.
|
||||
*/
|
||||
|
||||
/*
|
||||
Cephes Math Library Release 2.3: June, 1995
|
||||
Copyright 1984, 1987, 1989, 1995 by Stephen L. Moshier
|
||||
*/
|
||||
|
||||
|
||||
/* Constant definitions for math error conditions
|
||||
*/
|
||||
|
||||
#include "SoftFloat-3e/platform.h"
|
||||
#include "SoftFloat-3e/softfloat.h"
|
||||
|
||||
#define DOMAIN 1 /* argument domain error */
|
||||
#define SING 2 /* argument singularity */
|
||||
#define OVERFLOW 3 /* overflow range error */
|
||||
#define UNDERFLOW 4 /* underflow range error */
|
||||
#define TLOSS 5 /* total loss of precision */
|
||||
#define PLOSS 6 /* partial loss of precision */
|
||||
|
||||
#define EDOM 33
|
||||
#define ERANGE 34
|
||||
|
||||
/* Complex numeral. */
|
||||
typedef struct
|
||||
{
|
||||
double r;
|
||||
double i;
|
||||
} cmplx;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float r;
|
||||
float i;
|
||||
} cmplxf;
|
||||
|
||||
/* Long double complex numeral. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float128_t r;
|
||||
float128_t i;
|
||||
} cmplxl;
|
||||
|
||||
|
||||
/* Type of computer arithmetic */
|
||||
|
||||
/* PDP-11, Pro350, VAX:
|
||||
*/
|
||||
/* #define DEC 1 */
|
||||
|
||||
/* Intel IEEE, low order words come first:
|
||||
*/
|
||||
#define IBMPC 1
|
||||
|
||||
/* Motorola IEEE, high order words come first
|
||||
* (Sun 680x0 workstation):
|
||||
*/
|
||||
/* #define MIEEE 1 */
|
||||
|
||||
/* UNKnown arithmetic, invokes coefficients given in
|
||||
* normal decimal format. Beware of range boundary
|
||||
* problems (MACHEP, MAXLOG, etc. in const.c) and
|
||||
* roundoff problems in pow.c:
|
||||
* (Sun SPARCstation)
|
||||
*/
|
||||
/* #define UNK 1 */
|
||||
|
||||
/* If you define UNK, then be sure to set BIGENDIAN properly. */
|
||||
/* #define BIGENDIAN 1 */
|
||||
|
||||
/* Define this `volatile' if your compiler thinks
|
||||
* that floating point arithmetic obeys the associative
|
||||
* and distributive laws. It will defeat some optimizations
|
||||
* (but probably not enough of them).
|
||||
*
|
||||
* #define VOLATILE volatile
|
||||
*/
|
||||
#define VOLATILE
|
||||
|
||||
/* For 12-byte long doubles on an i386, pad a 16-bit short 0
|
||||
* to the end of real constants initialized by integer arrays.
|
||||
*
|
||||
* #define XPD 0,
|
||||
*
|
||||
* Otherwise, the type is 10 bytes long and XPD should be
|
||||
* defined blank (e.g., Microsoft C).
|
||||
*
|
||||
* #define XPD
|
||||
*/
|
||||
#define XPD 0,
|
||||
|
||||
/* Define to support tiny denormal numbers, else undefine. */
|
||||
#define DENORMAL 1
|
||||
|
||||
/* Define to ask for infinity support, else undefine. */
|
||||
#define INFINITIES 1
|
||||
|
||||
/* Define to ask for support of numbers that are Not-a-Number,
|
||||
else undefine. This may automatically define INFINITIES in some files. */
|
||||
#define NANS 1
|
||||
|
||||
/* Define to distinguish between -0.0 and +0.0. */
|
||||
#define MINUSZERO 1
|
||||
|
||||
/* Define 1 for ANSI C atan2() function
|
||||
and ANSI prototypes for float arguments.
|
||||
See atan.c and clog.c. */
|
||||
#define ANSIC 1
|
||||
|
||||
/* Variable for error reporting. See mtherr.c. */
|
||||
extern int merror;
|
||||
|
||||
/* Forward declarations */
|
||||
extern float128_t F128_MINLOGL;
|
||||
|
||||
extern float128_t F128_MAXNUML;
|
||||
extern float128_t F128_PIL;
|
||||
extern float128_t F128_PIO2L, F128_PIO4L;
|
||||
|
||||
float128_t cephes_f128_atanl(float128_t x);
|
||||
#if ANSIC
|
||||
float128_t cephes_f128_atan2l( float128_t y, float128_t x );
|
||||
#else
|
||||
float128_t cephes_f128_atan2l( float128_t x, float128_t y );
|
||||
#endif
|
||||
float128_t cephes_f128_ceill(float128_t x);
|
||||
float128_t cephes_f128_cosl(float128_t x);
|
||||
float128_t cephes_f128_fabsl(float128_t x);
|
||||
float128_t cephes_f128_floorl(float128_t x);
|
||||
float128_t cephes_f128_frexpl( float128_t x, int *pw2 );
|
||||
int cephes_f128_isfinitel(float128_t x);
|
||||
int cephes_f128_isnanl(float128_t x);
|
||||
float128_t cephes_f128_ldexpl( float128_t x, int pw2 );
|
||||
float128_t cephes_f128_polevll( float128_t x, void *PP, int n );
|
||||
float128_t cephes_f128_p1evll( float128_t x, void *PP, int n );
|
||||
int cephes_f128_signbitl(float128_t x);
|
||||
float128_t cephes_f128_sinl(float128_t x);
|
||||
int mtherr( char *name, int code );
|
||||
|
||||
/* Public symbol declarations */
|
||||
float128_t cephes_f128_log2l(float128_t x);
|
||||
Vendored
-85
@@ -1,85 +0,0 @@
|
||||
/* mtherr.c
|
||||
*
|
||||
* Library common error handling routine
|
||||
*
|
||||
*
|
||||
*
|
||||
* SYNOPSIS:
|
||||
*
|
||||
* char *fctnam;
|
||||
* int code;
|
||||
* int mtherr();
|
||||
*
|
||||
* mtherr( fctnam, code );
|
||||
*
|
||||
*
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* This routine may be called to report one of the following
|
||||
* error conditions (in the include file mconf.h).
|
||||
*
|
||||
* Mnemonic Value Significance
|
||||
*
|
||||
* DOMAIN 1 argument domain error
|
||||
* SING 2 function singularity
|
||||
* OVERFLOW 3 overflow range error
|
||||
* UNDERFLOW 4 underflow range error
|
||||
* TLOSS 5 total loss of precision
|
||||
* PLOSS 6 partial loss of precision
|
||||
* EDOM 33 Unix domain error code
|
||||
* ERANGE 34 Unix range error code
|
||||
*
|
||||
* The default version of the file prints the function name,
|
||||
* passed to it by the pointer fctnam, followed by the
|
||||
* error condition. The display is directed to the standard
|
||||
* output device. The routine then returns to the calling
|
||||
* program. Users may wish to modify the program to abort by
|
||||
* calling exit() under severe error conditions such as domain
|
||||
* errors.
|
||||
*
|
||||
* Since all error conditions pass control to this function,
|
||||
* the display may be easily changed, eliminated, or directed
|
||||
* to an error logging device.
|
||||
*
|
||||
* SEE ALSO:
|
||||
*
|
||||
* mconf.h
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Cephes Math Library Release 2.0: April, 1987
|
||||
Copyright 1984, 1987 by Stephen L. Moshier
|
||||
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
|
||||
*/
|
||||
|
||||
#include "mconf.h"
|
||||
|
||||
int merror = 0;
|
||||
|
||||
int mtherr( char *name, int code )
|
||||
{
|
||||
#if 0
|
||||
/* Display string passed by calling program,
|
||||
* which is supposed to be the name of the
|
||||
* function in which the error occurred:
|
||||
*/
|
||||
printf( "\n%s ", name );
|
||||
|
||||
/* Set global error message word */
|
||||
merror = code;
|
||||
|
||||
/* Display error message defined
|
||||
* by the code argument.
|
||||
*/
|
||||
if( (code <= 0) || (code >= 7) )
|
||||
code = 0;
|
||||
printf( "%s error\n", ermsg[code] );
|
||||
|
||||
#endif
|
||||
/* Return to calling
|
||||
* program
|
||||
*/
|
||||
return( 0 );
|
||||
}
|
||||
Vendored
-94
@@ -1,94 +0,0 @@
|
||||
/* polevll.c
|
||||
* p1evll.c
|
||||
*
|
||||
* Evaluate polynomial
|
||||
*
|
||||
*
|
||||
*
|
||||
* SYNOPSIS:
|
||||
*
|
||||
* int N;
|
||||
* float128_t x, y, coef[N+1], polevl[];
|
||||
*
|
||||
* y = polevll( x, coef, N );
|
||||
*
|
||||
*
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* Evaluates polynomial of degree N:
|
||||
*
|
||||
* 2 N
|
||||
* y = C + C x + C x +...+ C x
|
||||
* 0 1 2 N
|
||||
*
|
||||
* Coefficients are stored in reverse order:
|
||||
*
|
||||
* coef[0] = C , ..., coef[N] = C .
|
||||
* N 0
|
||||
*
|
||||
* The function p1evll() assumes that coef[N] = 1.0 and is
|
||||
* omitted from the array. Its calling arguments are
|
||||
* otherwise the same as polevll().
|
||||
*
|
||||
*
|
||||
* SPEED:
|
||||
*
|
||||
* In the interest of speed, there are no checks for out
|
||||
* of bounds arithmetic. This routine is used by most of
|
||||
* the functions in the library. Depending on available
|
||||
* equipment features, the user may wish to rewrite the
|
||||
* program in microcode or assembly language.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Cephes Math Library Release 2.2: July, 1992
|
||||
Copyright 1984, 1987, 1988, 1992 by Stephen L. Moshier
|
||||
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
|
||||
*/
|
||||
#include "mconf.h"
|
||||
|
||||
|
||||
/* Polynomial evaluator:
|
||||
* P[0] x^n + P[1] x^(n-1) + ... + P[n]
|
||||
*/
|
||||
float128_t cephes_f128_polevll( float128_t x, void *PP, int n )
|
||||
{
|
||||
|
||||
struct softfloat_state state = {};
|
||||
register float128_t y;
|
||||
float128_t *P;
|
||||
|
||||
P = (float128_t *) PP;
|
||||
y = *P++;
|
||||
do
|
||||
{
|
||||
y = f128_add(&state, f128_mul(&state, y, x), *P++);
|
||||
}
|
||||
while( --n );
|
||||
return(y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Polynomial evaluator:
|
||||
* x^n + P[0] x^(n-1) + P[1] x^(n-2) + ... + P[n]
|
||||
*/
|
||||
float128_t cephes_f128_p1evll( float128_t x, void *PP, int n )
|
||||
{
|
||||
struct softfloat_state state = {};
|
||||
register float128_t y;
|
||||
float128_t *P;
|
||||
|
||||
P = (float128_t *) PP;
|
||||
n -= 1;
|
||||
y = f128_add(&state, x, *P++);
|
||||
do
|
||||
{
|
||||
y = f128_add(&state, f128_mul(&state, y, x), *P++);
|
||||
}
|
||||
while( --n );
|
||||
return( y );
|
||||
}
|
||||
Vendored
-302
@@ -1,302 +0,0 @@
|
||||
/* sinl.c
|
||||
*
|
||||
* Circular sine, float128_t precision
|
||||
*
|
||||
*
|
||||
*
|
||||
* SYNOPSIS:
|
||||
*
|
||||
* float128_t x, y, sinl();
|
||||
*
|
||||
* y = sinl( x );
|
||||
*
|
||||
*
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* Range reduction is into intervals of pi/4. The reduction
|
||||
* error is nearly eliminated by contriving an extended precision
|
||||
* modular arithmetic.
|
||||
*
|
||||
* Two polynomial approximating functions are employed.
|
||||
* Between 0 and pi/4 the sine is approximated by the Cody
|
||||
* and Waite polynomial form
|
||||
* x + x^3 P(x^2) .
|
||||
* Between pi/4 and pi/2 the cosine is represented as
|
||||
* 1 - .5 x^2 + x^4 Q(x^2) .
|
||||
*
|
||||
*
|
||||
* ACCURACY:
|
||||
*
|
||||
* Relative error:
|
||||
* arithmetic domain # trials peak rms
|
||||
* IEEE +-3.6e16 100,000 2.0e-34 5.3e-35
|
||||
*
|
||||
* ERROR MESSAGES:
|
||||
*
|
||||
* message condition value returned
|
||||
* sin total loss x > 2^55 0.0
|
||||
*
|
||||
*/
|
||||
/* cosl.c
|
||||
*
|
||||
* Circular cosine, float128_t precision
|
||||
*
|
||||
*
|
||||
*
|
||||
* SYNOPSIS:
|
||||
*
|
||||
* float128_t x, y, cosl();
|
||||
*
|
||||
* y = cosl( x );
|
||||
*
|
||||
*
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* Range reduction is into intervals of pi/4. The reduction
|
||||
* error is nearly eliminated by contriving an extended precision
|
||||
* modular arithmetic.
|
||||
*
|
||||
* Two polynomial approximating functions are employed.
|
||||
* Between 0 and pi/4 the cosine is approximated by
|
||||
* 1 - .5 x^2 + x^4 Q(x^2) .
|
||||
* Between pi/4 and pi/2 the sine is represented by the Cody
|
||||
* and Waite polynomial form
|
||||
* x + x^3 P(x^2) .
|
||||
*
|
||||
*
|
||||
* ACCURACY:
|
||||
*
|
||||
* Relative error:
|
||||
* arithmetic domain # trials peak rms
|
||||
* IEEE +-3.6e16 100,000 2.0e-34 5.2e-35
|
||||
*
|
||||
* ERROR MESSAGES:
|
||||
*
|
||||
* message condition value returned
|
||||
* cos total loss x > 2^55 0.0
|
||||
*/
|
||||
|
||||
/* sin.c */
|
||||
|
||||
/*
|
||||
Cephes Math Library Release 2.2: December, 1990
|
||||
Copyright 1985, 1990 by Stephen L. Moshier
|
||||
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
|
||||
*/
|
||||
|
||||
#include "mconf.h"
|
||||
|
||||
/* sin(x) = x + x^3 P(x^2)
|
||||
* Theoretical peak relative error = 5.6e-39
|
||||
* relative peak error spread = 1.7e-9
|
||||
*/
|
||||
|
||||
static float128_t sincof[12] = {
|
||||
{0x07424c0cc240ddd5ULL, 0x3fab3d6c15b6d187ULL}, // 6.410290407010279602425714995528976754871E-26L,
|
||||
{0x0f48760e659301d0ULL, 0xbfb47619a65f0be7ULL}, // -3.868105354403065333804959405965295962871E-23L,
|
||||
{0xcb791f8ea7c13184ULL, 0x3fbd71b8ee9a64e1ULL}, // 1.957294039628045847156851410307133941611E-20L,
|
||||
{0x0b420eabbeb9d9bcULL, 0xbfc62f49b467cdf7ULL}, // -8.220635246181818130416407184286068307901E-18L,
|
||||
{0x4be70cee4054eef9ULL, 0x3fce952c77030ab5ULL}, // 2.811457254345322887443598804951004537784E-15L,
|
||||
{0xe782874b38cbd281ULL, 0xbfd6ae7f3e733b81ULL}, // -7.647163731819815869711749952353081768709E-13L,
|
||||
{0x97c83627668fe57cULL, 0x3fde6124613a86d0ULL}, // 1.605904383682161459812515654720205050216E-10L,
|
||||
{0x38fe73eef2ec94cdULL, 0xbfe5ae64567f544eULL}, // -2.505210838544171877505034150892770940116E-8L,
|
||||
{0x38faac1c6f6fa52aULL, 0x3fec71de3a556c73ULL}, // 2.755731922398589065255731765498970284004E-6L,
|
||||
{0xa01a01a019fc52ccULL, 0xbff2a01a01a01a01ULL}, // -1.984126984126984126984126984045294307281E-4L,
|
||||
{0x1111111111111083ULL, 0x3ff8111111111111ULL}, // 8.333333333333333333333333333333119885283E-3L,
|
||||
{0x5555555555555555ULL, 0xbffc555555555555ULL}, // -1.666666666666666666666666666666666647199E-1L
|
||||
};
|
||||
/* cos(x) = 1 - .5 x^2 + x^2 (x^2 P(x^2))
|
||||
* Theoretical peak relative error = 2.1e-37,
|
||||
* relative peak error spread = 1.4e-8
|
||||
*/
|
||||
static float128_t coscof[11] = {
|
||||
{0x86919a6fdf15a4b3ULL, 0x3fafefc8801eb0a1ULL}, // 1.601961934248327059668321782499768648351E-24L,
|
||||
{0x902367b3281c9510ULL, 0xbfb90ce245980e11ULL}, // -8.896621117922334603659240022184527001401E-22L,
|
||||
{0xcf5102d043ad399aULL, 0x3fc1e542b8eb4f0dULL}, // 4.110317451243694098169570731967589555498E-19L,
|
||||
{0xa8272970c73ab5ffULL, 0xbfca6827863b2960ULL}, // -1.561920696747074515985647487260202922160E-16L,
|
||||
{0xf9016edb75d1fb52ULL, 0x3fd2ae7f3e733b51ULL}, // 4.779477332386900932514186378501779328195E-14L,
|
||||
{0xc3e862188c1c1f15ULL, 0xbfda93974a8c07c9ULL}, // -1.147074559772972328629102981460088437917E-11L,
|
||||
{0x7b517ff3abf58399ULL, 0x3fe21eed8eff8d89ULL}, // 2.087675698786809897637922200570559726116E-9L,
|
||||
{0xc72eef5d4453f45cULL, 0xbfe927e4fb7789f5ULL}, // -2.755731922398589065255365968070684102298E-7L,
|
||||
{0xa01a019fdf56450dULL, 0x3fefa01a01a01a01ULL}, // 2.480158730158730158730158440896461945271E-5L,
|
||||
{0x6c16c16c16b76e10ULL, 0xbff56c16c16c16c1ULL}, // -1.388888888888888888888888888765724370132E-3L,
|
||||
{0x55555555555553fdULL, 0x3ffa555555555555ULL}, // 4.166666666666666666666666666666459301466E-2L
|
||||
};
|
||||
/*
|
||||
static float128_t DP1 = 7.853981554508209228515625E-1L;
|
||||
static float128_t DP2 = 7.94662735614792836713604629039764404296875E-9L;
|
||||
static float128_t DP3 = 3.0616169978683829430651648306875026455243736148E-17L;
|
||||
static float128_t lossth = 5.49755813888e11L;
|
||||
*/
|
||||
static float128_t DP1 =
|
||||
{0x8400000000000000ULL, 0x3ffe921fb54442d1ULL};
|
||||
//7.853981633974483067550664827649598009884357452392578125E-1L;
|
||||
static float128_t DP2 =
|
||||
{0xe000000000000000ULL, 0x3fc4a62633145c06ULL};
|
||||
//2.8605943630549158983813312792950660807511260829685741796657E-18L;
|
||||
static float128_t DP3 =
|
||||
{0xa67cc74020bbea64ULL, 0x3f8bcd129024e088ULL};
|
||||
//2.1679525325309452561992610065108379921905808E-35L;
|
||||
|
||||
static const float128_t lossth = {0x0000000000000000ULL, 0x4036000000000000ULL}; // 3.6028797018963968E16L; /* 2^55 */
|
||||
static const float128_t zero = {0, 0};
|
||||
static const float128_t one = {0, 0x3fff000000000000ULL};
|
||||
|
||||
float128_t cephes_f128_sinl(float128_t x)
|
||||
{
|
||||
struct softfloat_state state = {};
|
||||
float128_t y, z, zz;
|
||||
int j, sign;
|
||||
|
||||
/* make argument positive but save the sign */
|
||||
sign = 1;
|
||||
if( f128_lt(&state, x, zero) )
|
||||
{
|
||||
x = f128_complement_sign(x);
|
||||
sign = -1;
|
||||
}
|
||||
|
||||
if( f128_lt(&state, lossth, x))
|
||||
{
|
||||
mtherr( "sinl", TLOSS );
|
||||
return zero;
|
||||
}
|
||||
|
||||
y = cephes_f128_floorl( f128_div(&state, x, F128_PIO4L) ); /* integer part of x/PIO4 */
|
||||
|
||||
/* strip high bits of integer part to prevent integer overflow */
|
||||
z = cephes_f128_ldexpl( y, -4 );
|
||||
z = cephes_f128_floorl(z); /* integer part of y/8 */
|
||||
z = f128_sub(&state, y, cephes_f128_ldexpl( z, 4 )); /* y - 16 * (y/16) */
|
||||
|
||||
j = f128_to_i32(&state, z, softfloat_round_near_even, true); /* convert to integer for tests on the phase angle */
|
||||
/* map zeros to origin */
|
||||
if( j & 1 )
|
||||
{
|
||||
j += 1;
|
||||
y = f128_add(&state, y, one);
|
||||
}
|
||||
j = j & 07; /* octant modulo 360 degrees */
|
||||
/* reflect in x axis */
|
||||
if( j > 3)
|
||||
{
|
||||
sign = -sign;
|
||||
j -= 4;
|
||||
}
|
||||
|
||||
/* Extended precision modular arithmetic */
|
||||
// z = ((x - y * DP1) - y * DP2) - y * DP3;
|
||||
{
|
||||
float128_t tmp1 = f128_mul(&state, y, DP1);
|
||||
float128_t tmp2 = f128_mul(&state, y, DP2);
|
||||
float128_t tmp3 = f128_mul(&state, y, DP3);
|
||||
float128_t tmp4 = f128_sub(&state, x, tmp1);
|
||||
float128_t tmp5 = f128_sub(&state, tmp4, tmp2);
|
||||
z = f128_sub(&state, tmp5, tmp3);
|
||||
}
|
||||
|
||||
z = f128_sub(&state, f128_sub(&state, f128_sub(&state, x, f128_mul(&state, y, DP1)), f128_mul(&state, y, DP2)), f128_mul(&state, y, DP3));
|
||||
|
||||
zz = f128_mul(&state, z, z);
|
||||
if( (j==1) || (j==2) )
|
||||
{
|
||||
// y = 1.0L - ldexpl(zz,-1) + zz * zz * polevll( zz, coscof, 10 );
|
||||
float128_t tmp1 = f128_mul(&state, zz, zz);
|
||||
float128_t tmp2 = f128_mul(&state, tmp1, cephes_f128_polevll( zz, coscof, 10 ));
|
||||
float128_t tmp3 = f128_sub(&state, one, cephes_f128_ldexpl(zz,-1));
|
||||
y = f128_add(&state, tmp3, tmp2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// y = z + z * (zz * polevll( zz, sincof, 11 ));
|
||||
float128_t tmp1 = f128_mul(&state, zz, cephes_f128_polevll( zz, sincof, 11 ));
|
||||
float128_t tmp2 = f128_mul(&state, z, tmp1);
|
||||
y = f128_add(&state, z, tmp2);
|
||||
}
|
||||
|
||||
if(sign < 0)
|
||||
y = f128_complement_sign(y);
|
||||
|
||||
return(y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
float128_t cephes_f128_cosl(float128_t x)
|
||||
{
|
||||
struct softfloat_state state = {};
|
||||
float128_t y, z, zz;
|
||||
long i;
|
||||
int j, sign;
|
||||
|
||||
/* make argument positive */
|
||||
sign = 1;
|
||||
if( f128_lt(&state, x, zero) )
|
||||
x = f128_complement_sign(x);
|
||||
|
||||
|
||||
if( f128_lt(&state, lossth, x))
|
||||
{
|
||||
mtherr( "cosl", TLOSS );
|
||||
return zero;
|
||||
}
|
||||
|
||||
y = cephes_f128_floorl( f128_div(&state, x, F128_PIO4L));
|
||||
z = cephes_f128_ldexpl( y, -4 );
|
||||
z = cephes_f128_floorl(z); /* integer part of y/8 */
|
||||
z = f128_sub(&state, y, cephes_f128_ldexpl( z, 4 )); /* y - 16 * (y/16) */
|
||||
|
||||
/* integer and fractional part modulo one octant */
|
||||
i = f128_to_i32(&state, z, softfloat_round_near_even, true);
|
||||
if( i & 1 ) /* map zeros to origin */
|
||||
{
|
||||
i += 1;
|
||||
y = f128_add(&state, y, one);
|
||||
}
|
||||
j = i & 07;
|
||||
if( j > 3)
|
||||
{
|
||||
j -=4;
|
||||
sign = -sign;
|
||||
}
|
||||
|
||||
if( j > 1 )
|
||||
sign = -sign;
|
||||
|
||||
/* Extended precision modular arithmetic */
|
||||
// z = ((x - y * DP1) - y * DP2) - y * DP3;
|
||||
{
|
||||
float128_t tmp1 = f128_mul(&state, y, DP1);
|
||||
float128_t tmp2 = f128_mul(&state, y, DP2);
|
||||
float128_t tmp3 = f128_mul(&state, y, DP3);
|
||||
float128_t tmp4 = f128_sub(&state, x, tmp1);
|
||||
float128_t tmp5 = f128_sub(&state, tmp4, tmp2);
|
||||
z = f128_sub(&state, tmp5, tmp3);
|
||||
}
|
||||
|
||||
zz = f128_mul(&state, z, z);
|
||||
if( (j==1) || (j==2) )
|
||||
{
|
||||
// y = z + z * (zz * polevll( zz, sincof, 11 ));
|
||||
float128_t tmp1 = f128_mul(&state, zz, cephes_f128_polevll( zz, sincof, 11 ));
|
||||
float128_t tmp2 = f128_mul(&state, z, tmp1);
|
||||
y = f128_add(&state, z, tmp2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// y = 1.0L - ldexpl(zz,-1) + zz * zz * polevll( zz, coscof, 10 );
|
||||
float128_t tmp1 = f128_mul(&state, zz, zz);
|
||||
float128_t tmp2 = f128_mul(&state, tmp1, cephes_f128_polevll( zz, coscof, 10 ));
|
||||
float128_t tmp3 = f128_sub(&state, one, cephes_f128_ldexpl(zz,-1));
|
||||
y = f128_add(&state, tmp3, tmp2);
|
||||
}
|
||||
|
||||
if(sign < 0)
|
||||
y = f128_complement_sign(y);
|
||||
|
||||
return(y);
|
||||
}
|
||||
Vendored
-224
@@ -1,224 +0,0 @@
|
||||
/* tanl.c
|
||||
*
|
||||
* Circular tangent, 128-bit float128_t precision
|
||||
*
|
||||
*
|
||||
*
|
||||
* SYNOPSIS:
|
||||
*
|
||||
* float128_t x, y, tanl();
|
||||
*
|
||||
* y = tanl( x );
|
||||
*
|
||||
*
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* Returns the circular tangent of the radian argument x.
|
||||
*
|
||||
* Range reduction is modulo pi/4. A rational function
|
||||
* x + x**3 P(x**2)/Q(x**2)
|
||||
* is employed in the basic interval [0, pi/4].
|
||||
*
|
||||
*
|
||||
*
|
||||
* ACCURACY:
|
||||
*
|
||||
* Relative error:
|
||||
* arithmetic domain # trials peak rms
|
||||
* IEEE +-3.6e16 100,000 3.0e-34 7.2e-35
|
||||
*
|
||||
* ERROR MESSAGES:
|
||||
*
|
||||
* message condition value returned
|
||||
* tan total loss x > 2^55 0.0
|
||||
*
|
||||
*/
|
||||
/* cotl.c
|
||||
*
|
||||
* Circular cotangent, float128_t precision
|
||||
*
|
||||
*
|
||||
*
|
||||
* SYNOPSIS:
|
||||
*
|
||||
* float128_t x, y, cotl();
|
||||
*
|
||||
* y = cotl( x );
|
||||
*
|
||||
*
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* Returns the circular cotangent of the radian argument x.
|
||||
*
|
||||
* Range reduction is modulo pi/4. A rational function
|
||||
* x + x**3 P(x**2)/Q(x**2)
|
||||
* is employed in the basic interval [0, pi/4].
|
||||
*
|
||||
*
|
||||
*
|
||||
* ACCURACY:
|
||||
*
|
||||
* Relative error:
|
||||
* arithmetic domain # trials peak rms
|
||||
* IEEE +-3.6e16 100,000 2.9e-34 7.2e-35
|
||||
*
|
||||
*
|
||||
* ERROR MESSAGES:
|
||||
*
|
||||
* message condition value returned
|
||||
* cot total loss x > 2^55 0.0
|
||||
* cot singularity x = 0 MAXNUM
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Cephes Math Library Release 2.2: December, 1990
|
||||
Copyright 1984, 1990 by Stephen L. Moshier
|
||||
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
|
||||
*/
|
||||
|
||||
#include "mconf.h"
|
||||
|
||||
/* tan(x) = x + x^3 P(x^2)
|
||||
* 0 <= |x| <= pi/4
|
||||
* Theoretical peak relative error = 4.3e-38
|
||||
* relative peak error spread = 6.1e-11
|
||||
*/
|
||||
static float128_t P[6] = {
|
||||
{0x09978dc7ae2a2f4bULL, 0xbffefa5d486820e2ULL}, // -9.889929415807650724957118893791829849557E-1L,
|
||||
{0x52a017b1ca7c4799ULL, 0x40093e130edd1294ULL}, // 1.272297782199996882828849455156962260810E3L,
|
||||
{0x8857161b398b3c53ULL, 0xc0119f024bdcc6c3ULL}, // -4.249691853501233575668486667664718192660E5L,
|
||||
{0xcc299261a6616b83ULL, 0x401889b0ed404622ULL}, // 5.160188250214037865511600561074819366815E7L,
|
||||
{0x37d9311de4cdbf04ULL, 0xc01e1304fe4d6331ULL}, // -2.307030822693734879744223131873392503321E9L,
|
||||
{0x6e9f0eac6b638a9aULL, 0x4021ada98af62f83ULL}, // 2.883414728874239697964612246732416606301E10L
|
||||
};
|
||||
static float128_t Q[6] = {
|
||||
/* 1.000000000000000000000000000000000000000E0L, */
|
||||
{0xeb01d728f7d3bb04ULL, 0xc009494f98d3c1caULL}, // -1.317243702830553658702531997959756728291E3L,
|
||||
{0xcdd312b4ac46a6cdULL, 0x4011ba538d331a98ULL}, // 4.529422062441341616231663543669583527923E5L,
|
||||
{0x2a1a6372eebd73a1ULL, 0xc018b57281a9f10bULL}, // -5.733709132766856723608447733926138506824E7L,
|
||||
{0x3e9defb0e348fbe5ULL, 0x401e48d6025d9b41ULL}, // 2.758476078803232151774723646710890525496E9L,
|
||||
{0x7cd82869db5580d1ULL, 0xc022355d0fdbd24eULL}, // -4.152206921457208101480801635640958361612E10L,
|
||||
{0x92f74b01508aa7f3ULL, 0x4023423f2838a3a2ULL}, // 8.650244186622719093893836740197250197602E10L
|
||||
};
|
||||
|
||||
static float128_t DP1 =
|
||||
{0x8400000000000000ULL, 0x3ffe921fb54442d1ULL};
|
||||
//7.853981633974483067550664827649598009884357452392578125E-1L;
|
||||
static float128_t DP2 =
|
||||
{0xe000000000000000ULL, 0x3fc4a62633145c06ULL};
|
||||
//2.8605943630549158983813312792950660807511260829685741796657E-18L;
|
||||
static float128_t DP3 =
|
||||
{0xa67cc74020bbea64ULL, 0x3f8bcd129024e088ULL};
|
||||
// 2.1679525325309452561992610065108379921905808E-35L;
|
||||
|
||||
static const float128_t lossth = {0x0000000000000000ULL, 0x4036000000000000ULL}; // 3.6028797018963968E16L; /* 2^55 */
|
||||
|
||||
static const float128_t zero = {0, 0};
|
||||
static const float128_t one = {0, 0x3fff000000000000ULL};
|
||||
static const float128_t neg_one = {0, 0xbfff000000000000ULL};
|
||||
|
||||
static const float128_t max_quad = {0x35d511e976394d7aULL, 0x3fbc79ca10c92422ULL};
|
||||
|
||||
static float128_t tancotl( struct softfloat_state *state, float128_t xx, int cotflg );
|
||||
|
||||
float128_t cephes_f128_tanl(float128_t x)
|
||||
{
|
||||
struct softfloat_state state = {};
|
||||
return( tancotl(&state, x,0) );
|
||||
}
|
||||
|
||||
|
||||
float128_t cotl(float128_t x)
|
||||
{
|
||||
struct softfloat_state state = {};
|
||||
|
||||
if( f128_eq(&state, x, zero) )
|
||||
{
|
||||
mtherr( "cotl", SING );
|
||||
return( F128_MAXNUML );
|
||||
}
|
||||
return( tancotl(&state, x,1) );
|
||||
}
|
||||
|
||||
|
||||
static float128_t tancotl( struct softfloat_state *state, float128_t xx, int cotflg )
|
||||
{
|
||||
float128_t x, y, z, zz;
|
||||
int j, sign;
|
||||
|
||||
/* make argument positive but save the sign */
|
||||
// if (xx < 0.0L)
|
||||
if( f128_lt(state, xx, zero) )
|
||||
{
|
||||
x = f128_sub(state, zero, xx);
|
||||
sign = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = xx;
|
||||
sign = 1;
|
||||
}
|
||||
|
||||
//if (x > lossth)
|
||||
if (f128_lt(state, lossth, x))
|
||||
{
|
||||
if( cotflg )
|
||||
mtherr( "cotl", TLOSS );
|
||||
else
|
||||
mtherr( "tanl", TLOSS );
|
||||
return zero;
|
||||
}
|
||||
|
||||
/* compute x mod PIO4 */
|
||||
y = cephes_f128_floorl( f128_div(state, x, F128_PIO4L));
|
||||
|
||||
/* strip high bits of integer part */
|
||||
z = cephes_f128_ldexpl( y, -4 );
|
||||
z = cephes_f128_floorl(z); /* integer part of y/16 */
|
||||
z = f128_sub(state, y, cephes_f128_ldexpl( z, 4 )); /* y - 16 * (y/16) */
|
||||
|
||||
/* integer and fractional part modulo one octant */
|
||||
j = f128_to_i32(state, z, softfloat_round_near_even, true);
|
||||
|
||||
/* map zeros and singularities to origin */
|
||||
if( j & 1 )
|
||||
{
|
||||
j += 1;
|
||||
y = f128_add(state, y, one);
|
||||
}
|
||||
|
||||
z = f128_sub(state, f128_sub(state, f128_sub(state, x, f128_mul(state, y, DP1)), f128_mul(state, y, DP2)), f128_mul(state, y, DP3));
|
||||
|
||||
zz = f128_mul(state, z, z);
|
||||
|
||||
// if( zz > 1.0e-20L )
|
||||
if (f128_lt(state, max_quad, zz))
|
||||
{
|
||||
y = f128_add(state, z, f128_mul(state, z, f128_div(state, f128_mul(state, zz, cephes_f128_polevll( zz, P, 5 )), cephes_f128_p1evll(zz, Q, 6))));
|
||||
}
|
||||
else
|
||||
{
|
||||
y = z;
|
||||
}
|
||||
|
||||
if( j & 2 )
|
||||
{
|
||||
if( cotflg )
|
||||
y = f128_complement_sign(y);
|
||||
else
|
||||
y = f128_div(state, neg_one, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( cotflg )
|
||||
y = f128_div(state, one, y);
|
||||
}
|
||||
|
||||
if( sign < 0 )
|
||||
y = f128_complement_sign(y);
|
||||
|
||||
return( y );
|
||||
}
|
||||
-332
@@ -1,332 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# ====- code-format-helper, runs code formatters from the ci or in a hook --*- python -*--==#
|
||||
#
|
||||
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
# See https://llvm.org/LICENSE.txt for license information.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
# ==--------------------------------------------------------------------------------------==#
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import List, Optional
|
||||
|
||||
"""
|
||||
This script is run by GitHub actions to ensure that the code in PR's conform to
|
||||
the coding style of LLVM. It can also be installed as a pre-commit git hook to
|
||||
check the coding style before submitting it. The canonical source of this script
|
||||
is in the LLVM source tree under llvm/utils/git.
|
||||
|
||||
For C/C++ code it uses clang-format.
|
||||
|
||||
You can learn more about the LLVM coding style on llvm.org:
|
||||
https://llvm.org/docs/CodingStandards.html
|
||||
|
||||
You can install this script as a git hook by symlinking it to the .git/hooks
|
||||
directory:
|
||||
|
||||
ln -s $(pwd)/llvm/utils/git/code-format-helper.py .git/hooks/pre-commit
|
||||
|
||||
You can control the exact path to clang-format with the following
|
||||
environment variable: $CLANG_FORMAT_PATH.
|
||||
"""
|
||||
|
||||
|
||||
class FormatArgs:
|
||||
start_rev: str = None
|
||||
end_rev: str = None
|
||||
repo: str = None
|
||||
changed_files: List[str] = []
|
||||
token: str = None
|
||||
verbose: bool = True
|
||||
issue_number: int = 0
|
||||
write_comment_to_file: str = None
|
||||
|
||||
def __init__(self, args: argparse.Namespace = None) -> None:
|
||||
if not args is None:
|
||||
self.start_rev = args.start_rev
|
||||
self.end_rev = args.end_rev
|
||||
self.repo = args.repo
|
||||
self.token = args.token
|
||||
self.changed_files = args.changed_files
|
||||
self.issue_number = args.issue_number
|
||||
self.write_comment_to_file = args.write_comment_to_file
|
||||
|
||||
|
||||
class FormatHelper:
|
||||
COMMENT_TAG = "<!--CODE FORMAT COMMENT: {fmt}-->"
|
||||
name: str
|
||||
friendly_name: str
|
||||
comment: dict = None
|
||||
|
||||
@property
|
||||
def comment_tag(self) -> str:
|
||||
return self.COMMENT_TAG.replace("fmt", self.name)
|
||||
|
||||
@property
|
||||
def instructions(self) -> str:
|
||||
raise NotImplementedError()
|
||||
|
||||
def has_tool(self) -> bool:
|
||||
raise NotImplementedError()
|
||||
|
||||
def format_run(self, changed_files: List[str], args: FormatArgs) -> Optional[str]:
|
||||
raise NotImplementedError()
|
||||
|
||||
def pr_comment_text_for_diff(self, diff: str) -> str:
|
||||
return f"""
|
||||
:warning: {self.friendly_name}, {self.name} found issues in your code. :warning:
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
You can test this locally with the following command:
|
||||
</summary>
|
||||
|
||||
``````````bash
|
||||
{self.instructions}
|
||||
``````````
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
View the diff from {self.name} here.
|
||||
</summary>
|
||||
|
||||
``````````diff
|
||||
{diff}
|
||||
``````````
|
||||
|
||||
</details>
|
||||
"""
|
||||
|
||||
# TODO: any type should be replaced with the correct github type, but it requires refactoring to
|
||||
# not require the github module to be installed everywhere.
|
||||
def find_comment(self, pr: any) -> any:
|
||||
for comment in pr.as_issue().get_comments():
|
||||
if self.comment_tag in comment.body:
|
||||
return comment
|
||||
return None
|
||||
|
||||
def update_pr(self, comment_text: str, args: FormatArgs, create_new: bool) -> None:
|
||||
import github
|
||||
from github import IssueComment, PullRequest
|
||||
|
||||
repo = github.Github(args.token).get_repo(args.repo)
|
||||
pr = repo.get_issue(args.issue_number).as_pull_request()
|
||||
|
||||
comment_text = self.comment_tag + "\n\n" + comment_text
|
||||
|
||||
existing_comment = self.find_comment(pr)
|
||||
|
||||
if args.write_comment_to_file:
|
||||
if create_new or existing_comment:
|
||||
self.comment = {"body": comment_text}
|
||||
if existing_comment:
|
||||
self.comment["id"] = existing_comment.id
|
||||
return
|
||||
|
||||
if existing_comment:
|
||||
existing_comment.edit(comment_text)
|
||||
elif create_new:
|
||||
pr.as_issue().create_comment(comment_text)
|
||||
|
||||
def run(self, changed_files: List[str], args: FormatArgs) -> bool:
|
||||
changed_files = [arg for arg in changed_files if "third-party" not in arg]
|
||||
diff = self.format_run(changed_files, args)
|
||||
should_update_gh = args.token is not None and args.repo is not None
|
||||
|
||||
if diff is None:
|
||||
if should_update_gh:
|
||||
comment_text = (
|
||||
":white_check_mark: With the latest revision "
|
||||
f"this PR passed the {self.friendly_name}."
|
||||
)
|
||||
self.update_pr(comment_text, args, create_new=False)
|
||||
return True
|
||||
elif len(diff) > 0:
|
||||
if should_update_gh:
|
||||
comment_text = self.pr_comment_text_for_diff(diff)
|
||||
self.update_pr(comment_text, args, create_new=True)
|
||||
else:
|
||||
print(
|
||||
f"Warning: {self.friendly_name}, {self.name} detected "
|
||||
"some issues with your code formatting..."
|
||||
)
|
||||
return False
|
||||
else:
|
||||
# The formatter failed but didn't output a diff (e.g. some sort of
|
||||
# infrastructure failure).
|
||||
comment_text = (
|
||||
f":warning: The {self.friendly_name} failed without printing "
|
||||
"a diff. Check the logs for stderr output. :warning:"
|
||||
)
|
||||
self.update_pr(comment_text, args, create_new=False)
|
||||
return False
|
||||
|
||||
|
||||
class ClangFormatHelper(FormatHelper):
|
||||
name = "git-clang-format"
|
||||
friendly_name = "C/C++ code formatter"
|
||||
|
||||
|
||||
@property
|
||||
def instructions(self) -> str:
|
||||
return " ".join(self.cf_cmd)
|
||||
|
||||
def should_include_extensionless_file(self, path: str) -> bool:
|
||||
return path.startswith("libcxx/include")
|
||||
|
||||
def filter_changed_files(self, changed_files: List[str]) -> List[str]:
|
||||
filtered_files = []
|
||||
for path in changed_files:
|
||||
_, ext = os.path.splitext(path)
|
||||
if ext in (".cpp", ".c", ".h", ".hpp", ".hxx", ".cxx", ".inc", ".cppm"):
|
||||
filtered_files.append(path)
|
||||
elif ext == "" and self.should_include_extensionless_file(path):
|
||||
filtered_files.append(path)
|
||||
return filtered_files
|
||||
|
||||
@property
|
||||
def clang_fmt_path(self) -> str:
|
||||
if "CLANG_FORMAT_PATH" in os.environ:
|
||||
return os.environ["CLANG_FORMAT_PATH"]
|
||||
return "git-clang-format-19"
|
||||
|
||||
def has_tool(self) -> bool:
|
||||
cmd = [self.clang_fmt_path, "-h"]
|
||||
proc = None
|
||||
try:
|
||||
proc = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except:
|
||||
return False
|
||||
return proc.returncode == 0
|
||||
|
||||
def format_run(self, changed_files: List[str], args: FormatArgs) -> Optional[str]:
|
||||
cpp_files = self.filter_changed_files(changed_files)
|
||||
if not cpp_files:
|
||||
return None
|
||||
|
||||
cf_cmd = [
|
||||
self.clang_fmt_path,
|
||||
"--binary=clang-format-19",
|
||||
"--diff",
|
||||
"--diff_from_common_commit",
|
||||
]
|
||||
|
||||
if args.start_rev and args.end_rev:
|
||||
cf_cmd.append(args.start_rev)
|
||||
cf_cmd.append(args.end_rev)
|
||||
|
||||
cf_cmd.append("--")
|
||||
cf_cmd += cpp_files
|
||||
|
||||
if args.verbose:
|
||||
print(f"Running: {' '.join(cf_cmd)}")
|
||||
self.cf_cmd = cf_cmd
|
||||
proc = subprocess.run(cf_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
sys.stdout.write(proc.stderr.decode("utf-8"))
|
||||
|
||||
if proc.returncode != 0:
|
||||
# formatting needed, or the command otherwise failed
|
||||
if args.verbose:
|
||||
print(f"error: {self.name} exited with code {proc.returncode}")
|
||||
# Print the diff in the log so that it is viewable there
|
||||
print(proc.stdout.decode("utf-8"))
|
||||
return proc.stdout.decode("utf-8")
|
||||
else:
|
||||
return None
|
||||
|
||||
ALL_FORMATTERS = [ClangFormatHelper()]
|
||||
|
||||
def hook_main():
|
||||
# fill out args
|
||||
args = FormatArgs()
|
||||
args.verbose = False
|
||||
|
||||
# find the changed files
|
||||
cmd = ["git", "diff", "--cached", "--name-only", "--diff-filter=d"]
|
||||
proc = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
output = proc.stdout.decode("utf-8")
|
||||
for line in output.splitlines():
|
||||
args.changed_files.append(line)
|
||||
|
||||
failed_fmts = []
|
||||
for fmt in ALL_FORMATTERS:
|
||||
if fmt.has_tool():
|
||||
if not fmt.run(args.changed_files, args):
|
||||
failed_fmts.append(fmt.name)
|
||||
if fmt.comment:
|
||||
comments.append(fmt.comment)
|
||||
else:
|
||||
print(f"Couldn't find {fmt.name}, can't check " + fmt.friendly_name.lower())
|
||||
|
||||
if len(failed_fmts) > 0:
|
||||
sys.exit(1)
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
script_path = os.path.abspath(__file__)
|
||||
if ".git/hooks" in script_path:
|
||||
hook_main()
|
||||
sys.exit(0)
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--token", type=str, required=False, help="GitHub authentication token"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--repo",
|
||||
type=str,
|
||||
default=os.getenv("GITHUB_REPOSITORY", "llvm/llvm-project"),
|
||||
help="The GitHub repository that we are working with in the form of <owner>/<repo> (e.g. llvm/llvm-project)",
|
||||
)
|
||||
parser.add_argument("--issue-number", type=int, required=True)
|
||||
parser.add_argument(
|
||||
"--start-rev",
|
||||
type=str,
|
||||
required=True,
|
||||
help="Compute changes from this revision.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--end-rev", type=str, required=True, help="Compute changes to this revision"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--changed-files",
|
||||
type=str,
|
||||
help="Comma separated list of files that has been changed",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--write-comment-to-file",
|
||||
type=str,
|
||||
help="Don't post comments on the PR, instead write the comments and metadata a file",
|
||||
)
|
||||
|
||||
args = FormatArgs(parser.parse_args())
|
||||
|
||||
changed_files = []
|
||||
if args.changed_files:
|
||||
changed_files = args.changed_files.split(",")
|
||||
|
||||
failed_formatters = []
|
||||
comments = []
|
||||
for fmt in ALL_FORMATTERS:
|
||||
if not fmt.run(changed_files, args):
|
||||
failed_formatters.append(fmt.name)
|
||||
if fmt.comment:
|
||||
comments.append(fmt.comment)
|
||||
|
||||
if len(comments):
|
||||
with open(args.write_comment_to_file, "w") as f:
|
||||
import json
|
||||
|
||||
json.dump(comments, f)
|
||||
|
||||
if len(failed_formatters) > 0:
|
||||
print(f"error: some formatters failed: {' '.join(failed_formatters)}")
|
||||
sys.exit(1)
|
||||
Loaded 100 of 2530 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user